1 | /* |
2 | * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. |
3 | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
5 | * of this software and associated documentation files (the "Software"), to deal |
6 | * in the Software without restriction, including without limitation the rights |
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
8 | * copies of the Software, and to permit persons to whom the Software is |
9 | * furnished to do so, subject to the following conditions: |
10 | |
11 | * The above copyright notice and this permission notice shall be included in all |
12 | * copies or substantial portions of the Software. |
13 | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
20 | * SOFTWARE. |
21 | */ |
22 | |
23 | #ifndef _TVG_SVG_LOADER_COMMON_H_ |
24 | #define _TVG_SVG_LOADER_COMMON_H_ |
25 | |
26 | #include "tvgCommon.h" |
27 | #include "tvgArray.h" |
28 | |
29 | struct SvgNode; |
30 | struct SvgStyleGradient; |
31 | |
32 | //NOTE: Please update simpleXmlNodeTypeToString() as well. |
33 | enum class SvgNodeType |
34 | { |
35 | Doc, |
36 | G, |
37 | Defs, |
38 | Animation, |
39 | Arc, |
40 | Circle, |
41 | Ellipse, |
42 | Image, |
43 | Line, |
44 | Path, |
45 | Polygon, |
46 | Polyline, |
47 | Rect, |
48 | Text, |
49 | TextArea, |
50 | Tspan, |
51 | Use, |
52 | Video, |
53 | ClipPath, |
54 | Mask, |
55 | CssStyle, |
56 | Symbol, |
57 | Unknown |
58 | }; |
59 | |
60 | /* |
61 | // TODO - remove? |
62 | enum class SvgLengthType |
63 | { |
64 | Percent, |
65 | Px, |
66 | Pc, |
67 | Pt, |
68 | Mm, |
69 | Cm, |
70 | In, |
71 | }; |
72 | */ |
73 | |
74 | enum class SvgFillFlags |
75 | { |
76 | Paint = 0x01, |
77 | Opacity = 0x02, |
78 | Gradient = 0x04, |
79 | FillRule = 0x08, |
80 | ClipPath = 0x16 |
81 | }; |
82 | |
83 | constexpr bool operator &(SvgFillFlags a, SvgFillFlags b) |
84 | { |
85 | return int(a) & int(b); |
86 | } |
87 | |
88 | constexpr SvgFillFlags operator |(SvgFillFlags a, SvgFillFlags b) |
89 | { |
90 | return SvgFillFlags(int(a) | int(b)); |
91 | } |
92 | |
93 | enum class SvgStrokeFlags |
94 | { |
95 | Paint = 0x1, |
96 | Opacity = 0x2, |
97 | Gradient = 0x4, |
98 | Scale = 0x8, |
99 | Width = 0x10, |
100 | Cap = 0x20, |
101 | Join = 0x40, |
102 | Dash = 0x80, |
103 | Miterlimit = 0x100 |
104 | }; |
105 | |
106 | constexpr bool operator &(SvgStrokeFlags a, SvgStrokeFlags b) |
107 | { |
108 | return int(a) & int(b); |
109 | } |
110 | |
111 | constexpr SvgStrokeFlags operator |(SvgStrokeFlags a, SvgStrokeFlags b) |
112 | { |
113 | return SvgStrokeFlags(int(a) | int(b)); |
114 | } |
115 | |
116 | |
117 | enum class SvgGradientType |
118 | { |
119 | Linear, |
120 | Radial |
121 | }; |
122 | |
123 | enum class SvgStyleFlags |
124 | { |
125 | Color = 0x01, |
126 | Fill = 0x02, |
127 | FillRule = 0x04, |
128 | FillOpacity = 0x08, |
129 | Opacity = 0x010, |
130 | Stroke = 0x20, |
131 | StrokeWidth = 0x40, |
132 | StrokeLineJoin = 0x80, |
133 | StrokeLineCap = 0x100, |
134 | StrokeOpacity = 0x200, |
135 | StrokeDashArray = 0x400, |
136 | Transform = 0x800, |
137 | ClipPath = 0x1000, |
138 | Mask = 0x2000, |
139 | MaskType = 0x4000, |
140 | Display = 0x8000, |
141 | PaintOrder = 0x10000, |
142 | StrokeMiterlimit = 0x20000 |
143 | }; |
144 | |
145 | constexpr bool operator &(SvgStyleFlags a, SvgStyleFlags b) |
146 | { |
147 | return int(a) & int(b); |
148 | } |
149 | |
150 | constexpr SvgStyleFlags operator |(SvgStyleFlags a, SvgStyleFlags b) |
151 | { |
152 | return SvgStyleFlags(int(a) | int(b)); |
153 | } |
154 | |
155 | enum class SvgStopStyleFlags |
156 | { |
157 | StopDefault = 0x0, |
158 | StopOpacity = 0x01, |
159 | StopColor = 0x02 |
160 | }; |
161 | |
162 | constexpr bool operator &(SvgStopStyleFlags a, SvgStopStyleFlags b) |
163 | { |
164 | return int(a) & int(b); |
165 | } |
166 | |
167 | constexpr SvgStopStyleFlags operator |(SvgStopStyleFlags a, SvgStopStyleFlags b) |
168 | { |
169 | return SvgStopStyleFlags(int(a) | int(b)); |
170 | } |
171 | |
172 | enum class SvgGradientFlags |
173 | { |
174 | None = 0x0, |
175 | GradientUnits = 0x1, |
176 | SpreadMethod = 0x2, |
177 | X1 = 0x4, |
178 | X2 = 0x8, |
179 | Y1 = 0x10, |
180 | Y2 = 0x20, |
181 | Cx = 0x40, |
182 | Cy = 0x80, |
183 | R = 0x100, |
184 | Fx = 0x200, |
185 | Fy = 0x400 |
186 | }; |
187 | |
188 | constexpr bool operator &(SvgGradientFlags a, SvgGradientFlags b) |
189 | { |
190 | return int(a) & int(b); |
191 | } |
192 | |
193 | constexpr SvgGradientFlags operator |(SvgGradientFlags a, SvgGradientFlags b) |
194 | { |
195 | return SvgGradientFlags(int(a) | int(b)); |
196 | } |
197 | |
198 | enum class SvgFillRule |
199 | { |
200 | Winding = 0, |
201 | OddEven = 1 |
202 | }; |
203 | |
204 | enum class SvgMaskType |
205 | { |
206 | Luminance = 0, |
207 | Alpha |
208 | }; |
209 | |
210 | //Length type to recalculate %, pt, pc, mm, cm etc |
211 | enum class SvgParserLengthType |
212 | { |
213 | Vertical, |
214 | Horizontal, |
215 | //In case of, for example, radius of radial gradient |
216 | Other |
217 | }; |
218 | |
219 | enum class SvgViewFlag |
220 | { |
221 | None = 0x0, |
222 | Width = 0x01, //viewPort width |
223 | Height = 0x02, //viewPort height |
224 | Viewbox = 0x04, //viewBox x,y,w,h - used only if all 4 are correctly set |
225 | WidthInPercent = 0x08, |
226 | HeightInPercent = 0x10 |
227 | }; |
228 | |
229 | constexpr bool operator &(SvgViewFlag a, SvgViewFlag b) |
230 | { |
231 | return static_cast<int>(a) & static_cast<int>(b); |
232 | } |
233 | |
234 | constexpr SvgViewFlag operator |(SvgViewFlag a, SvgViewFlag b) |
235 | { |
236 | return SvgViewFlag(int(a) | int(b)); |
237 | } |
238 | |
239 | constexpr SvgViewFlag operator ^(SvgViewFlag a, SvgViewFlag b) |
240 | { |
241 | return SvgViewFlag(int(a) ^ int(b)); |
242 | } |
243 | |
244 | enum class AspectRatioAlign |
245 | { |
246 | None, |
247 | XMinYMin, |
248 | XMidYMin, |
249 | XMaxYMin, |
250 | XMinYMid, |
251 | XMidYMid, |
252 | XMaxYMid, |
253 | XMinYMax, |
254 | XMidYMax, |
255 | XMaxYMax |
256 | }; |
257 | |
258 | enum class AspectRatioMeetOrSlice |
259 | { |
260 | Meet, |
261 | Slice |
262 | }; |
263 | |
264 | struct SvgDocNode |
265 | { |
266 | float w; //unit: point or in percentage see: SvgViewFlag |
267 | float h; //unit: point or in percentage see: SvgViewFlag |
268 | float vx; |
269 | float vy; |
270 | float vw; |
271 | float vh; |
272 | SvgViewFlag viewFlag; |
273 | SvgNode* defs; |
274 | SvgNode* style; |
275 | AspectRatioAlign align; |
276 | AspectRatioMeetOrSlice meetOrSlice; |
277 | }; |
278 | |
279 | struct SvgGNode |
280 | { |
281 | }; |
282 | |
283 | struct SvgDefsNode |
284 | { |
285 | Array<SvgStyleGradient*> gradients; |
286 | }; |
287 | |
288 | struct SvgSymbolNode |
289 | { |
290 | float w, h; |
291 | float vx, vy, vw, vh; |
292 | AspectRatioAlign align; |
293 | AspectRatioMeetOrSlice meetOrSlice; |
294 | bool overflowVisible; |
295 | bool hasViewBox; |
296 | bool hasWidth; |
297 | bool hasHeight; |
298 | }; |
299 | |
300 | struct SvgUseNode |
301 | { |
302 | float x, y, w, h; |
303 | bool isWidthSet; |
304 | bool isHeightSet; |
305 | SvgNode* symbol; |
306 | }; |
307 | |
308 | struct SvgEllipseNode |
309 | { |
310 | float cx; |
311 | float cy; |
312 | float rx; |
313 | float ry; |
314 | }; |
315 | |
316 | struct SvgCircleNode |
317 | { |
318 | float cx; |
319 | float cy; |
320 | float r; |
321 | }; |
322 | |
323 | struct SvgRectNode |
324 | { |
325 | float x; |
326 | float y; |
327 | float w; |
328 | float h; |
329 | float rx; |
330 | float ry; |
331 | bool hasRx; |
332 | bool hasRy; |
333 | }; |
334 | |
335 | struct SvgLineNode |
336 | { |
337 | float x1; |
338 | float y1; |
339 | float x2; |
340 | float y2; |
341 | }; |
342 | |
343 | struct SvgImageNode |
344 | { |
345 | float x, y, w, h; |
346 | char* href; |
347 | }; |
348 | |
349 | struct SvgPathNode |
350 | { |
351 | char* path; |
352 | }; |
353 | |
354 | struct SvgPolygonNode |
355 | { |
356 | Array<float> pts; |
357 | }; |
358 | |
359 | struct SvgClipNode |
360 | { |
361 | bool userSpace; |
362 | }; |
363 | |
364 | struct SvgMaskNode |
365 | { |
366 | SvgMaskType type; |
367 | bool userSpace; |
368 | }; |
369 | |
370 | struct SvgCssStyleNode |
371 | { |
372 | }; |
373 | |
374 | struct SvgLinearGradient |
375 | { |
376 | float x1; |
377 | float y1; |
378 | float x2; |
379 | float y2; |
380 | bool isX1Percentage; |
381 | bool isY1Percentage; |
382 | bool isX2Percentage; |
383 | bool isY2Percentage; |
384 | }; |
385 | |
386 | struct SvgRadialGradient |
387 | { |
388 | float cx; |
389 | float cy; |
390 | float fx; |
391 | float fy; |
392 | float r; |
393 | bool isCxPercentage; |
394 | bool isCyPercentage; |
395 | bool isFxPercentage; |
396 | bool isFyPercentage; |
397 | bool isRPercentage; |
398 | }; |
399 | |
400 | struct SvgComposite |
401 | { |
402 | char *url; |
403 | SvgNode* node; |
404 | bool applying; //flag for checking circular dependency. |
405 | }; |
406 | |
407 | struct SvgColor |
408 | { |
409 | uint8_t r; |
410 | uint8_t g; |
411 | uint8_t b; |
412 | }; |
413 | |
414 | struct SvgPaint |
415 | { |
416 | SvgStyleGradient* gradient; |
417 | char *url; |
418 | SvgColor color; |
419 | bool none; |
420 | bool curColor; |
421 | }; |
422 | |
423 | struct SvgDash |
424 | { |
425 | Array<float> array; |
426 | }; |
427 | |
428 | struct SvgStyleGradient |
429 | { |
430 | SvgGradientType type; |
431 | char* id; |
432 | char* ref; |
433 | FillSpread spread; |
434 | SvgRadialGradient* radial; |
435 | SvgLinearGradient* linear; |
436 | Matrix* transform; |
437 | Array<Fill::ColorStop> stops; |
438 | SvgGradientFlags flags; |
439 | bool userSpace; |
440 | |
441 | void clear() |
442 | { |
443 | stops.reset(); |
444 | free(transform); |
445 | free(radial); |
446 | free(linear); |
447 | free(ref); |
448 | free(id); |
449 | } |
450 | }; |
451 | |
452 | struct SvgStyleFill |
453 | { |
454 | SvgFillFlags flags; |
455 | SvgPaint paint; |
456 | int opacity; |
457 | FillRule fillRule; |
458 | }; |
459 | |
460 | struct SvgStyleStroke |
461 | { |
462 | SvgStrokeFlags flags; |
463 | SvgPaint paint; |
464 | int opacity; |
465 | float scale; |
466 | float width; |
467 | float centered; |
468 | StrokeCap cap; |
469 | StrokeJoin join; |
470 | float miterlimit; |
471 | SvgDash dash; |
472 | int dashCount; |
473 | }; |
474 | |
475 | struct SvgStyleProperty |
476 | { |
477 | SvgStyleFill fill; |
478 | SvgStyleStroke stroke; |
479 | SvgComposite clipPath; |
480 | SvgComposite mask; |
481 | int opacity; |
482 | SvgColor color; |
483 | bool curColorSet; |
484 | char* cssClass; |
485 | bool paintOrder; //true if default (fill, stroke), false otherwise |
486 | SvgStyleFlags flags; |
487 | SvgStyleFlags flagsImportance; //indicates the importance of the flag - if set, higher priority is applied (https://drafts.csswg.org/css-cascade-4/#importance) |
488 | }; |
489 | |
490 | struct SvgNode |
491 | { |
492 | SvgNodeType type; |
493 | SvgNode* parent; |
494 | Array<SvgNode*> child; |
495 | char *id; |
496 | SvgStyleProperty *style; |
497 | Matrix* transform; |
498 | union { |
499 | SvgGNode g; |
500 | SvgDocNode doc; |
501 | SvgDefsNode defs; |
502 | SvgUseNode use; |
503 | SvgCircleNode circle; |
504 | SvgEllipseNode ellipse; |
505 | SvgPolygonNode polygon; |
506 | SvgPolygonNode polyline; |
507 | SvgRectNode rect; |
508 | SvgPathNode path; |
509 | SvgLineNode line; |
510 | SvgImageNode image; |
511 | SvgMaskNode mask; |
512 | SvgClipNode clip; |
513 | SvgCssStyleNode cssStyle; |
514 | SvgSymbolNode symbol; |
515 | } node; |
516 | bool display; |
517 | ~SvgNode(); |
518 | }; |
519 | |
520 | struct SvgParser |
521 | { |
522 | SvgNode* node; |
523 | SvgStyleGradient* styleGrad; |
524 | Fill::ColorStop gradStop; |
525 | SvgStopStyleFlags flags; |
526 | struct |
527 | { |
528 | float x, y, w, h; |
529 | } global; |
530 | struct |
531 | { |
532 | bool parsedFx; |
533 | bool parsedFy; |
534 | } gradient; |
535 | }; |
536 | |
537 | struct SvgNodeIdPair |
538 | { |
539 | SvgNode* node; |
540 | char *id; |
541 | }; |
542 | |
543 | struct SvgLoaderData |
544 | { |
545 | Array<SvgNode*> stack; |
546 | SvgNode* doc = nullptr; |
547 | SvgNode* def = nullptr; |
548 | SvgNode* cssStyle = nullptr; |
549 | Array<SvgStyleGradient*> gradients; |
550 | SvgStyleGradient* latestGradient = nullptr; //For stops |
551 | SvgParser* svgParse = nullptr; |
552 | Array<SvgNodeIdPair> cloneNodes; |
553 | Array<SvgNodeIdPair> nodesToStyle; |
554 | int level = 0; |
555 | bool result = false; |
556 | bool style = false; |
557 | }; |
558 | |
559 | struct Box |
560 | { |
561 | float x, y, w, h; |
562 | }; |
563 | |
564 | /* |
565 | * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strtof-strtod-l-wcstod-wcstod-l?view=vs-2017 |
566 | * |
567 | * src should be one of the following form : |
568 | * |
569 | * [whitespace] [sign] {digits [radix digits] | radix digits} [{e | E} [sign] digits] |
570 | * [whitespace] [sign] {INF | INFINITY} |
571 | * [whitespace] [sign] NAN [sequence] |
572 | * |
573 | * No hexadecimal form supported |
574 | * no sequence supported after NAN |
575 | */ |
576 | float customStrtof(const char *nptr, char **endptr); |
577 | |
578 | #endif |
579 | |