[SVGDom] <polygon> & <polyline> support
authorfmalita <fmalita@chromium.org>
Fri, 12 Aug 2016 19:15:33 +0000 (12:15 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 12 Aug 2016 19:15:33 +0000 (12:15 -0700)
R=robertphillips@google.com,stephana@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2235273003

Review-Url: https://codereview.chromium.org/2235273003

BUILD.gn
experimental/svg/model/SkSVGAttribute.h
experimental/svg/model/SkSVGAttributeParser.cpp
experimental/svg/model/SkSVGAttributeParser.h
experimental/svg/model/SkSVGDOM.cpp
experimental/svg/model/SkSVGNode.h
experimental/svg/model/SkSVGPoly.cpp [new file with mode: 0644]
experimental/svg/model/SkSVGPoly.h [new file with mode: 0644]
experimental/svg/model/SkSVGTypes.h
experimental/svg/model/SkSVGValue.h
gyp/svg.gyp

index ff3c492..d7dd484 100644 (file)
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -524,6 +524,7 @@ test_lib("experimental_svg_model") {
     "experimental/svg/model/SkSVGDOM.cpp",
     "experimental/svg/model/SkSVGNode.cpp",
     "experimental/svg/model/SkSVGPath.cpp",
+    "experimental/svg/model/SkSVGPoly.cpp",
     "experimental/svg/model/SkSVGRect.cpp",
     "experimental/svg/model/SkSVGRenderContext.cpp",
     "experimental/svg/model/SkSVGSVG.cpp",
index 4ac595d..d2f0cf2 100644 (file)
@@ -18,6 +18,7 @@ enum class SkSVGAttribute {
     kFill,
     kFillOpacity,
     kHeight,
+    kPoints,
     kRx,
     kRy,
     kStroke,
index 308eb62..f8bfa20 100644 (file)
@@ -427,3 +427,41 @@ bool SkSVGAttributeParser::parseLineJoin(SkSVGLineJoin* join) {
 
     return parsedValue && this->parseEOSToken();
 }
+
+// https://www.w3.org/TR/SVG/shapes.html#PolygonElementPointsAttribute
+bool SkSVGAttributeParser::parsePoints(SkSVGPointsType* points) {
+    SkTDArray<SkPoint> pts;
+
+    bool parsedValue = false;
+    for (;;) {
+        this->parseWSToken();
+
+        SkScalar x, y;
+        if (!this->parseScalarToken(&x)) {
+            break;
+        }
+
+        // comma-wsp:
+        //     (wsp+ comma? wsp*) | (comma wsp*)
+        bool wsp   = this->parseWSToken();
+        bool comma = this->parseExpectedStringToken(",");
+        if (!(wsp || comma)) {
+            break;
+        }
+        this->parseWSToken();
+
+        if (!this->parseScalarToken(&y)) {
+            break;
+        }
+
+        pts.push(SkPoint::Make(x, y));
+        parsedValue = true;
+    }
+
+    if (parsedValue && this->parseEOSToken()) {
+        *points = pts;
+        return true;
+    }
+
+    return false;
+}
index 637bf4a..d1ead39 100644 (file)
@@ -22,6 +22,7 @@ public:
     bool parsePaint(SkSVGPaint*);
     bool parseLineCap(SkSVGLineCap*);
     bool parseLineJoin(SkSVGLineJoin*);
+    bool parsePoints(SkSVGPointsType*);
 
 private:
     // Stack-only
index 6e4bc49..4ae5fed 100644 (file)
@@ -14,6 +14,7 @@
 #include "SkSVGG.h"
 #include "SkSVGNode.h"
 #include "SkSVGPath.h"
+#include "SkSVGPoly.h"
 #include "SkSVGRect.h"
 #include "SkSVGRenderContext.h"
 #include "SkSVGSVG.h"
@@ -122,6 +123,18 @@ bool SetLineJoinAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
     return true;
 }
 
+bool SetPointsAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
+                        const char* stringValue) {
+    SkSVGPointsType points;
+    SkSVGAttributeParser parser(stringValue);
+    if (!parser.parsePoints(&points)) {
+        return false;
+    }
+
+    node->setAttribute(attr, SkSVGPointsValue(points));
+    return true;
+}
+
 SkString TrimmedString(const char* first, const char* last) {
     SkASSERT(first);
     SkASSERT(last);
@@ -204,6 +217,7 @@ SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
     { "fill"           , { SkSVGAttribute::kFill          , SetPaintAttribute     }},
     { "fill-opacity"   , { SkSVGAttribute::kFillOpacity   , SetNumberAttribute    }},
     { "height"         , { SkSVGAttribute::kHeight        , SetLengthAttribute    }},
+    { "points"         , { SkSVGAttribute::kPoints        , SetPointsAttribute    }},
     { "rx"             , { SkSVGAttribute::kRx            , SetLengthAttribute    }},
     { "ry"             , { SkSVGAttribute::kRy            , SetLengthAttribute    }},
     { "stroke"         , { SkSVGAttribute::kStroke        , SetPaintAttribute     }},
@@ -220,10 +234,12 @@ SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
 };
 
 SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = {
-    { "g"   , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make();    }},
-    { "path", []() -> sk_sp<SkSVGNode> { return SkSVGPath::Make(); }},
-    { "rect", []() -> sk_sp<SkSVGNode> { return SkSVGRect::Make(); }},
-    { "svg" , []() -> sk_sp<SkSVGNode> { return SkSVGSVG::Make();  }},
+    { "g"       , []() -> sk_sp<SkSVGNode> { return SkSVGG::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();          }},
 };
 
 struct ConstructionContext {
index 38a17d8..1e5c3be 100644 (file)
@@ -19,6 +19,8 @@ class SkSVGValue;
 enum class SkSVGTag {
     kG,
     kPath,
+    kPolygon,
+    kPolyline,
     kRect,
     kSvg
 };
diff --git a/experimental/svg/model/SkSVGPoly.cpp b/experimental/svg/model/SkSVGPoly.cpp
new file mode 100644 (file)
index 0000000..bcc716f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkCanvas.h"
+#include "SkSVGRenderContext.h"
+#include "SkSVGPoly.h"
+#include "SkSVGValue.h"
+
+SkSVGPoly::SkSVGPoly(SkSVGTag t) : INHERITED(t) {}
+
+void SkSVGPoly::setPoints(const SkSVGPointsType& pts) {
+    fPath.reset();
+    fPath.addPoly(pts.value().begin(),
+                  pts.value().count(),
+                  this->tag() == SkSVGTag::kPolygon); // only polygons are auto-closed
+}
+
+void SkSVGPoly::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
+    switch (attr) {
+    case SkSVGAttribute::kPoints:
+        if (const auto* pts = v.as<SkSVGPointsValue>()) {
+            this->setPoints(*pts);
+        }
+        break;
+    default:
+        this->INHERITED::onSetAttribute(attr, v);
+    }
+}
+
+void SkSVGPoly::onDraw(SkCanvas* canvas, const SkSVGLengthContext&, const SkPaint& paint) const {
+    canvas->drawPath(fPath, paint);
+}
diff --git a/experimental/svg/model/SkSVGPoly.h b/experimental/svg/model/SkSVGPoly.h
new file mode 100644 (file)
index 0000000..3ae8dc6
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSVGPoly_DEFINED
+#define SkSVGPoly_DEFINED
+
+#include "SkPath.h"
+#include "SkSVGShape.h"
+
+// Handles <polygon> and <polyline> elements.
+class SkSVGPoly final : public SkSVGShape {
+public:
+    virtual ~SkSVGPoly() = default;
+
+    static sk_sp<SkSVGPoly> MakePolygon() {
+        return sk_sp<SkSVGPoly>(new SkSVGPoly(SkSVGTag::kPolygon));
+    }
+
+    static sk_sp<SkSVGPoly> MakePolyline() {
+        return sk_sp<SkSVGPoly>(new SkSVGPoly(SkSVGTag::kPolyline));
+    }
+
+    void setPoints(const SkSVGPointsType&);
+
+protected:
+    void onSetAttribute(SkSVGAttribute, const SkSVGValue&) override;
+
+    void onDraw(SkCanvas*, const SkSVGLengthContext&, const SkPaint&) const override;
+
+private:
+    SkSVGPoly(SkSVGTag);
+
+    SkPath fPath;
+
+    typedef SkSVGShape INHERITED;
+};
+
+#endif // SkSVGPoly_DEFINED
index c8330e1..18ec3ce 100644 (file)
 
 #include "SkColor.h"
 #include "SkMatrix.h"
