Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: experimental/svg/model/SkSVGDOM.cpp

Issue 2327233003: [SVGDom] Initial linear gradient support (Closed)
Patch Set: review Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « experimental/svg/model/SkSVGDOM.h ('k') | experimental/svg/model/SkSVGDefs.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkCanvas.h" 8 #include "SkCanvas.h"
9 #include "SkDOM.h" 9 #include "SkDOM.h"
10 #include "SkParsePath.h" 10 #include "SkParsePath.h"
11 #include "SkString.h" 11 #include "SkString.h"
12 #include "SkSVGAttributeParser.h" 12 #include "SkSVGAttributeParser.h"
13 #include "SkSVGCircle.h" 13 #include "SkSVGCircle.h"
14 #include "SkSVGDefs.h"
14 #include "SkSVGDOM.h" 15 #include "SkSVGDOM.h"
15 #include "SkSVGEllipse.h" 16 #include "SkSVGEllipse.h"
16 #include "SkSVGG.h" 17 #include "SkSVGG.h"
17 #include "SkSVGLine.h" 18 #include "SkSVGLine.h"
19 #include "SkSVGLinearGradient.h"
18 #include "SkSVGNode.h" 20 #include "SkSVGNode.h"
19 #include "SkSVGPath.h" 21 #include "SkSVGPath.h"
20 #include "SkSVGPoly.h" 22 #include "SkSVGPoly.h"
21 #include "SkSVGRect.h" 23 #include "SkSVGRect.h"
22 #include "SkSVGRenderContext.h" 24 #include "SkSVGRenderContext.h"
25 #include "SkSVGStop.h"
23 #include "SkSVGSVG.h" 26 #include "SkSVGSVG.h"
24 #include "SkSVGTypes.h" 27 #include "SkSVGTypes.h"
25 #include "SkSVGValue.h" 28 #include "SkSVGValue.h"
26 #include "SkTSearch.h" 29 #include "SkTSearch.h"
27 30
28 namespace { 31 namespace {
29 32
30 bool SetPaintAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, 33 bool SetPaintAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
31 const char* stringValue) { 34 const char* stringValue) {
32 SkSVGPaint paint; 35 SkSVGPaint paint;
33 SkSVGAttributeParser parser(stringValue); 36 SkSVGAttributeParser parser(stringValue);
34 if (!parser.parsePaint(&paint)) { 37 if (!parser.parsePaint(&paint)) {
35 // Until we have paint server support, failing here will cause default/a ll-black rendering. 38 return false;
36 // It's better to just not draw for now.
37 paint = SkSVGPaint(SkSVGPaint::Type::kNone);
38
39 // return false;
40 } 39 }
41 40
42 node->setAttribute(attr, SkSVGPaintValue(paint)); 41 node->setAttribute(attr, SkSVGPaintValue(paint));
43 return true; 42 return true;
44 } 43 }
45 44
45 bool SetColorAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
46 const char* stringValue) {
47 SkSVGColorType color;
48 SkSVGAttributeParser parser(stringValue);
49 if (!parser.parseColor(&color)) {
50 return false;
51 }
52
53 node->setAttribute(attr, SkSVGColorValue(color));
54 return true;
55 }
56
57 bool SetIRIAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
58 const char* stringValue) {
59 SkSVGStringType iri;
60 SkSVGAttributeParser parser(stringValue);
61 if (!parser.parseIRI(&iri)) {
62 return false;
63 }
64
65 node->setAttribute(attr, SkSVGStringValue(iri));
66 return true;
67 }
68
46 bool SetPathDataAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, 69 bool SetPathDataAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
47 const char* stringValue) { 70 const char* stringValue) {
48 SkPath path; 71 SkPath path;
49 if (!SkParsePath::FromSVGString(stringValue, &path)) { 72 if (!SkParsePath::FromSVGString(stringValue, &path)) {
50 return false; 73 return false;
51 } 74 }
52 75
53 node->setAttribute(attr, SkSVGPathValue(path)); 76 node->setAttribute(attr, SkSVGPathValue(path));
54 return true; 77 return true;
55 } 78 }
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 bool (*fSetter)(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, const cha r* stringValue); 238 bool (*fSetter)(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, const cha r* stringValue);
216 }; 239 };
217 240
218 SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = { 241 SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
219 { "cx" , { SkSVGAttribute::kCx , SetLengthAttribute }}, 242 { "cx" , { SkSVGAttribute::kCx , SetLengthAttribute }},
220 { "cy" , { SkSVGAttribute::kCy , SetLengthAttribute }}, 243 { "cy" , { SkSVGAttribute::kCy , SetLengthAttribute }},
221 { "d" , { SkSVGAttribute::kD , SetPathDataAttribute }}, 244 { "d" , { SkSVGAttribute::kD , SetPathDataAttribute }},
222 { "fill" , { SkSVGAttribute::kFill , SetPaintAttribute }}, 245 { "fill" , { SkSVGAttribute::kFill , SetPaintAttribute }},
223 { "fill-opacity" , { SkSVGAttribute::kFillOpacity , SetNumberAttribute }}, 246 { "fill-opacity" , { SkSVGAttribute::kFillOpacity , SetNumberAttribute }},
224 { "height" , { SkSVGAttribute::kHeight , SetLengthAttribute }}, 247 { "height" , { SkSVGAttribute::kHeight , SetLengthAttribute }},
248 { "offset" , { SkSVGAttribute::kOffset , SetLengthAttribute }},
225 { "opacity" , { SkSVGAttribute::kOpacity , SetNumberAttribute }}, 249 { "opacity" , { SkSVGAttribute::kOpacity , SetNumberAttribute }},
226 { "points" , { SkSVGAttribute::kPoints , SetPointsAttribute }}, 250 { "points" , { SkSVGAttribute::kPoints , SetPointsAttribute }},
227 { "r" , { SkSVGAttribute::kR , SetLengthAttribute }}, 251 { "r" , { SkSVGAttribute::kR , SetLengthAttribute }},
228 { "rx" , { SkSVGAttribute::kRx , SetLengthAttribute }}, 252 { "rx" , { SkSVGAttribute::kRx , SetLengthAttribute }},
229 { "ry" , { SkSVGAttribute::kRy , SetLengthAttribute }}, 253 { "ry" , { SkSVGAttribute::kRy , SetLengthAttribute }},
254 { "stop-color" , { SkSVGAttribute::kStopColor , SetColorAttribute }},
255 { "stop-opacity" , { SkSVGAttribute::kStopOpacity , SetNumberAttribute }},
230 { "stroke" , { SkSVGAttribute::kStroke , SetPaintAttribute }}, 256 { "stroke" , { SkSVGAttribute::kStroke , SetPaintAttribute }},
231 { "stroke-linecap" , { SkSVGAttribute::kStrokeLineCap , SetLineCapAttribute }}, 257 { "stroke-linecap" , { SkSVGAttribute::kStrokeLineCap , SetLineCapAttribute }},
232 { "stroke-linejoin", { SkSVGAttribute::kStrokeLineJoin, SetLineJoinAttribute }}, 258 { "stroke-linejoin", { SkSVGAttribute::kStrokeLineJoin, SetLineJoinAttribute }},
233 { "stroke-opacity" , { SkSVGAttribute::kStrokeOpacity , SetNumberAttribute }}, 259 { "stroke-opacity" , { SkSVGAttribute::kStrokeOpacity , SetNumberAttribute }},
234 { "stroke-width" , { SkSVGAttribute::kStrokeWidth , SetLengthAttribute }}, 260 { "stroke-width" , { SkSVGAttribute::kStrokeWidth , SetLengthAttribute }},
235 { "style" , { SkSVGAttribute::kUnknown , SetStyleAttributes }}, 261 { "style" , { SkSVGAttribute::kUnknown , SetStyleAttributes }},
236 { "transform" , { SkSVGAttribute::kTransform , SetTransformAttribut e }}, 262 { "transform" , { SkSVGAttribute::kTransform , SetTransformAttribut e }},
237 { "viewBox" , { SkSVGAttribute::kViewBox , SetViewBoxAttribute }}, 263 { "viewBox" , { SkSVGAttribute::kViewBox , SetViewBoxAttribute }},
238 { "width" , { SkSVGAttribute::kWidth , SetLengthAttribute }}, 264 { "width" , { SkSVGAttribute::kWidth , SetLengthAttribute }},
239 { "x" , { SkSVGAttribute::kX , SetLengthAttribute }}, 265 { "x" , { SkSVGAttribute::kX , SetLengthAttribute }},
240 { "x1" , { SkSVGAttribute::kX1 , SetLengthAttribute }}, 266 { "x1" , { SkSVGAttribute::kX1 , SetLengthAttribute }},
241 { "x2" , { SkSVGAttribute::kX2 , SetLengthAttribute }}, 267 { "x2" , { SkSVGAttribute::kX2 , SetLengthAttribute }},
268 { "xlink:href" , { SkSVGAttribute::kHref , SetIRIAttribute }},
242 { "y" , { SkSVGAttribute::kY , SetLengthAttribute }}, 269 { "y" , { SkSVGAttribute::kY , SetLengthAttribute }},
243 { "y1" , { SkSVGAttribute::kY1 , SetLengthAttribute }}, 270 { "y1" , { SkSVGAttribute::kY1 , SetLengthAttribute }},
244 { "y2" , { SkSVGAttribute::kY2 , SetLengthAttribute }}, 271 { "y2" , { SkSVGAttribute::kY2 , SetLengthAttribute }},
245 }; 272 };
246 273
247 SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = { 274 SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = {
248 { "circle" , []() -> sk_sp<SkSVGNode> { return SkSVGCircle::Make(); } }, 275 { "circle" , []() -> sk_sp<SkSVGNode> { return SkSVGCircle::Make(); }},
249 { "ellipse" , []() -> sk_sp<SkSVGNode> { return SkSVGEllipse::Make(); } }, 276 { "defs" , []() -> sk_sp<SkSVGNode> { return SkSVGDefs::Make(); }},
250 { "g" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); } }, 277 { "ellipse" , []() -> sk_sp<SkSVGNode> { return SkSVGEllipse::Make(); }},
251 { "line" , []() -> sk_sp<SkSVGNode> { return SkSVGLine::Make(); } }, 278 { "g" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); }},
252 { "path" , []() -> sk_sp<SkSVGNode> { return SkSVGPath::Make(); } }, 279 { "line" , []() -> sk_sp<SkSVGNode> { return SkSVGLine::Make(); }},
253 { "polygon" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolygon(); } }, 280 { "linearGradient", []() -> sk_sp<SkSVGNode> { return SkSVGLinearGradient::M ake(); }},
254 { "polyline", []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolyline(); } }, 281 { "path" , []() -> sk_sp<SkSVGNode> { return SkSVGPath::Make(); }},
255 { "rect" , []() -> sk_sp<SkSVGNode> { return SkSVGRect::Make(); } }, 282 { "polygon" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolygon (); }},
256 { "svg" , []() -> sk_sp<SkSVGNode> { return SkSVGSVG::Make(); } }, 283 { "polyline" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolylin e(); }},
284 { "rect" , []() -> sk_sp<SkSVGNode> { return SkSVGRect::Make(); }},
285 { "stop" , []() -> sk_sp<SkSVGNode> { return SkSVGStop::Make(); }},
286 { "svg" , []() -> sk_sp<SkSVGNode> { return SkSVGSVG::Make(); }},
257 }; 287 };
258 288
259 struct ConstructionContext { 289 struct ConstructionContext {
260 ConstructionContext() : fParent(nullptr) { } 290 ConstructionContext(SkSVGIDMapper* mapper) : fParent(nullptr), fIDMapper(map per) {}
261 ConstructionContext(const ConstructionContext& other, const sk_sp<SkSVGNode> & newParent) 291 ConstructionContext(const ConstructionContext& other, const sk_sp<SkSVGNode> & newParent)
262 : fParent(newParent.get()) { } 292 : fParent(newParent.get()), fIDMapper(other.fIDMapper) {}
263 293
264 const SkSVGNode* fParent; 294 const SkSVGNode* fParent;
295 SkSVGIDMapper* fIDMapper;
265 }; 296 };
266 297
267 void set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const char* value) { 298 void set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const char* value) {
268 const int attrIndex = SkStrSearch(&gAttributeParseInfo[0].fKey, 299 const int attrIndex = SkStrSearch(&gAttributeParseInfo[0].fKey,
269 SkTo<int>(SK_ARRAY_COUNT(gAttributeParseIn fo)), 300 SkTo<int>(SK_ARRAY_COUNT(gAttributeParseIn fo)),
270 name, sizeof(gAttributeParseInfo[0])); 301 name, sizeof(gAttributeParseInfo[0]));
271 if (attrIndex < 0) { 302 if (attrIndex < 0) {
272 #if defined(SK_VERBOSE_SVG_PARSING) 303 #if defined(SK_VERBOSE_SVG_PARSING)
273 SkDebugf("unhandled attribute: %s\n", name); 304 SkDebugf("unhandled attribute: %s\n", name);
274 #endif 305 #endif
275 return; 306 return;
276 } 307 }
277 308
278 SkASSERT(SkTo<size_t>(attrIndex) < SK_ARRAY_COUNT(gAttributeParseInfo)); 309 SkASSERT(SkTo<size_t>(attrIndex) < SK_ARRAY_COUNT(gAttributeParseInfo));
279 const auto& attrInfo = gAttributeParseInfo[attrIndex].fValue; 310 const auto& attrInfo = gAttributeParseInfo[attrIndex].fValue;
280 if (!attrInfo.fSetter(node, attrInfo.fAttr, value)) { 311 if (!attrInfo.fSetter(node, attrInfo.fAttr, value)) {
281 #if defined(SK_VERBOSE_SVG_PARSING) 312 #if defined(SK_VERBOSE_SVG_PARSING)
282 SkDebugf("could not parse attribute: '%s=\"%s\"'\n", name, value); 313 SkDebugf("could not parse attribute: '%s=\"%s\"'\n", name, value);
283 #endif 314 #endif
284 } 315 }
285 } 316 }
286 317
287 void parse_node_attributes(const SkDOM& xmlDom, const SkDOM::Node* xmlNode, 318 void parse_node_attributes(const SkDOM& xmlDom, const SkDOM::Node* xmlNode,
288 const sk_sp<SkSVGNode>& svgNode) { 319 const sk_sp<SkSVGNode>& svgNode, SkSVGIDMapper* mappe r) {
289 const char* name, *value; 320 const char* name, *value;
290 SkDOM::AttrIter attrIter(xmlDom, xmlNode); 321 SkDOM::AttrIter attrIter(xmlDom, xmlNode);
291 while ((name = attrIter.next(&value))) { 322 while ((name = attrIter.next(&value))) {
323 // We're handling id attributes out of band for now.
324 if (!strcmp(name, "id")) {
325 mapper->set(SkString(value), svgNode);
326 continue;
327 }
292 set_string_attribute(svgNode, name, value); 328 set_string_attribute(svgNode, name, value);
293 } 329 }
294 } 330 }
295 331
296 sk_sp<SkSVGNode> construct_svg_node(const SkDOM& dom, const ConstructionContext& ctx, 332 sk_sp<SkSVGNode> construct_svg_node(const SkDOM& dom, const ConstructionContext& ctx,
297 const SkDOM::Node* xmlNode) { 333 const SkDOM::Node* xmlNode) {
298 const char* elem = dom.getName(xmlNode); 334 const char* elem = dom.getName(xmlNode);
299 const SkDOM::Type elemType = dom.getType(xmlNode); 335 const SkDOM::Type elemType = dom.getType(xmlNode);
300 336
301 if (elemType == SkDOM::kText_Type) { 337 if (elemType == SkDOM::kText_Type) {
302 SkASSERT(dom.countChildren(xmlNode) == 0); 338 SkASSERT(dom.countChildren(xmlNode) == 0);
303 // TODO: text handling 339 // TODO: text handling
304 return nullptr; 340 return nullptr;
305 } 341 }
306 342
307 SkASSERT(elemType == SkDOM::kElement_Type); 343 SkASSERT(elemType == SkDOM::kElement_Type);
308 344
309 const int tagIndex = SkStrSearch(&gTagFactories[0].fKey, 345 const int tagIndex = SkStrSearch(&gTagFactories[0].fKey,
310 SkTo<int>(SK_ARRAY_COUNT(gTagFactories)), 346 SkTo<int>(SK_ARRAY_COUNT(gTagFactories)),
311 elem, sizeof(gTagFactories[0])); 347 elem, sizeof(gTagFactories[0]));
312 if (tagIndex < 0) { 348 if (tagIndex < 0) {
313 #if defined(SK_VERBOSE_SVG_PARSING) 349 #if defined(SK_VERBOSE_SVG_PARSING)
314 SkDebugf("unhandled element: <%s>\n", elem); 350 SkDebugf("unhandled element: <%s>\n", elem);
315 #endif 351 #endif
316 return nullptr; 352 return nullptr;
317 } 353 }
318 354
319 SkASSERT(SkTo<size_t>(tagIndex) < SK_ARRAY_COUNT(gTagFactories)); 355 SkASSERT(SkTo<size_t>(tagIndex) < SK_ARRAY_COUNT(gTagFactories));
320 sk_sp<SkSVGNode> node = gTagFactories[tagIndex].fValue(); 356 sk_sp<SkSVGNode> node = gTagFactories[tagIndex].fValue();
321 parse_node_attributes(dom, xmlNode, node); 357 parse_node_attributes(dom, xmlNode, node, ctx.fIDMapper);
322 358
323 ConstructionContext localCtx(ctx, node); 359 ConstructionContext localCtx(ctx, node);
324 for (auto* child = dom.getFirstChild(xmlNode, nullptr); child; 360 for (auto* child = dom.getFirstChild(xmlNode, nullptr); child;
325 child = dom.getNextSibling(child)) { 361 child = dom.getNextSibling(child)) {
326 sk_sp<SkSVGNode> childNode = construct_svg_node(dom, localCtx, child); 362 sk_sp<SkSVGNode> childNode = construct_svg_node(dom, localCtx, child);
327 if (childNode) { 363 if (childNode) {
328 node->appendChild(std::move(childNode)); 364 node->appendChild(std::move(childNode));
329 } 365 }
330 } 366 }
331 367
332 return node; 368 return node;
333 } 369 }
334 370
335 } // anonymous namespace 371 } // anonymous namespace
336 372
337 SkSVGDOM::SkSVGDOM(const SkSize& containerSize) 373 SkSVGDOM::SkSVGDOM(const SkSize& containerSize)
338 : fContainerSize(containerSize) { 374 : fContainerSize(containerSize) {
339 } 375 }
340 376
341 sk_sp<SkSVGDOM> SkSVGDOM::MakeFromDOM(const SkDOM& xmlDom, const SkSize& contain erSize) { 377 sk_sp<SkSVGDOM> SkSVGDOM::MakeFromDOM(const SkDOM& xmlDom, const SkSize& contain erSize) {
342 sk_sp<SkSVGDOM> dom = sk_make_sp<SkSVGDOM>(containerSize); 378 sk_sp<SkSVGDOM> dom = sk_make_sp<SkSVGDOM>(containerSize);
343 379
344 ConstructionContext ctx; 380 ConstructionContext ctx(&dom->fIDMapper);
345 dom->fRoot = construct_svg_node(xmlDom, ctx, xmlDom.getRootNode()); 381 dom->fRoot = construct_svg_node(xmlDom, ctx, xmlDom.getRootNode());
346 382
347 return dom; 383 return dom;
348 } 384 }
349 385
350 sk_sp<SkSVGDOM> SkSVGDOM::MakeFromStream(SkStream& svgStream, const SkSize& cont ainerSize) { 386 sk_sp<SkSVGDOM> SkSVGDOM::MakeFromStream(SkStream& svgStream, const SkSize& cont ainerSize) {
351 SkDOM xmlDom; 387 SkDOM xmlDom;
352 if (!xmlDom.build(svgStream)) { 388 if (!xmlDom.build(svgStream)) {
353 return nullptr; 389 return nullptr;
354 } 390 }
355 391
356 return MakeFromDOM(xmlDom, containerSize); 392 return MakeFromDOM(xmlDom, containerSize);
357 } 393 }
358 394
359 void SkSVGDOM::render(SkCanvas* canvas) const { 395 void SkSVGDOM::render(SkCanvas* canvas) const {
360 if (fRoot) { 396 if (fRoot) {
361 SkSVGRenderContext ctx(canvas, 397 SkSVGRenderContext ctx(canvas,
398 fIDMapper,
362 SkSVGLengthContext(fContainerSize), 399 SkSVGLengthContext(fContainerSize),
363 SkSVGPresentationContext()); 400 SkSVGPresentationContext());
364 fRoot->render(ctx); 401 fRoot->render(ctx);
365 } 402 }
366 } 403 }
367 404
368 void SkSVGDOM::setContainerSize(const SkSize& containerSize) { 405 void SkSVGDOM::setContainerSize(const SkSize& containerSize) {
369 // TODO: inval 406 // TODO: inval
370 fContainerSize = containerSize; 407 fContainerSize = containerSize;
371 } 408 }
372 409
373 void SkSVGDOM::setRoot(sk_sp<SkSVGNode> root) { 410 void SkSVGDOM::setRoot(sk_sp<SkSVGNode> root) {
374 fRoot = std::move(root); 411 fRoot = std::move(root);
375 } 412 }
OLDNEW
« no previous file with comments | « experimental/svg/model/SkSVGDOM.h ('k') | experimental/svg/model/SkSVGDefs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698