OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCanvas.h" | 8 #include "SkCanvas.h" |
9 #include "SkDOM.h" | 9 #include "SkDOM.h" |
10 #include "SkParse.h" | 10 #include "SkParse.h" |
11 #include "SkParsePath.h" | 11 #include "SkParsePath.h" |
| 12 #include "SkString.h" |
12 #include "SkSVGDOM.h" | 13 #include "SkSVGDOM.h" |
13 #include "SkSVGG.h" | 14 #include "SkSVGG.h" |
14 #include "SkSVGNode.h" | 15 #include "SkSVGNode.h" |
15 #include "SkSVGPath.h" | 16 #include "SkSVGPath.h" |
16 #include "SkSVGSVG.h" | 17 #include "SkSVGSVG.h" |
17 #include "SkSVGValue.h" | 18 #include "SkSVGValue.h" |
18 #include "SkTSearch.h" | 19 #include "SkTSearch.h" |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 node->setAttribute(attr, SkSVGPathValue(path)); | 112 node->setAttribute(attr, SkSVGPathValue(path)); |
112 return true; | 113 return true; |
113 } | 114 } |
114 | 115 |
115 bool SetTransformAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, | 116 bool SetTransformAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, |
116 const char* stringValue) { | 117 const char* stringValue) { |
117 node->setAttribute(attr, SkSVGTransformValue(ParseTransform(stringValue))); | 118 node->setAttribute(attr, SkSVGTransformValue(ParseTransform(stringValue))); |
118 return true; | 119 return true; |
119 } | 120 } |
120 | 121 |
| 122 // Breaks a "foo: bar; baz: ..." string into key:value pairs. |
| 123 class StyleIterator { |
| 124 public: |
| 125 StyleIterator(const char* str) : fPos(str) { } |
| 126 |
| 127 std::tuple<SkString, SkString> next() { |
| 128 SkString name, value; |
| 129 |
| 130 if (fPos) { |
| 131 const char* sep = this->nextSeparator(); |
| 132 SkASSERT(*sep == ';' || *sep == '\0'); |
| 133 |
| 134 const char* valueSep = strchr(fPos, ':'); |
| 135 if (valueSep && valueSep < sep) { |
| 136 name.set(fPos, valueSep - fPos); |
| 137 value.set(valueSep + 1, sep - valueSep - 1); |
| 138 } |
| 139 |
| 140 fPos = *sep ? sep + 1 : nullptr; |
| 141 } |
| 142 |
| 143 return std::make_tuple(name, value); |
| 144 } |
| 145 |
| 146 private: |
| 147 const char* nextSeparator() const { |
| 148 const char* sep = fPos; |
| 149 while (*sep != ';' && *sep != '\0') { |
| 150 sep++; |
| 151 } |
| 152 return sep; |
| 153 } |
| 154 |
| 155 const char* fPos; |
| 156 }; |
| 157 |
| 158 void set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const
char* value); |
| 159 |
| 160 bool SetStyleAttributes(const sk_sp<SkSVGNode>& node, SkSVGAttribute, |
| 161 const char* stringValue) { |
| 162 |
| 163 SkString name, value; |
| 164 StyleIterator iter(stringValue); |
| 165 for (;;) { |
| 166 std::tie(name, value) = iter.next(); |
| 167 if (name.isEmpty()) { |
| 168 break; |
| 169 } |
| 170 set_string_attribute(node, name.c_str(), value.c_str()); |
| 171 } |
| 172 |
| 173 return true; |
| 174 } |
| 175 |
121 template<typename T> | 176 template<typename T> |
122 struct SortedDictionaryEntry { | 177 struct SortedDictionaryEntry { |
123 const char* fKey; | 178 const char* fKey; |
124 const T fValue; | 179 const T fValue; |
125 }; | 180 }; |
126 | 181 |
127 struct AttrParseInfo { | 182 struct AttrParseInfo { |
128 SkSVGAttribute fAttr; | 183 SkSVGAttribute fAttr; |
129 bool (*fSetter)(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, const cha
r* stringValue); | 184 bool (*fSetter)(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, const cha
r* stringValue); |
130 }; | 185 }; |
131 | 186 |
132 SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = { | 187 SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = { |
133 { "d", { SkSVGAttribute::d, SetPathDataAttribute }}, | 188 { "d", { SkSVGAttribute::kD, SetPathDataAttribute }}, |
134 { "fill", { SkSVGAttribute::fill, SetPaintAttribute }}, | 189 { "fill", { SkSVGAttribute::kFill, SetPaintAttribute }}, |
135 { "stroke", { SkSVGAttribute::stroke, SetPaintAttribute }}, | 190 { "stroke", { SkSVGAttribute::kStroke, SetPaintAttribute }}, |
136 { "transform", { SkSVGAttribute::transform, SetTransformAttribute }}, | 191 { "style", { SkSVGAttribute::kUnknown, SetStyleAttributes }}, |
| 192 { "transform", { SkSVGAttribute::kTransform, SetTransformAttribute }}, |
137 }; | 193 }; |
138 | 194 |
139 SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = { | 195 SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = { |
140 { "g" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); }}, | 196 { "g" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); }}, |
141 { "path", []() -> sk_sp<SkSVGNode> { return SkSVGPath::Make(); }}, | 197 { "path", []() -> sk_sp<SkSVGNode> { return SkSVGPath::Make(); }}, |
142 { "svg" , []() -> sk_sp<SkSVGNode> { return SkSVGSVG::Make(); }}, | 198 { "svg" , []() -> sk_sp<SkSVGNode> { return SkSVGSVG::Make(); }}, |
143 }; | 199 }; |
144 | 200 |
145 struct ConstructionContext { | 201 struct ConstructionContext { |
146 ConstructionContext() : fParent(nullptr) { } | 202 ConstructionContext() : fParent(nullptr) { } |
147 ConstructionContext(const ConstructionContext& other, const sk_sp<SkSVGNode>
& newParent) | 203 ConstructionContext(const ConstructionContext& other, const sk_sp<SkSVGNode>
& newParent) |
148 : fParent(newParent.get()) { } | 204 : fParent(newParent.get()) { } |
149 | 205 |
150 const SkSVGNode* fParent; | 206 const SkSVGNode* fParent; |
151 }; | 207 }; |
152 | 208 |
| 209 void set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const
char* value) { |
| 210 const int attrIndex = SkStrSearch(&gAttributeParseInfo[0].fKey, |
| 211 SkTo<int>(SK_ARRAY_COUNT(gAttributeParseIn
fo)), |
| 212 name, sizeof(gAttributeParseInfo[0])); |
| 213 if (attrIndex < 0) { |
| 214 SkDebugf("unhandled attribute: %s\n", name); |
| 215 return; |
| 216 } |
| 217 |
| 218 SkASSERT(SkTo<size_t>(attrIndex) < SK_ARRAY_COUNT(gAttributeParseInfo)); |
| 219 const auto& attrInfo = gAttributeParseInfo[attrIndex].fValue; |
| 220 if (!attrInfo.fSetter(node, attrInfo.fAttr, value)) { |
| 221 SkDebugf("could not parse attribute: '%s=\"%s\"'\n", name, value); |
| 222 } |
| 223 } |
| 224 |
153 void parse_node_attributes(const SkDOM& xmlDom, const SkDOM::Node* xmlNode, | 225 void parse_node_attributes(const SkDOM& xmlDom, const SkDOM::Node* xmlNode, |
154 const sk_sp<SkSVGNode>& svgNode) { | 226 const sk_sp<SkSVGNode>& svgNode) { |
155 const char* name, *value; | 227 const char* name, *value; |
156 SkDOM::AttrIter attrIter(xmlDom, xmlNode); | 228 SkDOM::AttrIter attrIter(xmlDom, xmlNode); |
157 while ((name = attrIter.next(&value))) { | 229 while ((name = attrIter.next(&value))) { |
158 const int attrIndex = SkStrSearch(&gAttributeParseInfo[0].fKey, | 230 set_string_attribute(svgNode, name, value); |
159 SkTo<int>(SK_ARRAY_COUNT(gAttributePar
seInfo)), | |
160 name, sizeof(gAttributeParseInfo[0])); | |
161 if (attrIndex < 0) { | |
162 SkDebugf("unhandled attribute: %s\n", name); | |
163 continue; | |
164 } | |
165 | |
166 SkASSERT(SkTo<size_t>(attrIndex) < SK_ARRAY_COUNT(gAttributeParseInfo)); | |
167 const auto& attrInfo = gAttributeParseInfo[attrIndex].fValue; | |
168 if (!attrInfo.fSetter(svgNode, attrInfo.fAttr, value)) { | |
169 SkDebugf("could not parse attribute: '%s=\"%s\"'\n", name, value); | |
170 } | |
171 } | 231 } |
172 } | 232 } |
173 | 233 |
174 sk_sp<SkSVGNode> construct_svg_node(const SkDOM& dom, const ConstructionContext&
ctx, | 234 sk_sp<SkSVGNode> construct_svg_node(const SkDOM& dom, const ConstructionContext&
ctx, |
175 const SkDOM::Node* xmlNode) { | 235 const SkDOM::Node* xmlNode) { |
176 const char* elem = dom.getName(xmlNode); | 236 const char* elem = dom.getName(xmlNode); |
177 const SkDOM::Type elemType = dom.getType(xmlNode); | 237 const SkDOM::Type elemType = dom.getType(xmlNode); |
178 | 238 |
179 if (elemType == SkDOM::kText_Type) { | 239 if (elemType == SkDOM::kText_Type) { |
180 SkASSERT(dom.countChildren(xmlNode) == 0); | 240 SkASSERT(dom.countChildren(xmlNode) == 0); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 void SkSVGDOM::render(SkCanvas* canvas) const { | 295 void SkSVGDOM::render(SkCanvas* canvas) const { |
236 if (fRoot) { | 296 if (fRoot) { |
237 fRoot->render(canvas); | 297 fRoot->render(canvas); |
238 } | 298 } |
239 } | 299 } |
240 | 300 |
241 void SkSVGDOM::setContainerSize(const SkSize& containerSize) { | 301 void SkSVGDOM::setContainerSize(const SkSize& containerSize) { |
242 // TODO: inval | 302 // TODO: inval |
243 fContainerSize = containerSize; | 303 fContainerSize = containerSize; |
244 } | 304 } |
OLD | NEW |