[svg] Several filter helper tweaks

- Allow resolving inputs without modifying their colorspace
- Add helper to get the colorspace of a particular input
- Make resolveColorspace() virtual and add filter context to its
  signature

Bug: skia:10841
Change-Id: I2e226ec26205f527c2d171140072f106ec35fbe0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/356416
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Tyler Denniston <tdenniston@google.com>
This commit is contained in:
Tyler Denniston 2021-01-20 17:31:36 -05:00 committed by Skia Commit-Bot
parent b5db4825b8
commit c7e482441e
11 changed files with 43 additions and 15 deletions

View File

@ -35,7 +35,8 @@ public:
* Spec: https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationProperties
* 'color-interpolation-filters' property.
*/
SkSVGColorspace resolveColorspace(const SkSVGRenderContext&) const;
virtual SkSVGColorspace resolveColorspace(const SkSVGRenderContext&,
const SkSVGFilterContext&) const;
/** Propagates any inherited presentation attributes in the given context. */
void applyProperties(SkSVGRenderContext*) const;

View File

@ -32,6 +32,11 @@ public:
void registerResult(const SkSVGStringType&, const sk_sp<SkImageFilter>&, const SkRect&, SkSVGColorspace);
SkSVGColorspace resolveInputColorspace(const SkSVGRenderContext&,
const SkSVGFeInputType&) const;
sk_sp<SkImageFilter> resolveInput(const SkSVGRenderContext&, const SkSVGFeInputType&) const;
sk_sp<SkImageFilter> resolveInput(const SkSVGRenderContext&, const SkSVGFeInputType&, SkSVGColorspace) const;
private:
@ -43,6 +48,9 @@ private:
const Result* findResultById(const SkSVGStringType&) const;
std::tuple<sk_sp<SkImageFilter>, SkSVGColorspace> getInput(const SkSVGRenderContext&,
const SkSVGFeInputType&) const;
SkRect fFilterEffectsRegion;
SkSVGObjectBoundingBoxUnits fPrimitiveUnits;

View File

@ -92,7 +92,8 @@ SkRect SkSVGFe::resolveFilterSubregion(const SkSVGRenderContext& ctx,
return subregion;
}
SkSVGColorspace SkSVGFe::resolveColorspace(const SkSVGRenderContext& ctx) const {
SkSVGColorspace SkSVGFe::resolveColorspace(const SkSVGRenderContext& ctx,
const SkSVGFilterContext&) const {
constexpr SkSVGColorspace kDefaultCS = SkSVGColorspace::kSRGB;
const SkSVGColorspace cs = *ctx.presentationContext().fInherited.fColorInterpolationFilters;
return cs == SkSVGColorspace::kAuto ? kDefaultCS : cs;

View File

@ -39,7 +39,7 @@ sk_sp<SkImageFilter> SkSVGFeBlend::onMakeImageFilter(const SkSVGRenderContext& c
const SkSVGFilterContext& fctx) const {
const SkRect cropRect = this->resolveFilterSubregion(ctx, fctx);
const SkBlendMode blendMode = GetBlendMode(this->getMode());
const SkSVGColorspace colorspace = this->resolveColorspace(ctx);
const SkSVGColorspace colorspace = this->resolveColorspace(ctx, fctx);
const sk_sp<SkImageFilter> background = fctx.resolveInput(ctx, fIn2, colorspace);
const sk_sp<SkImageFilter> foreground = fctx.resolveInput(ctx, this->getIn(), colorspace);
return SkImageFilters::Blend(blendMode, background, foreground, cropRect);

View File

@ -93,7 +93,7 @@ sk_sp<SkImageFilter> SkSVGFeColorMatrix::onMakeImageFilter(const SkSVGRenderCont
const SkSVGFilterContext& fctx) const {
return SkImageFilters::ColorFilter(
SkColorFilters::Matrix(makeMatrixForType()),
fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx)),
fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)),
this->resolveFilterSubregion(ctx, fctx));
}

View File