+#include "SkPoint.h"
 #include "SkRect.h"
 #include "SkScalar.h"
+#include "SkTDArray.h"
 #include "SkTypes.h"
 
 template <typename T>
@@ -22,6 +24,7 @@ public:
 
     SkSVGPrimitiveTypeWrapper(const SkSVGPrimitiveTypeWrapper&)            = default;
     SkSVGPrimitiveTypeWrapper& operator=(const SkSVGPrimitiveTypeWrapper&) = default;
+    SkSVGPrimitiveTypeWrapper& operator=(const T& v) { fValue = v; return *this; }
 
     bool operator==(const SkSVGPrimitiveTypeWrapper<T>& other) const {
         return fValue == other.fValue;
@@ -41,6 +44,7 @@ using SkSVGColorType      = SkSVGPrimitiveTypeWrapper<SkColor >;
 using SkSVGNumberType     = SkSVGPrimitiveTypeWrapper<SkScalar>;
 using SkSVGViewBoxType    = SkSVGPrimitiveTypeWrapper<SkRect  >;
 using SkSVGTransformType  = SkSVGPrimitiveTypeWrapper<SkMatrix>;
+using SkSVGPointsType     = SkSVGPrimitiveTypeWrapper<SkTDArray<SkPoint>>;
 
 class SkSVGLength {
 public:
index 583e602..8f93bd8 100644 (file)
@@ -24,6 +24,7 @@ public:
         kNumber,
         kPaint,
         kPath,
+        kPoints,
         kTransform,
         kViewBox,
     };
@@ -75,5 +76,6 @@ using SkSVGPaintValue     = SkSVGWrapperValue<SkSVGPaint        , SkSVGValue::Ty
 using SkSVGLineCapValue   = SkSVGWrapperValue<SkSVGLineCap      , SkSVGValue::Type::kLineCap  >;
 using SkSVGLineJoinValue  = SkSVGWrapperValue<SkSVGLineJoin     , SkSVGValue::Type::kLineJoin >;
 using SkSVGNumberValue    = SkSVGWrapperValue<SkSVGNumberType   , SkSVGValue::Type::kNumber   >;
+using SkSVGPointsValue    = SkSVGWrapperValue<SkSVGPointsType   , SkSVGValue::Type::kPoints   >;
 
 #endif // SkSVGValue_DEFINED
index 4151a3d..50e4dbe 100644 (file)
@@ -57,6 +57,8 @@
         '../experimental/svg/model/SkSVGNode.cpp',
         '../experimental/svg/model/SkSVGPath.h',
         '../experimental/svg/model/SkSVGPath.cpp',
+        '../experimental/svg/model/SkSVGPoly.h',
+        '../experimental/svg/model/SkSVGPoly.cpp',
         '../experimental/svg/model/SkSVGRect.h',
         '../experimental/svg/model/SkSVGRect.cpp',
         '../experimental/svg/model/SkSVGRenderContext.h',