webgl2-sdf 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +100 -0
  2. package/node/bezier/bezier-curves-to-line-segs.d.ts +10 -0
  3. package/node/bezier/eval-de-casteljau.d.ts +17 -0
  4. package/node/bezier/from-to/from-to-2.d.ts +12 -0
  5. package/node/bezier/from-to/from-to-3.d.ts +12 -0
  6. package/node/bezier/from-to/from-to.d.ts +10 -0
  7. package/node/bezier/is-cubic-obtuse.d.ts +11 -0
  8. package/node/bezier/is-quad-obtuse.d.ts +11 -0
  9. package/node/bezier/is-really-point.d.ts +9 -0
  10. package/node/bezier/split-by-deviation-from-straight-line-cubic.d.ts +20 -0
  11. package/node/bezier/split-by-deviation-from-straight-line-quad.d.ts +11 -0
  12. package/node/bezier/split-into-line-segments.d.ts +10 -0
  13. package/node/debug-shaders.d.ts +9 -0
  14. package/node/generate-sdf.d.ts +18 -0
  15. package/node/helpers/calc-circs.d.ts +11 -0
  16. package/node/helpers/clip-line-segment-to-grid.d.ts +14 -0
  17. package/node/helpers/clip-line-segment-to-strips.d.ts +13 -0
  18. package/node/helpers/create-empty-grid.d.ts +8 -0
  19. package/node/helpers/create-empty-strips.d.ts +7 -0
  20. package/node/helpers/distance-seg-to-p.d.ts +5 -0
  21. package/node/helpers/find-close-cells.d.ts +3 -0
  22. package/node/helpers/find-crossing-cells.d.ts +3 -0
  23. package/node/helpers/get-distance-to-line-function.d.ts +10 -0
  24. package/node/helpers/jump-idx.d.ts +2 -0
  25. package/node/helpers/map-to-viewbox.d.ts +2 -0
  26. package/node/helpers/seg-box-x.d.ts +10 -0
  27. package/node/helpers/seg-strip-x.d.ts +9 -0
  28. package/node/index.d.ts +1 -0
  29. package/node/main-program.d.ts +4 -0
  30. package/node/max-aspect-ratio-before-stretch.d.ts +2 -0
  31. package/node/prepare-buffers.d.ts +10 -0
  32. package/node/row-count.d.ts +2 -0
  33. package/node/shaders/main.fragment.d.ts +2 -0
  34. package/node/shaders/main.vertex.d.ts +2 -0
  35. package/node/svg/get-beziers-from-raw-paths.d.ts +12 -0
  36. package/node/svg/get-paths-from-str.d.ts +9 -0
  37. package/node/svg/path-data-polyfill/parse-number.d.ts +10 -0
  38. package/node/svg/path-data-polyfill/parse-path-data-string.d.ts +9 -0
  39. package/node/svg/path-data-polyfill/source.d.ts +19 -0
  40. package/node/svg/path-segment/c.d.ts +19 -0
  41. package/node/svg/path-segment/h.d.ts +15 -0
  42. package/node/svg/path-segment/l.d.ts +16 -0
  43. package/node/svg/path-segment/q.d.ts +16 -0
  44. package/node/svg/path-segment/s.d.ts +20 -0
  45. package/node/svg/path-segment/t.d.ts +18 -0
  46. package/node/svg/path-segment/v.d.ts +15 -0
  47. package/node/svg/path-segment/z.d.ts +13 -0
  48. package/node/svg/path-state.d.ts +11 -0
  49. package/node/tex-width.d.ts +11 -0
  50. package/node/types/attribute.d.ts +6 -0
  51. package/node/types/cell.d.ts +18 -0
  52. package/node/types/gl-context.d.ts +28 -0
  53. package/node/types/gl-type.d.ts +2 -0
  54. package/node/types/gl-usage.d.ts +2 -0
  55. package/node/types/program.d.ts +16 -0
  56. package/node/types/strip.d.ts +8 -0
  57. package/node/types/texture.d.ts +4 -0
  58. package/node/utils/calc-circs.d.ts +11 -0
  59. package/node/utils/clip-line-segment-to-grid.d.ts +14 -0
  60. package/node/utils/clip-line-segment-to-strips.d.ts +13 -0
  61. package/node/utils/create-empty-grid.d.ts +8 -0
  62. package/node/utils/create-empty-strips.d.ts +7 -0
  63. package/node/utils/distance-seg-to-p.d.ts +5 -0
  64. package/node/utils/find-close-cells.d.ts +3 -0
  65. package/node/utils/find-crossing-cells.d.ts +3 -0
  66. package/node/utils/get-distance-to-line-function.d.ts +10 -0
  67. package/node/utils/jump-idx.d.ts +2 -0
  68. package/node/utils/map-to-viewbox.d.ts +2 -0
  69. package/node/utils/seg-box-x.d.ts +10 -0
  70. package/node/utils/seg-strip-x.d.ts +9 -0
  71. package/node/vector/dot.d.ts +8 -0
  72. package/node/vector/from-to-vec.d.ts +8 -0
  73. package/node/vector/len.d.ts +6 -0
  74. package/node/webgl-utils/compile-shader.d.ts +2 -0
  75. package/node/webgl-utils/get-gl-context.d.ts +10 -0
  76. package/node/webgl-utils/set-attribute.d.ts +15 -0
  77. package/node/webgl-utils/set-uniform-block.d.ts +9 -0
  78. package/node/webgl-utils/set-uniform.d.ts +4 -0
  79. package/node/webgl-utils/uniform-block.d.ts +6 -0
  80. package/node/webgl-utils/uniform-type.d.ts +2 -0
  81. package/node/webgl-utils/use-program.d.ts +17 -0
  82. package/node/webgl-utils/use-texture.d.ts +9 -0
  83. package/node/webgl2.d.ts +2 -0
  84. package/package.json +56 -0
  85. package/src/bezier/bezier-curves-to-line-segs.ts +39 -0
  86. package/src/bezier/eval-de-casteljau.ts +78 -0
  87. package/src/bezier/from-to/from-to-2.ts +159 -0
  88. package/src/bezier/from-to/from-to-3.ts +176 -0
  89. package/src/bezier/from-to/from-to.ts +30 -0
  90. package/src/bezier/is-cubic-obtuse.ts +31 -0
  91. package/src/bezier/is-quad-obtuse.ts +26 -0
  92. package/src/bezier/is-really-point.ts +25 -0
  93. package/src/bezier/split-by-deviation-from-straight-line-cubic.ts +109 -0
  94. package/src/bezier/split-by-deviation-from-straight-line-quad.ts +66 -0
  95. package/src/bezier/split-into-line-segments.ts +39 -0
  96. package/src/debug-shaders.ts +38 -0
  97. package/src/generate-sdf.ts +91 -0
  98. package/src/index.ts +2 -0
  99. package/src/main-program.ts +160 -0
  100. package/src/max-aspect-ratio-before-stretch.ts +5 -0
  101. package/src/prepare-buffers.ts +149 -0
  102. package/src/row-count.ts +6 -0
  103. package/src/shaders/main.fragment.ts +157 -0
  104. package/src/shaders/main.vertex.ts +55 -0
  105. package/src/svg/get-beziers-from-raw-paths.ts +112 -0
  106. package/src/svg/get-paths-from-str.ts +19 -0
  107. package/src/svg/path-data-polyfill/parse-number.ts +138 -0
  108. package/src/svg/path-data-polyfill/parse-path-data-string.ts +26 -0
  109. package/src/svg/path-data-polyfill/source.ts +176 -0
  110. package/src/svg/path-segment/c.ts +34 -0
  111. package/src/svg/path-segment/h.ts +28 -0
  112. package/src/svg/path-segment/l.ts +30 -0
  113. package/src/svg/path-segment/q.ts +30 -0
  114. package/src/svg/path-segment/s.ts +40 -0
  115. package/src/svg/path-segment/t.ts +35 -0
  116. package/src/svg/path-segment/v.ts +28 -0
  117. package/src/svg/path-segment/z.ts +27 -0
  118. package/src/svg/path-state.ts +15 -0
  119. package/src/tex-width.ts +14 -0
  120. package/src/types/attribute.ts +9 -0
  121. package/src/types/cell.ts +21 -0
  122. package/src/types/gl-context.ts +28 -0
  123. package/src/types/gl-type.ts +16 -0
  124. package/src/types/gl-usage.ts +14 -0
  125. package/src/types/program.ts +14 -0
  126. package/src/types/strip.ts +11 -0
  127. package/src/types/texture.ts +7 -0
  128. package/src/types/typed-array.ts +16 -0
  129. package/src/utils/calc-circs.ts +129 -0
  130. package/src/utils/clip-line-segment-to-grid.ts +133 -0
  131. package/src/utils/clip-line-segment-to-strips.ts +196 -0
  132. package/src/utils/create-empty-grid.ts +32 -0
  133. package/src/utils/create-empty-strips.ts +21 -0
  134. package/src/utils/distance-seg-to-p.ts +50 -0
  135. package/src/utils/find-close-cells.ts +171 -0
  136. package/src/utils/find-crossing-cells.ts +40 -0
  137. package/src/utils/get-distance-to-line-function.ts +59 -0
  138. package/src/utils/is-point-in-box.ts +16 -0
  139. package/src/utils/jump-idx.ts +107 -0
  140. package/src/utils/map-to-viewbox.ts +41 -0
  141. package/src/utils/path.ts +137 -0
  142. package/src/utils/seg-box-x.ts +84 -0
  143. package/src/utils/seg-strip-x.ts +72 -0
  144. package/src/utils/sum.ts +13 -0
  145. package/src/vector/dot.ts +13 -0
  146. package/src/vector/from-to-vec.ts +13 -0
  147. package/src/vector/len.ts +11 -0
  148. package/src/webgl-utils/compile-shader.ts +15 -0
  149. package/src/webgl-utils/get-gl-context.ts +61 -0
  150. package/src/webgl-utils/set-attribute.ts +74 -0
  151. package/src/webgl-utils/set-uniform-block.ts +45 -0
  152. package/src/webgl-utils/set-uniform.ts +24 -0
  153. package/src/webgl-utils/uniform-block.ts +9 -0
  154. package/src/webgl-utils/uniform-type.ts +10 -0
  155. package/src/webgl-utils/use-program.ts +48 -0
  156. package/src/webgl-utils/use-texture.ts +34 -0
