[svg] Implement spot light sources
Note Chrome, Firefox and Inkscape (only other viewers I tested) disagree in smallish ways with the W3C png for filters-light-01. We're somewhere in the middle, but likely conforming enough to call it correct. Bug: skia:10841 Change-Id: Ia83b9936d260780148fe326b6d3b2248eef69aac Reviewed-on: https://skia-review.googlesource.com/c/skia/+/403036 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Tyler Denniston <tdenniston@google.com>
This commit is contained in:
parent
7c59ab868d
commit
cdcd9a76bb
@ -13,6 +13,7 @@
|
||||
|
||||
class SkSVGFeDistantLight;
|
||||
class SkSVGFePointLight;
|
||||
class SkSVGFeSpotLight;
|
||||
|
||||
class SkSVGFeLighting : public SkSVGFe {
|
||||
public:
|
||||
@ -42,6 +43,10 @@ protected:
|
||||
const SkSVGFilterContext&,
|
||||
const SkSVGFePointLight*) const = 0;
|
||||
|
||||
virtual sk_sp<SkImageFilter> makeSpotLight(const SkSVGRenderContext&,
|
||||
const SkSVGFilterContext&,
|
||||
const SkSVGFeSpotLight*) const = 0;
|
||||
|
||||
SkColor resolveLightingColor(const SkSVGRenderContext&) const;
|
||||
|
||||
SkPoint3 resolveXYZ(const SkSVGRenderContext&,
|
||||
@ -74,6 +79,10 @@ protected:
|
||||
const SkSVGFilterContext&,
|
||||
const SkSVGFePointLight*) const final;
|
||||
|
||||
sk_sp<SkImageFilter> makeSpotLight(const SkSVGRenderContext&,
|
||||
const SkSVGFilterContext&,
|
||||
const SkSVGFeSpotLight*) const final;
|
||||
|
||||
private:
|
||||
SkSVGFeSpecularLighting() : INHERITED(SkSVGTag::kFeSpecularLighting) {}
|
||||
|
||||
@ -99,6 +108,10 @@ protected:
|
||||
const SkSVGFilterContext&,
|
||||
const SkSVGFePointLight*) const final;
|
||||
|
||||
sk_sp<SkImageFilter> makeSpotLight(const SkSVGRenderContext&,
|
||||
const SkSVGFilterContext&,
|
||||
const SkSVGFeSpotLight*) const final;
|
||||
|
||||
private:
|
||||
SkSVGFeDiffuseLighting() : INHERITED(SkSVGTag::kFeDiffuseLighting) {}
|
||||
|
||||
|
@ -45,13 +45,16 @@ sk_sp<SkImageFilter> SkSVGFeLighting::onMakeImageFilter(const SkSVGRenderContext
|
||||
case SkSVGTag::kFePointLight:
|
||||
return this->makePointLight(
|
||||
ctx, fctx, static_cast<const SkSVGFePointLight*>(child.get()));
|
||||
case SkSVGTag::kFeSpotLight:
|
||||
return this->makeSpotLight(
|
||||
ctx, fctx, static_cast<const SkSVGFeSpotLight*>(child.get()));
|
||||
default:
|
||||
// Ignore unknown children, such as <desc> elements
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SkDebugf("lighting filter effect needs exactly one light source");
|
||||
SkDebugf("lighting filter effect needs exactly one light source\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -115,6 +118,26 @@ sk_sp<SkImageFilter> SkSVGFeSpecularLighting::makePointLight(const SkSVGRenderCo
|
||||
this->resolveFilterSubregion(ctx, fctx));
|
||||
}
|
||||
|
||||
sk_sp<SkImageFilter> SkSVGFeSpecularLighting::makeSpotLight(const SkSVGRenderContext& ctx,
|
||||
const SkSVGFilterContext& fctx,
|
||||
const SkSVGFeSpotLight* light) const {
|
||||
const auto& limitingConeAngle = light->getLimitingConeAngle();
|
||||
const float cutoffAngle = limitingConeAngle.isValid() ? *limitingConeAngle : 180.f;
|
||||
|
||||
return SkImageFilters::SpotLitSpecular(
|
||||
this->resolveXYZ(ctx, fctx, light->getX(), light->getY(), light->getZ()),
|
||||
this->resolveXYZ(
|
||||
ctx, fctx, light->getPointsAtX(), light->getPointsAtY(), light->getPointsAtZ()),
|
||||
light->getSpecularExponent(),
|
||||
cutoffAngle,
|
||||
this->resolveLightingColor(ctx),
|
||||
this->getSurfaceScale(),
|
||||
fSpecularConstant,
|
||||
fSpecularExponent,
|
||||
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(
|
||||
@ -146,3 +169,22 @@ sk_sp<SkImageFilter> SkSVGFeDiffuseLighting::makePointLight(const SkSVGRenderCon
|
||||
fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)),
|
||||
this->resolveFilterSubregion(ctx, fctx));
|
||||
}
|
||||
|
||||
sk_sp<SkImageFilter> SkSVGFeDiffuseLighting::makeSpotLight(const SkSVGRenderContext& ctx,
|
||||
const SkSVGFilterContext& fctx,
|
||||
const SkSVGFeSpotLight* light) const {
|
||||
const auto& limitingConeAngle = light->getLimitingConeAngle();
|
||||
const float cutoffAngle = limitingConeAngle.isValid() ? *limitingConeAngle : 180.f;
|
||||
|
||||
return SkImageFilters::SpotLitDiffuse(
|
||||
this->resolveXYZ(ctx, fctx, light->getX(), light->getY(), light->getZ()),
|
||||
this->resolveXYZ(
|
||||
ctx, fctx, light->getPointsAtX(), light->getPointsAtY(), light->getPointsAtZ()),
|
||||
light->getSpecularExponent(),
|
||||
cutoffAngle,
|
||||
this->resolveLightingColor(ctx),
|
||||
this->getSurfaceScale(),
|
||||
this->getDiffuseConstant(),
|
||||
fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)),
|
||||
this->resolveFilterSubregion(ctx, fctx));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user