summaryrefslogtreecommitdiff
path: root/svg
diff options
context:
space:
mode:
Diffstat (limited to 'svg')
-rw-r--r--svg/SkSVG.cpp28
-rw-r--r--svg/SkSVGCircle.cpp45
-rw-r--r--svg/SkSVGCircle.h24
-rw-r--r--svg/SkSVGClipPath.cpp40
-rw-r--r--svg/SkSVGClipPath.h23
-rw-r--r--svg/SkSVGDefs.cpp24
-rw-r--r--svg/SkSVGDefs.h23
-rw-r--r--svg/SkSVGElements.cpp86
-rw-r--r--svg/SkSVGElements.h73
-rw-r--r--svg/SkSVGEllipse.cpp47
-rw-r--r--svg/SkSVGEllipse.h25
-rw-r--r--svg/SkSVGFeColorMatrix.cpp24
-rw-r--r--svg/SkSVGFeColorMatrix.h26
-rw-r--r--svg/SkSVGFilter.cpp25
-rw-r--r--svg/SkSVGFilter.h27
-rw-r--r--svg/SkSVGG.cpp16
-rw-r--r--svg/SkSVGG.h21
-rw-r--r--svg/SkSVGGradient.cpp114
-rw-r--r--svg/SkSVGGradient.h29
-rw-r--r--svg/SkSVGGroup.cpp45
-rw-r--r--svg/SkSVGGroup.h28
-rw-r--r--svg/SkSVGImage.cpp44
-rw-r--r--svg/SkSVGImage.h28
-rw-r--r--svg/SkSVGLine.cpp30
-rw-r--r--svg/SkSVGLine.h25
-rw-r--r--svg/SkSVGLinearGradient.cpp44
-rw-r--r--svg/SkSVGLinearGradient.h28
-rw-r--r--svg/SkSVGMask.cpp33
-rw-r--r--svg/SkSVGMask.h29
-rw-r--r--svg/SkSVGMetadata.cpp24
-rw-r--r--svg/SkSVGMetadata.h23
-rw-r--r--svg/SkSVGPaintState.cpp454
-rw-r--r--svg/SkSVGParser.cpp441
-rw-r--r--svg/SkSVGPath.cpp37
-rw-r--r--svg/SkSVGPath.h22
-rw-r--r--svg/SkSVGPolygon.cpp33
-rw-r--r--svg/SkSVGPolygon.h23
-rw-r--r--svg/SkSVGPolyline.cpp43
-rw-r--r--svg/SkSVGPolyline.h27
-rw-r--r--svg/SkSVGRadialGradient.cpp42
-rw-r--r--svg/SkSVGRadialGradient.h30
-rw-r--r--svg/SkSVGRect.cpp35
-rw-r--r--svg/SkSVGRect.h26
-rw-r--r--svg/SkSVGSVG.cpp76
-rw-r--r--svg/SkSVGSVG.h34
-rw-r--r--svg/SkSVGStop.cpp24
-rw-r--r--svg/SkSVGStop.h23
-rw-r--r--svg/SkSVGSymbol.cpp22
-rw-r--r--svg/SkSVGSymbol.h22
-rw-r--r--svg/SkSVGText.cpp39
-rw-r--r--svg/SkSVGText.h32
-rw-r--r--svg/SkSVGUse.cpp30
-rw-r--r--svg/SkSVGUse.h28
53 files changed, 2644 insertions, 0 deletions
diff --git a/svg/SkSVG.cpp b/svg/SkSVG.cpp
new file mode 100644
index 00000000..fdfc13a6
--- /dev/null
+++ b/svg/SkSVG.cpp
@@ -0,0 +1,28 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVG.h"
+#include 'SkSVGParser.h"
+
+SkSVG::SkSVG() {
+}
+
+SkSVG::~SkSVG() {
+}
+
+bool SkSVG::decodeStream(SkStream* stream);
+{
+ size_t size = stream->read(nil, 0);
+ SkAutoMalloc storage(size);
+ char* data = (char*)storage.get();
+ size_t actual = stream->read(data, size);
+ SkASSERT(size == actual);
+ SkSVGParser parser(*fMaker);
+ return parser.parse(data, actual, &fErrorCode, &fErrorLineNumber);
+}
diff --git a/svg/SkSVGCircle.cpp b/svg/SkSVGCircle.cpp
new file mode 100644
index 00000000..e34e1795
--- /dev/null
+++ b/svg/SkSVGCircle.cpp
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGCircle.h"
+#include "SkSVGParser.h"
+#include "SkParse.h"
+#include <stdio.h>
+
+const SkSVGAttribute SkSVGCircle::gAttributes[] = {
+ SVG_ATTRIBUTE(cx),
+ SVG_ATTRIBUTE(cy),
+ SVG_ATTRIBUTE(r)
+};
+
+DEFINE_SVG_INFO(Circle)
+
+void SkSVGCircle::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("oval");
+ INHERITED::translate(parser, defState);
+ SkScalar cx, cy, r;
+ SkParse::FindScalar(f_cx.c_str(), &cx);
+ SkParse::FindScalar(f_cy.c_str(), &cy);
+ SkParse::FindScalar(f_r.c_str(), &r);
+ SkScalar left, top, right, bottom;
+ left = cx - r;
+ top = cy - r;
+ right = cx + r;
+ bottom = cy + r;
+ char scratch[16];
+ sprintf(scratch, "%g", SkScalarToDouble(left));
+ parser._addAttribute("left", scratch);
+ sprintf(scratch, "%g", SkScalarToDouble(top));
+ parser._addAttribute("top", scratch);
+ sprintf(scratch, "%g", SkScalarToDouble(right));
+ parser._addAttribute("right", scratch);
+ sprintf(scratch, "%g", SkScalarToDouble(bottom));
+ parser._addAttribute("bottom", scratch);
+ parser._endElement();
+}
diff --git a/svg/SkSVGCircle.h b/svg/SkSVGCircle.h
new file mode 100644
index 00000000..11851627
--- /dev/null
+++ b/svg/SkSVGCircle.h
@@ -0,0 +1,24 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGCircle_DEFINED
+#define SkSVGCircle_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGCircle : public SkSVGElement {
+ DECLARE_SVG_INFO(Circle);
+private:
+ SkString f_cx;
+ SkString f_cy;
+ SkString f_r;
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGCircle_DEFINED
diff --git a/svg/SkSVGClipPath.cpp b/svg/SkSVGClipPath.cpp
new file mode 100644
index 00000000..fa3a7991
--- /dev/null
+++ b/svg/SkSVGClipPath.cpp
@@ -0,0 +1,40 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGClipPath.h"
+#include "SkSVGParser.h"
+#include "SkSVGUse.h"
+
+DEFINE_SVG_NO_INFO(ClipPath)
+
+bool SkSVGClipPath::isDef() {
+ return true;
+}
+
+bool SkSVGClipPath::isNotDef() {
+ return false;
+}
+
+void SkSVGClipPath::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("clip");
+ INHERITED::translate(parser, defState);
+ SkASSERT(fChildren.count() == 1);
+ SkSVGElement* child = *fChildren.begin();
+ SkASSERT(child->getType() == SkSVGType_Use);
+ SkSVGUse* use = (SkSVGUse*) child;
+ SkSVGElement* ref = NULL;
+ const char* refStr = &use->f_xlink_href.c_str()[1];
+ SkASSERT(parser.getIDs().find(refStr, &ref));
+ SkASSERT(ref);
+ if (ref->getType() == SkSVGType_Rect)
+ parser._addAttribute("rectangle", refStr);
+ else
+ parser._addAttribute("path", refStr);
+ parser._endElement();
+}
diff --git a/svg/SkSVGClipPath.h b/svg/SkSVGClipPath.h
new file mode 100644
index 00000000..9ba4fbc7
--- /dev/null
+++ b/svg/SkSVGClipPath.h
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGClipPath_DEFINED
+#define SkSVGClipPath_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGClipPath : public SkSVGElement {
+ DECLARE_SVG_INFO(ClipPath);
+ virtual bool isDef();
+ virtual bool isNotDef();
+private:
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGClipPath_DEFINED
diff --git a/svg/SkSVGDefs.cpp b/svg/SkSVGDefs.cpp
new file mode 100644
index 00000000..3b9bc201
--- /dev/null
+++ b/svg/SkSVGDefs.cpp
@@ -0,0 +1,24 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGDefs.h"
+
+DEFINE_SVG_NO_INFO(Defs)
+
+bool SkSVGDefs::isDef() {
+ return true;
+}
+
+bool SkSVGDefs::isNotDef() {
+ return false;
+}
+
+void SkSVGDefs::translate(SkSVGParser& parser, bool defState) {
+ INHERITED::translate(parser, defState);
+}
diff --git a/svg/SkSVGDefs.h b/svg/SkSVGDefs.h
new file mode 100644
index 00000000..daa68940
--- /dev/null
+++ b/svg/SkSVGDefs.h
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGDefs_DEFINED
+#define SkSVGDefs_DEFINED
+
+#include "SkSVGGroup.h"
+
+class SkSVGDefs : public SkSVGGroup {
+ DECLARE_SVG_INFO(Defs);
+ virtual bool isDef();
+ virtual bool isNotDef();
+private:
+ typedef SkSVGGroup INHERITED;
+};
+
+#endif // SkSVGDefs_DEFINED
diff --git a/svg/SkSVGElements.cpp b/svg/SkSVGElements.cpp
new file mode 100644
index 00000000..a1bd1005
--- /dev/null
+++ b/svg/SkSVGElements.cpp
@@ -0,0 +1,86 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGElements.h"
+#include "SkSVGParser.h"
+
+SkSVGBase::~SkSVGBase() {
+}
+
+void SkSVGBase::addAttribute(SkSVGParser& parser, int attrIndex,
+ const char* attrValue, size_t attrLength) {
+ SkString* first = (SkString*) ((char*) this + sizeof(SkSVGElement));
+ first += attrIndex;
+ first->set(attrValue, attrLength);
+}
+
+
+SkSVGElement::SkSVGElement() : fParent(NULL), fIsDef(false), fIsNotDef(true) {
+}
+
+SkSVGElement::~SkSVGElement() {
+}
+
+SkSVGElement* SkSVGElement::getGradient() {
+ return NULL;
+}
+
+bool SkSVGElement::isGroupParent() {
+ SkSVGElement* parent = fParent;
+ while (parent) {
+ if (parent->getType() != SkSVGType_G)
+ return false;
+ parent = parent->fParent;
+ }
+ return true;
+}
+
+bool SkSVGElement::isDef() {
+ return isGroupParent() == false ? fParent->isDef() : fIsDef;
+}
+
+bool SkSVGElement::isFlushable() {
+ return true;
+}
+
+bool SkSVGElement::isGroup() {
+ return false;
+}
+
+bool SkSVGElement::isNotDef() {
+ return isGroupParent() == false ? fParent->isNotDef() : fIsNotDef;
+}
+
+bool SkSVGElement::onEndElement(SkSVGParser& parser) {
+ if (f_id.size() > 0)
+ parser.getIDs().set(f_id.c_str(), f_id.size(), this);
+ return false;
+}
+
+bool SkSVGElement::onStartElement(SkSVGElement* child) {
+ *fChildren.append() = child;
+ return false;
+}
+
+void SkSVGElement::translate(SkSVGParser& parser, bool) {
+ if (f_id.size() > 0)
+ SVG_ADD_ATTRIBUTE(id);
+}
+
+void SkSVGElement::setIsDef() {
+ fIsDef = isDef();
+}
+
+//void SkSVGElement::setIsNotDef() {
+// fIsNotDef = isNotDef();
+//}
+
+void SkSVGElement::write(SkSVGParser& , SkString& ) {
+ SkASSERT(0);
+}
diff --git a/svg/SkSVGElements.h b/svg/SkSVGElements.h
new file mode 100644
index 00000000..d00e4347
--- /dev/null
+++ b/svg/SkSVGElements.h
@@ -0,0 +1,73 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGElements_DEFINED
+#define SkSVGElements_DEFINED
+
+#include "SkSVGPaintState.h"
+#include "SkSVGTypes.h"
+#include "SkTDArray.h"
+
+class SkSVGParser;
+
+#define DECLARE_SVG_INFO(_type) \
+public: \
+ virtual ~SkSVG##_type(); \
+ static const SkSVGAttribute gAttributes[]; \
+ virtual int getAttributes(const SkSVGAttribute** attrPtr); \
+ virtual SkSVGTypes getType() const; \
+ virtual void translate(SkSVGParser& parser, bool defState); \
+ typedef SkSVG##_type BASE_CLASS
+
+#define DEFINE_SVG_INFO(_type) \
+ SkSVG##_type::~SkSVG##_type() {} \
+ int SkSVG##_type::getAttributes(const SkSVGAttribute** attrPtr) { \
+ *attrPtr = gAttributes; \
+ return SK_ARRAY_COUNT(gAttributes); \
+ } \
+ SkSVGTypes SkSVG##_type::getType() const { return SkSVGType_##_type; }
+
+#define DEFINE_SVG_NO_INFO(_type) \
+ SkSVG##_type::~SkSVG##_type() {} \
+ int SkSVG##_type::getAttributes(const SkSVGAttribute** ) { return 0; } \
+ SkSVGTypes SkSVG##_type::getType() const { return SkSVGType_##_type; }
+
+
+struct SkSVGTypeName {
+ const char* fName;
+ SkSVGTypes fType;
+};
+
+class SkSVGElement : public SkSVGBase {
+public:
+ SkSVGElement();
+ virtual ~SkSVGElement();
+ virtual SkSVGElement* getGradient();
+ virtual SkSVGTypes getType() const = 0;
+ virtual bool isDef();
+ virtual bool isFlushable();
+ virtual bool isGroup();
+ virtual bool isNotDef();
+ virtual bool onEndElement(SkSVGParser& parser);
+ virtual bool onStartElement(SkSVGElement* child);
+ void setIsDef();
+// void setIsNotDef();
+ virtual void translate(SkSVGParser& parser, bool defState);
+ virtual void write(SkSVGParser& , SkString& color);
+ SkString f_id;
+ SkSVGPaint fPaintState;
+ SkTDArray<SkSVGElement*> fChildren;
+ SkSVGElement* fParent;
+ bool fIsDef;
+ bool fIsNotDef;
+private:
+ bool isGroupParent();
+};
+
+#endif // SkSVGElements_DEFINED
diff --git a/svg/SkSVGEllipse.cpp b/svg/SkSVGEllipse.cpp
new file mode 100644
index 00000000..281e4e92
--- /dev/null
+++ b/svg/SkSVGEllipse.cpp
@@ -0,0 +1,47 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGEllipse.h"
+#include "SkSVGParser.h"
+#include "SkParse.h"
+#include <stdio.h>
+
+const SkSVGAttribute SkSVGEllipse::gAttributes[] = {
+ SVG_ATTRIBUTE(cx),
+ SVG_ATTRIBUTE(cy),
+ SVG_ATTRIBUTE(rx),
+ SVG_ATTRIBUTE(ry)
+};
+
+DEFINE_SVG_INFO(Ellipse)
+
+void SkSVGEllipse::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("oval");
+ INHERITED::translate(parser, defState);
+ SkScalar cx, cy, rx, ry;
+ SkParse::FindScalar(f_cx.c_str(), &cx);
+ SkParse::FindScalar(f_cy.c_str(), &cy);
+ SkParse::FindScalar(f_rx.c_str(), &rx);
+ SkParse::FindScalar(f_ry.c_str(), &ry);
+ SkScalar left, top, right, bottom;
+ left = cx - rx;
+ top = cy - ry;
+ right = cx + rx;
+ bottom = cy + ry;
+ char scratch[16];
+ sprintf(scratch, "%g", SkScalarToDouble(left));
+ parser._addAttribute("left", scratch);
+ sprintf(scratch, "%g", SkScalarToDouble(top));
+ parser._addAttribute("top", scratch);
+ sprintf(scratch, "%g", SkScalarToDouble(right));
+ parser._addAttribute("right", scratch);
+ sprintf(scratch, "%g", SkScalarToDouble(bottom));
+ parser._addAttribute("bottom", scratch);
+ parser._endElement();
+}
diff --git a/svg/SkSVGEllipse.h b/svg/SkSVGEllipse.h
new file mode 100644
index 00000000..c039c830
--- /dev/null
+++ b/svg/SkSVGEllipse.h
@@ -0,0 +1,25 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGEllipse_DEFINED
+#define SkSVGEllipse_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGEllipse : public SkSVGElement {
+ DECLARE_SVG_INFO(Ellipse);
+private:
+ SkString f_cx;
+ SkString f_cy;
+ SkString f_rx;
+ SkString f_ry;
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGEllipse_DEFINED
diff --git a/svg/SkSVGFeColorMatrix.cpp b/svg/SkSVGFeColorMatrix.cpp
new file mode 100644
index 00000000..4e2d32a1
--- /dev/null
+++ b/svg/SkSVGFeColorMatrix.cpp
@@ -0,0 +1,24 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGFeColorMatrix.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGFeColorMatrix::gAttributes[] = {
+ SVG_LITERAL_ATTRIBUTE(color-interpolation-filters, f_color_interpolation_filters),
+ SVG_ATTRIBUTE(result),
+ SVG_ATTRIBUTE(type),
+ SVG_ATTRIBUTE(values)
+};
+
+DEFINE_SVG_INFO(FeColorMatrix)
+
+void SkSVGFeColorMatrix::translate(SkSVGParser& parser, bool defState) {
+ INHERITED::translate(parser, defState);
+}
diff --git a/svg/SkSVGFeColorMatrix.h b/svg/SkSVGFeColorMatrix.h
new file mode 100644
index 00000000..389995ac
--- /dev/null
+++ b/svg/SkSVGFeColorMatrix.h
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGFeColorMatrix_DEFINED
+#define SkSVGFeColorMatrix_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGFeColorMatrix : public SkSVGElement {
+ DECLARE_SVG_INFO(FeColorMatrix);
+protected:
+ SkString f_color_interpolation_filters;
+ SkString f_result;
+ SkString f_type;
+ SkString f_values;
+private:
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGFeColorMatrix_DEFINED
diff --git a/svg/SkSVGFilter.cpp b/svg/SkSVGFilter.cpp
new file mode 100644
index 00000000..207f176b
--- /dev/null
+++ b/svg/SkSVGFilter.cpp
@@ -0,0 +1,25 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGFilter.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGFilter::gAttributes[] = {
+ SVG_ATTRIBUTE(filterUnits),
+ SVG_ATTRIBUTE(height),
+ SVG_ATTRIBUTE(width),
+ SVG_ATTRIBUTE(x),
+ SVG_ATTRIBUTE(y)
+};
+
+DEFINE_SVG_INFO(Filter)
+
+void SkSVGFilter::translate(SkSVGParser& parser, bool defState) {
+// INHERITED::translate(parser, defState);
+}
diff --git a/svg/SkSVGFilter.h b/svg/SkSVGFilter.h
new file mode 100644
index 00000000..f615bd06
--- /dev/null
+++ b/svg/SkSVGFilter.h
@@ -0,0 +1,27 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGFilter_DEFINED
+#define SkSVGFilter_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGFilter : public SkSVGElement {
+ DECLARE_SVG_INFO(Filter);
+protected:
+ SkString f_filterUnits;
+ SkString f_height;
+ SkString f_width;
+ SkString f_x;
+ SkString f_y;
+private:
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGFilter_DEFINEDRITED;
diff --git a/svg/SkSVGG.cpp b/svg/SkSVGG.cpp
new file mode 100644
index 00000000..21a7aa86
--- /dev/null
+++ b/svg/SkSVGG.cpp
@@ -0,0 +1,16 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGG.h"
+
+DEFINE_SVG_NO_INFO(G)
+
+void SkSVGG::translate(SkSVGParser& parser, bool defState) {
+ INHERITED::translate(parser, defState);
+}
diff --git a/svg/SkSVGG.h b/svg/SkSVGG.h
new file mode 100644
index 00000000..4fa27d29
--- /dev/null
+++ b/svg/SkSVGG.h
@@ -0,0 +1,21 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGG_DEFINED
+#define SkSVGG_DEFINED
+
+#include "SkSVGGroup.h"
+
+class SkSVGG : public SkSVGGroup {
+ DECLARE_SVG_INFO(G);
+private:
+ typedef SkSVGGroup INHERITED;
+};
+
+#endif // SkSVGG_DEFINED
diff --git a/svg/SkSVGGradient.cpp b/svg/SkSVGGradient.cpp
new file mode 100644
index 00000000..bbcca18f
--- /dev/null
+++ b/svg/SkSVGGradient.cpp
@@ -0,0 +1,114 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGGradient.h"
+#include "SkSVGParser.h"
+#include "SkSVGStop.h"
+
+SkSVGGradient::SkSVGGradient() {
+}
+
+SkSVGElement* SkSVGGradient::getGradient() {
+ return this;
+}
+
+bool SkSVGGradient::isDef() {
+ return true;
+}
+
+bool SkSVGGradient::isNotDef() {
+ return false;
+}
+
+void SkSVGGradient::translate(SkSVGParser& parser, bool defState) {
+ INHERITED::translate(parser, defState);
+ // !!! no support for 'objectBoundingBox' yet
+ bool first = true;
+ bool addedFirst = false;
+ bool addedLast = false;
+ SkString offsets("[");
+ SkString* lastOffset = NULL;
+ for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
+ SkASSERT((*ptr)->getType() == SkSVGType_Stop);
+ SkSVGStop* stop = (SkSVGStop*) *ptr;
+ if (first && stop->f_offset.equals("0") == false) {
+ addedFirst = true;
+ offsets.append("0,");
+ }
+ SkString* thisOffset = &stop->f_offset;
+ if (lastOffset && thisOffset->equals(*lastOffset)) {
+ if (thisOffset->equals("1")) {
+ offsets.remove(offsets.size() - 2, 2);
+ offsets.append(".999,");
+ } else {
+ SkASSERT(0); // !!! need to write this case
+ }
+ }
+ offsets.append(*thisOffset);
+ if (ptr == fChildren.end() - 1) { // last
+ if (stop->f_offset.equals("1") == false) {
+ offsets.append(",1");
+ addedLast = true;
+ }
+ } else
+ offsets.appendUnichar(',');
+ first = false;
+ lastOffset = thisOffset;
+ }
+ offsets.appendUnichar(']');
+ parser._addAttribute("offsets", offsets);
+ if (addedFirst)
+ parser.translate(*fChildren.begin(), defState);
+ for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++)
+ parser.translate(*ptr, defState);
+ if (addedLast)
+ parser.translate(*(fChildren.end() - 1), defState);
+}
+
+void SkSVGGradient::translateGradientUnits(SkString& units) {
+ // !!! no support for 'objectBoundingBox' yet
+ SkASSERT(strcmp(units.c_str(), "userSpaceOnUse") == 0);
+}
+
+void SkSVGGradient::write(SkSVGParser& parser, SkString& baseColor) {
+ if (baseColor.c_str()[0] != '#')
+ return;
+ SkSVGPaint* saveHead = parser.fHead;
+ parser.fHead = &fPaintState;
+ parser.fSuppressPaint = true;
+ SkString originalID(f_id);
+ f_id.set("mask"); // write out gradient named given name + color (less initial #)
+ f_id.append(baseColor.c_str() + 1);
+ SkString originalColors;
+ for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
+ SkSVGStop* colorElement = (SkSVGStop*) *ptr;
+ SkString& color = colorElement->fPaintState.f_stopColor;
+ originalColors.append(color);
+ originalColors.appendUnichar(',');
+ SkASSERT(color.c_str()[0] == '#');
+ SkString replacement;
+ replacement.set("0x");
+ replacement.append(color.c_str() + 1, 2); // add stop colors using given color, turning existing stop color into alpha
+ SkASSERT(baseColor.c_str()[0] == '#');
+ SkASSERT(baseColor.size() == 7);
+ replacement.append(baseColor.c_str() + 1);
+ color.set(replacement);
+ }
+ translate(parser, true);
+ const char* originalPtr = originalColors.c_str(); // restore original gradient values
+ for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
+ SkSVGStop* color = (SkSVGStop*) *ptr;
+ const char* originalEnd = strchr(originalPtr, ',');
+ color->fPaintState.f_stopColor.set(originalPtr, originalEnd - originalPtr);
+ originalPtr = originalEnd + 1;
+ }
+ f_id.set(originalID);
+ parser.fSuppressPaint = false;
+ parser.fHead = saveHead;
+}
diff --git a/svg/SkSVGGradient.h b/svg/SkSVGGradient.h
new file mode 100644
index 00000000..286ff185
--- /dev/null
+++ b/svg/SkSVGGradient.h
@@ -0,0 +1,29 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGGradient_DEFINED
+#define SkSVGGradient_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGGradient : public SkSVGElement {
+public:
+ SkSVGGradient();
+ virtual SkSVGElement* getGradient();
+ virtual bool isDef();
+ virtual bool isNotDef();
+ virtual void write(SkSVGParser& , SkString& color);
+protected:
+ void translate(SkSVGParser& , bool defState);
+ void translateGradientUnits(SkString& units);
+private:
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGGradient_DEFINED
diff --git a/svg/SkSVGGroup.cpp b/svg/SkSVGGroup.cpp
new file mode 100644
index 00000000..420179d8
--- /dev/null
+++ b/svg/SkSVGGroup.cpp
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGGroup.h"
+#include "SkSVGParser.h"
+
+SkSVGGroup::SkSVGGroup() {
+ fIsNotDef = false;
+}
+
+SkSVGElement* SkSVGGroup::getGradient() {
+ for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
+ SkSVGElement* result = (*ptr)->getGradient();
+ if (result != NULL)
+ return result;
+ }
+ return NULL;
+}
+
+bool SkSVGGroup::isDef() {
+ return fParent ? fParent->isDef() : false;
+}
+
+bool SkSVGGroup::isFlushable() {
+ return false;
+}
+
+bool SkSVGGroup::isGroup() {
+ return true;
+}
+
+bool SkSVGGroup::isNotDef() {
+ return fParent ? fParent->isNotDef() : false;
+}
+
+void SkSVGGroup::translate(SkSVGParser& parser, bool defState) {
+ for (SkSVGElement** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++)
+ parser.translate(*ptr, defState);
+}
diff --git a/svg/SkSVGGroup.h b/svg/SkSVGGroup.h
new file mode 100644
index 00000000..f579a980
--- /dev/null
+++ b/svg/SkSVGGroup.h
@@ -0,0 +1,28 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGGroup_DEFINED
+#define SkSVGGroup_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGGroup : public SkSVGElement {
+public:
+ SkSVGGroup();
+ virtual SkSVGElement* getGradient();
+ virtual bool isDef();
+ virtual bool isFlushable();
+ virtual bool isGroup();
+ virtual bool isNotDef();
+ void translate(SkSVGParser& , bool defState);
+private:
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGGroup_DEFINED
diff --git a/svg/SkSVGImage.cpp b/svg/SkSVGImage.cpp
new file mode 100644
index 00000000..97b8df86
--- /dev/null
+++ b/svg/SkSVGImage.cpp
@@ -0,0 +1,44 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGImage.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGImage::gAttributes[] = {
+ SVG_ATTRIBUTE(height),
+ SVG_ATTRIBUTE(width),
+ SVG_ATTRIBUTE(x),
+ SVG_LITERAL_ATTRIBUTE(xlink:href, f_xlink_href),
+ SVG_ATTRIBUTE(y)
+};
+
+DEFINE_SVG_INFO(Image)
+
+void SkSVGImage::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("image");
+ INHERITED::translate(parser, defState);
+ SVG_ADD_ATTRIBUTE(x);
+ SVG_ADD_ATTRIBUTE(y);
+// SVG_ADD_ATTRIBUTE(width);
+// SVG_ADD_ATTRIBUTE(height);
+ translateImage(parser);
+ parser._endElement();
+}
+
+void SkSVGImage::translateImage(SkSVGParser& parser) {
+ SkASSERT(f_xlink_href.size() > 0);
+ const char* data = f_xlink_href.c_str();
+ SkASSERT(strncmp(data, "data:image/", 11) == 0);
+ data += 11;
+ SkASSERT(strncmp(data, "png;", 4) == 0 || strncmp(data, "jpeg;", 5) == 0);
+ data = strchr(data, ';');
+ SkASSERT(strncmp(data, ";base64,", 8) == 0);
+ data += 8;
+ parser._addAttribute("base64", data);
+}
diff --git a/svg/SkSVGImage.h b/svg/SkSVGImage.h
new file mode 100644
index 00000000..b63beef5
--- /dev/null
+++ b/svg/SkSVGImage.h
@@ -0,0 +1,28 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGImage_DEFINED
+#define SkSVGImage_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGImage : public SkSVGElement {
+public:
+ DECLARE_SVG_INFO(Image);
+private:
+ void translateImage(SkSVGParser& parser);
+ SkString f_height;
+ SkString f_width;
+ SkString f_x;
+ SkString f_xlink_href;
+ SkString f_y;
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGImage_DEFINED
diff --git a/svg/SkSVGLine.cpp b/svg/SkSVGLine.cpp
new file mode 100644
index 00000000..9158c99b
--- /dev/null
+++ b/svg/SkSVGLine.cpp
@@ -0,0 +1,30 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGLine.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGLine::gAttributes[] = {
+ SVG_ATTRIBUTE(x1),
+ SVG_ATTRIBUTE(x2),
+ SVG_ATTRIBUTE(y1),
+ SVG_ATTRIBUTE(y2)
+};
+
+DEFINE_SVG_INFO(Line)
+
+void SkSVGLine::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("line");
+ INHERITED::translate(parser, defState);
+ SVG_ADD_ATTRIBUTE(x1);
+ SVG_ADD_ATTRIBUTE(y1);
+ SVG_ADD_ATTRIBUTE(x2);
+ SVG_ADD_ATTRIBUTE(y2);
+ parser._endElement();
+}
diff --git a/svg/SkSVGLine.h b/svg/SkSVGLine.h
new file mode 100644
index 00000000..3e437e01
--- /dev/null
+++ b/svg/SkSVGLine.h
@@ -0,0 +1,25 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGLine_DEFINED
+#define SkSVGLine_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGLine : public SkSVGElement {
+ DECLARE_SVG_INFO(Line);
+private:
+ SkString f_x1;
+ SkString f_x2;
+ SkString f_y1;
+ SkString f_y2;
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGLine_DEFINED
diff --git a/svg/SkSVGLinearGradient.cpp b/svg/SkSVGLinearGradient.cpp
new file mode 100644
index 00000000..f89ee534
--- /dev/null
+++ b/svg/SkSVGLinearGradient.cpp
@@ -0,0 +1,44 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGLinearGradient.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGLinearGradient::gAttributes[] = {
+ SVG_ATTRIBUTE(gradientTransform),
+ SVG_ATTRIBUTE(gradientUnits),
+ SVG_ATTRIBUTE(x1),
+ SVG_ATTRIBUTE(x2),
+ SVG_ATTRIBUTE(y1),
+ SVG_ATTRIBUTE(y2)
+};
+
+DEFINE_SVG_INFO(LinearGradient)
+
+void SkSVGLinearGradient::translate(SkSVGParser& parser, bool defState) {
+ if (fMatrixID.size() == 0)
+ parser.translateMatrix(f_gradientTransform, &fMatrixID);
+ parser._startElement("linearGradient");
+ if (fMatrixID.size() > 0)
+ parser._addAttribute("matrix", fMatrixID);
+ INHERITED::translateGradientUnits(f_gradientUnits);
+ SkString points;
+ points.appendUnichar('[');
+ points.append(f_x1);
+ points.appendUnichar(',');
+ points.append(f_y1);
+ points.appendUnichar(',');
+ points.append(f_x2);
+ points.appendUnichar(',');
+ points.append(f_y2);
+ points.appendUnichar(']');
+ parser._addAttribute("points", points.c_str());
+ INHERITED::translate(parser, defState);
+ parser._endElement();
+}
diff --git a/svg/SkSVGLinearGradient.h b/svg/SkSVGLinearGradient.h
new file mode 100644
index 00000000..8eda0650
--- /dev/null
+++ b/svg/SkSVGLinearGradient.h
@@ -0,0 +1,28 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGLinearGradient_DEFINED
+#define SkSVGLinearGradient_DEFINED
+
+#include "SkSVGGradient.h"
+
+class SkSVGLinearGradient : public SkSVGGradient {
+ DECLARE_SVG_INFO(LinearGradient);
+private:
+ SkString f_gradientTransform;
+ SkString f_gradientUnits;
+ SkString f_x1;
+ SkString f_x2;
+ SkString f_y1;
+ SkString f_y2;
+ SkString fMatrixID;
+ typedef SkSVGGradient INHERITED;
+};
+
+#endif // SkSVGLinearGradient_DEFINED
diff --git a/svg/SkSVGMask.cpp b/svg/SkSVGMask.cpp
new file mode 100644
index 00000000..7526d18e
--- /dev/null
+++ b/svg/SkSVGMask.cpp
@@ -0,0 +1,33 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGMask.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGMask::gAttributes[] = {
+ SVG_ATTRIBUTE(height),
+ SVG_ATTRIBUTE(maskUnits),
+ SVG_ATTRIBUTE(width),
+ SVG_ATTRIBUTE(x),
+ SVG_ATTRIBUTE(y)
+};
+
+DEFINE_SVG_INFO(Mask)
+
+bool SkSVGMask::isDef() {
+ return false;
+}
+
+bool SkSVGMask::isNotDef() {
+ return false;
+}
+
+void SkSVGMask::translate(SkSVGParser& parser, bool defState) {
+ INHERITED::translate(parser, defState);
+}
diff --git a/svg/SkSVGMask.h b/svg/SkSVGMask.h
new file mode 100644
index 00000000..2e1fd501
--- /dev/null
+++ b/svg/SkSVGMask.h
@@ -0,0 +1,29 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * 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 "SkSVGGroup.h"
+
+class SkSVGMask : public SkSVGGroup {
+ DECLARE_SVG_INFO(Mask);
+ virtual bool isDef();
+ virtual bool isNotDef();
+protected:
+ SkString f_height;
+ SkString f_maskUnits;
+ SkString f_width;
+ SkString f_x;
+ SkString f_y;
+private:
+ typedef SkSVGGroup INHERITED;
+};
+
+#endif // SkSVGMask_DEFINED
diff --git a/svg/SkSVGMetadata.cpp b/svg/SkSVGMetadata.cpp
new file mode 100644
index 00000000..0f8850ec
--- /dev/null
+++ b/svg/SkSVGMetadata.cpp
@@ -0,0 +1,24 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGMetadata.h"
+#include "SkSVGParser.h"
+
+DEFINE_SVG_NO_INFO(Metadata)
+
+bool SkSVGMetadata::isDef() {
+ return false;
+}
+
+bool SkSVGMetadata::isNotDef() {
+ return false;
+}
+
+void SkSVGMetadata::translate(SkSVGParser& parser, bool defState) {
+}
diff --git a/svg/SkSVGMetadata.h b/svg/SkSVGMetadata.h
new file mode 100644
index 00000000..2dcb3a2c
--- /dev/null
+++ b/svg/SkSVGMetadata.h
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGMetadata_DEFINED
+#define SkSVGMetadata_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGMetadata : public SkSVGElement {
+ DECLARE_SVG_INFO(Metadata);
+ virtual bool isDef();
+ virtual bool isNotDef();
+private:
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGMetadata_DEFINED
diff --git a/svg/SkSVGPaintState.cpp b/svg/SkSVGPaintState.cpp
new file mode 100644
index 00000000..5db624d0
--- /dev/null
+++ b/svg/SkSVGPaintState.cpp
@@ -0,0 +1,454 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGPaintState.h"
+#include "SkSVGElements.h"
+#include "SkSVGParser.h"
+#include "SkParse.h"
+
+SkSVGAttribute SkSVGPaint::gAttributes[] = {
+ SVG_LITERAL_ATTRIBUTE(clip-path, f_clipPath),
+ SVG_LITERAL_ATTRIBUTE(clip-rule, f_clipRule),
+ SVG_LITERAL_ATTRIBUTE(enable-background, f_enableBackground),
+ SVG_ATTRIBUTE(fill),
+ SVG_LITERAL_ATTRIBUTE(fill-rule, f_fillRule),
+ SVG_ATTRIBUTE(filter),
+ SVG_LITERAL_ATTRIBUTE(font-family, f_fontFamily),
+ SVG_LITERAL_ATTRIBUTE(font-size, f_fontSize),
+ SVG_LITERAL_ATTRIBUTE(letter-spacing, f_letterSpacing),
+ SVG_ATTRIBUTE(mask),
+ SVG_ATTRIBUTE(opacity),
+ SVG_LITERAL_ATTRIBUTE(stop-color, f_stopColor),
+ SVG_LITERAL_ATTRIBUTE(stop-opacity, f_stopOpacity),
+ SVG_ATTRIBUTE(stroke),
+ SVG_LITERAL_ATTRIBUTE(stroke-dasharray, f_strokeDasharray),
+ SVG_LITERAL_ATTRIBUTE(stroke-linecap, f_strokeLinecap),
+ SVG_LITERAL_ATTRIBUTE(stroke-linejoin, f_strokeLinejoin),
+ SVG_LITERAL_ATTRIBUTE(stroke-miterlimit, f_strokeMiterlimit),
+ SVG_LITERAL_ATTRIBUTE(stroke-width, f_strokeWidth),
+ SVG_ATTRIBUTE(style),
+ SVG_ATTRIBUTE(transform)
+};
+
+const int SkSVGPaint::kAttributesSize = SK_ARRAY_COUNT(SkSVGPaint::gAttributes);
+
+SkSVGPaint::SkSVGPaint() : fNext(NULL) {
+}
+
+SkString* SkSVGPaint::operator[](int index) {
+ SkASSERT(index >= 0);
+ SkASSERT(index < &fTerminal - &fInitial);
+ SkASSERT(&fTerminal - &fInitial == kTerminal - kInitial);
+ SkString* result = &fInitial + index + 1;
+ return result;
+}
+
+void SkSVGPaint::addAttribute(SkSVGParser& parser, int attrIndex,
+ const char* attrValue, size_t attrLength) {
+ SkString* attr = (*this)[attrIndex];
+ switch(attrIndex) {
+ case kClipPath:
+ case kClipRule:
+ case kEnableBackground:
+ case kFill:
+ case kFillRule:
+ case kFilter:
+ case kFontFamily:
+ case kFontSize:
+ case kLetterSpacing:
+ case kMask:
+ case kOpacity:
+ case kStopColor:
+ case kStopOpacity:
+ case kStroke:
+ case kStroke_Dasharray:
+ case kStroke_Linecap:
+ case kStroke_Linejoin:
+ case kStroke_Miterlimit:
+ case kStroke_Width:
+ case kTransform:
+ attr->set(attrValue, attrLength);
+ return;
+ case kStyle: {
+ // iterate through colon / semi-colon delimited pairs
+ int pairs = SkParse::Count(attrValue, ';');
+ const char* attrEnd = attrValue + attrLength;
+ do {
+ const char* end = strchr(attrValue, ';');
+ if (end == NULL)
+ end = attrEnd;
+ const char* delimiter = strchr(attrValue, ':');
+ SkASSERT(delimiter != 0 && delimiter < end);
+ int index = parser.findAttribute(this, attrValue, (int) (delimiter - attrValue), true);
+ SkASSERT(index >= 0);
+ delimiter++;
+ addAttribute(parser, index, delimiter, (int) (end - delimiter));
+ attrValue = end + 1;
+ } while (--pairs);
+ return;
+ }
+ default:
+ SkASSERT(0);
+ }
+}
+
+bool SkSVGPaint::flush(SkSVGParser& parser, bool isFlushable, bool isDef) {
+ SkSVGPaint current;
+ SkSVGPaint* walking = parser.fHead;
+ int index;
+ while (walking != NULL) {
+ for (index = kInitial + 1; index < kTerminal; index++) {
+ SkString* lastAttr = (*walking)[index];
+ if (lastAttr->size() == 0)
+ continue;
+ if (current[index]->size() > 0)
+ continue;
+ current[index]->set(*lastAttr);
+ }
+ walking = walking->fNext;
+ }
+ bool paintChanged = false;
+ SkSVGPaint& lastState = parser.fLastFlush;
+ if (isFlushable == false) {
+ if (isDef == true) {
+ if (current.f_mask.size() > 0 && current.f_mask.equals(lastState.f_mask) == false) {
+ SkSVGElement* found;
+ const char* idStart = strchr(current.f_mask.c_str(), '#');
+ SkASSERT(idStart);
+ SkString id(idStart + 1, strlen(idStart) - 2);
+ bool itsFound = parser.fIDs.find(id.c_str(), &found);
+ SkASSERT(itsFound);
+ SkSVGElement* gradient = found->getGradient();
+ if (gradient) {
+ gradient->write(parser, current.f_fill);
+ gradient->write(parser, current.f_stroke);
+ }
+ }
+ }
+ goto setLast;
+ }
+ {
+ bool changed[kTerminal];
+ memset(changed, 0, sizeof(changed));
+ for (index = kInitial + 1; index < kTerminal; index++) {
+ if (index == kTransform || index == kClipPath || index == kStopColor || index == kStopOpacity ||
+ index == kClipRule || index == kFillRule)
+ continue;
+ SkString* lastAttr = lastState[index];
+ SkString* currentAttr = current[index];
+ paintChanged |= changed[index] = lastAttr->equals(*currentAttr) == false;
+ }
+ if (paintChanged) {
+ if (current.f_mask.size() > 0) {
+ if (current.f_fill.equals("none") == false && strncmp(current.f_fill.c_str(), "url(#", 5) != 0) {
+ SkASSERT(current.f_fill.c_str()[0] == '#');
+ SkString replacement("url(#mask");
+ replacement.append(current.f_fill.c_str() + 1);
+ replacement.appendUnichar(')');
+ current.f_fill.set(replacement);
+ }
+ if (current.f_stroke.equals("none") == false && strncmp(current.f_stroke.c_str(), "url(#", 5) != 0) {
+ SkASSERT(current.f_stroke.c_str()[0] == '#');
+ SkString replacement("url(#mask");
+ replacement.append(current.f_stroke.c_str() + 1);
+ replacement.appendUnichar(')');
+ current.f_stroke.set(replacement);
+ }
+ }
+ if (current.f_fill.equals("none") && current.f_stroke.equals("none"))
+ current.f_opacity.set("0");
+ if (parser.fSuppressPaint == false) {
+ parser._startElement("paint");
+ bool success = writeChangedAttributes(parser, current, changed);
+ if (success == false)
+ return paintChanged;
+ success = writeChangedElements(parser, current, changed);
+ if (success == false)
+ return paintChanged;
+ parser._endElement(); // paint
+ }
+ }
+ }
+setLast:
+ for (index = kInitial + 1; index < kTerminal; index++) {
+ SkString* lastAttr = lastState[index];
+ SkString* currentAttr = current[index];
+ lastAttr->set(*currentAttr);
+ }
+ return paintChanged;
+}
+
+int SkSVGPaint::getAttributes(const SkSVGAttribute** attrPtr) {
+ *attrPtr = gAttributes;
+ return kAttributesSize;
+}
+
+void SkSVGPaint::setSave(SkSVGParser& parser) {
+ SkTDArray<SkString*> clips;
+ SkSVGPaint* walking = parser.fHead;
+ int index;
+ SkMatrix sum;
+ sum.reset();
+ while (walking != NULL) {
+ for (index = kInitial + 1; index < kTerminal; index++) {
+ SkString* lastAttr = (*walking)[index];
+ if (lastAttr->size() == 0)
+ continue;
+ if (index == kTransform) {
+ const char* str = lastAttr->c_str();
+ SkASSERT(strncmp(str, "matrix(", 7) == 0);
+ str += 6;
+ const char* strEnd = strrchr(str, ')');
+ SkASSERT(strEnd != NULL);
+ SkString mat(str, strEnd - str);
+ SkSVGParser::ConvertToArray(mat);
+ SkScalar values[6];
+ SkParse::FindScalars(mat.c_str() + 1, values, 6);
+ SkMatrix matrix;
+ matrix.reset();
+ matrix.setScaleX(values[0]);
+ matrix.setSkewY(values[1]);
+ matrix.setSkewX(values[2]);
+ matrix.setScaleY(values[3]);
+ matrix.setTranslateX(values[4]);
+ matrix.setTranslateY(values[5]);
+ sum.setConcat(matrix, sum);
+ continue;
+ }
+ if ( index == kClipPath)
+ *clips.insert(0) = lastAttr;
+ }
+ walking = walking->fNext;
+ }
+ if ((sum == parser.fLastTransform) == false) {
+ SkMatrix inverse;
+ bool success = parser.fLastTransform.invert(&inverse);
+ SkASSERT(success == true);
+ SkMatrix output;
+ output.setConcat(inverse, sum);
+ parser.fLastTransform = sum;
+ SkString outputStr;
+ outputStr.appendUnichar('[');
+ outputStr.appendScalar(output.getScaleX());
+ outputStr.appendUnichar(',');
+ outputStr.appendScalar(output.getSkewX());
+ outputStr.appendUnichar(',');
+ outputStr.appendScalar(output.getTranslateX());
+ outputStr.appendUnichar(',');
+ outputStr.appendScalar(output.getSkewY());
+ outputStr.appendUnichar(',');
+ outputStr.appendScalar(output.getScaleY());
+ outputStr.appendUnichar(',');
+ outputStr.appendScalar(output.getTranslateY());
+ outputStr.appendUnichar(',');
+ outputStr.appendScalar(output.getPerspX());
+ outputStr.appendUnichar(',');
+ outputStr.appendScalar(output.getPerspY());
+ outputStr.append(",1]");
+ parser._startElement("matrix");
+ parser._addAttributeLen("matrix", outputStr.c_str(), outputStr.size());
+ parser._endElement();
+ }
+#if 0 // incomplete
+ if (parser.fTransformClips.size() > 0) {
+ // need to reset the clip when the 'g' scope is ended
+ parser._startElement("add");
+ const char* start = strchr(current->f_clipPath.c_str(), '#') + 1;
+ SkASSERT(start);
+ parser._addAttributeLen("use", start, strlen(start) - 1);
+ parser._endElement(); // clip
+ }
+#endif
+}
+
+bool SkSVGPaint::writeChangedAttributes(SkSVGParser& parser,
+ SkSVGPaint& current, bool* changed) {
+ SkSVGPaint& lastState = parser.fLastFlush;
+ for (int index = kInitial + 1; index < kTerminal; index++) {
+ if (changed[index] == false)
+ continue;
+ SkString* topAttr = current[index];
+ size_t attrLength = topAttr->size();
+ if (attrLength == 0)
+ continue;
+ const char* attrValue = topAttr->c_str();
+ SkString* lastAttr = lastState[index];
+ switch(index) {
+ case kClipPath:
+ case kClipRule:
+ case kEnableBackground:
+ break;
+ case kFill:
+ if (topAttr->equals("none") == false && lastAttr->equals("none") == true)
+ parser._addAttribute("stroke", "false");
+ goto fillStrokeAttrCommon;
+ case kFillRule:
+ case kFilter:
+ case kFontFamily:
+ break;
+ case kFontSize:
+ parser._addAttributeLen("textSize", attrValue, attrLength);
+ break;
+ case kLetterSpacing:
+ parser._addAttributeLen("textTracking", attrValue, attrLength);
+ break;
+ case kMask:
+ break;
+ case kOpacity:
+ break;
+ case kStopColor:
+ break;
+ case kStopOpacity:
+ break;
+ case kStroke:
+ if (topAttr->equals("none") == false && lastAttr->equals("none") == true)
+ parser._addAttribute("stroke", "true");
+fillStrokeAttrCommon:
+ if (strncmp(attrValue, "url(", 4) == 0) {
+ SkASSERT(attrValue[4] == '#');
+ const char* idStart = attrValue + 5;
+ const char* idEnd = strrchr(attrValue, ')');
+ SkASSERT(idStart < idEnd);
+ SkString id(idStart, idEnd - idStart);
+ SkSVGElement* found;
+ if (strncmp(id.c_str(), "mask", 4) != 0) {
+ bool itsFound = parser.fIDs.find(id.c_str(), &found);
+ SkASSERT(itsFound);
+ SkASSERT(found->getType() == SkSVGType_LinearGradient ||
+ found->getType() == SkSVGType_RadialGradient);
+ }
+ parser._addAttribute("shader", id.c_str());
+ }
+ break;
+ case kStroke_Dasharray:
+ break;
+ case kStroke_Linecap:
+ parser._addAttributeLen("strokeCap", attrValue, attrLength);
+ break;
+ case kStroke_Linejoin:
+ parser._addAttributeLen("strokeJoin", attrValue, attrLength);
+ break;
+ case kStroke_Miterlimit:
+ parser._addAttributeLen("strokeMiter", attrValue, attrLength);
+ break;
+ case kStroke_Width:
+ parser._addAttributeLen("strokeWidth", attrValue, attrLength);
+ case kStyle:
+ case kTransform:
+ break;
+ default:
+ SkASSERT(0);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool SkSVGPaint::writeChangedElements(SkSVGParser& parser,
+ SkSVGPaint& current, bool* changed) {
+ SkSVGPaint& lastState = parser.fLastFlush;
+ for (int index = kInitial + 1; index < kTerminal; index++) {
+ SkString* topAttr = current[index];
+ size_t attrLength = topAttr->size();
+ if (attrLength == 0)
+ continue;
+ const char* attrValue = topAttr->c_str();
+ SkString* lastAttr = lastState[index];
+ switch(index) {
+ case kClipPath:
+ case kClipRule:
+ // !!! need to add this outside of paint
+ break;
+ case kEnableBackground:
+ // !!! don't know what to do with this
+ break;
+ case kFill:
+ goto addColor;
+ case kFillRule:
+ case kFilter:
+ break;
+ case kFontFamily:
+ parser._startElement("typeface");
+ parser._addAttributeLen("fontName", attrValue, attrLength);
+ parser._endElement(); // typeface
+ break;
+ case kFontSize:
+ case kLetterSpacing:
+ break;
+ case kMask:
+ case kOpacity:
+ if (changed[kStroke] == false && changed[kFill] == false) {
+ parser._startElement("color");
+ SkString& opacity = current.f_opacity;
+ parser._addAttributeLen("color", parser.fLastColor.c_str(), parser.fLastColor.size());
+ parser._addAttributeLen("alpha", opacity.c_str(), opacity.size());
+ parser._endElement(); // color
+ }
+ break;
+ case kStopColor:
+ break;
+ case kStopOpacity:
+ break;
+ case kStroke:
+addColor:
+ if (strncmp(lastAttr->c_str(), "url(", 4) == 0 && strncmp(attrValue, "url(", 4) != 0) {
+ parser._startElement("shader");
+ parser._endElement();
+ }
+ if (topAttr->equals(*lastAttr))
+ continue;
+ {
+ bool urlRef = strncmp(attrValue, "url(", 4) == 0;
+ bool colorNone = strcmp(attrValue, "none") == 0;
+ bool lastEqual = parser.fLastColor.equals(attrValue, attrLength);
+ bool newColor = urlRef == false && colorNone == false && lastEqual == false;
+ if (newColor || changed[kOpacity]) {
+ parser._startElement("color");
+ if (newColor || changed[kOpacity]) {
+ parser._addAttributeLen("color", attrValue, attrLength);
+ parser.fLastColor.set(attrValue, attrLength);
+ }
+ if (changed[kOpacity]) {
+ SkString& opacity = current.f_opacity;
+ parser._addAttributeLen("alpha", opacity.c_str(), opacity.size());
+ }
+ parser._endElement(); // color
+ }
+ }
+ break;
+ case kStroke_Dasharray:
+ parser._startElement("dash");
+ SkSVGParser::ConvertToArray(*topAttr);
+ parser._addAttribute("intervals", topAttr->c_str());
+ parser._endElement(); // dash
+ break;
+ case kStroke_Linecap:
+ case kStroke_Linejoin:
+ case kStroke_Miterlimit:
+ case kStroke_Width:
+ case kStyle:
+ case kTransform:
+ break;
+ default:
+ SkASSERT(0);
+ return false;
+ }
+ }
+ return true;
+}
+
+void SkSVGPaint::Push(SkSVGPaint** head, SkSVGPaint* newRecord) {
+ newRecord->fNext = *head;
+ *head = newRecord;
+}
+
+void SkSVGPaint::Pop(SkSVGPaint** head) {
+ SkSVGPaint* next = (*head)->fNext;
+ *head = next;
+}
diff --git a/svg/SkSVGParser.cpp b/svg/SkSVGParser.cpp
new file mode 100644
index 00000000..74ea0236
--- /dev/null
+++ b/svg/SkSVGParser.cpp
@@ -0,0 +1,441 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGParser.h"
+#include "SkSVGCircle.h"
+#include "SkSVGClipPath.h"
+#include "SkSVGDefs.h"
+#include "SkSVGEllipse.h"
+#include "SkSVGFeColorMatrix.h"
+#include "SkSVGFilter.h"
+#include "SkSVGG.h"
+#include "SkSVGImage.h"
+#include "SkSVGLine.h"
+#include "SkSVGLinearGradient.h"
+#include "SkSVGMask.h"
+#include "SkSVGMetadata.h"
+#include "SkSVGPath.h"
+#include "SkSVGPolygon.h"
+#include "SkSVGPolyline.h"
+#include "SkSVGRadialGradient.h"
+#include "SkSVGRect.h"
+#include "SkSVGSVG.h"
+#include "SkSVGStop.h"
+#include "SkSVGSymbol.h"
+#include "SkSVGText.h"
+#include "SkSVGUse.h"
+#include "SkTSearch.h"
+#include <stdio.h>
+
+static int gGeneratedMatrixID = 0;
+
+SkSVGParser::SkSVGParser(SkXMLParserError* errHandler) :
+ SkXMLParser(errHandler),
+ fHead(&fEmptyPaint), fIDs(256),
+ fXMLWriter(&fStream), fCurrElement(NULL), fInSVG(false), fSuppressPaint(false) {
+ fLastTransform.reset();
+ fEmptyPaint.f_fill.set("black");
+ fEmptyPaint.f_stroke.set("none");
+ fEmptyPaint.f_strokeMiterlimit.set("4");
+ fEmptyPaint.f_fillRule.set("winding");
+ fEmptyPaint.f_opacity.set("1");
+ fEmptyPaint.fNext = NULL;
+ for (int index = SkSVGPaint::kInitial + 1; index < SkSVGPaint::kTerminal; index++) {
+ SkString* initial = fEmptyPaint[index];
+ if (initial->size() == 0)
+ continue;
+ fLastFlush[index]->set(*initial);
+ }
+}
+
+SkSVGParser::~SkSVGParser() {
+}
+
+void SkSVGParser::Delete(SkTDArray<SkSVGElement*>& fChildren) {
+ SkSVGElement** ptr;
+ for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
+ Delete((*ptr)->fChildren);
+ delete *ptr;
+ }
+}
+
+int SkSVGParser::findAttribute(SkSVGBase* element, const char* attrValue,
+ size_t len, bool isPaint) {
+ const SkSVGAttribute* attributes;
+ size_t count = element->getAttributes(&attributes);
+ size_t result = 0;
+ while (result < count) {
+ if (strncmp(attributes->fName, attrValue, len) == 0 && strlen(attributes->fName) == len) {
+ SkASSERT(result == (attributes->fOffset -
+ (isPaint ? sizeof(SkString) : sizeof(SkSVGElement))) / sizeof(SkString));
+ return result;
+ }
+ attributes++;
+ result++;
+ }
+ return -1;
+}
+
+#if 0
+const char* SkSVGParser::getFinal() {
+ _startElement("screenplay");
+ // generate defs
+ SkSVGElement** ptr;
+ for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
+ SkSVGElement* element = *ptr;
+ translate(element, true);
+ }
+ // generate onLoad
+ _startElement("event");
+ _addAttribute("kind", "onLoad");
+ _startElement("paint");
+ _addAttribute("antiAlias", "true");
+ _endElement();
+ for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
+ SkSVGElement* element = *ptr;
+ translate(element, false);
+ }
+ _endElement(); // event
+ _endElement(); // screenplay
+ Delete(fChildren);
+ fStream.write("", 1);
+ return fStream.getStream();
+}
+#endif
+
+SkString& SkSVGParser::getPaintLast(SkSVGPaint::Field field) {
+ SkSVGPaint* state = fHead;
+ do {
+ SkString* attr = (*state)[field];
+ SkASSERT(attr);
+ if (attr->size() > 0)
+ return *attr;
+ state = state->fNext;
+ } while (state);
+ SkASSERT(0);
+ SkASSERT(fEmptyPaint[field]);
+ return *fEmptyPaint[field];
+}
+
+bool SkSVGParser::isStrokeAndFill( SkSVGPaint** strokeState, SkSVGPaint** fillState) {
+ SkSVGPaint* walking = fHead;
+ bool stroke = false;
+ bool fill = false;
+ bool strokeSet = false;
+ bool fillSet = false;
+ while (walking != NULL) {
+ if (strokeSet == false && walking->f_stroke.size() > 0) {
+ stroke = walking->f_stroke.equals("none") == false;
+ *strokeState = walking;
+ strokeSet = true;
+ }
+ if (fillSet == false && walking->f_fill.size() > 0) {
+ fill = walking->f_fill.equals("none") == false;
+ *fillState = walking;
+ fillSet = true;
+ }
+ walking = walking->fNext;
+ }
+ return stroke && fill;
+}
+
+bool SkSVGParser::onAddAttribute(const char name[], const char value[]) {
+ return onAddAttributeLen(name, value, strlen(value));
+}
+
+bool SkSVGParser::onAddAttributeLen(const char name[], const char value[], size_t len) {
+ if (fCurrElement == NULL) // this signals we should ignore attributes for this element
+ return true;
+ if (fCurrElement->fIsDef == false && fCurrElement->fIsNotDef == false)
+ return false; // also an ignored element
+ size_t nameLen = strlen(name);
+ int attrIndex = findAttribute(fCurrElement, name, nameLen, false);
+ if (attrIndex == -1) {
+ attrIndex = findAttribute(&fCurrElement->fPaintState, name, nameLen, true);
+ if (attrIndex >= 0) {
+ fCurrElement->fPaintState.addAttribute(*this, attrIndex, value, len);
+ return false;
+ }
+ if (nameLen == 2 && strncmp("id", name, nameLen) == 0) {
+ fCurrElement->f_id.set(value, len);
+ return false;
+ }
+ if (strchr(name, ':') != 0) // part of a different namespace
+ return false;
+ }
+ SkASSERT(attrIndex >= 0);
+ fCurrElement->addAttribute(*this, attrIndex, value, len);
+ return false;
+}
+
+bool SkSVGParser::onEndElement(const char elem[]) {
+ int parentIndex = fParents.count() - 1;
+ if (parentIndex >= 0) {
+ SkSVGElement* element = fParents[parentIndex];
+ element->onEndElement(*this);
+ fParents.remove(parentIndex);
+ }
+ return false;
+}
+
+bool SkSVGParser::onStartElement(const char name[]) {
+ return onStartElementLen(name, strlen(name));
+}
+
+bool SkSVGParser::onStartElementLen(const char name[], size_t len) {
+ if (strncmp(name, "svg", len) == 0) {
+ fInSVG = true;
+ } else if (fInSVG == false)
+ return false;
+ const char* nextColon = strchr(name, ':');
+ if (nextColon && (size_t)(nextColon - name) < len)
+ return false;
+ SkSVGTypes type = GetType(name, len);
+// SkASSERT(type >= 0);
+ if (type < 0) {
+ type = SkSVGType_G;
+// return true;
+ }
+ SkSVGElement* parent = fParents.count() > 0 ? fParents.top() : NULL;
+ SkSVGElement* element = CreateElement(type, parent);
+ bool result = false;
+ if (parent) {
+ element->fParent = parent;
+ result = fParents.top()->onStartElement(element);
+ } else
+ *fChildren.append() = element;
+ if (strncmp(name, "svg", len) != 0)
+ *fParents.append() = element;
+ fCurrElement = element;
+ return result;
+}
+
+bool SkSVGParser::onText(const char text[], int len) {
+ if (fInSVG == false)
+ return false;
+ SkSVGTypes type = fCurrElement->getType();
+ if (type != SkSVGType_Text && type != SkSVGType_Tspan)
+ return false;
+ SkSVGText* textElement = (SkSVGText*) fCurrElement;
+ textElement->f_text.set(text, len);
+ return false;
+}
+
+static int32_t strokeFillID = 0;
+
+void SkSVGParser::translate(SkSVGElement* element, bool isDef) {
+ SkSVGPaint::Push(&fHead, &element->fPaintState);
+ bool isFlushable = element->isFlushable();
+ if ((element->fIsDef == false && element->fIsNotDef == false) ||
+ (element->fIsDef && isDef == false && element->fIsNotDef == false) ||
+ (element->fIsDef == false && isDef && element->fIsNotDef)) {
+ isFlushable = false;
+ }
+ SkSVGPaint* strokeState = NULL, * fillState = NULL;
+ if (isFlushable)
+ element->fPaintState.setSave(*this);
+ if (isFlushable && isStrokeAndFill(&strokeState, &fillState)) {
+ SkString& elementID = element->f_id;
+ if (elementID.size() == 0) {
+ elementID.set("sf");
+ elementID.appendS32(++strokeFillID);
+ }
+ SkString saveStroke(strokeState->f_stroke);
+ SkString saveFill(fillState->f_fill);
+ strokeState->f_stroke.set("none");
+ element->fPaintState.flush(*this, isFlushable, isDef);
+ element->translate(*this, isDef);
+ strokeState->f_stroke.set(saveStroke);
+ fillState->f_fill.set("none");
+ if (element->fPaintState.flush(*this, isFlushable, isDef)) {
+ _startElement("add");
+ _addAttributeLen("use", elementID.c_str(), elementID.size());
+ _endElement(); // add
+ }
+ fillState->f_fill.set(saveFill);
+ } else {
+ element->fPaintState.flush(*this, isFlushable, isDef);
+ if (isFlushable || element->isGroup())
+ element->translate(*this, isDef);
+ }
+ SkSVGPaint::Pop(&fHead);
+}
+
+void SkSVGParser::translateMatrix(SkString& string, SkString* stringID) {
+ if (string.size() == 0)
+ return;
+ if (stringID->size() > 0) {
+ _startElement("add");
+ _addAttribute("use", stringID->c_str());
+ _endElement(); // add
+ return;
+ }
+ SkASSERT(strncmp(string.c_str(), "matrix", 6) == 0);
+ ++gGeneratedMatrixID;
+ _startElement("matrix");
+ char idStr[24];
+ strcpy(idStr, "sk_matrix");
+ sprintf(idStr + strlen(idStr), "%d", gGeneratedMatrixID);
+ _addAttribute("id", idStr);
+ stringID->set(idStr);
+ const char* str = string.c_str();
+ SkASSERT(strncmp(str, "matrix(", 7) == 0);
+ str += 6;
+ const char* strEnd = strrchr(str, ')');
+ SkASSERT(strEnd != NULL);
+ SkString mat(str, strEnd - str);
+ ConvertToArray(mat);
+ const char* elems[6];
+ static const int order[] = {0, 3, 1, 4, 2, 5};
+ const int* orderPtr = order;
+ str = mat.c_str();
+ strEnd = str + mat.size();
+ while (str < strEnd) {
+ elems[*orderPtr++] = str;
+ while (str < strEnd && *str != ',' )
+ str++;
+ str++;
+ }
+ string.reset();
+ for (int index = 0; index < 6; index++) {
+ const char* end = strchr(elems[index], ',');
+ if (end == NULL)
+ end= strchr(elems[index], ']');
+ string.append(elems[index], end - elems[index] + 1);
+ }
+ string.remove(string.size() - 1, 1);
+ string.append(",0,0,1]");
+ _addAttribute("matrix", string);
+ _endElement(); // matrix
+}
+
+static bool is_whitespace(char ch) {
+ return ch > 0 && ch <= ' ';
+}
+
+void SkSVGParser::ConvertToArray(SkString& vals) {
+ vals.appendUnichar(']');
+ char* valCh = (char*) vals.c_str();
+ valCh[0] = '[';
+ int index = 1;
+ while (valCh[index] != ']') {
+ while (is_whitespace(valCh[index]))
+ index++;
+ bool foundComma = false;
+ char next;
+ do {
+ next = valCh[index++];
+ if (next == ',') {
+ foundComma = true;
+ continue;
+ }
+ if (next == ']') {
+ index--;
+ goto undoLastComma;
+ }
+ if (next == ' ')
+ break;
+ foundComma = false;
+ } while (is_whitespace(next) == false);
+ if (foundComma == false)
+ valCh[index - 1] = ',';
+ }
+undoLastComma:
+ while (is_whitespace(valCh[--index]))
+ ;
+ if (valCh[index] == ',')
+ valCh[index] = ' ';
+}
+
+#define CASE_NEW(type) case SkSVGType_##type : created = new SkSVG##type(); break
+
+SkSVGElement* SkSVGParser::CreateElement(SkSVGTypes type, SkSVGElement* parent) {
+ SkSVGElement* created = NULL;
+ switch (type) {
+ CASE_NEW(Circle);
+ CASE_NEW(ClipPath);
+ CASE_NEW(Defs);
+ CASE_NEW(Ellipse);
+ CASE_NEW(FeColorMatrix);
+ CASE_NEW(Filter);
+ CASE_NEW(G);
+ CASE_NEW(Image);
+ CASE_NEW(Line);
+ CASE_NEW(LinearGradient);
+ CASE_NEW(Mask);
+ CASE_NEW(Metadata);
+ CASE_NEW(Path);
+ CASE_NEW(Polygon);
+ CASE_NEW(Polyline);
+ CASE_NEW(RadialGradient);
+ CASE_NEW(Rect);
+ CASE_NEW(Stop);
+ CASE_NEW(SVG);
+ CASE_NEW(Symbol);
+ CASE_NEW(Text);
+ CASE_NEW(Tspan);
+ CASE_NEW(Use);
+ default:
+ SkASSERT(0);
+ return NULL;
+ }
+ created->fParent = parent;
+ bool isDef = created->fIsDef = created->isDef();
+ bool isNotDef = created->fIsNotDef = created->isNotDef();
+ if (isDef) {
+ SkSVGElement* up = parent;
+ while (up && up->fIsDef == false) {
+ up->fIsDef = true;
+ up = up->fParent;
+ }
+ }
+ if (isNotDef) {
+ SkSVGElement* up = parent;
+ while (up && up->fIsNotDef == false) {
+ up->fIsNotDef = true;
+ up = up->fParent;
+ }
+ }
+ return created;
+}
+
+const SkSVGTypeName gSVGTypeNames[] = {
+ {"circle", SkSVGType_Circle},
+ {"clipPath", SkSVGType_ClipPath},
+ {"defs", SkSVGType_Defs},
+ {"ellipse", SkSVGType_Ellipse},
+ {"feColorMatrix", SkSVGType_FeColorMatrix},
+ {"filter", SkSVGType_Filter},
+ {"g", SkSVGType_G},
+ {"image", SkSVGType_Image},
+ {"line", SkSVGType_Line},
+ {"linearGradient", SkSVGType_LinearGradient},
+ {"mask", SkSVGType_Mask},
+ {"metadata", SkSVGType_Metadata},
+ {"path", SkSVGType_Path},
+ {"polygon", SkSVGType_Polygon},
+ {"polyline", SkSVGType_Polyline},
+ {"radialGradient", SkSVGType_RadialGradient},
+ {"rect", SkSVGType_Rect},
+ {"stop", SkSVGType_Stop},
+ {"svg", SkSVGType_SVG},
+ {"symbol", SkSVGType_Symbol},
+ {"text", SkSVGType_Text},
+ {"tspan", SkSVGType_Tspan},
+ {"use", SkSVGType_Use}
+};
+
+const int kSVGTypeNamesSize = SK_ARRAY_COUNT(gSVGTypeNames);
+
+SkSVGTypes SkSVGParser::GetType(const char match[], size_t len ) {
+ int index = SkStrSearch(&gSVGTypeNames[0].fName, kSVGTypeNamesSize, match,
+ len, sizeof(gSVGTypeNames[0]));
+ return index >= 0 && index < kSVGTypeNamesSize ? gSVGTypeNames[index].fType :
+ (SkSVGTypes) -1;
+}
diff --git a/svg/SkSVGPath.cpp b/svg/SkSVGPath.cpp
new file mode 100644
index 00000000..ab18a65a
--- /dev/null
+++ b/svg/SkSVGPath.cpp
@@ -0,0 +1,37 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGPath.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGPath::gAttributes[] = {
+ SVG_ATTRIBUTE(d)
+};
+
+DEFINE_SVG_INFO(Path)
+
+void SkSVGPath::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("path");
+ INHERITED::translate(parser, defState);
+ bool hasMultiplePaths = false;
+ const char* firstZ = strchr(f_d.c_str(), 'z');
+ if (firstZ != NULL) {
+ firstZ++; // skip over 'z'
+ while (*firstZ == ' ')
+ firstZ++;
+ hasMultiplePaths = *firstZ != '\0';
+ }
+ if (hasMultiplePaths) {
+ SkString& fillRule = parser.getPaintLast(SkSVGPaint::kFillRule);
+ if (fillRule.size() > 0)
+ parser._addAttribute("fillType", fillRule.equals("evenodd") ? "evenOdd" : "winding");
+ }
+ SVG_ADD_ATTRIBUTE(d);
+ parser._endElement();
+}
diff --git a/svg/SkSVGPath.h b/svg/SkSVGPath.h
new file mode 100644
index 00000000..de325a7b
--- /dev/null
+++ b/svg/SkSVGPath.h
@@ -0,0 +1,22 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGPath_DEFINED
+#define SkSVGPath_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGPath : public SkSVGElement {
+ DECLARE_SVG_INFO(Path);
+private:
+ SkString f_d;
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGPath_DEFINED
diff --git a/svg/SkSVGPolygon.cpp b/svg/SkSVGPolygon.cpp
new file mode 100644
index 00000000..4b458db9
--- /dev/null
+++ b/svg/SkSVGPolygon.cpp
@@ -0,0 +1,33 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGPolygon.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGPolygon::gAttributes[] = {
+ SVG_LITERAL_ATTRIBUTE(clip-rule, f_clipRule),
+ SVG_LITERAL_ATTRIBUTE(fill-rule, f_fillRule),
+ SVG_ATTRIBUTE(points)
+};
+
+DEFINE_SVG_INFO(Polygon)
+
+void SkSVGPolygon::addAttribute(SkSVGParser& parser, int attrIndex,
+ const char* attrValue, size_t attrLength) {
+ INHERITED::addAttribute(parser, attrIndex, attrValue, attrLength);
+}
+
+void SkSVGPolygon::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("polygon");
+ SkSVGElement::translate(parser, defState);
+ SVG_ADD_ATTRIBUTE(points);
+ if (f_fillRule.size() > 0)
+ parser._addAttribute("fillType", f_fillRule.equals("evenodd") ? "evenOdd" : "winding");
+ parser._endElement();
+}
diff --git a/svg/SkSVGPolygon.h b/svg/SkSVGPolygon.h
new file mode 100644
index 00000000..b2848d06
--- /dev/null
+++ b/svg/SkSVGPolygon.h
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGPolygon_DEFINED
+#define SkSVGPolygon_DEFINED
+
+#include "SkSVGPolyline.h"
+
+class SkSVGPolygon : public SkSVGPolyline {
+ DECLARE_SVG_INFO(Polygon);
+ virtual void addAttribute(SkSVGParser& , int attrIndex,
+ const char* attrValue, size_t attrLength);
+private:
+ typedef SkSVGPolyline INHERITED;
+};
+
+#endif // SkSVGPolygon_DEFINED
diff --git a/svg/SkSVGPolyline.cpp b/svg/SkSVGPolyline.cpp
new file mode 100644
index 00000000..83dad488
--- /dev/null
+++ b/svg/SkSVGPolyline.cpp
@@ -0,0 +1,43 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGPolyline.h"
+#include "SkSVGParser.h"
+
+enum {
+ kCliipRule,
+ kFillRule,
+ kPoints
+};
+
+const SkSVGAttribute SkSVGPolyline::gAttributes[] = {
+ SVG_LITERAL_ATTRIBUTE(clip-rule, f_clipRule),
+ SVG_LITERAL_ATTRIBUTE(fill-rule, f_fillRule),
+ SVG_ATTRIBUTE(points)
+};
+
+DEFINE_SVG_INFO(Polyline)
+
+void SkSVGPolyline::addAttribute(SkSVGParser& , int attrIndex,
+ const char* attrValue, size_t attrLength) {
+ if (attrIndex != kPoints)
+ return;
+ f_points.set("[");
+ f_points.append(attrValue, attrLength);
+ SkSVGParser::ConvertToArray(f_points);
+}
+
+void SkSVGPolyline::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("polyline");
+ INHERITED::translate(parser, defState);
+ SVG_ADD_ATTRIBUTE(points);
+ if (f_fillRule.size() > 0)
+ parser._addAttribute("fillType", f_fillRule.equals("evenodd") ? "evenOdd" : "winding");
+ parser._endElement();
+}
diff --git a/svg/SkSVGPolyline.h b/svg/SkSVGPolyline.h
new file mode 100644
index 00000000..b8d5af45
--- /dev/null
+++ b/svg/SkSVGPolyline.h
@@ -0,0 +1,27 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGPolyline_DEFINED
+#define SkSVGPolyline_DEFINED
+
+#include "SkSVGElements.h"
+#include "SkString.h"
+
+class SkSVGPolyline : public SkSVGElement {
+ DECLARE_SVG_INFO(Polyline);
+ virtual void addAttribute(SkSVGParser& , int attrIndex,
+ const char* attrValue, size_t attrLength);
+protected:
+ SkString f_clipRule;
+ SkString f_fillRule;
+ SkString f_points;
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGPolyline_DEFINED
diff --git a/svg/SkSVGRadialGradient.cpp b/svg/SkSVGRadialGradient.cpp
new file mode 100644
index 00000000..4fdf4322
--- /dev/null
+++ b/svg/SkSVGRadialGradient.cpp
@@ -0,0 +1,42 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGRadialGradient.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGRadialGradient::gAttributes[] = {
+ SVG_ATTRIBUTE(cx),
+ SVG_ATTRIBUTE(cy),
+ SVG_ATTRIBUTE(fx),
+ SVG_ATTRIBUTE(fy),
+ SVG_ATTRIBUTE(gradientTransform),
+ SVG_ATTRIBUTE(gradientUnits),
+ SVG_ATTRIBUTE(r)
+};
+
+DEFINE_SVG_INFO(RadialGradient)
+
+void SkSVGRadialGradient::translate(SkSVGParser& parser, bool defState) {
+ if (fMatrixID.size() == 0)
+ parser.translateMatrix(f_gradientTransform, &fMatrixID);
+ parser._startElement("radialGradient");
+ if (fMatrixID.size() > 0)
+ parser._addAttribute("matrix", fMatrixID);
+ INHERITED::translateGradientUnits(f_gradientUnits);
+ SkString center;
+ center.appendUnichar('[');
+ center.append(f_cx);
+ center.appendUnichar(',');
+ center.append(f_cy);
+ center.appendUnichar(']');
+ parser._addAttribute("center", center);
+ parser._addAttribute("radius", f_r);
+ INHERITED::translate(parser, defState);
+ parser._endElement();
+}
diff --git a/svg/SkSVGRadialGradient.h b/svg/SkSVGRadialGradient.h
new file mode 100644
index 00000000..8eba3f5e
--- /dev/null
+++ b/svg/SkSVGRadialGradient.h
@@ -0,0 +1,30 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGRadialGradient_DEFINED
+#define SkSVGRadialGradient_DEFINED
+
+#include "SkSVGGradient.h"
+
+class SkSVGRadialGradient : public SkSVGGradient {
+ DECLARE_SVG_INFO(RadialGradient);
+protected:
+ SkString f_cx;
+ SkString f_cy;
+ SkString f_fx;
+ SkString f_fy;
+ SkString f_gradientTransform;
+ SkString f_gradientUnits;
+ SkString f_r;
+ SkString fMatrixID;
+private:
+ typedef SkSVGGradient INHERITED;
+};
+
+#endif // SkSVGRadialGradient_DEFINED
diff --git a/svg/SkSVGRect.cpp b/svg/SkSVGRect.cpp
new file mode 100644
index 00000000..32a7f99c
--- /dev/null
+++ b/svg/SkSVGRect.cpp
@@ -0,0 +1,35 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGRect.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGRect::gAttributes[] = {
+ SVG_ATTRIBUTE(height),
+ SVG_ATTRIBUTE(width),
+ SVG_ATTRIBUTE(x),
+ SVG_ATTRIBUTE(y)
+};
+
+DEFINE_SVG_INFO(Rect)
+
+SkSVGRect::SkSVGRect() {
+ f_x.set("0");
+ f_y.set("0");
+}
+
+void SkSVGRect::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("rect");
+ INHERITED::translate(parser, defState);
+ SVG_ADD_ATTRIBUTE_ALIAS(left, x);
+ SVG_ADD_ATTRIBUTE_ALIAS(top, y);
+ SVG_ADD_ATTRIBUTE(width);
+ SVG_ADD_ATTRIBUTE(height);
+ parser._endElement();
+}
diff --git a/svg/SkSVGRect.h b/svg/SkSVGRect.h
new file mode 100644
index 00000000..4ae820c5
--- /dev/null
+++ b/svg/SkSVGRect.h
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGRect_DEFINED
+#define SkSVGRect_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGRect : public SkSVGElement {
+ DECLARE_SVG_INFO(Rect);
+ SkSVGRect();
+private:
+ SkString f_height;
+ SkString f_width;
+ SkString f_x;
+ SkString f_y;
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGRect_DEFINED
diff --git a/svg/SkSVGSVG.cpp b/svg/SkSVGSVG.cpp
new file mode 100644
index 00000000..fcce62de
--- /dev/null
+++ b/svg/SkSVGSVG.cpp
@@ -0,0 +1,76 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGSVG.h"
+#include "SkParse.h"
+#include "SkRect.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGSVG::gAttributes[] = {
+ SVG_LITERAL_ATTRIBUTE(enable-background, f_enable_background),
+ SVG_ATTRIBUTE(height),
+ SVG_ATTRIBUTE(overflow),
+ SVG_ATTRIBUTE(width),
+ SVG_ATTRIBUTE(version),
+ SVG_ATTRIBUTE(viewBox),
+ SVG_ATTRIBUTE(x),
+ SVG_LITERAL_ATTRIBUTE(xml:space, f_xml_space),
+ SVG_ATTRIBUTE(xmlns),
+ SVG_LITERAL_ATTRIBUTE(xmlns:xlink, f_xml_xlink),
+ SVG_ATTRIBUTE(y),
+};
+
+DEFINE_SVG_INFO(SVG)
+
+
+bool SkSVGSVG::isFlushable() {
+ return false;
+}
+
+void SkSVGSVG::translate(SkSVGParser& parser, bool defState) {
+ SkScalar height, width;
+ SkScalar viewBox[4];
+ const char* hSuffix = SkParse::FindScalar(f_height.c_str(), &height);
+ if (strcmp(hSuffix, "pt") == 0)
+ height = SkScalarMulDiv(height, SK_Scalar1 * 72, SK_Scalar1 * 96);
+ const char* wSuffix = SkParse::FindScalar(f_width.c_str(), &width);
+ if (strcmp(wSuffix, "pt") == 0)
+ width = SkScalarMulDiv(width, SK_Scalar1 * 72, SK_Scalar1 * 96);
+ SkParse::FindScalars(f_viewBox.c_str(), viewBox, 4);
+ SkRect box;
+ box.fLeft = SkScalarDiv(viewBox[0], width);
+ box.fTop = SkScalarDiv(viewBox[1], height);
+ box.fRight = SkScalarDiv(viewBox[2], width);
+ box.fBottom = SkScalarDiv(viewBox[3], height);
+ if (box.fLeft == 0 && box.fTop == 0 &&
+ box.fRight == SK_Scalar1 && box.fBottom == SK_Scalar1)
+ return;
+ parser._startElement("matrix");
+ if (box.fLeft != 0) {
+ SkString x;
+ x.appendScalar(box.fLeft);
+ parser._addAttributeLen("translateX", x.c_str(), x.size());
+ }
+ if (box.fTop != 0) {
+ SkString y;
+ y.appendScalar(box.fTop);
+ parser._addAttributeLen("translateY", y.c_str(), y.size());
+ }
+ if (box.fRight != SK_Scalar1) {
+ SkString x;
+ x.appendScalar(box.fRight);
+ parser._addAttributeLen("scaleX", x.c_str(), x.size());
+ }
+ if (box.fBottom != SK_Scalar1) {
+ SkString y;
+ y.appendScalar(box.fBottom);
+ parser._addAttributeLen("scaleY", y.c_str(), y.size());
+ }
+ parser._endElement();
+}
diff --git a/svg/SkSVGSVG.h b/svg/SkSVGSVG.h
new file mode 100644
index 00000000..155f9a9b
--- /dev/null
+++ b/svg/SkSVGSVG.h
@@ -0,0 +1,34 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGSVG_DEFINED
+#define SkSVGSVG_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGSVG : public SkSVGElement {
+ DECLARE_SVG_INFO(SVG);
+ virtual bool isFlushable();
+private:
+ SkString f_enable_background;
+ SkString f_height;
+ SkString f_overflow;
+ SkString f_width;
+ SkString f_version;
+ SkString f_viewBox;
+ SkString f_x;
+ SkString f_xml_space;
+ SkString f_xmlns;
+ SkString f_xml_xlink;
+ SkString f_y;
+
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGSVG_DEFINED
diff --git a/svg/SkSVGStop.cpp b/svg/SkSVGStop.cpp
new file mode 100644
index 00000000..0630f612
--- /dev/null
+++ b/svg/SkSVGStop.cpp
@@ -0,0 +1,24 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGStop.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGStop::gAttributes[] = {
+ SVG_ATTRIBUTE(offset)
+};
+
+DEFINE_SVG_INFO(Stop)
+
+void SkSVGStop::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("color");
+ INHERITED::translate(parser, defState);
+ parser._addAttribute("color", parser.getPaintLast(SkSVGPaint::kStopColor));
+ parser._endElement();
+}
diff --git a/svg/SkSVGStop.h b/svg/SkSVGStop.h
new file mode 100644
index 00000000..e55936be
--- /dev/null
+++ b/svg/SkSVGStop.h
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGStop_DEFINED
+#define SkSVGStop_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGStop : public SkSVGElement {
+ DECLARE_SVG_INFO(Stop);
+private:
+ SkString f_offset;
+ friend class SkSVGGradient;
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGStop_DEFINED
diff --git a/svg/SkSVGSymbol.cpp b/svg/SkSVGSymbol.cpp
new file mode 100644
index 00000000..ce341e64
--- /dev/null
+++ b/svg/SkSVGSymbol.cpp
@@ -0,0 +1,22 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGSymbol.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGSymbol::gAttributes[] = {
+ SVG_ATTRIBUTE(viewBox)
+};
+
+DEFINE_SVG_INFO(Symbol)
+
+void SkSVGSymbol::translate(SkSVGParser& parser, bool defState) {
+ INHERITED::translate(parser, defState);
+ // !!! children need to be written into document
+}
diff --git a/svg/SkSVGSymbol.h b/svg/SkSVGSymbol.h
new file mode 100644
index 00000000..80fd61a1
--- /dev/null
+++ b/svg/SkSVGSymbol.h
@@ -0,0 +1,22 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGSymbol_DEFINED
+#define SkSVGSymbol_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGSymbol : public SkSVGElement {
+ DECLARE_SVG_INFO(Symbol);
+private:
+ SkString f_viewBox;
+ typedef SkSVGElement INHERITED;
+};
+
+#endif // SkSVGSymbol_DEFINED
diff --git a/svg/SkSVGText.cpp b/svg/SkSVGText.cpp
new file mode 100644
index 00000000..dfaba086
--- /dev/null
+++ b/svg/SkSVGText.cpp
@@ -0,0 +1,39 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGText.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGText::gAttributes[] = {
+ SVG_ATTRIBUTE(x),
+ SVG_ATTRIBUTE(y)
+};
+
+DEFINE_SVG_INFO(Text)
+
+void SkSVGText::translate(SkSVGParser& parser, bool defState) {
+ parser._startElement("text");
+ INHERITED::translate(parser, defState);
+ SVG_ADD_ATTRIBUTE(x);
+ SVG_ADD_ATTRIBUTE(y);
+ SVG_ADD_ATTRIBUTE(text);
+ parser._endElement();
+}
+
+
+const SkSVGAttribute SkSVGTspan::gAttributes[] = {
+ SVG_ATTRIBUTE(x),
+ SVG_ATTRIBUTE(y)
+};
+
+DEFINE_SVG_INFO(Tspan)
+
+void SkSVGTspan::translate(SkSVGParser& parser, bool defState) {
+ INHERITED::translate(parser, defState);
+}
diff --git a/svg/SkSVGText.h b/svg/SkSVGText.h
new file mode 100644
index 00000000..5ac2fbdd
--- /dev/null
+++ b/svg/SkSVGText.h
@@ -0,0 +1,32 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGText_DEFINED
+#define SkSVGText_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGText : public SkSVGElement {
+ DECLARE_SVG_INFO(Text);
+protected:
+ SkString f_x;
+ SkString f_y;
+ SkString f_text; // not an attribute
+private:
+ typedef SkSVGElement INHERITED;
+ friend class SkSVGParser;
+};
+
+class SkSVGTspan : public SkSVGText {
+ DECLARE_SVG_INFO(Tspan);
+private:
+ typedef SkSVGText INHERITED;
+};
+
+#endif // SkSVGText_DEFINED
diff --git a/svg/SkSVGUse.cpp b/svg/SkSVGUse.cpp
new file mode 100644
index 00000000..0496d98b
--- /dev/null
+++ b/svg/SkSVGUse.cpp
@@ -0,0 +1,30 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkSVGUse.h"
+#include "SkSVGParser.h"
+
+const SkSVGAttribute SkSVGUse::gAttributes[] = {
+ SVG_ATTRIBUTE(height),
+ SVG_ATTRIBUTE(width),
+ SVG_ATTRIBUTE(x),
+ SVG_LITERAL_ATTRIBUTE(xlink:href, f_xlink_href),
+ SVG_ATTRIBUTE(y)
+};
+
+DEFINE_SVG_INFO(Use)
+
+void SkSVGUse::translate(SkSVGParser& parser, bool defState) {
+ INHERITED::translate(parser, defState);
+ parser._startElement("add");
+ const char* start = strchr(f_xlink_href.c_str(), '#') + 1;
+ SkASSERT(start);
+ parser._addAttributeLen("use", start, strlen(start) - 1);
+ parser._endElement(); // clip
+}
diff --git a/svg/SkSVGUse.h b/svg/SkSVGUse.h
new file mode 100644
index 00000000..b907189f
--- /dev/null
+++ b/svg/SkSVGUse.h
@@ -0,0 +1,28 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkSVGUse_DEFINED
+#define SkSVGUse_DEFINED
+
+#include "SkSVGElements.h"
+
+class SkSVGUse : public SkSVGElement {
+ DECLARE_SVG_INFO(Use);
+protected:
+ SkString f_height;
+ SkString f_width;
+ SkString f_x;
+ SkString f_xlink_href;
+ SkString f_y;
+private:
+ typedef SkSVGElement INHERITED;
+ friend class SkSVGClipPath;
+};
+
+#endif // SkSVGUse_DEFINED