@ -47,7 +47,7 @@ SkBlendMode SkSVGFeComposite::BlendModeForOperator(SkSVGFeCompositeOperator op)
sk_sp<SkImageFilter> SkSVGFeComposite::onMakeImageFilter(const SkSVGRenderContext& ctx,
const SkSVGFilterContext& fctx) const {
const SkRect cropRect = this->resolveFilterSubregion(ctx, fctx);
const SkSVGColorspace colorspace = this->resolveColorspace(ctx);
const SkSVGColorspace colorspace = this->resolveColorspace(ctx, fctx);
const sk_sp<SkImageFilter> background = fctx.resolveInput(ctx, fIn2, colorspace);
const sk_sp<SkImageFilter> foreground = fctx.resolveInput(ctx, this->getIn(), colorspace);
if (fOperator == SkSVGFeCompositeOperator::kArithmetic) {

View File

@ -29,9 +29,10 @@ sk_sp<SkImageFilter> SkSVGFeGaussianBlur::onMakeImageFilter(const SkSVGRenderCon
sigmaY *= objBounds.height();
}
return SkImageFilters::Blur(sigmaX, sigmaY,
fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx)),
this->resolveFilterSubregion(ctx, fctx));
return SkImageFilters::Blur(
sigmaX, sigmaY,
fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx)),
this->resolveFilterSubregion(ctx, fctx));
}
template <>

View File

@ -23,7 +23,7 @@ bool SkSVGFeMorphology::parseAndSetAttribute(const char* name, const char* value
sk_sp<SkImageFilter> SkSVGFeMorphology::onMakeImageFilter(const SkSVGRenderContext& ctx,
const SkSVGFilterContext& fctx) const {
const SkRect cropRect = this->resolveFilterSubregion(ctx, fctx);
const SkSVGColorspace colorspace = this->resolveColorspace(ctx);
const SkSVGColorspace colorspace = this->resolveColorspace(ctx, fctx);
sk_sp<SkImageFilter> input = fctx.resolveInput(ctx, this->getIn(), colorspace);
SkScalar rx = fRadius.fX;

View File

@ -28,6 +28,7 @@ sk_sp<SkImageFilter> SkSVGFeOffset::onMakeImageFilter(const SkSVGRenderContext&
dy *= objBounds.height();
}
sk_sp<SkImageFilter> in = fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx));
sk_sp<SkImageFilter> in =
fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx, fctx));
return SkImageFilters::Offset(dx, dy, std::move(in), this->resolveFilterSubregion(ctx, fctx));
}

View File

@ -46,7 +46,7 @@ sk_sp<SkImageFilter> SkSVGFilter::buildFilterDAG(const SkSVGRenderContext& ctx)
feNode.applyProperties(&localCtx);
// TODO: there are specific composition rules that need to be followed
cs = feNode.resolveColorspace(ctx);
cs = feNode.resolveColorspace(ctx, fctx);
filter = feNode.makeImageFilter(localCtx, fctx);
if (!feResultType.isEmpty()) {

View File

@ -49,9 +49,8 @@ void SkSVGFilterContext::registerResult(const SkSVGStringType& id,
fResults[id] = {result, subregion, resultColorspace};
}
sk_sp<SkImageFilter> SkSVGFilterContext::resolveInput(const SkSVGRenderContext& ctx,
const SkSVGFeInputType& inputType,
SkSVGColorspace colorspace) const {
std::tuple<sk_sp<SkImageFilter>, SkSVGColorspace> SkSVGFilterContext::getInput(
const SkSVGRenderContext& ctx, const SkSVGFeInputType& inputType) const {
SkSVGColorspace inputCS = SkSVGColorspace::kSRGB;
sk_sp<SkImageFilter> result;
switch (inputType.type()) {
@ -81,8 +80,25 @@ sk_sp<SkImageFilter> SkSVGFilterContext::resolveInput(const SkSVGRenderContext&
}
default:
SkDebugf("unhandled filter input type %d\n", inputType.type());
return nullptr;
break;
}
return {result, inputCS};
}
SkSVGColorspace SkSVGFilterContext::resolveInputColorspace(
const SkSVGRenderContext& ctx, const SkSVGFeInputType& inputType) const {
return std::get<1>(this->getInput(ctx, inputType));
}
sk_sp<SkImageFilter> SkSVGFilterContext::resolveInput(const SkSVGRenderContext& ctx,
const SkSVGFeInputType& inputType) const {
return std::get<0>(this->getInput(ctx, inputType));
}
sk_sp<SkImageFilter> SkSVGFilterContext::resolveInput(const SkSVGRenderContext& ctx,
const SkSVGFeInputType& inputType,
SkSVGColorspace colorspace) const {
auto [result, inputCS] = this->getInput(ctx, inputType);
return ConvertFilterColorspace(std::move(result), inputCS, colorspace);
}