aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/svg/model/SkSVGDOM.cpp
diff options
context:
space:
mode:
authorGravatar fmalita <fmalita@chromium.org>2016-09-12 17:06:47 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-09-12 17:06:47 -0700
commit28d5b72d86fdfae20dc47ba548748f119c7273e3 (patch)
tree579d10ae07a10a882ca68d00c2da6fa407c0c658 /experimental/svg/model/SkSVGDOM.cpp
parent8c24f4fae3389b9937eb73128e76226cffebdd72 (diff)
[SVGDom] Initial linear gradient support
Kind of a big change, to connect several new bits into something useful: * ID tracking & lookup * new asPaint() node virtual to support shader (and in the future filter) based paint servers * <defs>, <linearGradient> and <stop> element support * 'href', 'offset', 'stop-color', 'stop-opacity' attribute support * IRI/FuncIRI and rgb(...) parsing BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2327233003 Review-Url: https://codereview.chromium.org/2327233003
Diffstat (limited to 'experimental/svg/model/SkSVGDOM.cpp')
-rw-r--r--experimental/svg/model/SkSVGDOM.cpp75
1 files changed, 56 insertions, 19 deletions
diff --git a/experimental/svg/model/SkSVGDOM.cpp b/experimental/svg/model/SkSVGDOM.cpp
index c123bc6bfb..d6e4f4c9bd 100644
--- a/experimental/svg/model/SkSVGDOM.cpp
+++ b/experimental/svg/model/SkSVGDOM.cpp
@@ -11,15 +11,18 @@
#include "SkString.h"
#include "SkSVGAttributeParser.h"
#include "SkSVGCircle.h"
+#include "SkSVGDefs.h"
#include "SkSVGDOM.h"
#include "SkSVGEllipse.h"
#include "SkSVGG.h"
#include "SkSVGLine.h"
+#include "SkSVGLinearGradient.h"
#include "SkSVGNode.h"
#include "SkSVGPath.h"
#include "SkSVGPoly.h"
#include "SkSVGRect.h"
#include "SkSVGRenderContext.h"
+#include "SkSVGStop.h"
#include "SkSVGSVG.h"
#include "SkSVGTypes.h"
#include "SkSVGValue.h"
@@ -32,17 +35,37 @@ bool SetPaintAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
SkSVGPaint paint;
SkSVGAttributeParser parser(stringValue);
if (!parser.parsePaint(&paint)) {
- // Until we have paint server support, failing here will cause default/all-black rendering.
- // It's better to just not draw for now.
- paint = SkSVGPaint(SkSVGPaint::Type::kNone);
-
- // return false;
+ return false;
}
node->setAttribute(attr, SkSVGPaintValue(paint));
return true;
}
+bool SetColorAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
+ const char* stringValue) {
+ SkSVGColorType color;
+ SkSVGAttributeParser parser(stringValue);
+ if (!parser.parseColor(&color)) {
+ return false;
+ }
+
+ node->setAttribute(attr, SkSVGColorValue(color));
+ return true;
+}
+
+bool SetIRIAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
+ const char* stringValue) {
+ SkSVGStringType iri;
+ SkSVGAttributeParser parser(stringValue);
+ if (!parser.parseIRI(&iri)) {
+ return false;
+ }
+
+ node->setAttribute(attr, SkSVGStringValue(iri));
+ return true;
+}
+
bool SetPathDataAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
const char* stringValue) {
SkPath path;
@@ -222,11 +245,14 @@ SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
{ "fill" , { SkSVGAttribute::kFill , SetPaintAttribute }},
{ "fill-opacity" , { SkSVGAttribute::kFillOpacity , SetNumberAttribute }},
{ "height" , { SkSVGAttribute::kHeight , SetLengthAttribute }},
+ { "offset" , { SkSVGAttribute::kOffset , SetLengthAttribute }},
{ "opacity" , { SkSVGAttribute::kOpacity , SetNumberAttribute }},
{ "points" , { SkSVGAttribute::kPoints , SetPointsAttribute }},
{ "r" , { SkSVGAttribute::kR , SetLengthAttribute }},
{ "rx" , { SkSVGAttribute::kRx , SetLengthAttribute }},
{ "ry" , { SkSVGAttribute::kRy , SetLengthAttribute }},
+ { "stop-color" , { SkSVGAttribute::kStopColor , SetColorAttribute }},
+ { "stop-opacity" , { SkSVGAttribute::kStopOpacity , SetNumberAttribute }},
{ "stroke" , { SkSVGAttribute::kStroke , SetPaintAttribute }},
{ "stroke-linecap" , { SkSVGAttribute::kStrokeLineCap , SetLineCapAttribute }},
{ "stroke-linejoin", { SkSVGAttribute::kStrokeLineJoin, SetLineJoinAttribute }},
@@ -239,29 +265,34 @@ SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
{ "x" , { SkSVGAttribute::kX , SetLengthAttribute }},
{ "x1" , { SkSVGAttribute::kX1 , SetLengthAttribute }},
{ "x2" , { SkSVGAttribute::kX2 , SetLengthAttribute }},
+ { "xlink:href" , { SkSVGAttribute::kHref , SetIRIAttribute }},
{ "y" , { SkSVGAttribute::kY , SetLengthAttribute }},
{ "y1" , { SkSVGAttribute::kY1 , SetLengthAttribute }},
{ "y2" , { SkSVGAttribute::kY2 , SetLengthAttribute }},
};
SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = {
- { "circle" , []() -> sk_sp<SkSVGNode> { return SkSVGCircle::Make(); }},
- { "ellipse" , []() -> sk_sp<SkSVGNode> { return SkSVGEllipse::Make(); }},
- { "g" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); }},
- { "line" , []() -> sk_sp<SkSVGNode> { return SkSVGLine::Make(); }},
- { "path" , []() -> sk_sp<SkSVGNode> { return SkSVGPath::Make(); }},
- { "polygon" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolygon(); }},
- { "polyline", []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolyline(); }},
- { "rect" , []() -> sk_sp<SkSVGNode> { return SkSVGRect::Make(); }},
- { "svg" , []() -> sk_sp<SkSVGNode> { return SkSVGSVG::Make(); }},
+ { "circle" , []() -> sk_sp<SkSVGNode> { return SkSVGCircle::Make(); }},
+ { "defs" , []() -> sk_sp<SkSVGNode> { return SkSVGDefs::Make(); }},
+ { "ellipse" , []() -> sk_sp<SkSVGNode> { return SkSVGEllipse::Make(); }},
+ { "g" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); }},
+ { "line" , []() -> sk_sp<SkSVGNode> { return SkSVGLine::Make(); }},
+ { "linearGradient", []() -> sk_sp<SkSVGNode> { return SkSVGLinearGradient::Make(); }},
+ { "path" , []() -> sk_sp<SkSVGNode> { return SkSVGPath::Make(); }},
+ { "polygon" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolygon(); }},
+ { "polyline" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolyline(); }},
+ { "rect" , []() -> sk_sp<SkSVGNode> { return SkSVGRect::Make(); }},
+ { "stop" , []() -> sk_sp<SkSVGNode> { return SkSVGStop::Make(); }},
+ { "svg" , []() -> sk_sp<SkSVGNode> { return SkSVGSVG::Make(); }},
};
struct ConstructionContext {
- ConstructionContext() : fParent(nullptr) { }
+ ConstructionContext(SkSVGIDMapper* mapper) : fParent(nullptr), fIDMapper(mapper) {}
ConstructionContext(const ConstructionContext& other, const sk_sp<SkSVGNode>& newParent)
- : fParent(newParent.get()) { }
+ : fParent(newParent.get()), fIDMapper(other.fIDMapper) {}
const SkSVGNode* fParent;
+ SkSVGIDMapper* fIDMapper;
};
void set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const char* value) {
@@ -285,10 +316,15 @@ void set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const
}
void parse_node_attributes(const SkDOM& xmlDom, const SkDOM::Node* xmlNode,
- const sk_sp<SkSVGNode>& svgNode) {
+ const sk_sp<SkSVGNode>& svgNode, SkSVGIDMapper* mapper) {
const char* name, *value;
SkDOM::AttrIter attrIter(xmlDom, xmlNode);
while ((name = attrIter.next(&value))) {
+ // We're handling id attributes out of band for now.
+ if (!strcmp(name, "id")) {
+ mapper->set(SkString(value), svgNode);
+ continue;
+ }
set_string_attribute(svgNode, name, value);
}
}
@@ -318,7 +354,7 @@ sk_sp<SkSVGNode> construct_svg_node(const SkDOM& dom, const ConstructionContext&
SkASSERT(SkTo<size_t>(tagIndex) < SK_ARRAY_COUNT(gTagFactories));
sk_sp<SkSVGNode> node = gTagFactories[tagIndex].fValue();
- parse_node_attributes(dom, xmlNode, node);
+ parse_node_attributes(dom, xmlNode, node, ctx.fIDMapper);
ConstructionContext localCtx(ctx, node);
for (auto* child = dom.getFirstChild(xmlNode, nullptr); child;
@@ -341,7 +377,7 @@ SkSVGDOM::SkSVGDOM(const SkSize& containerSize)
sk_sp<SkSVGDOM> SkSVGDOM::MakeFromDOM(const SkDOM& xmlDom, const SkSize& containerSize) {
sk_sp<SkSVGDOM> dom = sk_make_sp<SkSVGDOM>(containerSize);
- ConstructionContext ctx;
+ ConstructionContext ctx(&dom->fIDMapper);
dom->fRoot = construct_svg_node(xmlDom, ctx, xmlDom.getRootNode());
return dom;
@@ -359,6 +395,7 @@ sk_sp<SkSVGDOM> SkSVGDOM::MakeFromStream(SkStream& svgStream, const SkSize& cont
void SkSVGDOM::render(SkCanvas* canvas) const {
if (fRoot) {
SkSVGRenderContext ctx(canvas,
+ fIDMapper,
SkSVGLengthContext(fContainerSize),
SkSVGPresentationContext());
fRoot->render(ctx);