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

Side by Side Diff: src/svg/parser/SkSVGPaintState.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/SkSVGMetadata.cpp ('k') | src/svg/parser/SkSVGParser.cpp » ('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 "SkSVGPaintState.h"
10 #include "SkSVGElements.h"
11 #include "SkSVGParser.h"
12 #include "SkParse.h"
13
14 SkSVGAttribute SkSVGPaint::gAttributes[] = {
15 SVG_LITERAL_ATTRIBUTE(clip-path, f_clipPath),
16 SVG_LITERAL_ATTRIBUTE(clip-rule, f_clipRule),
17 SVG_LITERAL_ATTRIBUTE(enable-background, f_enableBackground),
18 SVG_ATTRIBUTE(fill),
19 SVG_LITERAL_ATTRIBUTE(fill-rule, f_fillRule),
20 SVG_ATTRIBUTE(filter),
21 SVG_LITERAL_ATTRIBUTE(font-family, f_fontFamily),
22 SVG_LITERAL_ATTRIBUTE(font-size, f_fontSize),
23 SVG_LITERAL_ATTRIBUTE(letter-spacing, f_letterSpacing),
24 SVG_ATTRIBUTE(mask),
25 SVG_ATTRIBUTE(opacity),
26 SVG_LITERAL_ATTRIBUTE(stop-color, f_stopColor),
27 SVG_LITERAL_ATTRIBUTE(stop-opacity, f_stopOpacity),
28 SVG_ATTRIBUTE(stroke),
29 SVG_LITERAL_ATTRIBUTE(stroke-dasharray, f_strokeDasharray),
30 SVG_LITERAL_ATTRIBUTE(stroke-linecap, f_strokeLinecap),
31 SVG_LITERAL_ATTRIBUTE(stroke-linejoin, f_strokeLinejoin),
32 SVG_LITERAL_ATTRIBUTE(stroke-miterlimit, f_strokeMiterlimit),
33 SVG_LITERAL_ATTRIBUTE(stroke-width, f_strokeWidth),
34 SVG_ATTRIBUTE(style),
35 SVG_ATTRIBUTE(transform)
36 };
37
38 const int SkSVGPaint::kAttributesSize = SK_ARRAY_COUNT(SkSVGPaint::gAttributes);
39
40 SkSVGPaint::SkSVGPaint() : fNext(nullptr) {
41 }
42
43 SkString* SkSVGPaint::operator[](int index) {
44 SkASSERT(index >= 0);
45 SkASSERT(index < &fTerminal - &fInitial);
46 SkASSERT(&fTerminal - &fInitial == kTerminal - kInitial);
47 SkString* result = &fInitial + index + 1;
48 return result;
49 }
50
51 void SkSVGPaint::addAttribute(SkSVGParser& parser, int attrIndex,
52 const char* attrValue, size_t attrLength) {
53 SkString* attr = (*this)[attrIndex];
54 switch(attrIndex) {
55 case kClipPath:
56 case kClipRule:
57 case kEnableBackground:
58 case kFill:
59 case kFillRule:
60 case kFilter:
61 case kFontFamily:
62 case kFontSize:
63 case kLetterSpacing:
64 case kMask:
65 case kOpacity:
66 case kStopColor:
67 case kStopOpacity:
68 case kStroke:
69 case kStroke_Dasharray:
70 case kStroke_Linecap:
71 case kStroke_Linejoin:
72 case kStroke_Miterlimit:
73 case kStroke_Width:
74 case kTransform:
75 attr->set(attrValue, attrLength);
76 return;
77 case kStyle: {
78 // iterate through colon / semi-colon delimited pairs
79 int pairs = SkParse::Count(attrValue, ';');
80 const char* attrEnd = attrValue + attrLength;
81 do {
82 const char* end = strchr(attrValue, ';');
83 if (end == nullptr)
84 end = attrEnd;
85 const char* delimiter = strchr(attrValue, ':');
86 SkASSERT(delimiter != 0 && delimiter < end);
87 int index = parser.findAttribute(this, attrValue, (int) (delimit er - attrValue), true);
88 SkASSERT(index >= 0);
89 delimiter++;
90 addAttribute(parser, index, delimiter, (int) (end - delimiter));
91 attrValue = end + 1;
92 } while (--pairs);
93 return;
94 }
95 default:
96 SkASSERT(0);
97 }
98 }
99
100 bool SkSVGPaint::flush(SkSVGParser& parser, bool isFlushable, bool isDef) {
101 SkSVGPaint current;
102 SkSVGPaint* walking = parser.fHead;
103 int index;
104 while (walking != nullptr) {
105 for (index = kInitial + 1; index < kTerminal; index++) {
106 SkString* lastAttr = (*walking)[index];
107 if (lastAttr->size() == 0)
108 continue;
109 if (current[index]->size() > 0)
110 continue;
111 current[index]->set(*lastAttr);
112 }
113 walking = walking->fNext;
114 }
115 bool paintChanged = false;
116 SkSVGPaint& lastState = parser.fLastFlush;
117 if (isFlushable == false) {
118 if (isDef == true) {
119 if (current.f_mask.size() > 0 && current.f_mask.equals(lastState.f_m ask) == false) {
120 SkSVGElement* found;
121 const char* idStart = strchr(current.f_mask.c_str(), '#');
122 SkASSERT(idStart);
123 SkString id(idStart + 1, strlen(idStart) - 2);
124 bool itsFound = parser.fIDs.find(id.c_str(), &found);
125 SkASSERT(itsFound);
126 SkSVGElement* gradient = found->getGradient();
127 if (gradient) {
128 gradient->write(parser, current.f_fill);
129 gradient->write(parser, current.f_stroke);
130 }
131 }
132 }
133 goto setLast;
134 }
135 {
136 bool changed[kTerminal];
137 memset(changed, 0, sizeof(changed));
138 for (index = kInitial + 1; index < kTerminal; index++) {
139 if (index == kTransform || index == kClipPath || index == kStopColor || index == kStopOpacity ||
140 index == kClipRule || index == kFillRule)
141 continue;
142 SkString* lastAttr = lastState[index];
143 SkString* currentAttr = current[index];
144 paintChanged |= changed[index] = lastAttr->equals(*currentAttr) == f alse;
145 }
146 if (paintChanged) {
147 if (current.f_mask.size() > 0) {
148 if (current.f_fill.equals("none") == false && strncmp(current.f_ fill.c_str(), "url(#", 5) != 0) {
149 SkASSERT(current.f_fill.c_str()[0] == '#');
150 SkString replacement("url(#mask");
151 replacement.append(current.f_fill.c_str() + 1);
152 replacement.appendUnichar(')');
153 current.f_fill.set(replacement);
154 }
155 if (current.f_stroke.equals("none") == false && strncmp(current. f_stroke.c_str(), "url(#", 5) != 0) {
156 SkASSERT(current.f_stroke.c_str()[0] == '#');
157 SkString replacement("url(#mask");
158 replacement.append(current.f_stroke.c_str() + 1);
159 replacement.appendUnichar(')');
160 current.f_stroke.set(replacement);
161 }
162 }
163 if (current.f_fill.equals("none") && current.f_stroke.equals("none") )
164 current.f_opacity.set("0");
165 if (parser.fSuppressPaint == false) {
166 parser._startElement("paint");
167 bool success = writeChangedAttributes(parser, current, changed);
168 if (success == false)
169 return paintChanged;
170 success = writeChangedElements(parser, current, changed);
171 if (success == false)
172 return paintChanged;
173 parser._endElement(); // paint
174 }
175 }
176 }
177 setLast:
178 for (index = kInitial + 1; index < kTerminal; index++) {
179 SkString* lastAttr = lastState[index];
180 SkString* currentAttr = current[index];
181 lastAttr->set(*currentAttr);
182 }
183 return paintChanged;
184 }
185
186 int SkSVGPaint::getAttributes(const SkSVGAttribute** attrPtr) {
187 *attrPtr = gAttributes;
188 return kAttributesSize;
189 }
190
191 void SkSVGPaint::setSave(SkSVGParser& parser) {
192 SkTDArray<SkString*> clips;
193 SkSVGPaint* walking = parser.fHead;
194 int index;
195 SkMatrix sum;
196 sum.reset();
197 while (walking != nullptr) {
198 for (index = kInitial + 1; index < kTerminal; index++) {
199 SkString* lastAttr = (*walking)[index];
200 if (lastAttr->size() == 0)
201 continue;
202 if (index == kTransform) {
203 const char* str = lastAttr->c_str();
204 SkASSERT(strncmp(str, "matrix(", 7) == 0);
205 str += 6;
206 const char* strEnd = strrchr(str, ')');
207 SkASSERT(strEnd != nullptr);
208 SkString mat(str, strEnd - str);
209 SkSVGParser::ConvertToArray(mat);
210 SkScalar values[6];
211 SkParse::FindScalars(mat.c_str() + 1, values, 6);
212 SkMatrix matrix;
213 matrix.reset();
214 matrix.setScaleX(values[0]);
215 matrix.setSkewY(values[1]);
216 matrix.setSkewX(values[2]);
217 matrix.setScaleY(values[3]);
218 matrix.setTranslateX(values[4]);
219 matrix.setTranslateY(values[5]);
220 sum.setConcat(matrix, sum);
221 continue;
222 }
223 if ( index == kClipPath)
224 *clips.insert(0) = lastAttr;
225 }
226 walking = walking->fNext;
227 }
228 if ((sum == parser.fLastTransform) == false) {
229 SkMatrix inverse;
230 bool success = parser.fLastTransform.invert(&inverse);
231 SkASSERT(success == true);
232 SkMatrix output;
233 output.setConcat(inverse, sum);
234 parser.fLastTransform = sum;
235 SkString outputStr;
236 outputStr.appendUnichar('[');
237 outputStr.appendScalar(output.getScaleX());
238 outputStr.appendUnichar(',');
239 outputStr.appendScalar(output.getSkewX());
240 outputStr.appendUnichar(',');
241 outputStr.appendScalar(output.getTranslateX());
242 outputStr.appendUnichar(',');
243 outputStr.appendScalar(output.getSkewY());
244 outputStr.appendUnichar(',');
245 outputStr.appendScalar(output.getScaleY());
246 outputStr.appendUnichar(',');
247 outputStr.appendScalar(output.getTranslateY());
248 outputStr.appendUnichar(',');
249 outputStr.appendScalar(output.getPerspX());
250 outputStr.appendUnichar(',');
251 outputStr.appendScalar(output.getPerspY());
252 outputStr.append(",1]");
253 parser._startElement("matrix");
254 parser._addAttributeLen("matrix", outputStr.c_str(), outputStr.size());
255 parser._endElement();
256 }
257 #if 0 // incomplete
258 if (parser.fTransformClips.size() > 0) {
259 // need to reset the clip when the 'g' scope is ended
260 parser._startElement("add");
261 const char* start = strchr(current->f_clipPath.c_str(), '#') + 1;
262 SkASSERT(start);
263 parser._addAttributeLen("use", start, strlen(start) - 1);
264 parser._endElement(); // clip
265 }
266 #endif
267 }
268
269 bool SkSVGPaint::writeChangedAttributes(SkSVGParser& parser,
270 SkSVGPaint& current, bool* changed) {
271 SkSVGPaint& lastState = parser.fLastFlush;
272 for (int index = kInitial + 1; index < kTerminal; index++) {
273 if (changed[index] == false)
274 continue;
275 SkString* topAttr = current[index];
276 size_t attrLength = topAttr->size();
277 if (attrLength == 0)
278 continue;
279 const char* attrValue = topAttr->c_str();
280 SkString* lastAttr = lastState[index];
281 switch(index) {
282 case kClipPath:
283 case kClipRule:
284 case kEnableBackground:
285 break;
286 case kFill:
287 if (topAttr->equals("none") == false && lastAttr->equals("none") == true)
288 parser._addAttribute("stroke", "false");
289 goto fillStrokeAttrCommon;
290 case kFillRule:
291 case kFilter:
292 case kFontFamily:
293 break;
294 case kFontSize:
295 parser._addAttributeLen("textSize", attrValue, attrLength);
296 break;
297 case kLetterSpacing:
298 parser._addAttributeLen("textTracking", attrValue, attrLength);
299 break;
300 case kMask:
301 break;
302 case kOpacity:
303 break;
304 case kStopColor:
305 break;
306 case kStopOpacity:
307 break;
308 case kStroke:
309 if (topAttr->equals("none") == false && lastAttr->equals("none") == true)
310 parser._addAttribute("stroke", "true");
311 fillStrokeAttrCommon:
312 if (strncmp(attrValue, "url(", 4) == 0) {
313 SkASSERT(attrValue[4] == '#');
314 const char* idStart = attrValue + 5;
315 const char* idEnd = strrchr(attrValue, ')');
316 SkASSERT(idStart < idEnd);
317 SkString id(idStart, idEnd - idStart);
318 SkSVGElement* found;
319 if (strncmp(id.c_str(), "mask", 4) != 0) {
320 bool itsFound = parser.fIDs.find(id.c_str(), &found);
321 SkASSERT(itsFound);
322 SkASSERT(found->getType() == SkSVGType_LinearGradient ||
323 found->getType() == SkSVGType_RadialGradient);
324 }
325 parser._addAttribute("shader", id.c_str());
326 }
327 break;
328 case kStroke_Dasharray:
329 break;
330 case kStroke_Linecap:
331 parser._addAttributeLen("strokeCap", attrValue, attrLength);
332 break;
333 case kStroke_Linejoin:
334 parser._addAttributeLen("strokeJoin", attrValue, attrLength);
335 break;
336 case kStroke_Miterlimit:
337 parser._addAttributeLen("strokeMiter", attrValue, attrLength);
338 break;
339 case kStroke_Width:
340 parser._addAttributeLen("strokeWidth", attrValue, attrLength);
341 case kStyle:
342 case kTransform:
343 break;
344 default:
345 SkASSERT(0);
346 return false;
347 }
348 }
349 return true;
350 }
351
352 bool SkSVGPaint::writeChangedElements(SkSVGParser& parser,
353 SkSVGPaint& current, bool* changed) {
354 SkSVGPaint& lastState = parser.fLastFlush;
355 for (int index = kInitial + 1; index < kTerminal; index++) {
356 SkString* topAttr = current[index];
357 size_t attrLength = topAttr->size();
358 if (attrLength == 0)
359 continue;
360 const char* attrValue = topAttr->c_str();
361 SkString* lastAttr = lastState[index];
362 switch(index) {
363 case kClipPath:
364 case kClipRule:
365 // !!! need to add this outside of paint
366 break;
367 case kEnableBackground:
368 // !!! don't know what to do with this
369 break;
370 case kFill:
371 goto addColor;
372 case kFillRule:
373 case kFilter:
374 break;
375 case kFontFamily:
376 parser._startElement("typeface");
377 parser._addAttributeLen("fontName", attrValue, attrLength);
378 parser._endElement(); // typeface
379 break;
380 case kFontSize:
381 case kLetterSpacing:
382 break;
383 case kMask:
384 case kOpacity:
385 if (changed[kStroke] == false && changed[kFill] == false) {
386 parser._startElement("color");
387 SkString& opacity = current.f_opacity;
388 parser._addAttributeLen("color", parser.fLastColor.c_str(), parser.fLastColor.size());
389 parser._addAttributeLen("alpha", opacity.c_str(), opacity.si ze());
390 parser._endElement(); // color
391 }
392 break;
393 case kStopColor:
394 break;
395 case kStopOpacity:
396 break;
397 case kStroke:
398 addColor:
399 if (strncmp(lastAttr->c_str(), "url(", 4) == 0 && strncmp(attrVa lue, "url(", 4) != 0) {
400 parser._startElement("shader");
401 parser._endElement();
402 }
403 if (topAttr->equals(*lastAttr))
404 continue;
405 {
406 bool urlRef = strncmp(attrValue, "url(", 4) == 0;
407 bool colorNone = strcmp(attrValue, "none") == 0;
408 bool lastEqual = parser.fLastColor.equals(attrValue, attrLen gth);
409 bool newColor = urlRef == false && colorNone == false && las tEqual == false;
410 if (newColor || changed[kOpacity]) {
411 parser._startElement("color");
412 if (newColor || changed[kOpacity]) {
413 parser._addAttributeLen("color", attrValue, attrLeng th);
414 parser.fLastColor.set(attrValue, attrLength);
415 }
416 if (changed[kOpacity]) {
417 SkString& opacity = current.f_opacity;
418 parser._addAttributeLen("alpha", opacity.c_str(), op acity.size());
419 }
420 parser._endElement(); // color
421 }
422 }
423 break;
424 case kStroke_Dasharray:
425 parser._startElement("dash");
426 SkSVGParser::ConvertToArray(*topAttr);
427 parser._addAttribute("intervals", topAttr->c_str());
428 parser._endElement(); // dash
429 break;
430 case kStroke_Linecap:
431 case kStroke_Linejoin:
432 case kStroke_Miterlimit:
433 case kStroke_Width:
434 case kStyle:
435 case kTransform:
436 break;
437 default:
438 SkASSERT(0);
439 return false;
440 }
441 }
442 return true;
443 }
444
445 void SkSVGPaint::Push(SkSVGPaint** head, SkSVGPaint* newRecord) {
446 newRecord->fNext = *head;
447 *head = newRecord;
448 }
449
450 void SkSVGPaint::Pop(SkSVGPaint** head) {
451 SkSVGPaint* next = (*head)->fNext;
452 *head = next;
453 }
OLDNEW
« no previous file with comments | « src/svg/parser/SkSVGMetadata.cpp ('k') | src/svg/parser/SkSVGParser.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698