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

162 lines
5.7 KiB
C++

#include "pch.h"
#include "RadialGradientView.h"
namespace winrt::RNSVG::implementation {
struct SvgRadialGradientStop {
float offset{0};
D2D1_COLOR_F color;
float opacity{1.0f};
};
REACT_STRUCT(RadialGradientProps)
struct RadialGradientProps : winrt::implements<RadialGradientProps, winrt::Microsoft::ReactNative::IComponentProps> {
RadialGradientProps(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(RadialGradientProps)
fx = cloneFromProps->fx;
fy = cloneFromProps->fy;
cx = cloneFromProps->cx;
cy = cloneFromProps->cy;
rx = cloneFromProps->rx;
ry = cloneFromProps->ry;
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(fx)
std::optional<std::wstring> fx;
REACT_FIELD(fy)
std::optional<std::wstring> fy;
REACT_FIELD(cx)
std::optional<std::wstring> cx;
REACT_FIELD(cy)
std::optional<std::wstring> cy;
REACT_FIELD(rx)
std::optional<std::wstring> rx;
REACT_FIELD(ry)
std::optional<std::wstring> ry;
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 RadialGradientView : winrt::implements<RadialGradientView, winrt::Windows::Foundation::IInspectable, RenderableView> {
public:
RadialGradientView() = 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<RadialGradientProps>();
m_stops.clear();
if (props->gradient) {
auto it = props->gradient->begin();
while (it != props->gradient->end()) {
SvgRadialGradientStop 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"radialGradient";
}
void OnRender(const SvgView &svgView, ID2D1SvgDocument &document, ID2D1SvgElement &element) noexcept override {
auto props = m_props.as<RadialGradientProps>();
SetCommonSvgProps(svgView, document, element, *props);
if (props->cx)
element.SetAttributeValue(
SvgStrings::cxAttributeName,
D2D1_SVG_ATTRIBUTE_STRING_TYPE::D2D1_SVG_ATTRIBUTE_STRING_TYPE_SVG,
props->cx->c_str());
if (props->cy)
element.SetAttributeValue(
SvgStrings::cyAttributeName,
D2D1_SVG_ATTRIBUTE_STRING_TYPE::D2D1_SVG_ATTRIBUTE_STRING_TYPE_SVG,
props->cy->c_str());
// RNSVG can decompose r to rx and ry, but D2D svgs don't support rx or ry, so if that is specified then take rx as
// r, and make sure the specified rx and ry are the same.
assert(props->rx == props->ry);
if (props->rx)
element.SetAttributeValue(
SvgStrings::rAttributeName,
D2D1_SVG_ATTRIBUTE_STRING_TYPE::D2D1_SVG_ATTRIBUTE_STRING_TYPE_SVG,
props->rx->c_str());
if (props->fx)
element.SetAttributeValue(
SvgStrings::fxAttributeName,
D2D1_SVG_ATTRIBUTE_STRING_TYPE::D2D1_SVG_ATTRIBUTE_STRING_TYPE_SVG,
props->fx->c_str());
if (props->fy)
element.SetAttributeValue(
SvgStrings::fyAttributeName,
D2D1_SVG_ATTRIBUTE_STRING_TYPE::D2D1_SVG_ATTRIBUTE_STRING_TYPE_SVG,
props->fy->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<SvgRadialGradientStop> m_stops;
};
void RegisterRadialGradientComponent(
const winrt::Microsoft::ReactNative::IReactPackageBuilderFabric &builder) noexcept {
RegisterRenderableComponent<RadialGradientProps, RadialGradientView>(L"RNSVGRadialGradient", builder);
}
} // namespace winrt::RNSVG::implementation