[svg] Initial mask plumbing

Introduce SkSVGMask and plumb related attributes.

Also consolidate the clip/mask/filter property types - they all support
the same values: <funciri>|none|inherit.

Bug: skia:10842
Change-Id: If45a75cccc19b84d6547237336fe5d562a85d594
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/353436
Commit-Queue: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@google.com>
Reviewed-by: Tyler Denniston <tdenniston@google.com>
This commit is contained in:
Florin Malita 2021-01-13 11:48:02 -05:00 committed by Skia Commit-Bot
parent 92969f2656
commit 836c2ca6a1
12 changed files with 114 additions and 98 deletions

View File

@ -98,8 +98,9 @@ struct SkSVGPresentationAttributes {
// uninherited
SkSVGProperty<SkSVGNumberType, false> fOpacity;
SkSVGProperty<SkSVGClip , false> fClipPath;
SkSVGProperty<SkSVGFilterType, false> fFilter;
SkSVGProperty<SkSVGFuncIRI , false> fClipPath;
SkSVGProperty<SkSVGFuncIRI , false> fMask;
SkSVGProperty<SkSVGFuncIRI , false> fFilter;
SkSVGProperty<SkSVGColor , false> fStopColor;
SkSVGProperty<SkSVGNumberType, false> fStopOpacity;
SkSVGProperty<SkSVGColor , false> fFloodColor;

View File

@ -0,0 +1,38 @@
/*
* Copyright 2021 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkSVGMask_DEFINED
#define SkSVGMask_DEFINED
#include "modules/svg/include/SkSVGHiddenContainer.h"
#include "modules/svg/include/SkSVGTypes.h"
class SkSVGMask final : public SkSVGHiddenContainer {
public:
static sk_sp<SkSVGMask> Make() {
return sk_sp<SkSVGMask>(new SkSVGMask());
}
SVG_ATTR(X , SkSVGLength, SkSVGLength(-10, SkSVGLength::Unit::kPercentage))
SVG_ATTR(Y , SkSVGLength, SkSVGLength(-10, SkSVGLength::Unit::kPercentage))
SVG_ATTR(Width , SkSVGLength, SkSVGLength(120, SkSVGLength::Unit::kPercentage))
SVG_ATTR(Height, SkSVGLength, SkSVGLength(120, SkSVGLength::Unit::kPercentage))
SVG_ATTR(MaskUnits, SkSVGObjectBoundingBoxUnits,
SkSVGObjectBoundingBoxUnits(SkSVGObjectBoundingBoxUnits::Type::kObjectBoundingBox))
SVG_ATTR(MaskContentUnits, SkSVGObjectBoundingBoxUnits,
SkSVGObjectBoundingBoxUnits(SkSVGObjectBoundingBoxUnits::Type::kUserSpaceOnUse))
private:
SkSVGMask() : INHERITED(SkSVGTag::kMask) {}
bool parseAndSetAttribute(const char*, const char*) override;
using INHERITED = SkSVGHiddenContainer;
};
#endif // SkSVGMask_DEFINED

View File

@ -34,6 +34,7 @@ enum class SkSVGTag {
kG,
kLine,
kLinearGradient,
kMask,
kPath,
kPattern,
kPolygon,
@ -121,8 +122,9 @@ public:
SVG_PRES_ATTR(Visibility , SkSVGVisibility, true)
// not inherited
SVG_PRES_ATTR(ClipPath , SkSVGClip , false)
SVG_PRES_ATTR(Filter , SkSVGFilterType, false)
SVG_PRES_ATTR(ClipPath , SkSVGFuncIRI , false)
SVG_PRES_ATTR(Mask , SkSVGFuncIRI , false)
SVG_PRES_ATTR(Filter , SkSVGFuncIRI , false)
SVG_PRES_ATTR(Opacity , SkSVGNumberType, false)
SVG_PRES_ATTR(StopColor , SkSVGColor , false)
SVG_PRES_ATTR(StopOpacity , SkSVGNumberType, false)

View File

@ -138,8 +138,8 @@ private:
SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete;
void applyOpacity(SkScalar opacity, uint32_t flags);
void applyFilter(const SkSVGFilterType&);
void applyClip(const SkSVGClip&);
void applyFilter(const SkSVGFuncIRI&);
void applyClip(const SkSVGFuncIRI&);
void updatePaintsWithCurrentColor(const SkSVGPresentationAttributes&);
const sk_sp<SkFontMgr>& fFontMgr;

View File

@ -196,24 +196,22 @@ private:
SkString fIRI;
};
class SkSVGClip {
// <funciri> | none (used for clip/mask/filter properties)
class SkSVGFuncIRI {
public:
enum class Type {
kNone,
kIRI,
};
SkSVGClip() : fType(Type::kNone) {}
explicit SkSVGClip(Type t) : fType(t) {}
explicit SkSVGClip(const SkString& iri) : fType(Type::kIRI), fIRI(iri) {}
SkSVGFuncIRI() : fType(Type::kNone) {}
explicit SkSVGFuncIRI(Type t) : fType(t) {}
explicit SkSVGFuncIRI(SkString&& iri) : fType(Type::kIRI), fIRI(std::move(iri)) {}
SkSVGClip(const SkSVGClip&) = default;
SkSVGClip& operator=(const SkSVGClip&) = default;
bool operator==(const SkSVGClip& other) const {
bool operator==(const SkSVGFuncIRI& other) const {
return fType == other.fType && fIRI == other.fIRI;
}
bool operator!=(const SkSVGClip& other) const { return !(*this == other); }
bool operator!=(const SkSVGFuncIRI& other) const { return !(*this == other); }
Type type() const { return fType; }
const SkString& iri() const { SkASSERT(fType == Type::kIRI); return fIRI; }
@ -569,35 +567,6 @@ private:
Type fType;
};
class SkSVGFilterType {
public:
enum class Type {
kNone,
kIRI,
kInherit,
};
SkSVGFilterType() : fType(Type::kNone) {}
explicit SkSVGFilterType(Type t) : fType(t) {}
explicit SkSVGFilterType(const SkString& iri) : fType(Type::kIRI), fIRI(iri) {}
bool operator==(const SkSVGFilterType& other) const {
return fType == other.fType && fIRI == other.fIRI;
}
bool operator!=(const SkSVGFilterType& other) const { return !(*this == other); }
const SkString& iri() const {
SkASSERT(fType == Type::kIRI);
return fIRI;
}
Type type() const { return fType; }
private:
Type fType;
SkString fIRI;
};
class SkSVGFeInputType {
public:
enum class Type {

View File

@ -71,7 +71,6 @@ private:
};
using SkSVGColorValue = SkSVGWrapperValue<SkSVGColorType , SkSVGValue::Type::kColor >;
using SkSVGFilterValue = SkSVGWrapperValue<SkSVGFilterType , SkSVGValue::Type::kFilter >;
using SkSVGLengthValue = SkSVGWrapperValue<SkSVGLength , SkSVGValue::Type::kLength >;
using SkSVGPathValue = SkSVGWrapperValue<SkPath , SkSVGValue::Type::kPath >;
using SkSVGTransformValue = SkSVGWrapperValue<SkSVGTransformType, SkSVGValue::Type::kTransform >;

View File

@ -539,16 +539,18 @@ bool SkSVGAttributeParser::parse(SkSVGPaint* paint) {
}
// https://www.w3.org/TR/SVG11/masking.html#ClipPathProperty
// https://www.w3.org/TR/SVG11/masking.html#MaskProperty
// https://www.w3.org/TR/SVG11/filters.html#FilterProperty
template <>
bool SkSVGAttributeParser::parse(SkSVGClip* clip) {
bool SkSVGAttributeParser::parse(SkSVGFuncIRI* firi) {
SkSVGStringType iri;
bool parsedValue = false;
if (this->parseExpectedStringToken("none")) {
*clip = SkSVGClip(SkSVGClip::Type::kNone);
*firi = SkSVGFuncIRI();
parsedValue = true;
} else if (this->parseFuncIRI(&iri)) {
*clip = SkSVGClip(iri);
*firi = SkSVGFuncIRI(std::move(iri));
parsedValue = true;
}
@ -692,26 +694,6 @@ bool SkSVGAttributeParser::parse(SkSVGFillRule* fillRule) {
return parsedValue && this->parseEOSToken();
}
// https://www.w3.org/TR/SVG11/filters.html#FilterProperty
template <>
bool SkSVGAttributeParser::parse(SkSVGFilterType* filter) {
SkSVGStringType iri;
bool parsedValue = false;
if (this->parseExpectedStringToken("none")) {
*filter = SkSVGFilterType(SkSVGFilterType::Type::kNone);
parsedValue = true;
} else if (this->parseExpectedStringToken("inherit")) {
*filter = SkSVGFilterType(SkSVGFilterType::Type::kInherit);
parsedValue = true;
} else if (this->parseFuncIRI(&iri)) {
*filter = SkSVGFilterType(iri);
parsedValue = true;
}
return parsedValue && this->parseEOSToken();
}
// https://www.w3.org/TR/SVG11/painting.html#VisibilityProperty
template <>
bool SkSVGAttributeParser::parse(SkSVGVisibility* visibility) {

View File

@ -25,6 +25,7 @@
#include "modules/svg/include/SkSVGG.h"
#include "modules/svg/include/SkSVGLine.h"
#include "modules/svg/include/SkSVGLinearGradient.h"
#include "modules/svg/include/SkSVGMask.h"
#include "modules/svg/include/SkSVGNode.h"
#include "modules/svg/include/SkSVGPath.h"
#include "modules/svg/include/SkSVGPattern.h"
@ -267,6 +268,7 @@ SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = {
{ "g" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); }},
{ "line" , []() -> sk_sp<SkSVGNode> { return SkSVGLine::Make(); }},
{ "linearGradient", []() -> sk_sp<SkSVGNode> { return SkSVGLinearGradient::Make(); }},
{ "mask" , []() -> sk_sp<SkSVGNode> { return SkSVGMask::Make(); }},
{ "path" , []() -> sk_sp<SkSVGNode> { return SkSVGPath::Make(); }},
{ "pattern" , []() -> sk_sp<SkSVGNode> { return SkSVGPattern::Make(); }},
{ "polygon" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolygon(); }},

View File

@ -0,0 +1,20 @@
/*
* 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"
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));
}

View File

@ -88,32 +88,33 @@ bool SkSVGNode::parseAndSetAttribute(const char* n, const char* v) {
SkSVGAttributeParser::parseProperty<decltype(fPresentationAttributes.f##attrName)>( \
svgName, n, v))
return PARSE_AND_SET( "clip-path" , ClipPath)
|| PARSE_AND_SET("clip-rule" , ClipRule)
|| PARSE_AND_SET("color" , Color)
|| PARSE_AND_SET("fill" , Fill)
|| PARSE_AND_SET("fill-opacity" , FillOpacity)
|| PARSE_AND_SET("fill-rule" , FillRule)
|| PARSE_AND_SET("filter" , Filter)
|| PARSE_AND_SET("flood-color" , FloodColor)
|| PARSE_AND_SET("flood-opacity" , FloodOpacity)
|| PARSE_AND_SET("font-family" , FontFamily)
|| PARSE_AND_SET("font-size" , FontSize)
|| PARSE_AND_SET("font-style" , FontStyle)
|| PARSE_AND_SET("font-weight" , FontWeight)
|| PARSE_AND_SET("opacity" , Opacity)
|| PARSE_AND_SET("stop-color" , StopColor)
|| PARSE_AND_SET("stop-opacity" , StopOpacity)
|| PARSE_AND_SET("stroke" , Stroke)
|| PARSE_AND_SET("stroke-dasharray" , StrokeDashArray)
|| PARSE_AND_SET("stroke-dashoffset", StrokeDashOffset)
|| PARSE_AND_SET("stroke-linecap" , StrokeLineCap)
|| PARSE_AND_SET("stroke-linejoin" , StrokeLineJoin)
|| PARSE_AND_SET("stroke-miterlimit", StrokeMiterLimit)
|| PARSE_AND_SET("stroke-opacity" , StrokeOpacity)
|| PARSE_AND_SET("stroke-width" , StrokeWidth)
|| PARSE_AND_SET("text-anchor" , TextAnchor)
|| PARSE_AND_SET("visibility" , Visibility);
return PARSE_AND_SET("clip-path" , ClipPath)
|| PARSE_AND_SET("clip-rule" , ClipRule)
|| PARSE_AND_SET("color" , Color)
|| PARSE_AND_SET("fill" , Fill)
|| PARSE_AND_SET("fill-opacity" , FillOpacity)
|| PARSE_AND_SET("fill-rule" , FillRule)
|| PARSE_AND_SET("filter" , Filter)
|| PARSE_AND_SET("flood-color" , FloodColor)
|| PARSE_AND_SET("flood-opacity" , FloodOpacity)
|| PARSE_AND_SET("font-family" , FontFamily)
|| PARSE_AND_SET("font-size" , FontSize)
|| PARSE_AND_SET("font-style" , FontStyle)
|| PARSE_AND_SET("font-weight" , FontWeight)
|| PARSE_AND_SET("mask" , Mask)
|| PARSE_AND_SET("opacity" , Opacity)
|| PARSE_AND_SET("stop-color" , StopColor)
|| PARSE_AND_SET("stop-opacity" , StopOpacity)
|| PARSE_AND_SET("stroke" , Stroke)
|| PARSE_AND_SET("stroke-dasharray" , StrokeDashArray)
|| PARSE_AND_SET("stroke-dashoffset", StrokeDashOffset)
|| PARSE_AND_SET("stroke-linecap" , StrokeLineCap)
|| PARSE_AND_SET("stroke-linejoin" , StrokeLineJoin)
|| PARSE_AND_SET("stroke-miterlimit", StrokeMiterLimit)
|| PARSE_AND_SET("stroke-opacity" , StrokeOpacity)
|| PARSE_AND_SET("stroke-width" , StrokeWidth)
|| PARSE_AND_SET("text-anchor" , TextAnchor)
|| PARSE_AND_SET("visibility" , Visibility);
#undef PARSE_AND_SET
}

View File

@ -468,8 +468,8 @@ void SkSVGRenderContext::applyOpacity(SkScalar opacity, uint32_t flags) {
}
}
void SkSVGRenderContext::applyFilter(const SkSVGFilterType& filter) {
if (filter.type() != SkSVGFilterType::Type::kIRI) {
void SkSVGRenderContext::applyFilter(const SkSVGFuncIRI& filter) {
if (filter.type() != SkSVGFuncIRI::Type::kIRI) {
return;
}
@ -497,8 +497,8 @@ void SkSVGRenderContext::saveOnce() {
SkASSERT(fCanvas->getSaveCount() > fCanvasSaveCount);
}
void SkSVGRenderContext::applyClip(const SkSVGClip& clip) {
if (clip.type() != SkSVGClip::Type::kIRI) {
void SkSVGRenderContext::applyClip(const SkSVGFuncIRI& clip) {
if (clip.type() != SkSVGFuncIRI::Type::kIRI) {
return;
}

View File

@ -30,6 +30,7 @@ skia_svg_public = [
"$_include/SkSVGIDMapper.h",
"$_include/SkSVGLinearGradient.h",
"$_include/SkSVGLine.h",
"$_include/SkSVGMask.h",
"$_include/SkSVGNode.h",
"$_include/SkSVGPath.h",
"$_include/SkSVGPattern.h",
@ -66,6 +67,7 @@ skia_svg_sources = [
"$_src/SkSVGGradient.cpp",
"$_src/SkSVGLine.cpp",
"$_src/SkSVGLinearGradient.cpp",
"$_src/SkSVGMask.cpp",
"$_src/SkSVGNode.cpp",
"$_src/SkSVGPath.cpp",
"$_src/SkSVGPattern.cpp",