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