Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: src/svg/parser/SkSVGParser.cpp

Issue 2154193003: Delete the legacy SVG parser (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/svg/parser/SkSVGPaintState.cpp ('k') | src/svg/parser/SkSVGPath.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9 #include "SkSVGParser.h"
10 #include "SkSVGCircle.h"
11 #include "SkSVGClipPath.h"
12 #include "SkSVGDefs.h"
13 #include "SkSVGEllipse.h"
14 #include "SkSVGFeColorMatrix.h"
15 #include "SkSVGFilter.h"
16 #include "SkSVGG.h"
17 #include "SkSVGImage.h"
18 #include "SkSVGLine.h"
19 #include "SkSVGLinearGradient.h"
20 #include "SkSVGMask.h"
21 #include "SkSVGMetadata.h"
22 #include "SkSVGPath.h"
23 #include "SkSVGPolygon.h"
24 #include "SkSVGPolyline.h"
25 #include "SkSVGRadialGradient.h"
26 #include "SkSVGRect.h"
27 #include "SkSVGSVG.h"
28 #include "SkSVGStop.h"
29 #include "SkSVGSymbol.h"
30 #include "SkSVGText.h"
31 #include "SkSVGUse.h"
32 #include "SkTSearch.h"
33 #include <stdio.h>
34
35 static int gGeneratedMatrixID = 0;
36
37 SkSVGParser::SkSVGParser(SkXMLParserError* errHandler) :
38 SkXMLParser(errHandler),
39 fHead(&fEmptyPaint), fIDs(256),
40 fXMLWriter(&fStream), fCurrElement(nullptr), fInSVG(false), fSuppressPai nt(false) {
41 fLastTransform.reset();
42 fEmptyPaint.f_fill.set("black");
43 fEmptyPaint.f_stroke.set("none");
44 fEmptyPaint.f_strokeMiterlimit.set("4");
45 fEmptyPaint.f_fillRule.set("winding");
46 fEmptyPaint.f_opacity.set("1");
47 fEmptyPaint.fNext = nullptr;
48 for (int index = SkSVGPaint::kInitial + 1; index < SkSVGPaint::kTerminal; in dex++) {
49 SkString* initial = fEmptyPaint[index];
50 if (initial->size() == 0)
51 continue;
52 fLastFlush[index]->set(*initial);
53 }
54 }
55
56 SkSVGParser::~SkSVGParser() {
57 }
58
59 void SkSVGParser::Delete(SkTDArray<SkSVGElement*>& fChildren) {
60 SkSVGElement** ptr;
61 for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
62 Delete((*ptr)->fChildren);
63 delete *ptr;
64 }
65 }
66
67 int SkSVGParser::findAttribute(SkSVGBase* element, const char* attrValue,
68 size_t len, bool isPaint) {
69 const SkSVGAttribute* attributes;
70 size_t count = element->getAttributes(&attributes);
71 size_t result = 0;
72 while (result < count) {
73 if (strncmp(attributes->fName, attrValue, len) == 0 && strlen(attributes ->fName) == len) {
74 SkASSERT(result == (attributes->fOffset -
75 (isPaint ? sizeof(SkString) : sizeof(SkSVGElement))) / sizeof(Sk String));
76 return result;
77 }
78 attributes++;
79 result++;
80 }
81 return -1;
82 }
83
84 #if 0
85 const char* SkSVGParser::getFinal() {
86 _startElement("screenplay");
87 // generate defs
88 SkSVGElement** ptr;
89 for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
90 SkSVGElement* element = *ptr;
91 translate(element, true);
92 }
93 // generate onLoad
94 _startElement("event");
95 _addAttribute("kind", "onLoad");
96 _startElement("paint");
97 _addAttribute("antiAlias", "true");
98 _endElement();
99 for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
100 SkSVGElement* element = *ptr;
101 translate(element, false);
102 }
103 _endElement(); // event
104 _endElement(); // screenplay
105 Delete(fChildren);
106 fStream.write("", 1);
107 return fStream.getStream();
108 }
109 #endif
110
111 SkString& SkSVGParser::getPaintLast(SkSVGPaint::Field field) {
112 SkSVGPaint* state = fHead;
113 do {
114 SkString* attr = (*state)[field];
115 SkASSERT(attr);
116 if (attr->size() > 0)
117 return *attr;
118 state = state->fNext;
119 } while (state);
120 SkASSERT(0);
121 SkASSERT(fEmptyPaint[field]);
122 return *fEmptyPaint[field];
123 }
124
125 bool SkSVGParser::isStrokeAndFill( SkSVGPaint** strokeState, SkSVGPaint** fillS tate) {
126 SkSVGPaint* walking = fHead;
127 bool stroke = false;
128 bool fill = false;
129 bool strokeSet = false;
130 bool fillSet = false;
131 while (walking != nullptr) {
132 if (strokeSet == false && walking->f_stroke.size() > 0) {
133 stroke = walking->f_stroke.equals("none") == false;
134 *strokeState = walking;
135 strokeSet = true;
136 }
137 if (fillSet == false && walking->f_fill.size() > 0) {
138 fill = walking->f_fill.equals("none") == false;
139 *fillState = walking;
140 fillSet = true;
141 }
142 walking = walking->fNext;
143 }
144 return stroke && fill;
145 }
146
147 bool SkSVGParser::onAddAttribute(const char name[], const char value[]) {
148 return onAddAttributeLen(name, value, strlen(value));
149 }
150
151 bool SkSVGParser::onAddAttributeLen(const char name[], const char value[], size_ t len) {
152 if (fCurrElement == nullptr) // this signals we should ignore attributes for this element
153 return true;
154 if (fCurrElement->fIsDef == false && fCurrElement->fIsNotDef == false)
155 return false; // also an ignored element
156 size_t nameLen = strlen(name);
157 int attrIndex = findAttribute(fCurrElement, name, nameLen, false);
158 if (attrIndex == -1) {
159 attrIndex = findAttribute(&fCurrElement->fPaintState, name, nameLen, tru e);
160 if (attrIndex >= 0) {
161 fCurrElement->fPaintState.addAttribute(*this, attrIndex, value, len) ;
162 return false;
163 }
164 if (nameLen == 2 && strncmp("id", name, nameLen) == 0) {
165 fCurrElement->f_id.set(value, len);
166 return false;
167 }
168 if (strchr(name, ':') != 0) // part of a different namespace
169 return false;
170 }
171 SkASSERT(attrIndex >= 0);
172 fCurrElement->addAttribute(*this, attrIndex, value, len);
173 return false;
174 }
175
176 bool SkSVGParser::onEndElement(const char elem[]) {
177 int parentIndex = fParents.count() - 1;
178 if (parentIndex >= 0) {
179 SkSVGElement* element = fParents[parentIndex];
180 element->onEndElement(*this);
181 fParents.remove(parentIndex);
182 }
183 return false;
184 }
185
186 bool SkSVGParser::onStartElement(const char name[]) {
187 return onStartElementLen(name, strlen(name));
188 }
189
190 bool SkSVGParser::onStartElementLen(const char name[], size_t len) {
191 if (strncmp(name, "svg", len) == 0) {
192 fInSVG = true;
193 } else if (fInSVG == false)
194 return false;
195 const char* nextColon = strchr(name, ':');
196 if (nextColon && (size_t)(nextColon - name) < len)
197 return false;
198 SkSVGTypes type = GetType(name, len);
199 // SkASSERT(type >= 0);
200 if (type < 0) {
201 type = SkSVGType_G;
202 // return true;
203 }
204 SkSVGElement* parent = fParents.count() > 0 ? fParents.top() : nullptr;
205 SkSVGElement* element = CreateElement(type, parent);
206 bool result = false;
207 if (parent) {
208 element->fParent = parent;
209 result = fParents.top()->onStartElement(element);
210 } else
211 *fChildren.append() = element;
212 if (strncmp(name, "svg", len) != 0)
213 *fParents.append() = element;
214 fCurrElement = element;
215 return result;
216 }
217
218 bool SkSVGParser::onText(const char text[], int len) {
219 if (fInSVG == false)
220 return false;
221 SkSVGTypes type = fCurrElement->getType();
222 if (type != SkSVGType_Text && type != SkSVGType_Tspan)
223 return false;
224 SkSVGText* textElement = (SkSVGText*) fCurrElement;
225 textElement->f_text.set(text, len);
226 return false;
227 }
228
229 static int32_t strokeFillID = 0;
230
231 void SkSVGParser::translate(SkSVGElement* element, bool isDef) {
232 SkSVGPaint::Push(&fHead, &element->fPaintState);
233 bool isFlushable = element->isFlushable();
234 if ((element->fIsDef == false && element->fIsNotDef == false) ||
235 (element->fIsDef && isDef == false && element->fIsNotDef == false) ||
236 (element->fIsDef == false && isDef && element->fIsNotDef)) {
237 isFlushable = false;
238 }
239 SkSVGPaint* strokeState = nullptr, * fillState = nullptr;
240 if (isFlushable)
241 element->fPaintState.setSave(*this);
242 if (isFlushable && isStrokeAndFill(&strokeState, &fillState)) {
243 SkString& elementID = element->f_id;
244 if (elementID.size() == 0) {
245 elementID.set("sf");
246 elementID.appendS32(++strokeFillID);
247 }
248 SkString saveStroke(strokeState->f_stroke);
249 SkString saveFill(fillState->f_fill);
250 strokeState->f_stroke.set("none");
251 element->fPaintState.flush(*this, isFlushable, isDef);
252 element->translate(*this, isDef);
253 strokeState->f_stroke.set(saveStroke);
254 fillState->f_fill.set("none");
255 if (element->fPaintState.flush(*this, isFlushable, isDef)) {
256 _startElement("add");
257 _addAttributeLen("use", elementID.c_str(), elementID.size());
258 _endElement(); // add
259 }
260 fillState->f_fill.set(saveFill);
261 } else {
262 element->fPaintState.flush(*this, isFlushable, isDef);
263 if (isFlushable || element->isGroup())
264 element->translate(*this, isDef);
265 }
266 SkSVGPaint::Pop(&fHead);
267 }
268
269 void SkSVGParser::translateMatrix(SkString& string, SkString* stringID) {
270 if (string.size() == 0)
271 return;
272 if (stringID->size() > 0) {
273 _startElement("add");
274 _addAttribute("use", stringID->c_str());
275 _endElement(); // add
276 return;
277 }
278 SkASSERT(strncmp(string.c_str(), "matrix", 6) == 0);
279 ++gGeneratedMatrixID;
280 _startElement("matrix");
281 char idStr[24];
282 strcpy(idStr, "sk_matrix");
283 sprintf(idStr + strlen(idStr), "%d", gGeneratedMatrixID);
284 _addAttribute("id", idStr);
285 stringID->set(idStr);
286 const char* str = string.c_str();
287 SkASSERT(strncmp(str, "matrix(", 7) == 0);
288 str += 6;
289 const char* strEnd = strrchr(str, ')');
290 SkASSERT(strEnd != nullptr);
291 SkString mat(str, strEnd - str);
292 ConvertToArray(mat);
293 const char* elems[6];
294 static const int order[] = {0, 3, 1, 4, 2, 5};
295 const int* orderPtr = order;
296 str = mat.c_str();
297 strEnd = str + mat.size();
298 while (str < strEnd) {
299 elems[*orderPtr++] = str;
300 while (str < strEnd && *str != ',' )
301 str++;
302 str++;
303 }
304 string.reset();
305 for (int index = 0; index < 6; index++) {
306 const char* end = strchr(elems[index], ',');
307 if (end == nullptr)
308 end= strchr(elems[index], ']');
309 string.append(elems[index], end - elems[index] + 1);
310 }
311 string.remove(string.size() - 1, 1);
312 string.append(",0,0,1]");
313 _addAttribute("matrix", string);
314 _endElement(); // matrix
315 }
316
317 static bool is_whitespace(char ch) {
318 return ch > 0 && ch <= ' ';
319 }
320
321 void SkSVGParser::ConvertToArray(SkString& vals) {
322 vals.appendUnichar(']');
323 char* valCh = (char*) vals.c_str();
324 valCh[0] = '[';
325 int index = 1;
326 while (valCh[index] != ']') {
327 while (is_whitespace(valCh[index]))
328 index++;
329 bool foundComma = false;
330 char next;
331 do {
332 next = valCh[index++];
333 if (next == ',') {
334 foundComma = true;
335 continue;
336 }
337 if (next == ']') {
338 index--;
339 goto undoLastComma;
340 }
341 if (next == ' ')
342 break;
343 foundComma = false;
344 } while (is_whitespace(next) == false);
345 if (foundComma == false)
346 valCh[index - 1] = ',';
347 }
348 undoLastComma:
349 while (is_whitespace(valCh[--index]))
350 ;
351 if (valCh[index] == ',')
352 valCh[index] = ' ';
353 }
354
355 #define CASE_NEW(type) case SkSVGType_##type : created = new SkSVG##type(); brea k
356
357 SkSVGElement* SkSVGParser::CreateElement(SkSVGTypes type, SkSVGElement* parent) {
358 SkSVGElement* created = nullptr;
359 switch (type) {
360 CASE_NEW(Circle);
361 CASE_NEW(ClipPath);
362 CASE_NEW(Defs);
363 CASE_NEW(Ellipse);
364 CASE_NEW(FeColorMatrix);
365 CASE_NEW(Filter);
366 CASE_NEW(G);
367 CASE_NEW(Image);
368 CASE_NEW(Line);
369 CASE_NEW(LinearGradient);
370 CASE_NEW(Mask);
371 CASE_NEW(Metadata);
372 CASE_NEW(Path);
373 CASE_NEW(Polygon);
374 CASE_NEW(Polyline);
375 CASE_NEW(RadialGradient);
376 CASE_NEW(Rect);
377 CASE_NEW(Stop);
378 CASE_NEW(SVG);
379 CASE_NEW(Symbol);
380 CASE_NEW(Text);
381 CASE_NEW(Tspan);
382 CASE_NEW(Use);
383 default:
384 SkASSERT(0);
385 return nullptr;
386 }
387 created->fParent = parent;
388 bool isDef = created->fIsDef = created->isDef();
389 bool isNotDef = created->fIsNotDef = created->isNotDef();
390 if (isDef) {
391 SkSVGElement* up = parent;
392 while (up && up->fIsDef == false) {
393 up->fIsDef = true;
394 up = up->fParent;
395 }
396 }
397 if (isNotDef) {
398 SkSVGElement* up = parent;
399 while (up && up->fIsNotDef == false) {
400 up->fIsNotDef = true;
401 up = up->fParent;
402 }
403 }
404 return created;
405 }
406
407 const SkSVGTypeName gSVGTypeNames[] = {
408 {"circle", SkSVGType_Circle},
409 {"clipPath", SkSVGType_ClipPath},
410 {"defs", SkSVGType_Defs},
411 {"ellipse", SkSVGType_Ellipse},
412 {"feColorMatrix", SkSVGType_FeColorMatrix},
413 {"filter", SkSVGType_Filter},
414 {"g", SkSVGType_G},
415 {"image", SkSVGType_Image},
416 {"line", SkSVGType_Line},
417 {"linearGradient", SkSVGType_LinearGradient},
418 {"mask", SkSVGType_Mask},
419 {"metadata", SkSVGType_Metadata},
420 {"path", SkSVGType_Path},
421 {"polygon", SkSVGType_Polygon},
422 {"polyline", SkSVGType_Polyline},
423 {"radialGradient", SkSVGType_RadialGradient},
424 {"rect", SkSVGType_Rect},
425 {"stop", SkSVGType_Stop},
426 {"svg", SkSVGType_SVG},
427 {"symbol", SkSVGType_Symbol},
428 {"text", SkSVGType_Text},
429 {"tspan", SkSVGType_Tspan},
430 {"use", SkSVGType_Use}
431 };
432
433 const int kSVGTypeNamesSize = SK_ARRAY_COUNT(gSVGTypeNames);
434
435 SkSVGTypes SkSVGParser::GetType(const char match[], size_t len ) {
436 int index = SkStrSearch(&gSVGTypeNames[0].fName, kSVGTypeNamesSize, match,
437 len, sizeof(gSVGTypeNames[0]));
438 return index >= 0 && index < kSVGTypeNamesSize ? gSVGTypeNames[index].fType :
439 (SkSVGTypes) -1;
440 }
OLDNEW
« no previous file with comments | « src/svg/parser/SkSVGPaintState.cpp ('k') | src/svg/parser/SkSVGPath.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698