@@ -0,0 +1,112 @@
1
+ import { PathState } from './path-state.js';
2
+ import { z } from './path-segment/z.js';
3
+ import { c } from './path-segment/c.js';
4
+ import { s } from './path-segment/s.js';
5
+ import { l } from './path-segment/l.js';
6
+ import { h } from './path-segment/h.js';
7
+ import { v } from './path-segment/v.js';
8
+ import { q } from './path-segment/q.js';
9
+ import { t } from './path-segment/t.js';
10
+
11
+
12
+ const pathFs: { [index:string] : (s: PathState) => number[][] } = {
13
+ c, // cubic bezier
14
+ h, // horizontal line
15
+ l, // line
16
+ q, // quadratic bezier
17
+ s, // cubic bezier (smooth)
18
+ t, // quadratic bezier (smooth)
19
+ v, // vertical line
20
+ z // close path
21
+ };
22
+
23
+
24
+ /**
25
+ * Returns order 1, 2 and 3 beziers from the given SVG DOM element. If a path
26
+ * data tag is not "C, Q or L, etc", i.e. if it is not an absolute bezier
27
+ * coordinate then it is converted into one.
28
+ *
29
+ * @param paths An SVG element
30
+ */
31
+ function getBeziersFromRawPaths(paths: { type: string, values: number[] }[]) {
32
+
33
+ if (paths.length === 0) {
34
+ return []; // A shape is not described
35
+ }
36
+
37
+ if (paths[0].type.toLowerCase() !== 'm') {
38
+ throw new Error(
39
+ 'Invalid SVG - every new path must start with an M or m.'
40
+ );
41
+ }
42
+
43
+ const s: PathState = { p: [0,0] };
44
+
45
+ const beziersArrays: number[][][][] = [];
46
+ let beziers: number[][][] = [];
47
+
48
+ let prevType: string | undefined = undefined;
49
+ for (let i=0; i<paths.length; i++) {
50
+ const pathSeg = paths[i];
51
+
52
+ const type = pathSeg.type.toLowerCase();
53
+ s.vals = pathSeg.values;
54
+
55
+ // If pathSeg was lowercase, it is relative - make absolute
56
+ if (pathSeg.type === type) {
57
+ if (type === 'v') {
58
+ s.vals[0] += s.p[1];
59
+ } else if (type === 'a') {
60
+ s.vals[5] += s.p[0];
61
+ s.vals[6] += s.p[1];
62
+ } else {
63
+ for (let i=0; i<s.vals.length; i++) {
64
+ s.vals[i] += s.p[i%2];
65
+ }
66
+ }
67
+ }
68
+
69
+ if (type === 'm') {
70
+ if (beziers.length) {
71
+ // This is a subpath, close as if the previous command was a
72
+ // Z or z.
73
+ if (prevType !== 'z') {
74
+ beziers.push(z(s));
75
+ }
76
+
77
+ // Start new path
78
+ beziersArrays.push(beziers);
79
+ beziers = [];
80
+ }
81
+
82
+ s.initialPoint = s.p = s.vals;
83
+ prevType = type;
84
+ continue;
85
+ }
86
+
87
+ const f = pathFs[type];
88
+ if (!f) { throw new Error('Invalid SVG - command not recognized.'); }
89
+
90
+ const ps = f(s);
91
+ s.p = ps[ps.length-1]; // Update current point
92
+ beziers.push(ps);
93
+
94
+ prevType = type;
95
+ }
96
+
97
+
98
+ if (beziers.length > 0) {
99
+ // This is a subpath, close as if the previous command was a Z or z.
100
+ if (prevType !== 'z') {
101
+ beziers.push(z(s));
102
+ }
103
+
104
+ // Start new path
105
+ beziersArrays.push(beziers);
106
+ }
107
+
108
+ return beziersArrays;
109
+ }
110
+
111
+
112
+ export { getBeziersFromRawPaths }
@@ -0,0 +1,19 @@
1
+ import { getBeziersFromRawPaths } from './get-beziers-from-raw-paths.js';
2
+ import { parsePathDataString } from './path-data-polyfill/parse-path-data-string.js';
3
+
4
+
5
+ /**
6
+ * Returns an array of loops with each loop consisting of an array of beziers
7
+ * and each bezier in turn consisting of an array of control points from the
8
+ * given SVG path string. An array of loops are returned (as opposed to a single
9
+ * loop) since an SVG path may have sub-paths.
10
+ * @param str The SVG path string, e.g. 'M1 1 C 5 1 5 2 4 2 C 3 3 1 3 1 1 z'
11
+ */
12
+ function getPathsFromStr(str: string): number[][][][] {
13
+ return getBeziersFromRawPaths(
14
+ parsePathDataString(str)
15
+ );
16
+ }
17
+
18
+
19
+ export { getPathsFromStr }
@@ -0,0 +1,138 @@
1
+ import { Source } from './source.js';
2
+
3
+
4
+ /**
5
+ * @hidden
6
+ * Parse a number from an SVG path. This very closely follows genericParseNumber(...) from
7
+ * Source/core/svg/SVGParserUtilities.cpp.
8
+ * Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
9
+ * @param source
10
+ */
11
+ function parseNumber(source: Source): number {
12
+ let exponent = 0;
13
+ let integer = 0;
14
+ let frac = 1;
15
+ let decimal = 0;
16
+ let sign = 1;
17
+ let expsign = 1;
18
+ const startIndex = source._currentIndex;
19
+
20
+ source._skipOptionalSpaces();
21
+
22
+ // Read the sign.
23
+ if (source._currentIndex < source._endIndex && source._string[source._currentIndex] === "+") {
24
+ source._currentIndex += 1;
25
+ } else if (source._currentIndex < source._endIndex && source._string[source._currentIndex] === "-") {
26
+ source._currentIndex += 1;
27
+ sign = -1;
28
+ }
29
+
30
+ if (
31
+ source._currentIndex === source._endIndex ||
32
+ (
33
+ (source._string[source._currentIndex] < "0" || source._string[source._currentIndex] > "9") &&
34
+ source._string[source._currentIndex] !== "."
35
+ )
36
+ ) {
37
+ throw new Error('The first character of a number must be one of [0-9+-.].');
38
+ }
39
+
40
+ // Read the integer part, build right-to-left.
41
+ const startIntPartIndex = source._currentIndex;
42
+
43
+ while (
44
+ source._currentIndex < source._endIndex &&
45
+ source._string[source._currentIndex] >= "0" &&
46
+ source._string[source._currentIndex] <= "9"
47
+ ) {
48
+ source._currentIndex += 1; // Advance to first non-digit.
49
+ }
50
+
51
+ if (source._currentIndex !== startIntPartIndex) {
52
+ let scanIntPartIndex = source._currentIndex - 1;
53
+ let multiplier = 1;
54
+
55
+ while (scanIntPartIndex >= startIntPartIndex) {
56
+ integer += multiplier * (Number(source._string[scanIntPartIndex]) - 0);
57
+ scanIntPartIndex -= 1;
58
+ multiplier *= 10;
59
+ }
60
+ }
61
+
62
+ // Read the decimals.
63
+ if (source._currentIndex < source._endIndex && source._string[source._currentIndex] === ".") {
64
+ source._currentIndex += 1;
65
+
66
+ if (
67
+ source._currentIndex >= source._endIndex ||
68
+ source._string[source._currentIndex] < "0" ||
69
+ source._string[source._currentIndex] > "9"
70
+ ) {
71
+ throw new Error('There must be a least one digit following the .')
72
+ }
73
+
74
+ while (
75
+ source._currentIndex < source._endIndex &&
76
+ source._string[source._currentIndex] >= "0" &&
77
+ source._string[source._currentIndex] <= "9"
78
+ ) {
79
+ frac *= 10;
80
+ decimal += (Number(source._string.charAt(source._currentIndex))) / frac;
81
+ source._currentIndex += 1;
82
+ }
83
+ }
84
+
85
+ // Read the exponent part.
86
+ if (
87
+ source._currentIndex !== startIndex &&
88
+ source._currentIndex + 1 < source._endIndex &&
89
+ (source._string[source._currentIndex] === "e" || source._string[source._currentIndex] === "E") &&
90
+ (source._string[source._currentIndex + 1] !== "x" && source._string[source._currentIndex + 1] !== "m")
91
+ ) {
92
+ source._currentIndex += 1;
93
+
94
+ // Read the sign of the exponent.
95
+ if (source._string[source._currentIndex] === "+") {
96
+ source._currentIndex += 1;
97
+ } else if (source._string[source._currentIndex] === "-") {
98
+ source._currentIndex += 1;
99
+ expsign = -1;
100
+ }
101
+
102
+ if (
103
+ source._currentIndex >= source._endIndex ||
104
+ source._string[source._currentIndex] < "0" ||
105
+ source._string[source._currentIndex] > "9"
106
+ ) {
107
+ throw new Error('There must be an exponent.')
108
+ }
109
+
110
+ while (
111
+ source._currentIndex < source._endIndex &&
112
+ source._string[source._currentIndex] >= "0" &&
113
+ source._string[source._currentIndex] <= "9"
114
+ ) {
115
+ exponent *= 10;
116
+ exponent += (Number(source._string[source._currentIndex]));
117
+ source._currentIndex += 1;
118
+ }
119
+ }
120
+
121
+ let number = integer + decimal;
122
+ number *= sign;
123
+
124
+ if (exponent) {
125
+ number *= Math.pow(10, expsign * exponent);
126
+ }
127
+
128
+ if (startIndex === source._currentIndex) {
129
+ throw new Error('Internal error: startIndex === source._currentIndex');
130
+ }
131
+
132
+ source._skipOptionalSpacesOrDelimiter();
133
+
134
+ return number;
135
+ }
136
+
137
+
138
+ export { parseNumber }
@@ -0,0 +1,26 @@
1
+ import { Source } from './source.js';
2
+
3
+
4
+ /**
5
+ * @hidden
6
+ * @param string
7
+ */
8
+ function parsePathDataString(string: string) {
9
+ if (!string.length) { return []; }
10
+
11
+ const source = new Source(string);
12
+ const pathData = [];
13
+
14
+ if (!source.initialCommandIsMoveTo()) {
15
+ throw new Error('Path must start with m or M');
16
+ }
17
+
18
+ while (source.hasMoreData()) {
19
+ pathData.push(source.parseSegment());
20
+ }
21
+
22
+ return pathData;
23
+ }
24
+
25
+
26
+ export { parsePathDataString }
@@ -0,0 +1,176 @@
1
+ import { parseNumber } from './parse-number.js';
2
+
3
+
4
+ /** @hidden */
5
+ const COMMAND_MAP: { [index:string]: string } = {
6
+ Z:"Z", M:"M", L:"L", C:"C", Q:"Q", A:"A", H:"H", V:"V", S:"S", T:"T",
7
+ z:"Z", m:"m", l:"l", c:"c", q:"q", a:"a", h:"h", v:"v", s:"s", t:"t"
8
+ };
9
+
10
+
11
+ /** @hidden */
12
+ class Source {
13
+ _string: string;
14
+ _currentIndex: number;
15
+ _endIndex: number;
16
+ _prevCommand: string | undefined;
17
+
18
+
19
+ constructor(string: string) {
20
+ this._string = string;
21
+ this._currentIndex = 0;
22
+ this._endIndex = this._string.length;
23
+ this._prevCommand = undefined;
24
+ this._skipOptionalSpaces();
25
+ }
26
+
27
+
28
+ parseSegment(): { type: string, values: number[] } {
29
+ const char = this._string[this._currentIndex];
30
+ let command = COMMAND_MAP[char];
31
+
32
+ if (command === undefined) {
33
+ if (this._prevCommand === undefined) {
34
+ throw new Error('Implicit command not allowed for first commands.')
35
+ }
36
+
37
+ // Check for remaining coordinates in the current command.
38
+ if ((char === "+" || char === "-" || char === "." || (char >= "0" && char <= "9")) &&
39
+ this._prevCommand !== "Z") {
40
+
41
+ if (this._prevCommand === "M") {
42
+ command = "L";
43
+ } else if (this._prevCommand === "m") {
44
+ command = "l";
45
+ } else {
46
+ command = this._prevCommand;
47
+ }
48
+ } else {
49
+ throw new Error('Remaining coordinates not found for implicit command');
50
+ }
51
+ } else {
52
+ this._currentIndex += 1;
53
+ }
54
+
55
+ this._prevCommand = command;
56
+
57
+ let values: number[] | undefined = undefined;
58
+ const cmd = command.toUpperCase();
59
+
60
+ if (cmd === "H" || cmd === "V") {
61
+ values = [parseNumber(this)];
62
+ } else if (cmd === "M" || cmd === "L" || cmd === "T") {
63
+ values = [parseNumber(this), parseNumber(this)];
64
+ } else if (cmd === "S" || cmd === "Q") {
65
+ values = [parseNumber(this), parseNumber(this), parseNumber(this), parseNumber(this)];
66
+ } else if (cmd === "C") {
67
+ values = [
68
+ parseNumber(this),
69
+ parseNumber(this),
70
+ parseNumber(this),
71
+ parseNumber(this),
72
+ parseNumber(this),
73
+ parseNumber(this)
74
+ ];
75
+ } else if (cmd === "A") {
76
+ values = [
77
+ parseNumber(this),
78
+ parseNumber(this),
79
+ parseNumber(this),
80
+ this._parseArcFlag(),
81
+ this._parseArcFlag(),
82
+ parseNumber(this),
83
+ parseNumber(this)
84
+ ];
85
+ } else if (cmd === "Z") {
86
+ this._skipOptionalSpaces();
87
+ values = [];
88
+ }
89
+
90
+ if (values === undefined) {
91
+ throw new Error('Unknown command')
92
+ } else {
93
+ return { type: command, values };
94
+ }
95
+ }
96
+
97
+
98
+ hasMoreData(): boolean {
99
+ return this._currentIndex < this._endIndex;
100
+ }
101
+
102
+
103
+ initialCommandIsMoveTo(): boolean {
104
+ // If the path is empty it is still valid, so return true.
105
+ if (!this.hasMoreData()) {
106
+ return true;
107
+ }
108
+
109
+ const command = COMMAND_MAP[this._string[this._currentIndex]];
110
+
111
+ return command === "M" || command === "m";
112
+ }
113
+
114
+
115
+ _isCurrentSpace(): boolean {
116
+ const char = this._string[this._currentIndex];
117
+ return char <= " " && (char === " " || char === "\n" || char === "\t" || char === "\r" || char === "\f");
118
+ }
119
+
120
+
121
+ _skipOptionalSpaces(): boolean {
122
+ while (this._currentIndex < this._endIndex && this._isCurrentSpace()) {
123
+ this._currentIndex += 1;
124
+ }
125
+
126
+ return this._currentIndex < this._endIndex;
127
+ }
128
+
129
+
130
+ _skipOptionalSpacesOrDelimiter(): boolean {
131
+ if (
132
+ this._currentIndex < this._endIndex &&
133
+ !this._isCurrentSpace() &&
134
+ this._string[this._currentIndex] !== ","
135
+ ) {
136
+ return false;
137
+ }
138
+
139
+ if (this._skipOptionalSpaces()) {
140
+ if (this._currentIndex < this._endIndex && this._string[this._currentIndex] === ",") {
141
+ this._currentIndex += 1;
142
+ this._skipOptionalSpaces();
143
+ }
144
+ }
145
+
146
+ return this._currentIndex < this._endIndex;
147
+ }
148
+
149
+
150
+ _parseArcFlag(): number {
151
+ if (this._currentIndex >= this._endIndex) {
152
+ throw new Error('Unable to parse arc flag');
153
+ }
154
+
155
+ let flag: number | undefined = undefined;
156
+ const flagChar = this._string[this._currentIndex];
157
+
158
+ this._currentIndex += 1;
159
+
160
+ if (flagChar === "0") {
161
+ flag = 0;
162
+ } else if (flagChar === "1") {
163
+ flag = 1;
164
+ } else {
165
+ throw new Error('Unable to parse arc flag - arc flag must be 0 or 1');
166
+ }
167
+
168
+ this._skipOptionalSpacesOrDelimiter();
169
+
170
+ return flag;
171
+ }
172
+ }
173
+
174
+
175
+ export { Source }
176
+
@@ -0,0 +1,34 @@
1
+ import { PathState } from "../path-state.js";
2
+
3
+
4
+ /**
5
+ * @hidden
6
+ * C and c: (from www.w3.org)
7
+ *
8
+ * params: x1 y1 x2 y2 x y
9
+ *
10
+ * Draws a cubic Bézier curve from the current point to (x,y)
11
+ * using (x1,y1) as the control point at the beginning of the
12
+ * curve and (x2,y2) as the control point at the end of the
13
+ * curve. C (uppercase) indicates that absolute coordinates
14
+ * will follow; c (lowercase) indicates that relative
15
+ * coordinates will follow. Multiple sets of coordinates may
16
+ * be specified to draw a polybézier. At the end of the
17
+ * command, the new current point becomes the final (x,y)
18
+ * coordinate pair used in the polybézier.
19
+ */
20
+ function c(s: PathState): number[][] {
21
+ const ps = [
22
+ s.p,
23
+ [s.vals![0], s.vals![1]],
24
+ [s.vals![2], s.vals![3]],
25
+ [s.vals![4], s.vals![5]]
26
+ ];
27
+ s.prev2ndCubicControlPoint = ps[2];
28
+ s.prev2ndQuadraticControlPoint = undefined;
29
+
30
+ return ps;
31
+ }
32
+
33
+
34
+ export { c }
@@ -0,0 +1,28 @@
1
+ import { PathState } from '../path-state.js';
2
+
3
+
4
+ /**
5
+ * @hidden
6
+ * H and h: (from www.w3.org)
7
+ *
8
+ * params: x
9
+ *
10
+ * Draws a horizontal line from the current point (cpx, cpy) to (x, cpy). H
11
+ * (uppercase) indicates that absolute coordinates will follow; h (lowercase)
12
+ * indicates that relative coordinates will follow. Multiple x values can be
13
+ * provided (although usually this doesn't make sense). At the end of the
14
+ * command, the new current point becomes (x, cpy) for the final value of x.
15
+ */
16
+ function h(s: PathState): number[][] {
17
+ const ps = [
18
+ s.p,
19
+ [s.vals![0], s.p[1]]
20
+ ];
21
+ s.prev2ndCubicControlPoint = undefined;
22
+ s.prev2ndQuadraticControlPoint = undefined;
23
+
24
+ return ps;
25
+ }
26
+
27
+
28
+ export { h }
@@ -0,0 +1,30 @@
1
+ import { PathState } from '../path-state.js';
2
+
3
+
4
+ /**
5
+ * @hidden
6
+ * L and l: (from www.w3.org)
7
+ *
8
+ * params: x y
9
+ *
10
+ * Draw a line from the current point to the given (x,y) coordinate which
11
+ * becomes the new current point. L (uppercase) indicates that absolute
12
+ * coordinates will follow; l (lowercase) indicates that relative coordinates
13
+ * will follow. A number of coordinates pairs may be specified to draw a
14
+ * polyline. At the end of the command, the new current point is set to the
15
+ * final set of coordinates provided.
16
+ */
17
+ function l(s: PathState): number[][] {
18
+ const ps = [
19
+ s.p,
20
+ s.vals!
21
+ ];
22
+
23
+ s.prev2ndCubicControlPoint = undefined;
24
+ s.prev2ndQuadraticControlPoint = undefined;
25
+
26
+ return ps;
27
+ }
28
+
29
+
30
+ export { l }
@@ -0,0 +1,30 @@
1
+ import { PathState } from '../path-state.js';
2
+
3
+
4
+ /**
5
+ * @hidden
6
+ * Q and q: (from www.w3.org)
7
+ *
8
+ * params: x1 y1 x y
9
+ *
10
+ * Draws a quadratic Bézier curve from the current point to (x,y) using (x1,y1)
11
+ * as the control point. Q (uppercase) indicates that absolute coordinates will
12
+ * follow; q (lowercase) indicates that relative coordinates will follow.
13
+ * Multiple sets of coordinates may be specified to draw a polybézier. At the
14
+ * end of the command, the new current point becomes the final (x,y) coordinate
15
+ * pair used in the polybézier.
16
+ */
17
+ function q(s: PathState): number[][] {
18
+ const QP1 = [s.vals![0], s.vals![1]];
19
+ const QP2 = [s.vals![2], s.vals![3]];
20
+
21
+ s.prev2ndCubicControlPoint = undefined;
22
+ s.prev2ndQuadraticControlPoint = QP1;
23
+
24
+ const ps = [s.p, QP1, QP2];
25
+
26
+ return ps;
27
+ }
28
+
29
+
30
+ export { q }
@@ -0,0 +1,40 @@
1
+ import { PathState } from "../path-state.js";
2
+
3
+
4
+ /**
5
+ * @hidden
6
+ * S and s: (from www.w3.org)
7
+ *
8
+ * params: x2 y2 x y
9
+ *
10
+ * Draws a cubic Bézier curve from the current point to (x,y). The first control
11
+ * point is assumed to be the reflection of the second control point on the
12
+ * previous command relative to the current point. (If there is no previous
13
+ * command or if the previous command was not an C, c, S or s, assume the first
14
+ * control point is coincident with the current point.) (x2,y2) is the second
15
+ * control point (i.e., the control point at the end of the curve). S
16
+ * (uppercase) indicates that absolute coordinates will follow; s (lowercase)
17
+ * indicates that relative coordinates will follow. Multiple sets of coordinates
18
+ * may be specified to draw a polybézier. At the end of the command, the new
19
+ * current point becomes the final (x,y) coordinate pair used in the polybézier.
20
+ */
21
+ function s(s: PathState): number[][] {
22
+ const p = s.prev2ndCubicControlPoint
23
+ ? [(s.p[0] - s.prev2ndCubicControlPoint[0]) + s.p[0],
24
+ (s.p[1] - s.prev2ndCubicControlPoint[1]) + s.p[1]]
25
+ : s.p;
26
+
27
+ const ps = [
28
+ s.p,
29
+ p,
30
+ [s.vals![0], s.vals![1]],
31
+ [s.vals![2], s.vals![3]]
32
+ ];
33
+ s.prev2ndCubicControlPoint = ps[2];
34
+ s.prev2ndQuadraticControlPoint = undefined;
35
+
36
+ return ps;
37
+ }
38
+
39
+
40
+ export { s }
@@ -0,0 +1,35 @@
1
+ import { PathState } from '../path-state.js';
2
+
3
+
4
+ /**
5
+ * @hidden
6
+ * T and t: (from www.w3.org)
7
+ *
8
+ * params: x y
9
+ *
10
+ * Draws a quadratic Bézier curve from the current point to (x,y). The control
11
+ * point is assumed to be the reflection of the control point on the previous
12
+ * command relative to the current point. (If there is no previous command or if
13
+ * the previous command was not a Q, q, T or t, assume the control point is
14
+ * coincident with the current point.) T (uppercase) indicates that absolute
15
+ * coordinates will follow; t (lowercase) indicates that relative coordinates
16
+ * will follow. At the end of the command, the new current point becomes the
17
+ * final (x,y) coordinate pair used in the polybézier.
18
+ */
19
+ function t(s: PathState): number[][] {
20
+ const p = s.prev2ndQuadraticControlPoint
21
+ ? [(s.p[0] - s.prev2ndQuadraticControlPoint[0]) + s.p[0],
22
+ (s.p[1] - s.prev2ndQuadraticControlPoint[1]) + s.p[1]]
23
+ : s.p;
24
+
25
+ const QP1 = p;
26
+ const QP2 = [s.vals![0], s.vals![1]];
27
+
28
+ s.prev2ndCubicControlPoint = undefined;
29
+ s.prev2ndQuadraticControlPoint = QP1;
30
+
31
+ return [s.p, QP1, QP2];
32
+ }
33
+
34
+
35
+ export { t }