Index: experimental/svg/model/SkSVGDOM.cpp |
diff --git a/experimental/svg/model/SkSVGDOM.cpp b/experimental/svg/model/SkSVGDOM.cpp |
index 6f782c3a96368d51bddb1e407732ae17205d9aaf..4e2f8989427d1a018064871e346f98b7939485f1 100644 |
--- a/experimental/svg/model/SkSVGDOM.cpp |
+++ b/experimental/svg/model/SkSVGDOM.cpp |
@@ -9,6 +9,7 @@ |
#include "SkDOM.h" |
#include "SkParse.h" |
#include "SkParsePath.h" |
+#include "SkString.h" |
#include "SkSVGDOM.h" |
#include "SkSVGG.h" |
#include "SkSVGNode.h" |
@@ -118,6 +119,60 @@ bool SetTransformAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, |
return true; |
} |
+// Breaks a "foo: bar; baz: ..." string into key:value pairs. |
+class StyleIterator { |
+public: |
+ StyleIterator(const char* str) : fPos(str) { } |
+ |
+ std::tuple<SkString, SkString> next() { |
+ SkString name, value; |
+ |
+ if (fPos) { |
+ const char* sep = this->nextSeparator(); |
+ SkASSERT(*sep == ';' || *sep == '\0'); |
+ |
+ const char* valueSep = strchr(fPos, ':'); |
+ if (valueSep && valueSep < sep) { |
+ name.set(fPos, valueSep - fPos); |
+ value.set(valueSep + 1, sep - valueSep - 1); |
+ } |
+ |
+ fPos = *sep ? sep + 1 : nullptr; |
+ } |
+ |
+ return std::make_tuple(name, value); |
+ } |
+ |
+private: |
+ const char* nextSeparator() const { |
+ const char* sep = fPos; |
+ while (*sep != ';' && *sep != '\0') { |
+ sep++; |
+ } |
+ return sep; |
+ } |
+ |
+ const char* fPos; |
+}; |
+ |
+void set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const char* value); |
+ |
+bool SetStyleAttributes(const sk_sp<SkSVGNode>& node, SkSVGAttribute, |
+ const char* stringValue) { |
+ |
+ SkString name, value; |
+ StyleIterator iter(stringValue); |
+ for (;;) { |
+ std::tie(name, value) = iter.next(); |
+ if (name.isEmpty()) { |
+ break; |
+ } |
+ set_string_attribute(node, name.c_str(), value.c_str()); |
+ } |
+ |
+ return true; |
+} |
+ |
template<typename T> |
struct SortedDictionaryEntry { |
const char* fKey; |
@@ -130,10 +185,11 @@ struct AttrParseInfo { |
}; |
SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = { |
- { "d", { SkSVGAttribute::d, SetPathDataAttribute }}, |
- { "fill", { SkSVGAttribute::fill, SetPaintAttribute }}, |
- { "stroke", { SkSVGAttribute::stroke, SetPaintAttribute }}, |
- { "transform", { SkSVGAttribute::transform, SetTransformAttribute }}, |
+ { "d", { SkSVGAttribute::kD, SetPathDataAttribute }}, |
+ { "fill", { SkSVGAttribute::kFill, SetPaintAttribute }}, |
+ { "stroke", { SkSVGAttribute::kStroke, SetPaintAttribute }}, |
+ { "style", { SkSVGAttribute::kUnknown, SetStyleAttributes }}, |
+ { "transform", { SkSVGAttribute::kTransform, SetTransformAttribute }}, |
}; |
SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = { |
@@ -150,24 +206,28 @@ struct ConstructionContext { |
const SkSVGNode* fParent; |
}; |
+void set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const char* value) { |
+ const int attrIndex = SkStrSearch(&gAttributeParseInfo[0].fKey, |
+ SkTo<int>(SK_ARRAY_COUNT(gAttributeParseInfo)), |
+ name, sizeof(gAttributeParseInfo[0])); |
+ if (attrIndex < 0) { |
+ SkDebugf("unhandled attribute: %s\n", name); |
+ return; |
+ } |
+ |
+ SkASSERT(SkTo<size_t>(attrIndex) < SK_ARRAY_COUNT(gAttributeParseInfo)); |
+ const auto& attrInfo = gAttributeParseInfo[attrIndex].fValue; |
+ if (!attrInfo.fSetter(node, attrInfo.fAttr, value)) { |
+ SkDebugf("could not parse attribute: '%s=\"%s\"'\n", name, value); |
+ } |
+} |
+ |
void parse_node_attributes(const SkDOM& xmlDom, const SkDOM::Node* xmlNode, |
const sk_sp<SkSVGNode>& svgNode) { |
const char* name, *value; |
SkDOM::AttrIter attrIter(xmlDom, xmlNode); |
while ((name = attrIter.next(&value))) { |
- const int attrIndex = SkStrSearch(&gAttributeParseInfo[0].fKey, |
- SkTo<int>(SK_ARRAY_COUNT(gAttributeParseInfo)), |
- name, sizeof(gAttributeParseInfo[0])); |
- if (attrIndex < 0) { |
- SkDebugf("unhandled attribute: %s\n", name); |
- continue; |
- } |
- |
- SkASSERT(SkTo<size_t>(attrIndex) < SK_ARRAY_COUNT(gAttributeParseInfo)); |
- const auto& attrInfo = gAttributeParseInfo[attrIndex].fValue; |
- if (!attrInfo.fSetter(svgNode, attrInfo.fAttr, value)) { |
- SkDebugf("could not parse attribute: '%s=\"%s\"'\n", name, value); |
- } |
+ set_string_attribute(svgNode, name, value); |
} |
} |