[svg] Implement feDiffuseLighting
https://www.w3.org/TR/SVG11/filters.html#feDiffuseLightingElement
- Add SkSVGFeDiffuseLighting node
- Move distant light source direction computation into a method on
SkSVGFeDistantLight
- Implement distant and point light sources for feDiffuseLighting
Bug: skia:10841
Change-Id: I74b8b9e04be5d2c5ac9f912d015dce96367040a1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/402645
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Tyler Denniston <tdenniston@google.com>
diff --git a/modules/svg/src/SkSVGDOM.cpp b/modules/svg/src/SkSVGDOM.cpp
index 4d26afe..7d0cb8f 100644
--- a/modules/svg/src/SkSVGDOM.cpp
+++ b/modules/svg/src/SkSVGDOM.cpp
@@ -242,6 +242,7 @@
{ "feBlend" , []() -> sk_sp<SkSVGNode> { return SkSVGFeBlend::Make(); }},
{ "feColorMatrix" , []() -> sk_sp<SkSVGNode> { return SkSVGFeColorMatrix::Make(); }},
{ "feComposite" , []() -> sk_sp<SkSVGNode> { return SkSVGFeComposite::Make(); }},
+ { "feDiffuseLighting" , []() -> sk_sp<SkSVGNode> { return SkSVGFeDiffuseLighting::Make(); }},
{ "feDisplacementMap" , []() -> sk_sp<SkSVGNode> { return SkSVGFeDisplacementMap::Make(); }},
{ "feDistantLight" , []() -> sk_sp<SkSVGNode> { return SkSVGFeDistantLight::Make(); }},
{ "feFlood" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFlood::Make(); }},
diff --git a/modules/svg/src/SkSVGFeLightSource.cpp b/modules/svg/src/SkSVGFeLightSource.cpp
index f1f74af..2f05957 100644
--- a/modules/svg/src/SkSVGFeLightSource.cpp
+++ b/modules/svg/src/SkSVGFeLightSource.cpp
@@ -9,6 +9,18 @@
#include "modules/svg/include/SkSVGFeLightSource.h"
#include "modules/svg/include/SkSVGValue.h"
+SkPoint3 SkSVGFeDistantLight::computeDirection() const {
+ // 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(fAzimuth);
+ const float elevationRad = SkDegreesToRadians(fElevation);
+ const float sinAzimuth = sinf(azimuthRad), cosAzimuth = cosf(azimuthRad);
+ const float sinElevation = sinf(elevationRad), cosElevation = cosf(elevationRad);
+ return SkPoint3::Make(cosAzimuth * cosElevation, sinAzimuth * cosElevation, sinElevation);
+}
+
bool SkSVGFeDistantLight::parseAndSetAttribute(const char* n, const char* v) {
return INHERITED::parseAndSetAttribute(n, v) ||
this->setAzimuth(SkSVGAttributeParser::parse<SkSVGNumberType>("azimuth", n, v)) ||
diff --git a/modules/svg/src/SkSVGFeLighting.cpp b/modules/svg/src/SkSVGFeLighting.cpp
index 14576ba..0882b00 100644
--- a/modules/svg/src/SkSVGFeLighting.cpp
+++ b/modules/svg/src/SkSVGFeLighting.cpp
@@ -95,19 +95,7 @@
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());
+ const SkPoint3 dir = light->computeDirection();
return SkImageFilters::DistantLitSpecular(
this->resolveXYZ(ctx, fctx, dir.fX, dir.fY, dir.fZ),
this->resolveLightingColor(ctx),
@@ -130,3 +118,35 @@
fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)),
this->resolveFilterSubregion(ctx, fctx));
}
+
+bool SkSVGFeDiffuseLighting::parseAndSetAttribute(const char* n, const char* v) {
+ return INHERITED::parseAndSetAttribute(n, v) ||
+ this->setDiffuseConstant(
+ SkSVGAttributeParser::parse<SkSVGNumberType>("diffuseConstant", n, v));
+}
+
+sk_sp<SkImageFilter> SkSVGFeDiffuseLighting::makeDistantLight(
+ const SkSVGRenderContext& ctx,
+ const SkSVGFilterContext& fctx,
+ const SkSVGFeDistantLight* light) const {
+ const SkPoint3 dir = light->computeDirection();
+ return SkImageFilters::DistantLitDiffuse(
+ this->resolveXYZ(ctx, fctx, dir.fX, dir.fY, dir.fZ),
+ this->resolveLightingColor(ctx),
+ this->getSurfaceScale(),
+ this->getDiffuseConstant(),
+ fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)),
+ this->resolveFilterSubregion(ctx, fctx));
+}
+
+sk_sp<SkImageFilter> SkSVGFeDiffuseLighting::makePointLight(const SkSVGRenderContext& ctx,
+ const SkSVGFilterContext& fctx,
+ const SkSVGFePointLight* light) const {
+ return SkImageFilters::PointLitDiffuse(
+ this->resolveXYZ(ctx, fctx, light->getX(), light->getY(), light->getZ()),
+ this->resolveLightingColor(ctx),
+ this->getSurfaceScale(),
+ this->getDiffuseConstant(),
+ fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)),
+ this->resolveFilterSubregion(ctx, fctx));
+}