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::d, SetPathDataAttribute }}, |
134 { "fill", { SkSVGAttribute::fill, SetPaintAttribute }}, | 189 { "fill", { SkSVGAttribute::fill, SetPaintAttribute }}, |
135 { "stroke", { SkSVGAttribute::stroke, SetPaintAttribute }}, | 190 { "stroke", { SkSVGAttribute::stroke, SetPaintAttribute }}, |
robertphillips
2016/07/29 11:37:28
Where in the spec is the 'style' attribute discuss
f(malita)
2016/07/29 13:04:05
https://www.w3.org/TR/SVG/styling.html#StyleAttrib
| |
191 { "style", { SkSVGAttribute::unknown, SetStyleAttributes }}, | |
136 { "transform", { SkSVGAttribute::transform, SetTransformAttribute }}, | 192 { "transform", { SkSVGAttribute::transform, 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 |