vglang 0.1.3

Fast and simple vector graphics programming language and svg-compatible high-level virtual machine.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
/// Angles are specified in one of two ways depending upon
/// whether they are used in CSS property syntax or SVG
/// presentation attribute syntax:
enum Angle { deg(float), grad(float), rad(float) }

/// A length is a distance Length, given as a number along with a unit which may be optional.
///
/// See [`length`](https://www.w3.org/TR/SVG11/types.html#DataTypeLength)
enum Length { 
    /// Represents the calculated font-size of the element. If used on the font-size property itself,
    /// it represents the inherited font-size of the element.
    em(float), 
    /// Represents the x-height of the element's font. In fonts with the x letter, this is generally
    /// the height of lowercase letters in the font; 1ex ≈ 0.5em in many fonts.
    ex(float), 
    /// Pixels
    px(float),
    /// Inches 
    inch(float), 
    /// Centimeters
    cm(float), 
    /// Millimeters
    mm(float), 
    /// Points, 1pt = 1/72nd of 1in
    pt(float), 
    /// Picas, 	1pc = 1/6th of 1in
    pc(float), 
    /// A percentage value
    percent(float),
}

/// Recognized color keyword names, compliant with svg 1.1.
enum ColorKeyWord {
    aliceblue,
    antiquewhite,
    aqua,
    aquamarine,
    azure,
    beige,
    bisque,
    black,
    blanchedalmond,
    blue,
    blueviolet,
    brown,
    burlywood,
    cadetblue,
    chartreuse,
    chocolate,
    coral,
    cornflowerblue,
    cornsilk,
    crimson,
    cyan,
    darkblue,
    darkcyan,
    darkgoldenrod,
    darkgray,
    darkgreen,
    darkgrey,
    darkkhaki,
    darkmagenta,
    darkolivegreen,
    darkorange,
    darkorchid,
    darkred,
    darksalmon,
    darkseagreen,
    darkslateblue,
    darkslategray,
    darkslategrey,
    darkturquoise,
    darkviolet,
    deeppink,
    deepskyblue,
    dimgray,
    dimgrey,
    dodgerblue,
    firebrick,
    floralwhite,
    forestgreen,
    fuchsia,
    gainsboro,
    ghostwhite,
    gold,
    goldenrod,
    gray,
    grey,
    green,
    greenyellow,
    honeydew,
    hotpink,
    indianred,
    indigo,
    ivory,
    khaki,
    lavender,
    lavenderblush,
    lawngreen,
    lemonchiffon,
    lightblue,
    lightcoral,
    lightcyan,
    lightgoldenrodyellow,
    lightgray,
    lightgreen,
    lightgrey,
    lightpink,
    lightsalmon,
    lightseagreen,
    lightskyblue,
    lightslategray,
    lightslategrey,
    lightsteelblue,
    lightyellow,
    lime,
    limegreen,
    linen,
    magenta,
    maroon,
    mediumaquamarine,
    mediumblue,
    mediumorchid,
    mediumpurple,
    mediumseagreen,
    mediumslateblue,
    mediumspringgreen,
    mediumturquoise,
    mediumvioletred,
    midnightblue,
    mintcream,
    mistyrose,
    moccasin,
    navajowhite,
    navy,
    oldlace,
    olive,
    olivedrab,
    orange,
    orangered,
    orchid,
    palegoldenrod,
    palegreen,
    paleturquoise,
    palevioletred,
    papayawhip,
    peachpuff,
    peru,
    pink,
    plum,
    powderblue,
    purple,
    red,
    rosybrown,
    royalblue,
    saddlebrown,
    salmon,
    sandybrown,
    seagreen,
    seashell,
    sienna,
    silver,
    skyblue,
    slateblue,
    slategray,
    slategrey,
    snow,
    springgreen,
    steelblue,
    tan,
    teal,
    thistle,
    tomato,
    turquoise,
    violet,
    wheat,
    white,
    whitesmoke,
    yellow,
    yellowgreen,
}

/// Color variant.
enum Color {
    /// A color represents with read,green and blue components.
    Rgb(ubyte,ubyte,ubyte),
    /// Represents as recognized color keywords.
    Keyword(ColorKeyWord),
}

enum Iri {
    Local(string),
    Path(string),
}

/// Functional notation for a reference. The syntax for this reference is the same as the [`CSS URI`].
///
/// [`CSS URI`]: https://developer.mozilla.org/en-US/docs/Web/CSS/url_value
data FuncIri(string);

/// A 2d coordinate point.
data Point(float,float);

/// Percentages are specified as a number followed by a "%" character:
data Percent(float);

/// ‘fillandstroketake on a value of type [`Paint`], which is specified as follows:
enum Paint {
    None,
    /// the explicit color to be used to paint the current object
    Color(Color), 
    /// A reference to a paint server.
    Server(FuncIri),
}

