Files
Schnappix/node_modules/react-native-svg/windows/RNSVG/Fabric/LinearGradientView.cpp
T

135 lines
5.0 KiB
C++

#include "pch.h"
#include "LinearGradientView.h"
namespace winrt::RNSVG::implementation {
struct SvgLinearGradientStop {
float offset{0};
D2D1_COLOR_F color;
float opacity{1.0f};
};
REACT_STRUCT(LinearGradientProps)
struct LinearGradientProps : winrt::implements<LinearGradientProps, winrt::Microsoft::ReactNative::IComponentProps> {
LinearGradientProps(const winrt::Microsoft::ReactNative::ViewProps &props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) REACT_SVG_RENDERABLE_COMMON_PROPS_INIT
{
REACT_BEGIN_SVG_RENDERABLE_COMMON_PROPS_CLONE(LinearGradientProps)
x1 = cloneFromProps->x1;
y1 = cloneFromProps->y1;
x2 = cloneFromProps->x2;
y2 = cloneFromProps->y2;
gradient = cloneFromProps->gradient;
gradientUnits = cloneFromProps->gradientUnits;
gradientTransform = cloneFromProps->gradientTransform;
REACT_END_SVG_RENDERABLE_COMMON_PROPS_CLONE
}
void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept {
winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this);
}
REACT_SVG_RENDERABLE_COMMON_PROPS;
REACT_FIELD(x1)
std::optional<std::wstring> x1;
REACT_FIELD(y1)
std::optional<std::wstring> y1;
REACT_FIELD(x2)
std::optional<std::wstring> x2;
REACT_FIELD(y2)
std::optional<std::wstring> y2;
REACT_FIELD(gradient)
std::optional<std::vector<float>> gradient{};
REACT_FIELD(gradientUnits)
std::optional<int32_t> gradientUnits;
REACT_FIELD(gradientTransform)
std::optional<std::vector<float>> gradientTransform;
};
struct LinearGradientView : winrt::implements<LinearGradientView, winrt::Windows::Foundation::IInspectable, RenderableView> {
public:
LinearGradientView() = default;
void UpdateProps(
const winrt::Microsoft::ReactNative::ComponentView &view,
const winrt::Microsoft::ReactNative::IComponentProps &newProps,
const winrt::Microsoft::ReactNative::IComponentProps &oldProps) noexcept override {
auto props = newProps.as<LinearGradientProps>();
m_stops.clear();
if (props->gradient) {
auto it = props->gradient->begin();
while (it != props->gradient->end()) {
SvgLinearGradientStop stop;
stop.offset = *it;
++it;
auto clr = static_cast<uint32_t>(*it);
stop.color = D2D1_COLOR_F{
((clr & 0x00FF0000) >> 16) / 255.0f,
((clr & 0x0000FF00) >> 8) / 255.0f,
(clr & 0x000000FF) / 255.0f,
((clr & 0xFF000000) >> 24) / 255.0f};
stop.opacity = ((clr & 0xFF000000) >> 24) / 255.0f;
++it;
m_stops.push_back(stop);
}
}
RenderableView::UpdateProps(view, newProps, oldProps);
}
const wchar_t *GetSvgElementName() noexcept override {
return L"linearGradient";
}
void OnRender(const SvgView &svgView, ID2D1SvgDocument &document, ID2D1SvgElement &element) noexcept override {
auto props = m_props.as<LinearGradientProps>();
SetCommonSvgProps(svgView, document, element, *props);
if (props->x1)
element.SetAttributeValue(
SvgStrings::x1AttributeName, D2D1_SVG_ATTRIBUTE_STRING_TYPE_SVG, props->x1.value().c_str());
if (props->y1)
element.SetAttributeValue(
SvgStrings::y1AttributeName, D2D1_SVG_ATTRIBUTE_STRING_TYPE_SVG, props->y1.value().c_str());
if (props->x2)
element.SetAttributeValue(
SvgStrings::x2AttributeName, D2D1_SVG_ATTRIBUTE_STRING_TYPE_SVG, props->x2.value().c_str());
if (props->y2)
element.SetAttributeValue(
SvgStrings::y2AttributeName, D2D1_SVG_ATTRIBUTE_STRING_TYPE_SVG, props->y2.value().c_str());
if (props->gradientUnits.value_or(0) == 0) {
element.SetAttributeValue(
SvgStrings::gradientUnitsAttributeName, D2D1_SVG_UNIT_TYPE::D2D1_SVG_UNIT_TYPE_OBJECT_BOUNDING_BOX);
} else {
element.SetAttributeValue(
SvgStrings::gradientUnitsAttributeName, D2D1_SVG_UNIT_TYPE::D2D1_SVG_UNIT_TYPE_USER_SPACE_ON_USE);
}
if (props->gradientTransform) {
auto &matrix = props->gradientTransform.value();
element.SetAttributeValue(
SvgStrings::gradientTransformAttributeName,
D2D1_MATRIX_3X2_F{matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]});
}
for (const auto &stop : m_stops) {
winrt::com_ptr<ID2D1SvgElement> svgStop;
element.CreateChild(SvgStrings::stopAttributeName, svgStop.put());
svgStop->SetAttributeValue(SvgStrings::offsetAttributeName, stop.offset);
svgStop->SetAttributeValue(SvgStrings::stopColorAttributeName, stop.color);
svgStop->SetAttributeValue(SvgStrings::stopOpacityAttributeName, stop.opacity);
}
}
private:
std::vector<SvgLinearGradientStop> m_stops;
};
void RegisterLinearGradientComponent(
const winrt::Microsoft::ReactNative::IReactPackageBuilderFabric &builder) noexcept {
RegisterRenderableComponent<LinearGradientProps, LinearGradientView>(L"RNSVGLinearGradient", builder);
}
} // namespace winrt::RNSVG::implementation