You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
2.8 KiB
66 lines
2.8 KiB
/*
|
|
* Copyright 2021 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "modules/svg/include/SkSVGMask.h"
|
|
|
|
#include "include/core/SkCanvas.h"
|
|
#include "include/effects/SkLumaColorFilter.h"
|
|
#include "modules/svg/include/SkSVGRenderContext.h"
|
|
|
|
bool SkSVGMask::parseAndSetAttribute(const char* n, const char* v) {
|
|
return INHERITED::parseAndSetAttribute(n, v) ||
|
|
this->setX(SkSVGAttributeParser::parse<SkSVGLength>("x", n, v)) ||
|
|
this->setY(SkSVGAttributeParser::parse<SkSVGLength>("y", n, v)) ||
|
|
this->setWidth(SkSVGAttributeParser::parse<SkSVGLength>("width", n, v)) ||
|
|
this->setHeight(SkSVGAttributeParser::parse<SkSVGLength>("height", n, v)) ||
|
|
this->setMaskUnits(
|
|
SkSVGAttributeParser::parse<SkSVGObjectBoundingBoxUnits>("maskUnits", n, v)) ||
|
|
this->setMaskContentUnits(
|
|
SkSVGAttributeParser::parse<SkSVGObjectBoundingBoxUnits>("maskContentUnits", n, v));
|
|
}
|
|
|
|
SkRect SkSVGMask::bounds(const SkSVGRenderContext& ctx) const {
|
|
return ctx.resolveOBBRect(fX, fY, fWidth, fHeight, fMaskUnits);
|
|
}
|
|
|
|
void SkSVGMask::renderMask(const SkSVGRenderContext& ctx) const {
|
|
// https://www.w3.org/TR/SVG11/masking.html#Masking
|
|
|
|
// Propagate any inherited properties that may impact mask effect behavior (e.g.
|
|
// color-interpolation). We call this explicitly here because the SkSVGMask
|
|
// nodes do not participate in the normal onRender path, which is when property
|
|
// propagation currently occurs.
|
|
// The local context also restores the filter layer created below on scope exit.
|
|
SkSVGRenderContext lctx(ctx);
|
|
this->onPrepareToRender(&lctx);
|
|
|
|
const auto ci = *lctx.presentationContext().fInherited.fColorInterpolation;
|
|
auto ci_filter = (ci == SkSVGColorspace::kLinearRGB)
|
|
? SkColorFilters::SRGBToLinearGamma()
|
|
: nullptr;
|
|
|
|
SkPaint mask_filter;
|
|
mask_filter.setColorFilter(
|
|
SkColorFilters::Compose(SkLumaColorFilter::Make(), std::move(ci_filter)));
|
|
|
|
// Mask color filter layer.
|
|
// Note: We could avoid this extra layer if we invert the stacking order
|
|
// (mask/content -> content/mask, kSrcIn -> kDstIn) and apply the filter
|
|
// via the top (mask) layer paint. That requires deferring mask rendering
|
|
// until after node content, which introduces extra state/complexity.
|
|
// Something to consider if masking performance ever becomes an issue.
|
|
lctx.canvas()->saveLayer(nullptr, &mask_filter);
|
|
|
|
const auto obbt = ctx.transformForCurrentOBB(fMaskContentUnits);
|
|
lctx.canvas()->translate(obbt.offset.x, obbt.offset.y);
|
|
lctx.canvas()->scale(obbt.scale.x, obbt.scale.y);
|
|
|
|
for (const auto& child : fChildren) {
|
|
child->render(lctx);
|
|
}
|
|
}
|