/// A pair of `number`s, where the second `number` is optional.
data NumberOptNumber(float, #[option] float);

/// Defines the coordinate system for attributesx1’, ‘y1’, ‘x2andy2’.
///
/// If attributegradientUnitsis not specified, then the effect is as if a value of 'objectBoundingBox' were specified.
enum Coords { 
    /// If gradientUnits="userSpaceOnUse", x1, y1, x2 and y2 represent values in the coordinate system
    /// that results from taking the current user coordinate system in place at the time when the gradient element
    /// is referenced (i.e., the user coordinate system for the element referencing the gradient element via afill’
    /// orstrokeproperty) and then applying the transform specified by attribute gradientTransform.
    UserSpaceOnUse,

    /// If gradientUnits="objectBoundingBox", the user coordinate system for attributes x1, y1, x2 and y2 is
    /// established using the bounding box of the element to which the gradient is applied (see Object bounding box units)
    /// and then applying the transform specified by attribute gradientTransform.
    ///
    /// When gradientUnits="objectBoundingBox" and gradientTransform is the identity matrix, the normal of the linear
    /// gradient is perpendicular to the gradient vector in object bounding box space (i.e., the abstract coordinate
    /// system where (0,0) is at the top/left of the object bounding box and (1,1) is at the bottom/right of the object bounding box).
    /// When the object's bounding box is not square, the gradient normal which is initially perpendicular to the gradient vector
    /// within object bounding box space may render non-perpendicular relative to the gradient vector in user space. If the gradient
    /// vector is parallel to one of the axes of the bounding box, the gradient normal will remain perpendicular. This transformation
    /// is due to application of the non-uniform scaling transformation from bounding box space to user space.
    ObjectBoundingBox,
}

/// A `transform` matrix type.
enum Transform {
    Translate(float,#[option] float), 
    Matrix([float;6]),
    Scale(float,#[option] float), 
    Rotate { angle: float, #[option] center: Point },
    SkewX(float),
    SkewY(float),
}

/// Indicates which channel of rgba is selected.
enum Channel { R,G,B,A }

/// The  property only applies to graphics elements that are contained within a [`ClipPath`](ClipPath) element.
enum ClipRule { Nonzero, EvenOdd }


/// Draws a cubic Bézier curve from the current point to `to` point,
/// using `ctrl1` as the control point at the beginning of the curve and `ctrl2` as the control point at the end of the curve.
data CubicBezier{ ctrl1: Point, ctrl2: Point, to: Point }
/// (smooth) Draws a cubic Bézier curve from the current point to `to` point,
/// using `ctrl1` as the control point at the beginning of the curve and `ctrl2` as the control point at the end of the curve.
data CubicBezierSmooth{ ctrl2: Point, to: Point }
/// Draws a quadratic Bézier curve from the current point to `to` point using `ctrl` as the control point.
data QuadraticBezier{ ctrl: Point, to: Point }
/// Draws an elliptical arc from the current point to `to` point.
///
/// The center (cx, cy) of the ellipse is calculated automatically to satisfy the constraints
/// imposed by the other parameters.
data Arc {
    rx: float,
    ry:float, 
    x_rotation: float, 
    large_arc: bool, 
    sweep: bool, 
    to: Point, 
}

/// A direction that representation a path drawing commander.
enum PathEvent {
    /// Close the current subpath by drawing a straight line from the current point to current subpath's initial point.
    Close,
    /// Start a new sub-path at the given (x,y) coordinate.
    MoveTo {
        points: vec[Point],
        relative: bool,
    }, 
    /// Draw a line from the current point to the given (x,y) coordinate which becomes the new current point.
    LineTo {
        points: vec[Point],
        relative: bool,
    },
    /// Draw a line from the current point to the given (x,y) coordinate which becomes the new current point.
    Horizontal(float,bool),
    /// Draw a line from the current point to the given (x,y) coordinate which becomes the new current point.
    Vertical(float, bool),
    /// Draws a cubic Bézier curve from the current point to `to` point,
    /// using `ctrl1` as the control point at the beginning of the curve and `ctrl2` as the control point at the end of the curve.
    CubicBezier(vec[CubicBezier],bool),
    /// (smooth) Draws a cubic Bézier curve from the current point to `to` point,
    /// using `ctrl1` as the control point at the beginning of the curve and `ctrl2` as the control point at the end of the curve.
    CubicBezierSmooth(vec[CubicBezierSmooth],bool),
    /// Draws a quadratic Bézier curve from the current point to `to` point using `ctrl` as the control point.
    QuadraticBezier(vec[QuadraticBezier],bool),
    /// (smooth) Draws a quadratic Bézier curve from the current point to `to` point using `ctrl` as the control point.
    QuadraticBezierSmooth(vec[Point], bool),
    /// Draws an elliptical arc from the current point to `to` point.
    ///
    /// The center (cx, cy) of the ellipse is calculated automatically to satisfy the constraints
    /// imposed by the other parameters.
    Arc(vec[Arc],bool),
}

/// The ‘fill-ruleproperty indicates the algorithm which is to be used to determine what parts of the canvas are
/// included inside the shape. For a simple, non-intersecting path, it is intuitively clear what region lies "inside";
/// however, for a more complex path, such as a path that intersects itself or where one subpath encloses another,
/// the interpretation of "inside" is not so obvious.
enum FillRule { 
    /// This rule determines the "insideness" of a point on the canvas by drawing a ray from that point to infinity in
    /// any direction and then examining the places where a segment of the shape crosses the ray. Starting with a count of zero,
    /// add one each time a path segment crosses the ray from left to right and subtract one each time a path segment crosses
    /// the ray from right to left. After counting the crossings, if the result is zero then the point is outside the path.
    /// Otherwise, it is inside.
    Nonzero, 
    /// This rule determines the "insideness" of a point on the canvas by drawing a ray from that point to infinity in any direction
    /// and counting the number of path segments from the given shape that the ray crosses. If this number is odd, the point is inside;
    /// if even, the point is outside.
    Evenodd,
}

/// Specifies the shape to be used at the end of open subpaths when they are stroked
#[rename("stroke-linecap")]
enum StrokeLineCap { Butt, Round, Square }

/// Specifies the shape to be used at the corners of paths or basic shapes when they are stroked.
#[rename("stroke-linejoin")]
enum StrokeLineJoin { Miter(#[option] float), Round, Bevel }

/// Indicates what happens if the gradient starts or ends inside the bounds of the target rectangle.
/// Possible values are: 'pad', which says to use the terminal colors of the gradient to fill the remainder of the target region,
/// 'reflect', which says to reflect the gradient pattern start-to-end, end-to-start, start-to-end, etc. continuously until the
/// target rectangle is filled, and repeat, which says to repeat the gradient pattern start-to-end, start-to-end, start-to-end,
/// etc. continuously until the target region is filled.
/// If the attribute is not specified, the effect is as if a value of 'pad' were specified.
enum SpreadMethod { Pad, Reflect, Repeat }

/// See [`css2`](https://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#descdef-font-style)
enum FontStyle { Normal, Italic, Oblique }

/// Same syntax and semantics as thefont-variantdescriptor within an @font-face rule.
/// Indication of whether this face is the small-caps variant of a font. Takes on the same values
/// as thefont-variantproperty, except that a comma-separated list is permitted.
///
/// If the attribute is not specified, the effect is as if a value of 'normal' were specified.
enum FontVariant { Normal, SmallCaps }

/// Same syntax and semantics as thefont-weightdescriptor within an @font-face rule.
enum FontWeight { Normal,Bold,Bolder,Lighter,W100,W200,W300,W400,W500,W600,W700,W800,W900 }

/// This property specifies a prioritized font family names and/or generic family names.
enum FontFamily { Serif,SansSerif,Cursive,Fantasy,Monospace,Generic(string) }

/// Same syntax and semantics as thefont-stretchdescriptor within an @font-face rule.
/// Indication of the condensed or expanded nature of the face relative to others in the same font family.
enum FontStretch {
    Normal,
    Wider,
    Narrower,
    UltraCondensed,
    ExtraCondensed,
    Condensed,
    SemiCondensed,
    SemiExpanded,
    Expanded,
    ExtraExpanded,
    UltraExpanded,
}

/// Data value used by `enable-background` property.
enum Background {
    /// A meaning of enable-background: accumulate (the initial/default value) depends on context:
    ///
    /// * If an ancestor container element has a property value of enable-background: new, then all
    /// graphics elements within the current container element are rendered both onto the parent container
    /// element's background image canvas and onto the target device.
    ///
    /// * Otherwise, there is no current background image canvas, so it is only necessary to render graphics
    /// elements onto the target device. (No need to render to the background image canvas.)
    Accumulate, 

    /// Indicate the subregion of the container element's user space where access to the background image is allowed to happen.
    New(#[option] BackgroundNew)
}

data BackgroundNew {
    x: float, y: float, width: float, height: float,
}

/// Identifies input for the given filter primitive. The value can be either one of six keywords or
/// can be a string which matches a previousresultattribute value within the samefilterelement.
/// If no value is provided and this is the first filter primitive, then this filter primitive will use
/// SourceGraphic as its input. If no value is provided and this is a subsequent filter primitive, then
/// this filter primitive will use the result from the previous filter primitive as its input.
///
/// If the value forresultappears multiple times within a givenfilterelement, then a reference
/// to that result will use the closest preceding filter primitive with the given value for attribute
/// ‘result’. Forward references to results are an error.
enum FeIn {
    /// This keyword represents the graphics elements that were the original input into the ‘filter’ element.
    /// For raster effects filter primitives, the graphics elements will be rasterized into an initially clear
    /// RGBA raster in image space. Pixels left untouched by the original graphic will be left clear. The image
    /// is specified to be rendered in linear RGBA pixels. The alpha channel of this image captures any
    /// anti-aliasing specified by SVG. (Since the raster is linear, the alpha channel of this image will
    /// represent the exact percent coverage of each pixel.)
    #[rename("SourceGraphic")]
    SourceGraphic, 
    
    /// This keyword represents the graphics elements that were the original input into the ‘filter’ element.
    /// SourceAlpha has all of the same rules as SourceGraphic except that only the alpha channel is used.
    /// The input image is an RGBA image consisting of implicitly black color values for the RGB channels,
    /// but whose alpha channel is the same as SourceGraphic. If this option is used, then some implementations
    /// might need to rasterize the graphics elements in order to extract the alpha channel.
    #[rename("SourceAlpha")]
    SourceAlpha, 

    /// This keyword represents an image snapshot of the canvas under the filter region at the time that the
    /// ‘filter’ element was invoked.
    #[rename("BackgroundImage")]
    BackgroundImage, 

    /// Same as BackgroundImage except only the alpha channel is used. See SourceAlpha and Accessing the background image.
    #[rename("BackgroundAlpha")]
    BackgroundAlpha,
    
    /// This keyword represents the value of the ‘fill’ property on the target element for the filter effect.
    /// The FillPaint image has conceptually infinite extent. Frequently this image is opaque everywhere,
    /// but it might not be if the "paint" itself has alpha, as in the case of a gradient or pattern which
    /// itself includes transparent or semi-transparent parts.
    #[rename("FillPaint")]
    FillPaint,

    /// This keyword represents the value of the ‘stroke’ property on the target element for the filter effect.
    /// The StrokePaint image has conceptually infinite extent. Frequently this image is opaque everywhere,
    /// but it might not be if the "paint" itself has alpha, as in the case of a gradient or pattern which
    /// itself includes transparent or semi-transparent parts. 
    #[rename("StrokePaint")]
    StrokePaint, 

    /// Reference to another filter-primitive result .
    Result(string), 
}

/// Assign output to a named register. otherwise the filter output will only be referenced by next filter primitive.
enum FeOut { Position, Named(string) }

/// Image blending modes
/// For the compositing formulas below, the following definitions apply:
/// * cr = Result color (RGB) - premultiplied
/// * qa = Opacity value at a given pixel for image A
/// * qb = Opacity value at a given pixel for image B
/// * ca = Color (RGB) at a given pixel for image A - premultiplied
/// * cb = Color (RGB) at a given pixel for image B - premultiplied
enum FeBlendMode {
    /// cr = (1 - qa) * cb + ca
    Normal,
    /// cr = (1-qa)*cb + (1-qb)*ca + ca*cb
    Multiply,
    /// cr = cb + ca - ca * cb
    Screen,
    /// cr = Min ((1 - qa) * cb + ca, (1 - qb) * ca + cb)
    Darken,
    /// cr = Max ((1 - qa) * cb + ca, (1 - qb) * ca + cb)
    Lighten,
}


enum TextLengthAdjust {
    /// 'spacing' indicates that only the advance values are adjusted. The glyphs themselves are not stretched or compressed.
    Spacing,

    /// 'spacingAndGlyphs' indicates that the advance values are adjusted and the glyphs themselves stretched or compressed
    /// in one axis (i.e., a direction parallel to the inline-progression-direction).
    SpacingAndGlyphs,
}

/// The ‘writing-modeproperty specifies whether the initial inline-progression-direction for atextelement shall be
/// left-to-right, right-to-left, or top-to-bottom. The ‘writing-modeproperty applies only totextelements;
/// the property is ignored fortspan’, ‘tref’, ‘altGlyphandtextPathsub-elements. (Note that the inline-progression-direction
/// can change within atextelement due to the Unicode bidirectional algorithm and propertiesdirectionandunicode-bidi’.
/// For more on bidirectional text, see Relationship with bidirectionality.)
enum WritingMode {
    /// Sets the initial inline-progression-direction to left-to-right, as is common in most Latin-based documents.
    /// For most characters, the current text position is advanced from left to right after each glyph is rendered.
    /// (When the character data includes characters which are subject to the Unicode bidirectional algorithm, the text
    /// advance rules are more complex. See Relationship with bidirectionality).
    LrTb,
    /// Sets the initial inline-progression-direction to right-to-left, as is common in Arabic or Hebrew scripts.
    /// (See Relationship with bidirectionality.)
    RlTb,
    /// Sets the initial inline-progression-direction to top-to-bottom, as is common in some Asian scripts,
    /// such as Chinese and Japanese. Though hardly as frequent as horizontal, this type of vertical layout also occurs
    /// in Latin based documents, particularly in table column or row labels. In most cases, the vertical baselines
    /// running through the middle of each glyph are aligned.
    TbRl,
    /// See [`LrTb`](WritingMode::LrTb)
    Lr,
    /// See [`RlTb`](WritingMode::RlTb)
    Rl,
    /// See [`TbRl`](WritingMode::TbRl)
    Tb,
}

/// Within text content elements, the alignment of text with regards to thetext-anchorproperty is determined by
/// the value of thedirectionproperty. For example, given atextelement with atext-anchorvalue of "end",
/// for adirectionvalue of "ltr", the text will extend to the left of the position of thetextelement'sx’
/// attribute value, while fordirectionvalue of "rtl", the text will extend to the right of the position of the
/// ‘textelement'sxattribute value.
///
/// A more complete discussion of bidirectionality can be found in the Text direction section of
/// [`CSS 2`](https://www.w3.org/TR/CSS2/visuren.html#direction).
///
/// See [`direction`](https://www.w3.org/TR/SVG11/text.html#DirectionProperty)
enum TextDirection {
    Ltr,
    Rtl,
}

/// Except for any additional information provided in this specification, the normative definition of the
/// [`unicode-bidi`] property is in CSS2
///
/// [`unicode-bidi`]: https://www.w3.org/TR/2008/REC-CSS2-20080411/visuren.html#propdef-unicode-bidi
enum UnicodeBidi {
    Normal,
    Embed,
    BidiOverride,
}

/// The ‘text-anchorproperty is used to align (start-, middle- or end-alignment) a string of text relative to a given point.
///
/// The ‘text-anchorproperty is applied to each individual text chunk within a giventextelement. Each text chunk has an
/// initial current text position, which represents the point in the user coordinate system resulting from (depending on context)
/// application of thexandyattributes on thetextelement, anyxoryattribute values on atspan’, ‘trefor
/// ‘altGlyphelement assigned explicitly to the first rendered character in a text chunk, or determination of the initial current
/// text position for atextPathelement.
enum TextAnchor {
    /// The rendered characters are aligned such that the start of the resulting rendered text is at the initial current text position.
    /// For an element with a ‘direction’ property value of "ltr" (typical for most European languages), the left side of the text is
    /// rendered at the initial text position. For an element with a ‘direction’ property value of "rtl" (typical for Arabic and Hebrew),
    /// the right side of the text is rendered at the initial text position. For an element with a vertical primary text direction
    /// (often typical for Asian text), the top side of the text is rendered at the initial text position.
    Start,
    /// The rendered characters are aligned such that the geometric middle of the resulting rendered text is at the initial
    /// current text position.
    Middle,
    /// The rendered characters are aligned such that the end of the resulting rendered text is at the initial current text position.
    /// For an element with a ‘direction’ property value of "ltr" (typical for most European languages), the right side of the text is
    /// rendered at the initial text position. For an element with a ‘direction’ property value of "rtl" (typical for Arabic and Hebrew),
    /// the left side of the text is rendered at the initial text position. For an element with a vertical primary text direction (often
    /// typical for Asian text), the bottom of the text is rendered at the initial text position.
    End,
}

/// See [`baseline`](https://www.w3.org/TR/SVG11/text.html#BaselineAlignmentProperties)
enum DominantBaseline {
    /// If this property occurs on a ‘text’ element, then the computed value depends on the value of the ‘writing-mode’ property.
    /// If the 'writing-mode' is horizontal, then the value of the dominant-baseline component is 'alphabetic', else if the
    /// 'writing-mode' is vertical, then the value of the dominant-baseline component is 'central'.
    ///
    /// If this property occurs on a ‘tspan’, ‘tref’, ‘altGlyph’ or ‘textPath’ element, then the dominant-baseline and the
    /// baseline-table components remain the same as those of the parent text content element. If the computed ‘baseline-shift’
    /// value actually shifts the baseline, then the baseline-table font-size component is set to the value of the ‘font-size’
    /// property on the element on which the ‘dominant-baseline’ property occurs, otherwise the baseline-table font-size remains
    /// the same as that of the element. If there is no parent text content element, the scaled-baseline-table value is
    /// constructed as above for ‘text’ elements.
    Auto,
    /// The dominant-baseline and the baseline-table components are set by determining the predominant script of the character
    /// data content. The ‘writing-mode’, whether horizontal or vertical, is used to select the appropriate set of baseline-tables
    /// and the dominant baseline is used to select the baseline-table that corresponds to that baseline. The baseline-table
    /// font-size component is set to the value of the ‘font-size’ property on the element on which the ‘dominant-baseline’ property
    /// occurs.
    UseScript,
    /// The dominant-baseline, the baseline-table, and the baseline-table font-size remain the same as that of the parent text
    /// content element.
    NoChange,
    /// The dominant-baseline and the baseline-table remain the same, but the baseline-table font-size is changed to the value
    /// of the ‘font-size’ property on this element. This re-scales the baseline-table for the current ‘font-size’.
    ResetSize,
    /// The baseline-identifier for the dominant-baseline is set to be 'ideographic', the derived baseline-table is constructed
    /// using the 'ideographic' baseline-table in the nominal font, and the baseline-table font-size is changed to the value of
    /// the ‘font-size’ property on this element.
    Ideographic,
    /// The baseline-identifier for the dominant-baseline is set to be 'alphabetic', the derived baseline-table is constructed
    /// using the 'alphabetic' baseline-table in the nominal font, and the baseline-table font-size is changed to the value of
    /// the ‘font-size’ property on this element.
    Alphabetic,
    /// The baseline-identifier for the dominant-baseline is set to be 'hanging', the derived baseline-table is constructed using
    /// the 'hanging' baseline-table in the nominal font, and the baseline-table font-size is changed to the value of the
    /// ‘font-size’ property on this element.
    Hanging,
    /// The baseline-identifier for the dominant-baseline is set to be 'mathematical', the derived baseline-table is constructed
    /// using the 'mathematical' baseline-table in the nominal font, and the baseline-table font-size is changed to the value of
    /// the ‘font-size’ property on this element.
    Mathematical,
    /// The baseline-identifier for the dominant-baseline is set to be 'central'. The derived baseline-table is constructed from
    /// the defined baselines in a baseline-table in the nominal font. That font baseline-table is chosen using the following
    /// priority order of baseline-table names: 'ideographic', 'alphabetic', 'hanging', 'mathematical'. The baseline-table font-size
    /// is changed to the value of the ‘font-size’ property on this element.
    Central,
    /// The baseline-identifier for the dominant-baseline is set to be 'middle'. The derived baseline-table is constructed from
    /// the defined baselines in a baseline-table in the nominal font. That font baseline -table is chosen using the following
    /// priority order of baseline-table names: 'alphabetic', 'ideographic', 'hanging', 'mathematical'. The baseline-table
    /// font-size is changed to the value of the ‘font-size’ property on this element.
    Middle,
    /// The baseline-identifier for the dominant-baseline is set to be 'text-after-edge'. The derived baseline-table is constructed
    /// from the defined baselines in a baseline-table in the nominal font. The choice of which font baseline-table to use from the
    /// baseline-tables in the nominal font is implementation defined. The baseline-table font-size is changed to the value of the
    /// ‘font-size’ property on this element.
    ///
    /// NOTE: using the following priority order of baseline-table names: 'alphabetic', 'ideographic', 'hanging', 'mathematical'
    /// is probably a reasonable strategy for determining which font baseline-table to use.
    TextAfterEdge,
    /// The baseline-identifier for the dominant-baseline is set to be 'text-before-edge'. The derived baseline-table is constructed
    /// from the defined baselines in a baseline-table in the nominal font. The choice of which baseline-table to use from the
    /// baseline-tables in the nominal font is implementation defined. The baseline-table font-size is changed to the value of the
    /// ‘font-size’ property on this element.
    ///
    /// NOTE: Using the following priority order of baseline-table names: 'alphabetic', 'ideographic', 'hanging', 'mathematical'
    /// is probably a reasonable strategy for determining which font baseline-table to use.
    TextBeforeEdge,
}

enum AlignmentBaseline {
    /// The value is the dominant-baseline of the script to which the character belongs - i.e.,
    /// use the dominant-baseline of the parent.
    Auto,
    /// The alignment-point of the object being aligned is aligned with the dominant-baseline of
    /// the parent text content element.
    Baseline,
    /// The alignment-point of the object being aligned is aligned with the "before-edge" baseline of
    /// the parent text content element.
    BeforeEdge,
    /// The alignment-point of the object being aligned is aligned with the "text-before-edge" baseline of
    /// the parent text content element.
    TextBeforeEdge,
    /// The alignment-point of the object being aligned is aligned with the "middle" baseline of the parent text content element.
    Middle,
    /// The alignment-point of the object being aligned is aligned with the "central" baseline of the parent text content element.
    Central,
    /// The alignment-point of the object being aligned is aligned with the "after-edge" baseline of the parent text content element.
    AfterEdge,
    /// The alignment-point of the object being aligned is aligned with the "text-after-edge" baseline of the parent text content element.
    TextAfterEdge,
    /// The alignment-point of the object being aligned is aligned with the "ideographic" baseline of the parent text content element.
    Ideographic,
    /// The alignment-point of the object being aligned is aligned with the "alphabetic" baseline of the parent text content element.
    Alphabetic,
    /// The alignment-point of the object being aligned is aligned with the "hanging" baseline of the parent text content element.
    Hanging,
    /// The alignment-point of the object being aligned is aligned with the "mathematical" baseline of the parent text content element.
    Mathematical,
}

/// The ‘baseline-shiftproperty allows repositioning of the dominant-baseline relative to the dominant-baseline of
/// the parent text content element. The shifted object might be a sub- or superscript. Within the shifted object,
/// the whole baseline-table is offset; not just a single baseline. The amount of the shift is determined from information
/// from the parent text content element, the sub- or superscript offset from the nominal font of the parent text content
/// element, percent of the "line-height" of the parent text content element or an absolute value.
enum BaselineShift {
    /// There is no baseline shift; the dominant-baseline remains in its original position.
    Baseline,
    /// The dominant-baseline is shifted to the default position for subscripts. The offset to this position
    /// is determined using the font data for the nominal font. Because in most fonts the subscript position
    /// is normally given relative to the "alphabetic" baseline, the user agent may compute the effective
    /// position for subscripts for superscripts when some other baseline is dominant. The suggested computation
    /// is to subtract the difference between the position of the dominant baseline and the position of the
    /// "alphabetic" baseline from the position of the subscript. The resulting offset is determined by multiplying
    /// the effective subscript position by the dominant baseline-table font-size. If there is no applicable font
    /// data the user agent may use heuristics to determine the offset.
    SubScripts,
    /// The dominant-baseline is shifted to the default position for superscripts. The offset to this position is
    /// determined using the font data for the nominal font. Because in most fonts the superscript position is normally
    /// given relative to the "alphabetic" baseline, the user agent may compute the effective position for superscripts
    /// when some other baseline is dominant. The suggested computation is to subtract the difference between the
    /// position of the dominant baseline and the position of the "alphabetic" baseline from the position of the
    /// superscript. The resulting offset is determined by multiplying the effective superscript position by the dominant
    /// baseline-table font-size. If there is no applicable font data the user agent may use heuristics to determine the
    /// offset.
    SuperScripts,
    /// The computed value of the property is this percentage multiplied by the computed "line-height" of the ‘text’ element.
    /// The dominant-baseline is shifted in the shift direction (positive value) or opposite to the shift direction
    /// (negative value) of the parent text content element by the computed value. A value of "0" is equivalent to "baseline".
    Value(Length),
}

/// This property describes decorations that are added to the text of an element.
enum TextDecoration {
    Underline,
    Overline,
    #[rename("line-through")]
    LineThrough,
    Blink,
}

/// Indicates the method by which text should be rendered along the path.
///
/// A value of align indicates that the glyphs should be rendered using simple 2x3 transformations such
/// that there is no stretching/warping of the glyphs. Typically, supplemental rotation, scaling and
/// translation transformations are done for each glyph to be rendered. As a result, with align, fonts
/// where the glyphs are designed to be connected (e.g., cursive fonts), the connections may not align
/// properly when text is rendered along a path.
///
/// A value of stretch indicates that the glyph outlines will be converted into paths, and then all end
/// points and control points will be adjusted to be along the perpendicular vectors from the path,
/// thereby stretching and possibly warping the glyphs. With this approach, connected glyphs, such as in
/// cursive scripts, will maintain their connections.
///
/// If the attribute is not specified, the effect is as if a value of align were specified.
enum TextPathMethod {
    Align,
    Stretch,
}

/// Indicates how the user agent should determine the spacing between glyphs that are to be rendered along a path.
///
/// A value of exact indicates that the glyphs should be rendered exactly according to the spacing rules as specified
/// in Text on a path layout rules.
///
///
/// A value of auto indicates that the user agent should use text-on-a-path layout algorithms to adjust the spacing
/// between glyphs in order to achieve visually appealing results.
///
/// If the attribute is not specified, the effect is as if a value of exact were specified.
enum TextPathSpacing {
    Auto,
    Exact,
}

/// The letter-spacing attribute controls spacing between text characters.
///
/// See [`letter-spacing`](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/letter-spacing)
enum LetterSpacing {
    Normal,
    Length(Length),
}

/// The word-spacing attribute specifies spacing behavior between words.
///
/// See [`word-spacing`](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/word-spacing)
enum WordSpacing {
    Normal,
    Length(Length),
}

/// see [`svg`] document for more information.
///
/// [`svg`]: https://www.w3.org/TR/SVG11/coords.html#PreserveAspectRatioAttribute
enum MeetOrSlice {
    Meet,
    Slice,
}

/// In some cases, typically when using theviewBoxattribute, i
/// t is desirable that the graphics stretch to fit non-uniformly
/// to take up the entire viewport. In other cases, it is desirable
/// that uniform scaling be used for the purposes of preserving
/// the aspect ratio of the graphics.
enum PreserveAspectRatio {
    None,
    /// Force uniform scaling
    ///
    /// Align the `<min-x>` of the element's ‘viewBox’ with the smallest X value of the viewport.
    /// Align the `<min-y>` of the element's ‘viewBox’ with the smallest Y value of the viewport.
    xMinYMin(MeetOrSlice),
    /// Force uniform scaling.
    ///
    /// Align the midpoint X value of the element's ‘viewBox’ with the midpoint X value of the viewport.
    /// Align the `<min-y>` of the element's ‘viewBox’ with the smallest Y value of the viewport.
    xMidYMin(MeetOrSlice),
    /// Force uniform scaling.
    ///
    /// Align the `<min-x>`+`<width>` of the element's ‘viewBox’ with the maximum X value of the viewport.
    /// Align the `<min-y>` of the element's ‘viewBox’ with the smallest Y value of the viewport.
    xMaxYMin(MeetOrSlice),
    /// Force uniform scaling.
    ///
    /// Align the `<min-x>` of the element's ‘viewBox’ with the smallest X value of the viewport.
    /// Align the midpoint Y value of the element's ‘viewBox’ with the midpoint Y value of the viewport.
    xMinYMid(MeetOrSlice),
    /// Force uniform scaling(the default).
    ///
    /// Align the midpoint X value of the element's ‘viewBox’ with the midpoint X value of the viewport.
    /// Align the midpoint Y value of the element's ‘viewBox’ with the midpoint Y value of the viewport.
    xMidYMid(MeetOrSlice),
    /// Force uniform scaling.
    ///
    /// Align the `<min-x>`+`<width>` of the element's ‘viewBox’ with the maximum X value of the viewport.
    /// Align the midpoint Y value of the element's ‘viewBox’ with the midpoint Y value of the viewport.
    xMaxYMid(MeetOrSlice),
    /// Force uniform scaling.
    ///
    /// Align the `<min-x>` of the element's ‘viewBox’ with the smallest X value of the viewport.
    /// Align the `<min-y>`+`<height>` of the element's ‘viewBox’ with the maximum Y value of the viewport.
    xMinYMax(MeetOrSlice),
    /// Force uniform scaling.
    ///
    /// Align the midpoint X value of the element's ‘viewBox’ with the midpoint X value of the viewport.
    /// Align the `<min-y>`+`<height>` of the element's ‘viewBox’ with the maximum Y value of the viewport.
    xMidYMax(MeetOrSlice),
    /// Force uniform scaling.
    ///
    /// Align the `<min-x>`+`<width>` of the element's ‘viewBox’ with the maximum X value of the viewport.
    /// Align the `<min-y>`+`<height>` of the element's ‘viewBox’ with the maximum Y value of the viewport.
    xMaxYMax(MeetOrSlice),
}


/// support for various international writing directions, such as left-to-right (e.g., Latin scripts) and
/// bidirectional (e.g., Hebrew or Arabic) and vertical (e.g., Asian scripts).
attr TextLayout {
    /// See [`WritingMode`]
    #[option]
    write_mode: WritingMode,
    /// See [`TextDirection`]
    #[option]
    direction: TextDirection,

    /// See [`UnicodeBidi`]
    #[option]
    unicode_bidi: UnicodeBidi,

    /// See [`TextAnchor`]
    #[option,variable,rename("text-anchor")]
    anchor: TextAnchor,

    /// See [`DominantBaseline`]
    #[option,variable]
    dominant_baseline: DominantBaseline,

    /// See [`AlignmentBaseline`]
    #[option,variable]
    alignment_baseline: AlignmentBaseline,

    /// See [`BaselineShift`]
    #[option,variable]
    baseline_shift: BaselineShift,

    /// See [`TextDecoration`]
    #[option,variable,rename("text-decoration")]
    decoration: TextDecoration,

    /// See [`LetterSpacing`]
    #[option,variable]
    letter_spacing: LetterSpacing,

    /// See [`WordSpacing`]
    #[option,variable]
    word_spacing: WordSpacing,
}

/// support for various international writing directions, such as left-to-right (e.g., Latin scripts) and
/// bidirectional (e.g., Hebrew or Arabic) and vertical (e.g., Asian scripts).
attr WithTransform(
    #[rename("transform")]
    vec[Transform]
);

/// Define a fragment with name.
attr Id(#[rename("id")] string);

/// The ‘fillinstruction paints the interior of the given graphical element.
attr Fill {
    /// paints color.
    ///
    /// `Inherited: yes`
    #[option, variable, init, rename("fill")]
    paint: Paint,

    /// fill painting rule, see [`FillRule`] for more information.
    ///
    /// `Inherited: yes`
    #[option, variable, rename("fill-rule")]
    rule: FillRule,

    /// defining the opacity of the paint server
    #[option, variable, rename("fill-opacity")]
    opacity: float,
}


/// This property affect how an element is stroked.
attr Stroke {
    /// paints color paints along the outline of the given graphical element.
    ///
    /// `Inherited: yes`
    #[option, variable, init, rename("stroke")]
    paint: Paint,
    /// This property specifies the width of the stroke on the current object
    ///
    /// `Inherited: yes`
    #[option, variable, rename("stroke-width")]
    width: Length,

    /// specifies the shape to be used at the end of open subpaths when they are stroked.
    ///
    /// `Inherited: yes`
    #[option,variable,rename("stroke-linecap")]
    linecap: StrokeLineCap,

    /// specifies the shape to be used at the corners of paths or basic shapes when they are stroked.
    ///
    /// `Inherited: yes`
    #[option,variable,rename("stroke-linejoin")]
    linejoin: StrokeLineJoin,

    /// controls the pattern of dashes and gaps used to stroke paths. `<dasharray>` contains a list of comma and/or
    /// white space separated `<length>s` and `<percentage>s` that specify the lengths of alternating dashes and gaps.
    /// If an odd number of values is provided, then the list of values is repeated to yield an even number of values.
    /// Thus, stroke-dasharray: 5,3,2 is equivalent to stroke-dasharray: 5,3,2,5,3,2.
    ///
    /// `Inherited: yes`
    #[option,variable,rename("stroke-dasharray")]
    dasharray: vec[Length],
    /// specifies the distance into the dash pattern to start the dash
    ///
    /// `Inherited: yes`
    #[option,variable,rename("stroke-dashoffset")]
    dashoffset: Length,

    /// specifies the opacity of the painting operation used to stroke the current object.
    #[option,variable,rename("stroke-opacity")]
    opacity: float,
}


/// Shorthand property for settingfont-style’, ‘font-variant’, ‘font-weight’, ‘font-size’, ‘line-heightandfont-family’.
attr Font {
    /// See [`FontFamily`]
    #[option,variable,rename("font-family")]
    family: vec[FontFamily],
    /// See [`FontStyle`]
    #[option,variable,rename("font-style")]
    style: FontStyle,
    /// See [`FontVariant`]
    #[option,variable,rename("font-variant")]
    variant: FontVariant,
    /// See [`FontWeight`]
    #[option,variable,rename("font-weight")]
    weight: FontWeight,
    /// This property refers to the size of the font from baseline to baseline when multiple lines of
    /// text are set solid in a multiline layout environment.
    #[option,variable,rename("font-size")]
    size: Length,
    /// See [`FontStretch`]
    #[option,variable,rename("font-stretch")]
    stretch: FontStretch,
}


/// enables access to the background image
attr EnableBackground(#[rename("enable-background")]Background);

/// Define a fragment by name.
attr WithFilter(#[rename("filter")]FuncIri);

/// Use mask to a element.
#[variable]
attr WithClipPath(#[rename("clip-path")] FuncIri);

/// Use mask to a element.
#[variable]
attr WithMask(
    #[rename("mask")]
    FuncIri
);

///Sspecifies object/group opacity
#[variable]
attr Opacity(
    #[rename("opacity")]
    float
);

/// It is often desirable to specify that a given set of graphics stretch to fit a particular container element.
/// The ‘viewBoxattribute provides this capability.
attr ViewBox {
    /// ViewBox left-top x coordinate,
    #[variable]
    minx: float,
    /// ViewBox left-top y coordinate,
    #[variable]
    miny: float,
    /// ViewBox width dimension.
    #[variable]
    width: float,
    /// ViewBox height dimension.
    #[variable]
    height: float,
    /// clip preserve aspect ratio.
    #[option, variable]
    aspect: PreserveAspectRatio,
}


/// All filter primitives have attributesx’, ‘y’, ‘widthandheightwhich identify a subregion which
/// restricts calculation and rendering of the given filter primitive. These attributes are defined according
/// to the same rules as other filter primitives' coordinate and length attributes and thus represent values
/// in the coordinate system established by attributeprimitiveUnitson thefilterelement.
///
/// ‘x’, ‘y’, ‘widthandheightdefault to the union (i.e., tightest fitting bounding box) of the subregions
/// defined for all referenced nodes. If there are no referenced nodes (e.g., forfeImageorfeTurbulence’),
/// or one or more of the referenced nodes is a standard input (one of SourceGraphic, SourceAlpha, BackgroundImage,
/// BackgroundAlpha, FillPaint or StrokePaint), or forfeTile(which is special because its principal function is
/// to replicate the referenced node in X and Y and thereby produce a usually larger result), the default subregion
/// is 0%,0%,100%,100%, where as a special-case the percentages are relative to the dimensions of the filter region,
/// thus making the the default filter primitive subregion equal to the filter region.
mixin FePrimitive {
    /// The minimum x coordinate for the subregion which restricts calculation and rendering of the given filter primitive.  
    #[option, variable]
    x: Length,

    /// The minimum y coordinate for the subregion which restricts calculation and rendering of the given filter primitive
    #[option, variable]
    y: Length,

    /// The width of the subregion which restricts calculation and rendering of the given filter primitive.
    #[option, variable]
    width: Length,

    /// The height of the subregion which restricts calculation and rendering of the given filter primitive.
    #[option, variable]
    height: Length,

    /// Assigned name for this filter primitive. If supplied, then graphics that result from processing this filter primitive can
    /// be referenced by an ‘in’ attribute on a subsequent filter primitive within the same ‘filter’ element. If no value is provided,
    /// the output will only be available for re-use as the implicit input into the next filter primitive if that filter primitive
    /// provides no value for its ‘in’ attribute.
    ///
    /// Note that a `filter-primitive-reference` is not an XML ID; instead, a `filter-primitive-reference` is only meaningful within a
    /// given ‘filter’ element and thus have only local scope. It is legal for the same `filter-primitive-reference` to appear multiple
    /// times within the same ‘filter’ element. When referenced, the `filter-primitive-reference` will use the closest preceding filter
    /// primitive with the given result.
    #[option, variable]
    result: string,
}

/// Create a new layer into which the backend render child elements.
#[rename("svg")]
el Canvas {
    /// a number (usually an integer) that represents the width of the rendering layer.
    #[variable]
    width: Length,
    /// a number (usually an integer) that represents the height of the rendering layer.
    #[variable]
    height: Length,
}

/// used as an alpha mask for compositing the current object into the background.
el Mask {
    /// Defines the coordinate system for attributes ‘x’, ‘y’, ‘width’ and ‘height’.
    ///
    /// If maskUnits="userSpaceOnUse", x, y, width and height represent values in the current user coordinate system
    /// in place at the time when the mask element is referenced (i.e., the user coordinate system for the element
    /// referencing themaskelement via themaskproperty).
    ///
    /// If maskUnits="objectBoundingBox", x, y, width and height represent fractions or percentages of the bounding box
    /// of the element to which the mask is applied. (See Object bounding box units.)
    ///
    /// If attribute maskUnits is not specified, then the effect is as if a value of 'objectBoundingBox' were specified.
    #[option, variable,rename("maskUnits")]
    units: Coords,

    /// Defines the coordinate system for the contents of the mask.
    ///
    /// If maskContentUnits="userSpaceOnUse", the user coordinate system for the contents of the mask element is the current user
    /// coordinate system in place at the time when the mask element is referenced (i.e., the user coordinate system for the element
    /// referencing themaskelement via themaskproperty).
    ///
    /// If maskContentUnits="objectBoundingBox", the user coordinate system for the contents of the mask is established using the
    /// bounding box of the element to which the mask is applied. (See Object bounding box units.)
    ///
    /// If attribute maskContentUnits is not specified, then the effect is as if a value of 'userSpaceOnUse' were specified.
    #[option, variable]
    content_units: Coords,

    /// The x-axis coordinate of one corner of the rectangle for the largest possible offscreen buffer. Note that the clipping
    /// path used to render any graphics within the mask will consist of the intersection of the current clipping path
    /// associated with the given object and the rectangle defined by x, y, width and height.
    ///
    /// If the attribute is not specified, the effect is as if a value of '-10%' were specified.
    #[option, variable, init]
    x: Length,

    /// The y-axis coordinate of one corner of the rectangle for the largest possible offscreen buffer.
    ///
    /// If the attribute is not specified, the effect is as if a value of '-10%' were specified.
    #[option, variable, init]
    y: Length,

    /// The width of the largest possible offscreen buffer. Note that the clipping path used to render any graphics within the
    /// mask will consist of the intersection of the current clipping path associated with the given object and the rectangle
    /// defined by x, y, width and height.
    ///
    /// A negative value is an error (see Error processing). A value of zero disables rendering of the element.
    ///
    /// If the attribute is not specified, the effect is as if a value of '120%' were specified.
    #[option, variable, init]
    width: Length,

    /// The height of the largest possible offscreen buffer.
    ///
    /// A negative value is an error (see Error processing). A value of zero disables rendering of the element.
    ///
    /// If the attribute is not specified, the effect is as if a value of '120%' were specified.
    #[option, variable, init]
    height: Length,
}

/// A clipping path is defined with aclipPathelement.
/// A clipping path is used/referenced using theclip-pathproperty.
el ClipPath(
    /// Defines the coordinate system for the contents of theclipPath’.
    ///
    /// If clipPathUnits="userSpaceOnUse", the contents of theclipPathrepresent values in the current user coordinate
    /// system in place at the time when theclipPathelement is referenced (i.e., the user coordinate system for the
    /// element referencing theclipPathelement via theclip-pathproperty).
    ///
    /// If clipPathUnits="objectBoundingBox", then the user coordinate system for the contents of theclipPathelement
    /// is established using the bounding box of the element to which the clipping path is applied (see Object bounding
    /// box units).
    ///
    /// If attributeclipPathUnitsis not specified, then the effect is as if a value of 'userSpaceOnUse' were specified.
    #[option, variable]
    Coords,
);

/// A filter effect consists of a series of graphics operations that are applied to a given source graphic to
/// produce a modified graphical result. The result of the filter effect is rendered to the target device
/// instead of the original source graphic. The following illustrates the process:
el Filter {
    /// Defines the coordinate system for attributes ‘x’, ‘y’, ‘width’ and ‘height’.
    ///
    /// If units="userSpaceOnUse", x, y, width and height represent values in the current user
    /// coordinate system in place at the time when the filter is referenced (i.e., the user coordinate system
    /// for the element referencing thefiltervia afilterproperty).
    ///
    /// If units="objectBoundingBox", then x, y, width and height represent fractions or percentages
    /// of the bounding box on the referencing element (see Object bounding box units).
    ///
    /// If attribute units is not specified, then the effect is if a value of 'objectBoundingBox' were
    /// specified.
    #[option, variable,rename("filterUnits")]
    units: Coords,

    /// Specifies the coordinate system for the various length values within the filter primitives and for the
    /// attributes that define the filter primitive subregion.
    ///
    /// If primitive_units="userSpaceOnUse", any length values within the filter definitions represent values in
    /// the current user coordinate system in place at the time when the filter element is referenced (i.e.,
    /// the user coordinate system for the element referencing thefilterelement via afilterproperty).
    ///
    /// If primitive_units="objectBoundingBox", then any length values within the filter definitions represent
    /// fractions or percentages of the bounding box on the referencing element (see Object bounding box units).
    /// Note that if only one number was specified in a `number-optional-number` value this number is expanded out
    /// before the primitiveUnits computation takes place.
    ///
    /// If attribute primitive_units is not specified, then the effect is as if a value of userSpaceOnUse were specified.
    #[option, variable]
    primitive_units: Coords,

    /// These attributes define a rectangular region on the canvas to which this filter applies.
    ///
    /// The amount of memory and processing time required to apply the filter are related to the size of this rectangle
    /// and the filterRes attribute of the filter.
    ///
    /// The coordinate system for these attributes depends on the value for attribute filterUnits.
    ///
    /// Negative values for width or height are an error (see Error processing). Zero values disable rendering of the
    /// element which referenced the filter.
    ///
    /// The bounds of this rectangle act as a hard clipping region for each filter primitive included with a given filter
    /// element; thus, if the effect of a given filter primitive would extend beyond the bounds of the rectangle (this
    /// sometimes happens when using a ‘feGaussianBlur’ filter primitive with a very large ‘stdDeviation’), parts of the
    /// effect will get clipped.
    ///
    /// If ‘x’ or ‘y’ is not specified, the effect is as if a value of -10% were specified.
    ///
    /// If ‘width’ or ‘height’ is not specified, the effect is as if a value of 120% were specified.    
    #[option, variable,init]
    x: Length,

    /// See [`x`](Self::x)
    #[option, variable,init]
    y: Length,

    /// See [`x`](Self::x)
    #[option, variable,init]
    width: Length,

    /// See [`x`](Self::x)
    #[option, variable,init]
    height: Length,

    /// This attribute takes the form x-pixels [y-pixels], and indicates the width and height of the
    /// intermediate images in pixels. If not provided, then the user agent will use reasonable values
    /// to produce a high-quality result on the output device.
    ///
    /// Care should be taken when assigning a non-default value to this attribute. Too small of a value
    /// may result in unwanted pixelation in the result. Too large of a value may result in slow
    /// processing and large memory usage.
    ///
    /// Negative values are an error (see Error processing). Zero values disable rendering of the
    /// element which referenced the filter.
    ///
    /// Non-integer values are truncated, i.e rounded to the closest integer value towards zero.
    #[option, variable]
    res: NumberOptNumber,
}


/// Defines a distant light source that can be used within a lighting filter primitive:
/// [`FeDiffuseLighting`] or [`FeSpecularLighting`].
///
/// The following diagram illustrates the angles whichazimuthandelevationrepresent in an XYZ coordinate system.
///
/// ![`distance light source`](https://www.w3.org/TR/SVG11/images/filters/azimuth-elevation.png)
leaf FeDistantLight {
    /// Direction angle for the light source on the XY plane (clockwise), in degrees from the x axis.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    azimuth: float,

    /// Direction angle for the light source from the XY plane towards the z axis, in degrees. Note the positive Z-axis points towards the viewer of the content.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    elevation: float,
}

/// Defines a point light source that can be used within a lighting filter primitive:
/// [`FeDiffuseLighting`] or [`FeSpecularLighting`].
leaf FePointLight {
    /// X location for the light source in the coordinate system established by attribute ‘primitiveUnits’ on the ‘filter’ element.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    x: float,

    /// Y location for the light source in the coordinate system established by attribute ‘primitiveUnits’ on the ‘filter’ element.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    y: float,

    /// Z location for the light source in the coordinate system established by attribute ‘primitiveUnits’ on the ‘filter’ element,
    /// assuming that, in the initial coordinate system, the positive Z-axis comes out towards the person viewing the content and
    /// assuming that one unit along the Z-axis equals one unit in X and Y.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    z: float,
}


/// Defines a spot light source that can be used within a lighting filter primitive:
/// [`FeDiffuseLighting`] or [`FeSpecularLighting`].
leaf FeSpotLight {
    /// X location for the light source in the coordinate system established by attribute ‘primitiveUnits’ on the ‘filter’ element.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    x: float,

    /// Y location for the light source in the coordinate system established by attribute ‘primitiveUnits’ on the ‘filter’ element.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    y: float,

    /// Z location for the light source in the coordinate system established by attribute ‘primitiveUnits’ on the ‘filter’ element,
    /// assuming that, in the initial coordinate system, the positive Z-axis comes out towards the person viewing the content and
    /// assuming that one unit along the Z-axis equals one unit in X and Y.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    z: float,

    /// X location in the coordinate system established by attribute ‘primitiveUnits’ on the ‘filter’ element of the point at which
    /// the light source is pointing.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    point_at_x: float,

    /// Y location in the coordinate system established by attribute ‘primitiveUnits’ on the ‘filter’ element of the point at which
    /// the light source is pointing.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    point_at_y: float,

    /// Z location in the coordinate system established by attribute ‘primitiveUnits’ on the ‘filter’ element of the point at which
    /// the light source is pointing, assuming that, in the initial coordinate system, the positive Z-axis comes out towards the
    /// person viewing the content and assuming that one unit along the Z-axis equals one unit in X and Y.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    point_at_z: float,

    /// Exponent value controlling the focus for the light source.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 1 were specified.
    #[option, variable]
    specular_exponent: float,

    /// A limiting cone which restricts the region where the light is projected. No light is projected outside the cone.
    /// ‘limitingConeAngle’ represents the angle in degrees between the spot light axis (i.e. the axis between the light
    /// source and the point to which it is pointing at) and the spot light cone. User agents should apply a smoothing
    /// technique such as anti-aliasing at the boundary of the cone.
    ///
    /// If no value is specified, then no limiting cone will be applied.
    #[option, variable]
    limiting_cone_angle: float,
}

/// This filter composites two objects together using commonly used imaging software blending modes.
/// It performs a pixel-wise combination of two input images.
leaf FeBlend mixin FePrimitive {
    /// Image blending mode
    #[option, variable]
    mode: FeBlendMode,

    /// The first input image to the blending operation.
    #[option, variable]
    in: FeIn,

    /// The second input image to the blending operation. This attribute can take on the same values as the ‘in’ attribute.
    #[option, variable]
    in2: FeIn,
}


/// Values of FeColorMatrix.
enum FeColorMatrixValues {
    /// a list of 20 matrix values.
    Matrix([float; 20]),

    /// `Saturate` is a single real number value (0 to 1).
    ///
    /// See [`feColorMatrixElement`](https://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement)
    Saturate(float),

    /// `HueRotate` is a single one real number value (degrees)
    ///
    /// See [`feColorMatrixElement`](https://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement)
    HueRotate(float),

    /// `LuminanceToAlpha`  is not applicable.
    ///
    /// See [`feColorMatrixElement`](https://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement)
    LuminanceToAlpha,
}


/// This filter applies a matrix transformation.
///
/// on the RGBA color and alpha values of every pixel on the input graphics to produce a result with a new
/// set of RGBA color and alpha values.
///
/// The calculations are performed on non-premultiplied color values. If the input graphics consists of
/// premultiplied color values, those values are automatically converted into non-premultiplied color values
/// for this operation.
///
/// These matrices often perform an identity mapping in the alpha channel. If that is the case, an implementation
/// can avoid the costly undoing and redoing of the premultiplication for all pixels with A = 1.
///
/// See [`feColorMatrix`](https://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement).
leaf FeColorMatrix mixin FePrimitive {
    /// See [`FeIn`]
    #[option, variable]
    in: FeIn,

    /// The contents of values depends on the value of attribute type:
    #[variable]
    values: FeColorMatrixValues,
}


/// transfer functions for the rgba channels.
///
/// See [`FeComponentTransfer`](FeComponentTransfer)
enum FeFunc {
    /// C' = C
    Identity,

    /// For table, the function is defined by linear interpolation between values given in the attribute tableValues.
    /// The table has n+1 values (i.e., v0 to vn) specifying the start and end values for n evenly sized interpolation regions.
    /// Interpolations use the following formula:
    ///
    /// For a value C < 1 find k such that:
    ///
    /// > k/n <= C < (k+1)/n
    ///
    /// The result C' is given by:
    ///
    /// > C' = vk + (C - k/n)*n * (vk+1 - vk)
    ///
    /// If C = 1 then:
    ///
    /// > C' = vn.
    Table(vec[float]),

    /// For discrete, the function is defined by the step function given in the attribute tableValues,
    /// which provides a list of n values (i.e., v0 to vn-1) in order to identify a step function consisting of n steps.
    /// The step function is defined by the following formula:
    ///
    /// For a value C < 1 find k such that:
    ///
    /// > k/n <= C < (k+1)/n
    ///
    /// The result C' is given by:
    ///
    /// > C' = vk
    ///
    /// If C = 1 then:
    ///
    /// > C' = vn-1.
    Discrete(vec[float]),

    /// For linear, the function is defined by the following linear equation:
    ///
    /// > C' = slope * C + intercept
    Linear {
        /// the slope of the linear function.
        slope: float,
        /// the intercept of the linear function.
        intercept: float,
    },

    /// For gamma, the function is defined by the following exponential function:
    ///
    /// > C' = amplitude * pow(C, exponent) + offset
    Gamma {
        /// the amplitude of the gamma function.
        /// If the attribute is not specified, then the effect is as if a value of 1 were specified.
        amplitude: float,
        /// the exponent of the gamma function.
        /// If the attribute is not specified, then the effect is as if a value of 1 were specified.
        exponent: float,
        /// the offset of the gamma function.
        /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
        offset: float,
    },
}

/// The compositing operation that is to be performed. All of the operator types except arithmetic match the
/// corresponding operation as described in `PORTERDUFF`. The arithmetic operator is described above. If attribute
/// operator is not specified, then the effect is as if a value of over were specified.
enum FeCompositeOperator {
    Over,
    In,
    Out,
    Atop,
    Xor,
    Arithmetic {
        /// Only applicable if operator="arithmetic".
        /// If the attribute is not specified, the effect is as if a value of 0 were specified.
        k1: float,

        /// Only applicable if operator="arithmetic".
        /// If the attribute is not specified, the effect is as if a value of 0 were specified.
        k2: float,

        /// Only applicable if operator="arithmetic".
        /// If the attribute is not specified, the effect is as if a value of 0 were specified.
        k3: float,

        /// Only applicable if operator="arithmetic".
        /// If the attribute is not specified, the effect is as if a value of 0 were specified.
        k4: float,
    },
}

/// Determines how to extend the input image as necessary with color values so that the matrix operations
/// can be applied when the kernel is positioned at or near the edge of the input image.
enum FeConvolveMatrixEdgeMode {
    Duplicate,
    Wrap,
    None,
}

/// A keyword indicating whether to erode (i.e., thin) or dilate (fatten) the source graphic.
/// If attribute `mode` is not specified, then the effect is as if a value of erode were specified.
enum FeMorphologyOperator {
    Erode,
    Dilate,
}


/// See [`stitch_tiles`](FeTurbulence::stitch_tiles)
enum FeStitchTiles {
    /// If stitchTiles="stitch", then the user agent will automatically adjust baseFrequency-x and baseFrequency-y values
    /// such that the feTurbulence node's width and height (i.e., the width and height of the current subregion) contains
    /// an integral number of the Perlin tile width and height for the first octave. The baseFrequency will be adjusted up    /// or down depending on which way has the smallest relative (not absolute) change as follows: Given the frequency,
    /// calculate lowFreq=floor(width*frequency)/width and hiFreq=ceil(width*frequency)/width. If frequency/lowFreq < hiFreq/frequency
    /// then use lowFreq, else use hiFreq. While generating turbulence values, generate lattice vectors as normal for Perlin Noise,
    /// except for those lattice points that lie on the right or bottom edges of the active area (the size of the resulting tile).
    /// In those cases, copy the lattice vector from the opposite edge of the active area.
    Stitch,
    /// If stitchTiles="noStitch", no attempt it made to achieve smooth transitions at the border of tiles which contain a turbulence
    /// function. Sometimes the result will show clear discontinuities at the tile borders.
    NoStitch,
}

/// Indicates whether the filter primitive should perform a noise or turbulence function.
/// If attribute type is not specified, then the effect is as if a value of turbulence were specified.
enum FeTurbulenceType {
    FractalNoise,
    Turbulence,
}


/// This filter primitive performs component-wise remapping of data as follows:
///
/// > R' = feFuncR( R )
///
/// > G' = feFuncG( G )
///
/// > B' = feFuncB( B )
///
/// > A' = feFuncA( A )
///
/// for every pixel. It allows operations like brightness adjustment, contrast adjustment, color balance or thresholding.
el FeComponentTransfer(#[option, variable, rename("in")] FeIn);

/// transfer function for the alpha component of the input graphic
///
/// See [`FeFunc`], [`FeComponentTransfer`]
leaf FeFuncA(FeFunc);

/// transfer function for the red component of the input graphic
///
/// See [`FeFunc`], [`FeComponentTransfer`]
leaf FeFuncR(FeFunc);

/// transfer function for the green component of the input graphic
///
/// See [`FeFunc`], [`FeComponentTransfer`]
leaf FeFuncG(FeFunc);

/// transfer function for the blue component of the input graphic
///
/// See [`FeFunc`], [`FeComponentTransfer`]
leaf FeFuncB(FeFunc);

/// This filter performs the combination of the two input images pixel-wise in image space using one of the Porter-Duff [`PORTERDUFF`]
/// compositing operations: over, in, atop, out, xor [`SVG-COMPOSITING`]. Additionally, a component-wise arithmetic operation (with
/// the result clamped between [0..1]) can be applied.
///
/// See [`feComposite`].
///
/// [`feComposite`]: https://www.w3.org/TR/SVG11/filters.html#feCompositeElement
/// [`PORTERDUFF`]: https://www.w3.org/TR/SVG11/refs.html#ref-PORTERDUFF
/// [`SVG-COMPOSITING`]: https://www.w3.org/TR/SVG11/refs.html#ref-SVG-COMPOSITING
leaf FeComposite mixin FePrimitive {
    /// See [`FeIn`]
    #[option,variable]
    in: FeIn,

    /// The second input image to the compositing operation. This attribute can take on the same values as the `r_in` attribute.
    #[variable]
    in2: FeIn,

    /// See [`FeCompositeOperator`]
    #[option,variable]
    operator: FeCompositeOperator,
}


/// feConvolveMatrix applies a matrix convolution filter effect. A convolution combines pixels
/// in the input image with neighboring pixels to produce a resulting image. A wide variety
/// of imaging operations can be achieved through convolutions, including blurring, edge detection,
/// sharpening, embossing and beveling.
///
/// See [`feConvolveMatrix`](https://www.w3.org/TR/SVG11/filters.html#feConvolveMatrixElement)
leaf FeConvolveMatrix mixin FePrimitive {
    /// See [`FeIn`]
    #[option,variable]
    in: FeIn,

    /// Indicates the number of cells in each dimension for ‘kernelMatrix’. The values provided must be `integer`s greater than zero.
    /// The first number, `orderX`, indicates the number of columns in the matrix. The second number, `orderY`, indicates the number
    /// of rows in the matrix. If `orderY` is not provided, it defaults to `orderX`.
    ///
    /// A typical value is order="3". It is recommended that only small values (e.g., 3) be used; higher values may result in very
    /// high CPU overhead and usually do not produce results that justify the impact on performance.
    ///
    /// If the attribute is not specified, the effect is as if a value of 3 were specified.
    #[option,variable]
    order: NumberOptNumber,

    /// The list of `number`s that make up the kernel matrix for the convolution. Values are separated by space
    /// characters and/or a comma. The number of entries in the list must equal `orderX` times `orderY`.
    #[variable]
    kernel: vec[float],

    /// After applying the ‘kernelMatrix’ to the input image to yield a number, that number is divided by ‘divisor’
    /// to yield the final destination color value. A divisor that is the sum of all the matrix values tends to have
    /// an evening effect on the overall color intensity of the result. It is an error to specify a divisor of zero.
    /// The default value is the sum of all values in kernelMatrix, with the exception that if the sum is zero, then
    /// the divisor is set to 1.
    #[option,variable]
    divisor: float,

    /// After applying the ‘kernelMatrix’ to the input image to yield a number and applying the ‘divisor’, the ‘bias’
    /// attribute is added to each component. One application of ‘bias’ is when it is desirable to have .5 gray value
    /// be the zero response of the filter. The bias property shifts the range of the filter. This allows representation
    /// of values that would otherwise be clamped to 0 or 1. If ‘bias’ is not specified, then the effect is as if a
    /// value of 0 were specified.
    #[option,variable]
    bias: float,

    /// After applying the ‘kernelMatrix’ to the input image to yield a number and applying the ‘divisor’, the ‘bias’
    /// attribute is added to each component. One application of ‘bias’ is when it is desirable to have .5 gray value
    /// be the zero response of the filter. The bias property shifts the range of the filter. This allows representation
    /// of values that would otherwise be clamped to 0 or 1. If ‘bias’ is not specified, then the effect is as if a
    /// value of 0 were specified.
    #[option,variable]
    target_x: int,

    /// Determines the positioning in Y of the convolution matrix relative to a given target pixel in the input image.
    /// The topmost row of the matrix is row number zero. The value must be such that: 0 <= targetY < orderY. By default,
    /// the convolution matrix is centered in Y over each pixel of the input image (i.e., targetY = floor ( orderY / 2 )).
    #[option,variable]
    target_y: int,

    /// Determines how to extend the input image as necessary with color values so that the matrix operations can be applied
    /// when the kernel is positioned at or near the edge of the input image.
    #[variable]
    edge_mode: FeConvolveMatrixEdgeMode,

    /// The first number is the `dx` value. The second number is the `dy` value. If the `dy` value is not specified,
    /// it defaults to the same value as `dx`. Indicates the intended distance in current filter units (i.e., units
    /// as determined by the value of attributeprimitiveUnits’) between successive columns and rows, respectively,
    /// in the kernelMatrix. By specifying value(s) for kernelUnitLength, the kernel becomes defined in a
    /// scalable, abstract coordinate system. If kernelUnitLength is not specified, the default value is one pixel
    /// in the offscreen bitmap, which is a pixel-based coordinate system, and thus potentially not scalable. For
    /// some level of consistency across display media and user agents, it is necessary that a value be provided for
    /// at least one of filterRes and kernelUnitLength. In some implementations, the most consistent results and
    /// the fastest performance will be achieved if the pixel grid of the temporary offscreen images aligns with the
    /// pixel grid of the kernel.
    ///
    /// A negative or zero value is an error (see Error processing).
    #[option,variable]
    kernel_unit_len: NumberOptNumber,

    /// A value of false indicates that the convolution will apply to all channels, including the alpha channel.
    ///
    /// See [`feConvolveMatrix`](https://www.w3.org/TR/SVG11/filters.html#feConvolveMatrixElement)
    #[variable]
    preserve_alpha: bool,
}

/// See [`feConvolveMatrix`](https://www.w3.org/TR/SVG11/filters.html#feDiffuseLightingElement)
el FeDiffuseLighting mixin FePrimitive {
    /// See [`FeIn`]
    #[variable]
    in: FeIn,

    /// height of surface when Ain = 1.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 1 were specified.
    #[option,variable]
    surface_scale: float,

    /// kd in Phong lighting model. In SVG, this can be any non-negative number.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 1 were specified.
    #[option,variable]
    diffuse_constant: float,

    /// The first number is the `dx` value. The second number is the `dy` value. If the `dy` value is not specified,
    /// it defaults to the same value as `dx`. Indicates the intended distance in current filter units (i.e., units
    /// as determined by the value of attribute ‘primitiveUnits’) for dx and dy, respectively, in the surface normal
    /// calculation formulas. By specifying value(s) for ‘kernelUnitLength’, the kernel becomes defined in a scalable,
    /// abstract coordinate system. If ‘kernelUnitLength’ is not specified, the dx and dy values should represent
    /// very small deltas relative to a given (x,y) position, which might be implemented in some cases as one pixel
    /// in the intermediate image offscreen bitmap, which is a pixel-based coordinate system, and thus potentially
    /// not scalable. For some level of consistency across display media and user agents, it is necessary that a value
    /// be provided for at least one of ‘filterRes’ and ‘kernelUnitLength’. Discussion of intermediate images are in the
    /// Introduction and in the description of attribute ‘filterRes’.
    ///
    /// A negative or zero value is an error (see Error processing).
    #[option,variable]
    kernel_unit_len: NumberOptNumber,
}


/// This filter primitive uses the pixels values from the image from in2 to spatially displace the image from in.
leaf FeDisplacementMap mixin FePrimitive {
    /// See [`FeIn`]
    #[option,variable]
    in: FeIn,

    /// See [`FeIn`]
    #[variable]
    in2: FeIn,

    /// Displacement scale factor. The amount is expressed in the coordinate system established by attribute ‘primitiveUnits’
    /// on the ‘filter’ element.
    ///
    /// When the value of this attribute is 0, this operation has no effect on the source image.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option,variable]
    scale: float,

    /// Indicates which channel from ‘in2’ to use to displace the pixels in ‘in’ along the x-axis.
    /// If attribute ‘xChannelSelector’ is not specified, then the effect is as if a value of A were
    /// specified.
    #[option,variable]
    x_channel_selector: Channel,

    /// Indicates which channel from ‘in2’ to use to displace the pixels in ‘in’ along the y-axis.
    /// If attribute ‘yChannelSelector’ is not specified, then the effect is as if a value of A were
    /// specified.
    #[option,variable]
    y_channel_selector: Channel,
}


/// This filter primitive creates a rectangle filled with the color and opacity values from properties flood-color a flood-opacity.
/// The rectangle is as large as the filter primitive subregion established by the x, y, width and height attributes on the
/// feFlood element.
leaf FeFlood mixin FePrimitive {
    /// indicates what color to use to flood the current filter primitive subregion.
    #[option,variable]
    color: Color,
    /// defines the opacity value to use across the entire filter primitive subregion.
    #[option,variable]
    opacity: float,
}


/// This filter primitive performs a Gaussian blur on the input image.
///
/// See [`feGaussianBlur`](https://www.w3.org/TR/SVG11/filters.html#feGaussianBlurElement)
leaf FeGaussianBlur mixin FePrimitive {
    /// See [`FeIn`]
    #[option,variable]
    in: FeIn,

    /// The standard deviation for the blur operation. If two `number`s are provided, the first number represents
    /// a standard deviation value along the x-axis of the coordinate system established by attribute ‘primitiveUnits’
    /// on the ‘filter’ element. The second value represents a standard deviation in Y. If one number is provided,
    /// then that value is used for both X and Y.
    ///
    /// A negative value is an error (see Error processing). A value of zero disables the effect of the given filter
    /// primitive (i.e., the result is the filter input image). If ‘stdDeviation’ is 0 in only one of X or Y, then the
    /// effect is that the blur is only applied in the direction that has a non-zero value.
    #[option,variable,init]
    std_deviation: NumberOptNumber,
}

/// This filter primitive composites input image layers on top of each other using the over operator with Input1
/// (corresponding to the firstfeMergeNodechild element) on the bottom and the last specified input, InputN
/// (corresponding to the lastfeMergeNodechild element), on top.
///
/// See [`feMerge`](https://www.w3.org/TR/SVG11/filters.html#feMergeElement)
el FeMerge mixin FePrimitive;

/// See [`FeMerge`]
leaf FeMergeNode(#[variable,rename("in")] FeIn);

/// This filter primitive refers to a graphic external to this filter element, which is loaded or rendered into an RGBA
/// raster and becomes the result of the filter primitive.
///
/// See [`feImage`](https://www.w3.org/TR/SVG11/filters.html#feImageElement)
leaf FeImage mixin FePrimitive {
    /// An IRI reference to the image source.
    #[variable]
    href: FuncIri,

    /// See [`PreserveAspectRatio`].
    #[option, variable]
    aspect: PreserveAspectRatio,
}

/// This filter primitive performs "fattening" or "thinning" of artwork.
/// It is particularly useful for fattening or thinning an alpha channel.
///
/// See [`feMorphology`](https://www.w3.org/TR/SVG11/filters.html#feMorphologyElement)
leaf FeMorphology mixin FePrimitive {
    /// See [`FeIn`]
    #[option, variable]
    in: FeIn,

    /// See [`FeMorphologyOperator`]
    #[option, variable]
    mode: FeMorphologyOperator,

    /// The radius (or radii) for the operation. If two `number`s are provided, the first number represents
    /// a x-radius and the second value represents a y-radius. If one number is provided, then that value
    /// is used for both X and Y. The values are in the coordinate system established by attribute
    /// ‘primitiveUnits’ on the ‘filter’ element.
    ///
    /// A negative value is an error (see Error processing). A value of zero disables the effect of the given
    /// filter primitive (i.e., the result is a transparent black image).
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable]
    radius: NumberOptNumber,
}

/// This filter primitive offsets the input image relative to its current position in the image space by the specified vector.
///
/// This is important for effects like drop shadows.
///
/// See [`feOffset`](https://www.w3.org/TR/SVG11/filters.html#feOffsetElement)
leaf FeOffset mixin FePrimitive {
    /// See [`FeIn`]
    #[option, variable]
    in: FeIn,

    /// The amount to offset the input graphic along the x-axis. The offset amount is expressed in the coordinate system established
    /// by attribute ‘primitiveUnits’ on the ‘filter’ element.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable,init]
    dx: float,

    /// The amount to offset the input graphic along the y-axis. The offset amount is expressed in the coordinate system established
    /// by attribute ‘primitiveUnits’ on the ‘filter’ element.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    #[option, variable,init]
    dy: float,
}

/// This filter primitive lights a source graphic using the alpha channel as a bump map.
/// The resulting image is an RGBA image based on the light color. The lighting calculation follows the standard specular component of
/// the Phong lighting model. The resulting image depends on the light color, light position and surface geometry of the input bump map.
/// The result of the lighting calculation is added. The filter primitive assumes that the viewer is at infinity in the z direction (i.e.,
/// the unit vector in the eye direction is (0,0,1) everywhere).
///
/// See [`feSpecularLighting`](https://www.w3.org/TR/SVG11/filters.html#feSpecularLightingElement)
el FeSpecularLighting mixin FePrimitive {
    /// See [`FeIn`]
    #[option, variable,init]
    in: FeIn,

    /// height of surface when Ain = 1.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 1 were specified.
    #[option, variable]
    surface_scale: float,

    /// height of surface when Ain = 1.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 1 were specified.
    #[option, variable]
    specular_constant: float,

    /// Exponent for specular term, larger is more "shiny". Range 1.0 to 128.0.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 1 were specified.
    #[option, variable]
    specular_exponent: float,

    /// The first number is the `dx` value. The second number is the `dy` value. If the `dy` value is not specified,
    /// it defaults to the same value as `dx`. Indicates the intended distance in current filter units (i.e., units
    /// as determined by the value of attribute ‘primitiveUnits’) for dx and dy, respectively, in the surface normal
    /// calculation formulas. By specifying value(s) for ‘kernelUnitLength’, the kernel becomes defined in a scalable,
    /// abstract coordinate system. If ‘kernelUnitLength’ is not specified, the dx and dy values should represent very
    /// small deltas relative to a given (x,y) position, which might be implemented in some cases as one pixel in the
    /// intermediate image offscreen bitmap, which is a pixel-based coordinate system, and thus potentially not scalable.
    /// For some level of consistency across display media and user agents, it is necessary that a value be provided
    /// for at least one of ‘filterRes’ and ‘kernelUnitLength’. Discussion of intermediate images are in the Introduction
    /// and in the description of attribute ‘filterRes’.
    ///
    /// A negative or zero value is an error (see Error processing).
    #[option, variable]
    kernel_unit_len: NumberOptNumber,
}

/// This filter primitive fills a target rectangle with a repeated, tiled pattern of an input image. The target rectangle is
/// as large as the filter primitive subregion established by the x, y, width and height attributes on the feTile
/// element.
///
/// See [`feTitle`](https://www.w3.org/TR/SVG11/filters.html#feTitleElement)
leaf FeTile mixin FePrimitive {
    /// See [`FeIn`]
    #[option, variable]
    in: FeIn,
}

/// This filter primitive creates an image using the Perlin turbulence function.
/// It allows the synthesis of artificial textures like clouds or marble. For a detailed description the of the Perlin turbulence
/// function, see "Texturing and Modeling", Ebert et al, AP Professional, 1994. The resulting image will fill the entire filter
/// primitive subregion for this filter primitive.
///
/// See [`feTurbulence`](https://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement)
leaf FeTurbulence mixin FePrimitive {
    /// The base frequency (frequencies) parameter(s) for the noise function. If two `number`s are provided, the first number
    /// represents a base frequency in the X direction and the second value represents a base frequency in the Y direction.
    /// If one number is provided, then that value is used for both X and Y.
    ///
    /// A negative value for base frequency is an error (see Error processing).
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specifie.
    #[option, variable]
    base_frequency: NumberOptNumber,

    /// The numOctaves parameter for the noise function.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 1 were specified.
    #[option, variable]
    num_octaves: int,

    /// The starting number for the pseudo random number generator.
    ///
    /// If the attribute is not specified, then the effect is as if a value of 0 were specified.
    /// When the seed number is handed over to the algorithm above it must first be truncated, i.e.
    /// rounded to the closest integer value towards zero.
    #[option, variable]
    seed: float,

    /// See [`FeStitchTiles`]
    #[option, variable]
    stitch_tiles: FeStitchTiles,

    /// See [`FeStitchTiles`]
    #[option, variable]
    type: FeTurbulenceType,
}


/// Linear gradients are defined by a linearGradient element.
el LinearGradient {
    /// Defines the coordinate system for attributes ‘x1’, ‘y1’, ‘x2’ and ‘y2’.
    #[option, variable,rename("gradientUnits")]
    units: Coords,

    /// Contains the definition of an optional additional transformation from the gradient coordinate system onto the
    /// target coordinate system (i.e., userSpaceOnUse or objectBoundingBox). This allows for things such as skewing
    /// the gradient. This additional transformation matrix is post-multiplied to (i.e., inserted to the right of)
    /// any previously defined transformations, including the implicit transformation necessary to convert from object
    /// bounding box units to user space.
    ///
    /// If attribute ‘gradientTransform’ is not specified, then the effect is as if an identity transform were specified.
    ///
    /// Variable: yes.
    #[option, variable, rename("gradientTransform")]
    transform: vec[Transform],

    /// ‘x1’, ‘y1’, ‘x2’ and ‘y2’ define a gradient vector for the linear gradient.
    /// This gradient vector provides starting and ending points onto which the gradient stops are mapped. The values
    /// of ‘x1’, ‘y1’, ‘x2’ and ‘y2’ can be either numbers or percents.
    ///
    /// If the attribute is not specified, the effect is as if a value of '0%' were specified.
    ///
    /// Variable: yes.
    #[option, variable, init]
    x1: Length,

    /// See [`x1`](LinearGradient::x1)
    #[option, variable, init]
    y1: Length,

    /// See [`x1`](LinearGradient::x1)
    #[option, variable, init]
    x2: Length,

    /// See [`x1`](LinearGradient::x1)
    #[option, variable, init]
    y2: Length,

    /// Indicates what happens if the gradient starts or ends inside the bounds of the target rectangle.
    #[option, variable]
    spread: SpreadMethod,

    #[option,variable, rename("xlink:href")] 
    href: Iri
}

/// Radial gradients are defined by a radialGradient element.
el RadialGradient {
    /// Defines the coordinate system for attributes ‘x1’, ‘y1’, ‘x2’ and ‘y2’.
    #[option, variable, rename("gradientUnits")]
    unit: Coords,

    /// Contains the definition of an optional additional transformation from the gradient coordinate system onto the
    /// target coordinate system (i.e., userSpaceOnUse or objectBoundingBox). This allows for things such as skewing
    /// the gradient. This additional transformation matrix is post-multiplied to (i.e., inserted to the right of)
    /// any previously defined transformations, including the implicit transformation necessary to convert from object
    /// bounding box units to user space.
    ///
    /// If attribute ‘gradientTransform’ is not specified, then the effect is as if an identity transform were specified.
    ///
    /// Variable: yes.
    #[option, variable, rename("gradientTransform")]
    transform: vec[Transform],

    /// ‘cx’, ‘cy’ and ‘r’ define the largest (i.e., outermost) circle for the radial gradient.
    /// The gradient will be drawn such that the 100% gradient stop is mapped to the perimeter
    /// of this largest (i.e., outermost) circle.
    ///
    /// If the attribute is not specified, the effect is as if a value of '50%' were specified.
    ///
    /// Variable: yes.
    #[option, variable,init]
    cx: Length,

    /// See [`cx`](RadialGradient::cx)
    /// If the attribute is not specified, the effect is as if a value of '50%' were specified.
    #[option, variable,init]
    cy: Length,

    /// See [`cx`](RadialGradient::cx)
    ///
    /// A negative value is an error (see Error processing). A value of zero will cause the area to be painted as a single color
    /// using the color and opacity of the last gradient stop.
    ///
    /// If the attribute is not specified, the effect is as if a value of '50%' were specified.
    ///
    /// Variable: yes.
    #[option, variable,init]
    r: Length,

    /// ‘fx’ and ‘fy’ define the focal point for the radial gradient. The gradient will be drawn such that the
    /// 0% gradient stop is mapped to (fx, fy).
    ///
    /// If attribute ‘fx’ is not specified, ‘fx’ will coincide with the presentational value of ‘cx’ for the element whether the value
    /// for 'cx' was inherited or not. If the element references an element that specifies a value for 'fx', then the value of 'fx'
    /// is inherited from the referenced element.
    ///
    /// Variable: yes.
    #[option, variable,init]
    fx: Length,

    /// See [`fx`](RadialGradient::fx)
    ///
    /// If attribute ‘fy’ is not specified, ‘fy’ will coincide with the presentational value of ‘cy’ for the element whether the value
    /// for 'cy' was inherited or not. If the element references an element that specifies a value for 'fy', then the value of 'fy'
    /// is inherited from the referenced element.
    ///
    /// Variable: yes.
    #[option, variable,init]
    fy: Length,

    /// Indicates what happens if the gradient starts or ends inside the bounds of the target rectangle.
    #[option, variable]
    spread: SpreadMethod,

    #[option,variable, rename("xlink:href")] 
    href: Iri
}

/// The ramp of colors to use on a gradient is defined by the stop elements that are child elements
/// to either the linearGradient element or the radialGradient element.
#[rename("stop")]
leaf GradientStop {
    /// The ‘offset’ attribute is either a `<number>` (usually ranging from 0 to 1) or a `<percent>`
    /// (usually ranging from 0% to 100%) which indicates where the gradient stop is placed.
    /// For linear gradients, the ‘offset’ attribute represents a location along the gradient vector.
    /// For radial gradients, it represents a percent distance from (fx,fy) to the edge of the
    /// outermost/largest circle.
    ///
    /// Variable: yes.
    #[variable]
    offset: float,

    /// indicates what color to use at that gradient stop
    #[option, variable,rename("stop-color")]
    color: Color,

    /// Defines the opacity of a given gradient stop.
    #[option, variable,rename("stop-opacity")]
    opacity: float,
}

/// A container element for grouping together related graphics elements.
#[rename("g")]
el Group;


/// Paths represent the outline of a shape which can be filled, stroked, used as a clipping path,
/// or any combination of the three.
leaf Path {
    /// The definition of the outline of a shape.
    #[variable,rename("d")]
    events: vec[PathEvent],

    /// The author's computation of the total length of the path, in user units.
    /// This value is used to calibrate the user agent's own distance-along-a-path
    /// calculations with that of the author. The user agent will scale all
    /// distance-along-a-path computations by the ratio of ‘pathLength’ to the user
    /// agent's own computed value for total path length. ‘pathLength’ potentially
    /// affects calculations for text on a path, motion animation and various stroke
    /// operations.
    ///
    /// A negative value is an error (see Error processing).
    #[option, variable]
    length: Length,
}

/// A pattern is used to fill or stroke an object using a pre-defined graphic object which can be replicated ("tiled")
/// at fixed intervals in x and y to cover the areas to be painted. Patterns are defined using a pattern element and
/// then referenced by properties fill and stroke on a given graphics element to indicate that the given element
/// shall be filled or stroked with the referenced pattern.
///
/// Attributes x, y, width, height and patternUnits define a reference rectangle somewhere on the infinite canvas.
/// The reference rectangle has its top/left at (x, y) and its bottom/right at (x + width, y + height). The tiling
/// theoretically extends a series of such rectangles to infinity in X and Y (positive and negative), with rectangles
/// starting at (x + m*width, y + n* height) for each possible integer value for m and n.
el Pattern {
    /// Defines the coordinate system for attributes ‘x’, ‘y’, ‘width’ and ‘height’.
    ///
    /// If patternUnits="objectBoundingBox", the user coordinate system for attributes x, y, width and height
    /// is established using the bounding box of the element to which the pattern is applied (see Object bounding box units)
    /// and then applying the transform specified by attribute patternTransform.
    ///
    /// If patternUnits="userSpaceOnUse", x, y, width and height represent values in the coordinate system
    /// that results from taking the current user coordinate system in place at the time when the pattern element
    /// is referenced (i.e., the user coordinate system for the element referencing thepatternelement via afill’
    /// orstrokeproperty) and then applying the transform specified by attribute patternTransform.
    ///
    /// If attribute `units` is not specified, then the effect is as if a value of 'objectBoundingBox' were specified.
    #[option, variable, rename("patternUnits")]
    units: Coords,
    /// Defines the coordinate system for the contents of the pattern. Note that this attribute has no effect
    /// if attribute viewBox is specified.
    ///
    /// If patternContentUnits="userSpaceOnUse", the user coordinate system for the contents of the pattern
    /// element is the coordinate system that results from taking the current user coordinate system in place
    /// at the time when the pattern element is referenced (i.e., the user coordinate system for the element
    /// referencing thepatternelement via afillorstrokeproperty) and then applying the transform
    /// specified by attribute patternTransform.
    ///
    /// If patternContentUnits="objectBoundingBox", the user coordinate system for the contents of the pattern
    /// element is established using the bounding box of the element to which the pattern is applied (see Object
    /// bounding box units) and then applying the transform specified by attribute patternTransform.
    ///
    /// If attribute `content_units` is not specified, then the effect is as if a value of 'userSpaceOnUse'
    /// were specified.
    #[option, variable]
    content_units: Coords,

    /// Contains the definition of an optional additional transformation from the pattern coordinate system onto the
    /// target coordinate system (i.e., 'userSpaceOnUse' or 'objectBoundingBox'). This allows for things such as
    /// skewing the pattern tiles. This additional transformation matrix is post-multiplied to (i.e., inserted to
    /// the right of) any previously defined transformations, including the implicit transformation necessary to convert
    /// from object bounding box units to user space.
    ///
    /// If attribute `transform` is not specified, then the effect is as if an identity transform were specified.
    #[option, variable]
    transform: Transform,

    /// x, y, width and height indicate how the pattern tiles are placed and spaced. These attributes represent
    /// coordinates and values in the coordinate space specified by the combination of attributes [`units`](Self::units) and
    /// [`content_units`](Self::content_units).
    ///
    /// If the attribute is not specified, the effect is as if a value of zero were specified.
    ///
    /// Animatable: yes.
    #[option, variable, init]
    x: Length,

    /// See [`x`](Self::x).
    ///
    /// If the attribute is not specified, the effect is as if a value of zero were specified.
    ///
    /// Animatable: yes.
    #[option, variable, init]
    y: Length,

    /// See [`x`](Self::x).
    ///
    /// If the attribute is not specified, the effect is as if a value of zero were specified.
    ///
    /// Animatable: yes.
    #[option, variable, init]
    width: Length,

    /// See [`x`](Self::x).
    ///
    /// If the attribute is not specified, the effect is as if a value of zero were specified.
    ///
    /// Animatable: yes.
    #[option, variable, init]
    height: Length,

    #[option,variable, rename("xlink:href")] 
    href: Iri
}

/// Use a fragment by name.
leaf Use(#[variable,rename("xlink:href")] Iri);


/// The rect element defines a rectangle which is axis-aligned with the current user coordinate system.
/// Rounded rectangles can be achieved by setting appropriate values for attributes rx and ry.
///
///
/// The values used for the x- and y-axis rounded corner radii are determined implicitly if the rx or ry attributes (or both) are not specified, or are specified but with invalid values. The values are also subject to clamping so that the lengths of the straight segments of the rectangle are never negative. The effective values for rx and ry are determined by following these steps in order:
///
/// 1. Let rx and ry be length values.
/// 1. If neither rx nor ry are properly specified, then set both rx and ry to 0. (This will result in square corners.)
/// 1. Otherwise, if a properly specified value is provided for rx, but not for ry, then set both rx and ry to the value of rx.
/// 1. Otherwise, if a properly specified value is provided for ry, but not for rx, then set both rx and ry to the value of ry.
/// 1. Otherwise, both rx and ry were specified properly. Set rx to the value of rx and ry to the value of ry.
/// 1. If rx is greater than half of width, then set rx to half of width.
/// 1. If ry is greater than half of height, then set ry to half of height.
/// 1. The effective values of rx and ry are rx and ry, respectively.
leaf Rect {
    /// The x-axis coordinate of the side of the rectangle which has the smaller x-axis coordinate value in the current user coordinate system.
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// Animatable: yes.
    #[variable]
    x: Length,

    /// The y-axis coordinate of the side of the rectangle which has the smaller y-axis coordinate value in the current user coordinate system.
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// Animatable: yes.
    #[variable]
    y: Length,

    /// The width of the rectangle.
    /// A negative value is an error (see Error processing). A value of zero disables rendering of the element.
    ///
    /// Animatable: yes.
    #[variable]
    width: Length,

    /// The height of the rectangle.
    /// A negative value is an error (see Error processing). A value of zero disables rendering of the element.
    ///
    /// Animatable: yes.
    #[variable]
    height: Length,

    /// For rounded rectangles, the x-axis radius of the ellipse used to round off the corners of the rectangle.
    /// A negative value is an error (see Error processing).
    ///
    /// Animatable: yes.
    #[option, variable]
    rx: Length,

    /// For rounded rectangles, the y-axis radius of the ellipse used to round off the corners of the rectangle.
    /// A negative value is an error (see Error processing).
    ///
    /// Animatable: yes.
    #[option, variable]
    ry: Length,
}


/// The circle element defines a circle based on a center point and a radius.
leaf Circle {
    /// The x-axis coordinate of the center of the circle.
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// Animatable: yes.
    #[variable]
    cx: Length,

    /// The y-axis coordinate of the center of the circle.
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// Animatable: yes.
    #[variable]
    cy: Length,

    /// The radius of the circle.
    /// A negative value is an error (see Error processing). A value of zero disables rendering of the element.
    ///
    /// Animatable: yes.
    #[variable]
    r: Length,
}

/// The ellipse element defines an ellipse which is axis-aligned with the current user coordinate
/// system based on a center point and two radii.
leaf Ellipse {
    /// The x-axis coordinate of the center of the ellipse.
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// Animatable: yes.
    #[option, variable]
    cx: Length,

    /// The y-axis coordinate of the center of the ellipse.
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// Animatable: yes.
    #[option, variable]
    cy: Length,

    /// The x-axis radius of the ellipse.
    /// A negative value is an error (see Error processing). A value of zero disables rendering of the element.
    ///
    /// Animatable: yes.
    #[variable]
    rx: Length,

    /// The y-axis radius of the ellipse.
    /// A negative value is an error (see Error processing). A value of zero disables rendering of the element.
    ///
    /// Animatable: yes.
    #[variable]
    ry: Length,
}

/// The line element defines a line segment that starts at one point and ends at another.
leaf Line {
    /// The x-axis coordinate of the start of the line.
    ///
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// Animatable: yes.
    #[variable]
    x1: Length,

    /// The y-axis coordinate of the start of the line.
    ///
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// Animatable: yes.
    #[variable]
    y1: Length,

    /// The x-axis coordinate of the end of the line.
    ///
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// Animatable: yes.
    #[variable]
    x2: Length,

    /// The y-axis coordinate of the end of the line.
    ///
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// Animatable: yes.
    #[variable]
    y2: Length,
}

/// The polyline element defines a set of connected straight line segments. Typically, polyline elements define open shapes.
leaf Polyline(
    /// The points that make up the polygon. All coordinate values are in the user coordinate system.
    ///
    /// Animatable: yes.
    #[variable,rename("points")]
    vec[Point],
);

/// The polygon element defines a closed shape consisting of a set of connected straight line segments.
leaf Polygon(
    /// The points that make up the polygon. All coordinate values are in the user coordinate system.
    ///
    /// Animatable: yes.
    #[variable,rename("points")]
    vec[Point],
);



/// The text element defines a graphics element consisting of text.
///
/// See [`text`](https://www.w3.org/TR/SVG11/text.html#TextElement)
mixin MixinText {
    /// If a single `coordinate` is provided, then the value represents the new absolute X coordinate for
    /// the current text position for rendering the glyphs that correspond to the first character within
    /// this element or any of its descendants.
    ///
    /// If a comma- or space-separated list of n `coordinate`s is provided, then the values represent new
    /// absolute X coordinates for the current text position for rendering the glyphs corresponding to
    /// each of the first n characters within this element or any of its descendants.
    ///
    /// For additional processing rules, refer to the description of the ‘x’ attribute on the ‘tspan’ element.
    ///
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    #[option, variable,init]
    x: vec[Length],

    /// The corresponding list of absolute Y coordinates for the glyphs corresponding to the characters within this element.
    /// The processing rules for the ‘y’ attribute parallel the processing rules for the ‘x’ attribute.
    ///
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    #[option, variable,init]
    y: vec[Length],

    /// Shifts in the current text position along the x-axis for the characters within this element or any of its descendants.
    ///
    /// Refer to the description of the ‘dx’ attribute on the ‘tspan’ element.
    ///
    /// If the attribute is not specified on this element or any of its descendants, no supplemental shifts along
    /// the x-axis will occur.
    #[option, variable]
    dx: vec[Length],

    /// Shifts in the current text position along the y-axis for the characters within this element or any of its descendants.
    ///
    /// Refer to the description of the ‘dy’ attribute on the ‘tspan’ element.
    ///
    /// If the attribute is not specified on this element or any of its descendants, no supplemental shifts along
    /// the y-axis will occur.
    #[option, variable]
    dy: vec[Length],

    /// The supplemental rotation about the current text position that will be applied to all of the glyphs corresponding
    /// to each character within this element.
    ///
    /// Refer to the description of the ‘rotate’ attribute on the ‘tspan’ element.
    ///
    /// If the attribute is not specified on this element or any of its descendants, no supplemental rotations will occur.
    #[option, variable]
    rotate: vec[Angle],

    /// The author's computation of the total sum of all of the advance values that correspond to character data within
    /// this element, including the advance value on the glyph (horizontal or vertical), the effect of properties ‘kerning’,
    /// ‘letter-spacing’ and ‘word-spacing’ and adjustments due to attributes ‘dx’ and ‘dy’ on ‘tspan’ elements. This value
    /// is used to calibrate the user agent's own calculations with that of the author.
    ///
    /// The purpose of this attribute is to allow the author to achieve exact alignment, in visual rendering order after any
    /// bidirectional reordering, for the first and last rendered glyphs that correspond to this element; thus, for the last
    /// rendered character (in visual rendering order after any bidirectional reordering), any supplemental inter-character
    /// spacing beyond normal glyph advances are ignored (in most cases) when the user agent determines the appropriate amount
    /// to expand/compress the text string to fit within a length of ‘textLength’.
    ///
    /// A negative value is an error (see Error processing).
    ///
    /// If the attribute is not specified, the effect is as if the author's computation exactly matched the value calculated
    /// by the user agent; thus, no advance adjustments are made.
    #[option, variable]
    text_length: vec[Length],

    /// Indicates the type of adjustments which the user agent shall make to make the rendered length of the text match the
    /// value specified on the ‘textLength’ attribute.
    ///
    /// The user agent is required to achieve correct start and end positions for the text strings, but the locations of
    /// intermediate glyphs are not predictable because user agents might employ advanced algorithms to stretch or compress
    /// text strings in order to balance correct start and end positioning with optimal typography.
    ///
    /// Note that, for a text string that contains n characters, the adjustments to the advance values often occur only for n−1
    /// characters (see description of attribute ‘textLength’), whereas stretching or compressing of the glyphs will be applied
    /// to all n characters.
    ///
    /// If the attribute is not specified, the effect is as a value of 'spacing' were specified.
    #[option, variable]
    length_adjust: TextLengthAdjust,
}

/// The text element defines a graphics element consisting of text.
///
/// See [`text`](https://www.w3.org/TR/SVG11/text.html#TextElement)
el Text mixin MixinText;

/// The text element defines a graphics element consisting of text.
///
/// See [`text`](https://www.w3.org/TR/SVG11/text.html#TextElement)
#[rename("tspan")]
el TextSpan mixin MixinText;

/// Text content chars.
leaf Characters(#[rename("value")] string);

/// In addition to text drawn in a straight line, SVG also includes the ability to place text along the
/// shape of a path element. To specify that a block of text is to be rendered along the shape of a path,
/// include the given text within a textPath element which includes an href attribute with an IRI
/// reference to a path element.
el TextPath {
    /// An offset from the start of the ‘path’ for the initial current text position,
    /// calculated using the user agent's [`distance along the path`] algorithm.
    ///
    /// If a `length` other than a percentage is given, then the ‘startOffset’ represents a
    /// distance along the path measured in the current user coordinate system.
    ///
    /// If a percentage is given, then the ‘startOffset’ represents a percentage distance along
    /// the entire path. Thus, startOffset="0%" indicates the start point of the path and
    /// startOffset="100%" indicates the end point of the path.
    ///
    /// If the attribute is not specified, the effect is as if a value of "0" were specified.
    ///
    /// [`distance along the path`]: https://www.w3.org/TR/SVG11/paths.html#DistanceAlongAPath
    #[option, variable]
    start_offset: Length,

    /// See [`TextPathMethod`]
    #[option, variable]
    method: TextPathMethod,

    /// See [`TextPathSpacing`]
    #[option, variable]
    spacing: TextPathSpacing,

    /// An IRI reference to the path element onto which the glyphs will be rendered.
    /// If `iri` is an invalid reference (e.g., no such element exists, or the referenced element is not apath’),
    /// then the textPath element is in error and its entire contents shall not be rendered by the user agent.
    #[variable]
    href: Iri,
}

group Shape := (Rect,Circle,Ellipse,Line,Polyline,Polygon);
group Gradient := (LinearGradient,RadialGradient);

children (Text,TextSpan,TextPath,Characters) of Text;
children (TextSpan,Characters) of TextSpan;
children (TextSpan,Characters) of TextPath;

children (
    Text,
    ClipPath,
    Filter,
    Mask,
    Group,
    Canvas,
    Shape,
    Gradient,
) of Group;

children (
    Text,
    ClipPath,
    Filter,
    Mask,
    Group,
    Canvas,
    Shape,
    Gradient,
) of Canvas;

children (
    FeBlend,
    FeColorMatrix,
    FeComponentTransfer, 
    FeComposite,
    FeConvolveMatrix,
    FeDiffuseLighting,
    FeDisplacementMap,
    FeFlood,
    FeGaussianBlur,
    FeMerge,
    FeImage,
    FeMorphology,
    FeOffset,
    FeSpecularLighting,
    FeTile,
    FeTurbulence,
) of Filter;

children (
    FeFuncR,
    FeFuncG,
    FeFuncB,
    FeFuncA,
) of FeComponentTransfer;

children FeMergeNode of FeMerge;

children (
    FeDistantLight,
    FePointLight,
    FeSpotLight,
) of FeDiffuseLighting;

children (
    FeDistantLight,
    FePointLight,
    FeSpotLight,
) of FeSpecularLighting;

children GradientStop of Gradient;

children (
    ClipPath,
    Filter,
    Mask,
    Text,
) of Pattern;

children (Shape,Text,Use) of ClipPath;

children (
    Text,
    ClipPath,
    Filter,
    Group,
    Canvas,
    Use,
    Shape,
    Gradient,
) of Mask;


apply (
    TextLayout,
    Font,
    WithFilter,
    Fill,
    Stroke,
) to (Text,TextSpan);

apply (
    EnableBackground,
    WithTransform,
    Fill,
    Stroke,
    WithFilter,
    WithClipPath,
    WithMask,
    Opacity,
    Font,
) to (
    Group,
    Canvas,
    Filter,
    Mask,
    Shape,
    Use,
    Path,
);

apply Id to (
    RadialGradient,
    LinearGradient,
    Group,
    Canvas,
    Filter,
    Mask,
    Text,
    TextSpan,
    Pattern,
    Path,
);

apply ViewBox to Canvas;
apply ViewBox to Pattern;