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
29struct SvgNode;
30struct SvgStyleGradient;
31
32//NOTE: Please update simpleXmlNodeTypeToString() as well.
33enum 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?
62enum class SvgLengthType
63{
64 Percent,
65 Px,
66 Pc,
67 Pt,
68 Mm,
69 Cm,
70 In,
71};
72*/
73
74enum class SvgFillFlags
75{
76 Paint = 0x01,
77 Opacity = 0x02,
78 Gradient = 0x04,
79 FillRule = 0x08,
80 ClipPath = 0x16
81};
82
83constexpr bool operator &(SvgFillFlags a, SvgFillFlags b)
84{
85 return int(a) & int(b);
86}
87
88constexpr SvgFillFlags operator |(SvgFillFlags a, SvgFillFlags b)
89{
90 return SvgFillFlags(int(a) | int(b));
91}
92
93enum 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
106constexpr bool operator &(SvgStrokeFlags a, SvgStrokeFlags b)
107{
108 return int(a) & int(b);
109}
110
111constexpr SvgStrokeFlags operator |(SvgStrokeFlags a, SvgStrokeFlags b)
112{
113 return SvgStrokeFlags(int(a) | int(b));
114}
115
116
117enum class SvgGradientType
118{
119 Linear,
120 Radial
121};
122
123enum 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
145constexpr bool operator &(SvgStyleFlags a, SvgStyleFlags b)
146{
147 return int(a) & int(b);
148}
149
150constexpr SvgStyleFlags operator |(SvgStyleFlags a, SvgStyleFlags b)
151{
152 return SvgStyleFlags(int(a) | int(b));
153}
154
155enum class SvgStopStyleFlags
156{
157 StopDefault = 0x0,
158 StopOpacity = 0x01,
159 StopColor = 0x02
160};
161
162constexpr bool operator &(SvgStopStyleFlags a, SvgStopStyleFlags b)
163{
164 return int(a) & int(b);
165}
166
167constexpr SvgStopStyleFlags operator |(SvgStopStyleFlags a, SvgStopStyleFlags b)
168{
169 return SvgStopStyleFlags(int(a) | int(b));
170}
171
172enum 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
188constexpr bool operator &(SvgGradientFlags a, SvgGradientFlags b)
189{
190 return int(a) & int(b);
191}
192
193constexpr SvgGradientFlags operator |(SvgGradientFlags a, SvgGradientFlags b)
194{
195 return SvgGradientFlags(int(a) | int(b));
196}
197
198enum class SvgFillRule
199{
200 Winding = 0,
201 OddEven = 1
202};
203
204enum class SvgMaskType
205{
206 Luminance = 0,
207 Alpha
208};
209
210//Length type to recalculate %, pt, pc, mm, cm etc
211enum class SvgParserLengthType
212{
213 Vertical,
214 Horizontal,
215 //In case of, for example, radius of radial gradient
216 Other
217};
218
219enum 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
229constexpr bool operator &(SvgViewFlag a, SvgViewFlag b)
230{
231 return static_cast<int>(a) & static_cast<int>(b);
232}
233
234constexpr SvgViewFlag operator |(SvgViewFlag a, SvgViewFlag b)
235{
236 return SvgViewFlag(int(a) | int(b));
237}
238
239constexpr SvgViewFlag operator ^(SvgViewFlag a, SvgViewFlag b)
240{
241 return SvgViewFlag(int(a) ^ int(b));
242}
243
244enum 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
258enum class AspectRatioMeetOrSlice
259{
260 Meet,
261 Slice
262};
263
264struct 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
279struct SvgGNode
280{
281};
282
283struct SvgDefsNode
284{
285 Array<SvgStyleGradient*> gradients;
286};
287
288struct 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
300struct SvgUseNode
301{
302 float x, y, w, h;
303 bool isWidthSet;
304 bool isHeightSet;
305 SvgNode* symbol;
306};
307
308struct SvgEllipseNode
309{
310 float cx;
311 float cy;
312 float rx;
313 float ry;
314};
315
316struct SvgCircleNode
317{
318 float cx;
319 float cy;
320 float r;
321};
322
323struct 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
335struct SvgLineNode
336{
337 float x1;
338 float y1;
339 float x2;
340 float y2;
341};
342
343struct SvgImageNode
344{
345 float x, y, w, h;
346 char* href;
347};
348
349struct SvgPathNode
350{
351 char* path;
352};
353
354struct SvgPolygonNode
355{
356 Array<float> pts;
357};
358
359struct SvgClipNode
360{
361 bool userSpace;
362};
363
364struct SvgMaskNode
365{
366 SvgMaskType type;
367 bool userSpace;
368};
369
370struct SvgCssStyleNode
371{
372};
373
374struct 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
386struct 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
400struct SvgComposite
401{
402 char *url;
403 SvgNode* node;
404 bool applying; //flag for checking circular dependency.
405};
406
407struct SvgColor
408{
409 uint8_t r;
410 uint8_t g;
411 uint8_t b;
412};
413
414struct SvgPaint
415{
416 SvgStyleGradient* gradient;
417 char *url;
418 SvgColor color;
419 bool none;
420 bool curColor;
421};
422
423struct SvgDash
424{
425 Array<float> array;
426};
427
428struct 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
452struct SvgStyleFill
453{
454 SvgFillFlags flags;
455 SvgPaint paint;
456 int opacity;
457 FillRule fillRule;
458};
459
460struct 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
475struct 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
490struct 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
520struct 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
537struct SvgNodeIdPair
538{
539 SvgNode* node;
540 char *id;
541};
542
543struct 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
559struct 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 */
576float customStrtof(const char *nptr, char **endptr);
577
578#endif
579