diff --git a/modules/svg/include/SkSVGFeLighting.h b/modules/svg/include/SkSVGFeLighting.h index 64326f709f..3a0da6718e 100644 --- a/modules/svg/include/SkSVGFeLighting.h +++ b/modules/svg/include/SkSVGFeLighting.h @@ -11,6 +11,7 @@ #include "modules/svg/include/SkSVGFe.h" #include "modules/svg/include/SkSVGTypes.h" +class SkSVGFeDistantLight; class SkSVGFePointLight; class SkSVGFeLighting : public SkSVGFe { @@ -33,6 +34,10 @@ protected: sk_sp onMakeImageFilter(const SkSVGRenderContext&, const SkSVGFilterContext&) const final; + virtual sk_sp makeDistantLight(const SkSVGRenderContext&, + const SkSVGFilterContext&, + const SkSVGFeDistantLight*) const = 0; + virtual sk_sp makePointLight(const SkSVGRenderContext&, const SkSVGFilterContext&, const SkSVGFePointLight*) const = 0; @@ -61,6 +66,10 @@ public: protected: bool parseAndSetAttribute(const char*, const char*) override; + sk_sp makeDistantLight(const SkSVGRenderContext&, + const SkSVGFilterContext&, + const SkSVGFeDistantLight*) const final; + sk_sp makePointLight(const SkSVGRenderContext&, const SkSVGFilterContext&, const SkSVGFePointLight*) const final; diff --git a/modules/svg/src/SkSVGFeLighting.cpp b/modules/svg/src/SkSVGFeLighting.cpp index 2c2c5e5070..14576ba746 100644 --- a/modules/svg/src/SkSVGFeLighting.cpp +++ b/modules/svg/src/SkSVGFeLighting.cpp @@ -39,9 +39,12 @@ sk_sp SkSVGFeLighting::onMakeImageFilter(const SkSVGRenderContext const SkSVGFilterContext& fctx) const { for (const auto& child : fChildren) { switch (child->tag()) { + case SkSVGTag::kFeDistantLight: + return this->makeDistantLight( + ctx, fctx, static_cast(child.get())); case SkSVGTag::kFePointLight: - return this->makePointLight(ctx, fctx, - static_cast(child.get())); + return this->makePointLight( + ctx, fctx, static_cast(child.get())); default: // Ignore unknown children, such as elements break; @@ -88,6 +91,33 @@ bool SkSVGFeSpecularLighting::parseAndSetAttribute(const char* n, const char* v) SkSVGAttributeParser::parse("specularExponent", n, v)); } +sk_sp SkSVGFeSpecularLighting::makeDistantLight( + const SkSVGRenderContext& ctx, + const SkSVGFilterContext& fctx, + const SkSVGFeDistantLight* light) const { + const auto computeDirection = [](float azimuth, float elevation) -> SkPoint3 { + // Computing direction from azimuth+elevation is two 3D rotations: + // - Rotate [1,0,0] about y axis first (elevation) + // - Rotate result about z axis (azimuth) + // Which is just the first column vector in the 3x3 matrix Rz*Ry. + const float azimuthRad = SkDegreesToRadians(azimuth); + const float elevationRad = SkDegreesToRadians(elevation); + const float sinAzimuth = sinf(azimuthRad), cosAzimuth = cosf(azimuthRad); + const float sinElevation = sinf(elevationRad), cosElevation = cosf(elevationRad); + return SkPoint3::Make(cosAzimuth * cosElevation, sinAzimuth * cosElevation, sinElevation); + }; + + const SkPoint3 dir = computeDirection(light->getAzimuth(), light->getElevation()); + return SkImageFilters::DistantLitSpecular( + this->resolveXYZ(ctx, fctx, dir.fX, dir.fY, dir.fZ), + this->resolveLightingColor(ctx), + this->getSurfaceScale(), + fSpecularConstant, + fSpecularExponent, + fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)), + this->resolveFilterSubregion(ctx, fctx)); +} + sk_sp SkSVGFeSpecularLighting::makePointLight(const SkSVGRenderContext& ctx, const SkSVGFilterContext& fctx, const SkSVGFePointLight* light) const {