"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",
kFill,
kFillOpacity,
kHeight,
+ kPoints,
kRx,
kRy,
kStroke,
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;
+}
bool parsePaint(SkSVGPaint*);
bool parseLineCap(SkSVGLineCap*);
bool parseLineJoin(SkSVGLineJoin*);
+ bool parsePoints(SkSVGPointsType*);
private:
// Stack-only
#include "SkSVGG.h"
#include "SkSVGNode.h"
#include "SkSVGPath.h"
+#include "SkSVGPoly.h"
#include "SkSVGRect.h"
#include "SkSVGRenderContext.h"
#include "SkSVGSVG.h"
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);
{ "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 }},
};
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 {
enum class SkSVGTag {
kG,
kPath,
+ kPolygon,
+ kPolyline,
kRect,
kSvg
};
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
#include "SkColor.h"
#include "SkMatrix.h"
+#include "SkPoint.h"
#include "SkRect.h"
#include "SkScalar.h"
+#include "SkTDArray.h"
#include "SkTypes.h"
template <typename T>
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;
using SkSVGNumberType = SkSVGPrimitiveTypeWrapper<SkScalar>;
using SkSVGViewBoxType = SkSVGPrimitiveTypeWrapper<SkRect >;
using SkSVGTransformType = SkSVGPrimitiveTypeWrapper<SkMatrix>;
+using SkSVGPointsType = SkSVGPrimitiveTypeWrapper<SkTDArray<SkPoint>>;
class SkSVGLength {
public:
kNumber,
kPaint,
kPath,
+ kPoints,
kTransform,
kViewBox,
};
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
'../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',