@emasoft/svg-matrix 1.1.0 → 1.2.0
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.
- package/bin/svg-matrix.js +7 -6
- package/bin/svgm.js +109 -40
- package/dist/svg-matrix.min.js +7 -7
- package/dist/svg-toolbox.min.js +148 -228
- package/dist/svgm.min.js +152 -232
- package/dist/version.json +5 -5
- package/package.json +1 -1
- package/scripts/postinstall.js +72 -41
- package/scripts/test-postinstall.js +18 -16
- package/scripts/version-sync.js +78 -60
- package/src/animation-optimization.js +190 -98
- package/src/animation-references.js +11 -3
- package/src/arc-length.js +23 -20
- package/src/bezier-analysis.js +9 -13
- package/src/bezier-intersections.js +18 -4
- package/src/browser-verify.js +35 -8
- package/src/clip-path-resolver.js +285 -114
- package/src/convert-path-data.js +20 -8
- package/src/css-specificity.js +33 -9
- package/src/douglas-peucker.js +272 -141
- package/src/geometry-to-path.js +79 -22
- package/src/gjk-collision.js +287 -126
- package/src/index.js +56 -21
- package/src/inkscape-support.js +122 -101
- package/src/logger.js +43 -27
- package/src/marker-resolver.js +201 -121
- package/src/mask-resolver.js +231 -98
- package/src/matrix.js +9 -5
- package/src/mesh-gradient.js +22 -14
- package/src/off-canvas-detection.js +53 -17
- package/src/path-optimization.js +356 -171
- package/src/path-simplification.js +671 -256
- package/src/pattern-resolver.js +1 -3
- package/src/polygon-clip.js +396 -78
- package/src/svg-boolean-ops.js +90 -23
- package/src/svg-collections.js +1546 -667
- package/src/svg-flatten.js +152 -38
- package/src/svg-matrix-lib.js +2 -2
- package/src/svg-parser.js +5 -1
- package/src/svg-rendering-context.js +3 -1
- package/src/svg-toolbox-lib.js +2 -2
- package/src/svg-toolbox.js +99 -457
- package/src/svg-validation-data.js +513 -345
- package/src/svg2-polyfills.js +156 -93
- package/src/svgm-lib.js +8 -4
- package/src/transform-optimization.js +168 -51
- package/src/transforms2d.js +73 -40
- package/src/transforms3d.js +34 -27
- package/src/use-symbol-resolver.js +175 -76
- package/src/vector.js +80 -44
- package/src/vendor/inkscape-hatch-polyfill.js +143 -108
- package/src/vendor/inkscape-hatch-polyfill.min.js +291 -1
- package/src/vendor/inkscape-mesh-polyfill.js +953 -766
- package/src/vendor/inkscape-mesh-polyfill.min.js +896 -1
- package/src/verification.js +3 -4
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
(function () {
|
|
11
11
|
// Name spaces -----------------------------------
|
|
12
|
-
const svgNS =
|
|
13
|
-
const xlinkNS =
|
|
14
|
-
const unitObjectBoundingBox =
|
|
15
|
-
const unitUserSpace =
|
|
12
|
+
const svgNS = "http://www.w3.org/2000/svg";
|
|
13
|
+
const xlinkNS = "http://www.w3.org/1999/xlink";
|
|
14
|
+
const unitObjectBoundingBox = "objectBoundingBox";
|
|
15
|
+
const unitUserSpace = "userSpaceOnUse";
|
|
16
16
|
|
|
17
17
|
// Set multiple attributes to an element
|
|
18
18
|
const setAttributes = (el, attrs) => {
|
|
@@ -24,13 +24,18 @@
|
|
|
24
24
|
// Copy attributes from the hatch with 'id' to the current element
|
|
25
25
|
const setReference = (el, id) => {
|
|
26
26
|
const attr = [
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
"x",
|
|
28
|
+
"y",
|
|
29
|
+
"pitch",
|
|
30
|
+
"rotate",
|
|
31
|
+
"hatchUnits",
|
|
32
|
+
"hatchContentUnits",
|
|
33
|
+
"transform",
|
|
29
34
|
];
|
|
30
35
|
const template = document.getElementById(id.slice(1));
|
|
31
36
|
|
|
32
|
-
if (template && template.nodeName ===
|
|
33
|
-
attr.forEach(a => {
|
|
37
|
+
if (template && template.nodeName === "hatch") {
|
|
38
|
+
attr.forEach((a) => {
|
|
34
39
|
let t = template.getAttribute(a);
|
|
35
40
|
if (el.getAttribute(a) === null && t !== null) {
|
|
36
41
|
el.setAttribute(a, t);
|
|
@@ -38,7 +43,7 @@
|
|
|
38
43
|
});
|
|
39
44
|
|
|
40
45
|
if (el.children.length === 0) {
|
|
41
|
-
Array.from(template.children).forEach(c => {
|
|
46
|
+
Array.from(template.children).forEach((c) => {
|
|
42
47
|
el.appendChild(c.cloneNode(true));
|
|
43
48
|
});
|
|
44
49
|
}
|
|
@@ -48,11 +53,12 @@
|
|
|
48
53
|
// Order pain-order of hatchpaths relative to their pitch
|
|
49
54
|
const orderHatchPaths = (paths) => {
|
|
50
55
|
const nodeArray = [];
|
|
51
|
-
paths.forEach(p => nodeArray.push(p));
|
|
56
|
+
paths.forEach((p) => nodeArray.push(p));
|
|
52
57
|
|
|
53
|
-
return nodeArray.sort(
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
return nodeArray.sort(
|
|
59
|
+
(a, b) =>
|
|
60
|
+
// (pitch - a.offset) - (pitch - b.offset)
|
|
61
|
+
Number(b.getAttribute("offset")) - Number(a.getAttribute("offset")),
|
|
56
62
|
);
|
|
57
63
|
};
|
|
58
64
|
|
|
@@ -92,55 +98,65 @@
|
|
|
92
98
|
|
|
93
99
|
while (i < len) {
|
|
94
100
|
switch (data[i].toUpperCase()) {
|
|
95
|
-
case
|
|
101
|
+
case "Z":
|
|
96
102
|
array.push(data[i]);
|
|
97
103
|
i += 1;
|
|
98
104
|
last = 0;
|
|
99
105
|
break;
|
|
100
|
-
case
|
|
101
|
-
case
|
|
102
|
-
case
|
|
103
|
-
array.push(
|
|
106
|
+
case "M":
|
|
107
|
+
case "L":
|
|
108
|
+
case "T":
|
|
109
|
+
array.push(
|
|
110
|
+
data[i],
|
|
111
|
+
new Point(Number(data[i + 1]), Number(data[i + 2])),
|
|
112
|
+
);
|
|
104
113
|
i += 3;
|
|
105
114
|
last = 1;
|
|
106
115
|
break;
|
|
107
|
-
case
|
|
116
|
+
case "H":
|
|
108
117
|
array.push(data[i], new Point(Number(data[i + 1]), null));
|
|
109
118
|
i += 2;
|
|
110
119
|
last = 2;
|
|
111
120
|
break;
|
|
112
|
-
case
|
|
121
|
+
case "V":
|
|
113
122
|
array.push(data[i], new Point(null, Number(data[i + 1])));
|
|
114
123
|
i += 2;
|
|
115
124
|
last = 3;
|
|
116
125
|
break;
|
|
117
|
-
case
|
|
126
|
+
case "C":
|
|
118
127
|
array.push(
|
|
119
|
-
data[i],
|
|
128
|
+
data[i],
|
|
129
|
+
new Point(Number(data[i + 1]), Number(data[i + 2])),
|
|
120
130
|
new Point(Number(data[i + 3]), Number(data[i + 4])),
|
|
121
|
-
new Point(Number(data[i + 5]), Number(data[i + 6]))
|
|
131
|
+
new Point(Number(data[i + 5]), Number(data[i + 6])),
|
|
122
132
|
);
|
|
123
133
|
i += 7;
|
|
124
134
|
last = 4;
|
|
125
135
|
break;
|
|
126
|
-
case
|
|
127
|
-
case
|
|
136
|
+
case "S":
|
|
137
|
+
case "Q":
|
|
128
138
|
array.push(
|
|
129
|
-
data[i],
|
|
130
|
-
new Point(Number(data[i +
|
|
139
|
+
data[i],
|
|
140
|
+
new Point(Number(data[i + 1]), Number(data[i + 2])),
|
|
141
|
+
new Point(Number(data[i + 3]), Number(data[i + 4])),
|
|
131
142
|
);
|
|
132
143
|
i += 5;
|
|
133
144
|
last = 5;
|
|
134
145
|
break;
|
|
135
|
-
case
|
|
146
|
+
case "A":
|
|
136
147
|
array.push(
|
|
137
|
-
data[i],
|
|
138
|
-
data[i +
|
|
148
|
+
data[i],
|
|
149
|
+
data[i + 1],
|
|
150
|
+
data[i + 2],
|
|
151
|
+
data[i + 3],
|
|
152
|
+
data[i + 4],
|
|
153
|
+
data[i + 5],
|
|
154
|
+
new Point(Number(data[i + 6]), Number(data[i + 7])),
|
|
139
155
|
);
|
|
140
156
|
i += 8;
|
|
141
157
|
last = 6;
|
|
142
158
|
break;
|
|
143
|
-
case
|
|
159
|
+
case "B":
|
|
144
160
|
array.push(data[i], data[i + 1]);
|
|
145
161
|
i += 2;
|
|
146
162
|
last = 7;
|
|
@@ -163,21 +179,25 @@
|
|
|
163
179
|
array.push(
|
|
164
180
|
new Point(Number(data[i]), Number(data[i + 1])),
|
|
165
181
|
new Point(Number(data[i + 2]), Number(data[i + 3])),
|
|
166
|
-
new Point(Number(data[i + 4]), Number(data[i + 5]))
|
|
182
|
+
new Point(Number(data[i + 4]), Number(data[i + 5])),
|
|
167
183
|
);
|
|
168
184
|
i += 6;
|
|
169
185
|
break;
|
|
170
186
|
case 5:
|
|
171
187
|
array.push(
|
|
172
188
|
new Point(Number(data[i]), Number(data[i + 1])),
|
|
173
|
-
new Point(Number(data[i + 2]), Number(data[i + 3]))
|
|
189
|
+
new Point(Number(data[i + 2]), Number(data[i + 3])),
|
|
174
190
|
);
|
|
175
191
|
i += 4;
|
|
176
192
|
break;
|
|
177
193
|
case 6:
|
|
178
194
|
array.push(
|
|
179
|
-
data[i],
|
|
180
|
-
|
|
195
|
+
data[i],
|
|
196
|
+
data[i + 1],
|
|
197
|
+
data[i + 2],
|
|
198
|
+
data[i + 3],
|
|
199
|
+
data[i + 4],
|
|
200
|
+
new Point(Number(data[i + 5]), Number(data[i + 6])),
|
|
181
201
|
);
|
|
182
202
|
i += 7;
|
|
183
203
|
break;
|
|
@@ -192,70 +212,72 @@
|
|
|
192
212
|
};
|
|
193
213
|
|
|
194
214
|
const getYDistance = (hatchpath) => {
|
|
195
|
-
const path = document.createElementNS(svgNS,
|
|
196
|
-
let d = hatchpath.getAttribute(
|
|
215
|
+
const path = document.createElementNS(svgNS, "path");
|
|
216
|
+
let d = hatchpath.getAttribute("d");
|
|
197
217
|
|
|
198
|
-
if (d[0].toUpperCase() !==
|
|
218
|
+
if (d[0].toUpperCase() !== "M") {
|
|
199
219
|
d = `M 0,0 ${d}`;
|
|
200
220
|
}
|
|
201
221
|
|
|
202
|
-
path.setAttribute(
|
|
222
|
+
path.setAttribute("d", d);
|
|
203
223
|
|
|
204
|
-
return
|
|
205
|
-
path.getPointAtLength(
|
|
224
|
+
return (
|
|
225
|
+
path.getPointAtLength(path.getTotalLength()).y -
|
|
226
|
+
path.getPointAtLength(0).y
|
|
227
|
+
);
|
|
206
228
|
};
|
|
207
229
|
|
|
208
230
|
// Point class --------------------------------------
|
|
209
231
|
class Point {
|
|
210
|
-
constructor
|
|
232
|
+
constructor(x, y) {
|
|
211
233
|
this.x = x;
|
|
212
234
|
this.y = y;
|
|
213
235
|
}
|
|
214
236
|
|
|
215
|
-
toString
|
|
237
|
+
toString() {
|
|
216
238
|
return `${this.x} ${this.y}`;
|
|
217
239
|
}
|
|
218
240
|
|
|
219
|
-
isPoint
|
|
241
|
+
isPoint() {
|
|
220
242
|
return true;
|
|
221
243
|
}
|
|
222
244
|
|
|
223
|
-
clone
|
|
245
|
+
clone() {
|
|
224
246
|
return new Point(this.x, this.y);
|
|
225
247
|
}
|
|
226
248
|
|
|
227
|
-
add
|
|
249
|
+
add(v) {
|
|
228
250
|
return new Point(this.x + v.x, this.y + v.y);
|
|
229
251
|
}
|
|
230
252
|
|
|
231
|
-
distSquared
|
|
253
|
+
distSquared(v) {
|
|
232
254
|
let x = this.x - v.x;
|
|
233
255
|
let y = this.y - v.y;
|
|
234
|
-
return
|
|
256
|
+
return x * x + y * y;
|
|
235
257
|
}
|
|
236
258
|
}
|
|
237
259
|
|
|
238
260
|
// Start of document processing ---------------------
|
|
239
|
-
const shapes = document.querySelectorAll(
|
|
261
|
+
const shapes = document.querySelectorAll("rect,circle,ellipse,path,text");
|
|
240
262
|
|
|
241
263
|
shapes.forEach((shape, i) => {
|
|
242
264
|
// Get id. If no id, create one.
|
|
243
|
-
let shapeId = shape.getAttribute(
|
|
265
|
+
let shapeId = shape.getAttribute("id");
|
|
244
266
|
if (!shapeId) {
|
|
245
|
-
shapeId =
|
|
246
|
-
shape.setAttribute(
|
|
267
|
+
shapeId = "hatch_shape_" + i;
|
|
268
|
+
shape.setAttribute("id", shapeId);
|
|
247
269
|
}
|
|
248
270
|
|
|
249
|
-
const fill = shape.getAttribute(
|
|
271
|
+
const fill = shape.getAttribute("fill") || shape.style.fill;
|
|
250
272
|
const fillURL = fill.match(/^url\(\s*"?\s*#([^\s"]+)"?\s*\)/);
|
|
251
273
|
|
|
252
274
|
if (fillURL && fillURL[1]) {
|
|
253
275
|
const hatch = document.getElementById(fillURL[1]);
|
|
254
276
|
|
|
255
|
-
if (hatch && hatch.nodeName ===
|
|
256
|
-
const href = hatch.getAttributeNS(xlinkNS,
|
|
277
|
+
if (hatch && hatch.nodeName === "hatch") {
|
|
278
|
+
const href = hatch.getAttributeNS(xlinkNS, "href");
|
|
257
279
|
|
|
258
|
-
if (href !== null && href !==
|
|
280
|
+
if (href !== null && href !== "") {
|
|
259
281
|
setReference(hatch, href);
|
|
260
282
|
}
|
|
261
283
|
|
|
@@ -265,26 +287,34 @@
|
|
|
265
287
|
}
|
|
266
288
|
|
|
267
289
|
const bbox = shape.getBBox();
|
|
268
|
-
const hatchDiag = Math.ceil(
|
|
269
|
-
bbox.width * bbox.width + bbox.height * bbox.height
|
|
270
|
-
)
|
|
290
|
+
const hatchDiag = Math.ceil(
|
|
291
|
+
Math.sqrt(bbox.width * bbox.width + bbox.height * bbox.height),
|
|
292
|
+
);
|
|
271
293
|
|
|
272
294
|
// Hatch variables
|
|
273
|
-
const units = hatch.getAttribute(
|
|
274
|
-
const contentUnits =
|
|
275
|
-
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
295
|
+
const units = hatch.getAttribute("hatchUnits") || unitObjectBoundingBox;
|
|
296
|
+
const contentUnits =
|
|
297
|
+
hatch.getAttribute("hatchContentUnits") || unitUserSpace;
|
|
298
|
+
const rotate = Number(hatch.getAttribute("rotate")) || 0;
|
|
299
|
+
const transform =
|
|
300
|
+
hatch.getAttribute("transform") ||
|
|
301
|
+
hatch.getAttribute("hatchTransform") ||
|
|
302
|
+
"";
|
|
303
|
+
const hatchpaths = orderHatchPaths(
|
|
304
|
+
hatch.querySelectorAll("hatchpath,hatchPath"),
|
|
305
|
+
);
|
|
306
|
+
const x =
|
|
307
|
+
units === unitObjectBoundingBox
|
|
308
|
+
? Number(hatch.getAttribute("x")) * bbox.width || 0
|
|
309
|
+
: Number(hatch.getAttribute("x")) || 0;
|
|
310
|
+
const y =
|
|
311
|
+
units === unitObjectBoundingBox
|
|
312
|
+
? Number(hatch.getAttribute("y")) * bbox.width || 0
|
|
313
|
+
: Number(hatch.getAttribute("y")) || 0;
|
|
314
|
+
let pitch =
|
|
315
|
+
units === unitObjectBoundingBox
|
|
316
|
+
? Number(hatch.getAttribute("pitch")) * bbox.width || 0
|
|
317
|
+
: Number(hatch.getAttribute("pitch")) || 0;
|
|
288
318
|
|
|
289
319
|
if (contentUnits === unitObjectBoundingBox && bbox.height) {
|
|
290
320
|
pitch /= bbox.height;
|
|
@@ -293,45 +323,46 @@
|
|
|
293
323
|
// A negative value is an error.
|
|
294
324
|
// A value of zero disables rendering of the element
|
|
295
325
|
if (pitch <= 0) {
|
|
296
|
-
console.error(
|
|
326
|
+
console.error("Non-positive pitch");
|
|
297
327
|
return;
|
|
298
328
|
}
|
|
299
329
|
|
|
300
330
|
// Pattern variables
|
|
301
|
-
const pattern = document.createElementNS(svgNS,
|
|
331
|
+
const pattern = document.createElementNS(svgNS, "pattern");
|
|
302
332
|
const patternId = `${fillURL[1]}_pattern`;
|
|
303
|
-
let patternWidth = bbox.width - bbox.width % pitch;
|
|
333
|
+
let patternWidth = bbox.width - (bbox.width % pitch);
|
|
304
334
|
let patternHeight = 0;
|
|
305
335
|
|
|
306
336
|
const xPositions = generatePositions(patternWidth, hatchDiag, x, pitch);
|
|
307
337
|
|
|
308
|
-
hatchpaths.forEach(hatchpath => {
|
|
309
|
-
let offset = Number(hatchpath.getAttribute(
|
|
310
|
-
offset = offset > pitch ?
|
|
311
|
-
const currentXPositions = xPositions.map(p => p + offset);
|
|
338
|
+
hatchpaths.forEach((hatchpath) => {
|
|
339
|
+
let offset = Number(hatchpath.getAttribute("offset")) || 0;
|
|
340
|
+
offset = offset > pitch ? offset % pitch : offset;
|
|
341
|
+
const currentXPositions = xPositions.map((p) => p + offset);
|
|
312
342
|
|
|
313
|
-
const path = document.createElementNS(svgNS,
|
|
314
|
-
let d =
|
|
343
|
+
const path = document.createElementNS(svgNS, "path");
|
|
344
|
+
let d = "";
|
|
315
345
|
|
|
316
346
|
for (let j = 0; j < hatchpath.attributes.length; ++j) {
|
|
317
347
|
const attr = hatchpath.attributes.item(j);
|
|
318
|
-
if (attr.name !==
|
|
348
|
+
if (attr.name !== "d") {
|
|
319
349
|
path.setAttribute(attr.name, attr.value);
|
|
320
350
|
}
|
|
321
351
|
}
|
|
322
352
|
|
|
323
|
-
if (hatchpath.getAttribute(
|
|
353
|
+
if (hatchpath.getAttribute("d") === null) {
|
|
324
354
|
d += currentXPositions.reduce(
|
|
325
|
-
(acc, xPos) => `${acc}M ${xPos} ${y} V ${hatchDiag} `,
|
|
355
|
+
(acc, xPos) => `${acc}M ${xPos} ${y} V ${hatchDiag} `,
|
|
356
|
+
"",
|
|
326
357
|
);
|
|
327
358
|
patternHeight = hatchDiag;
|
|
328
359
|
} else {
|
|
329
|
-
const hatchData = hatchpath.getAttribute(
|
|
360
|
+
const hatchData = hatchpath.getAttribute("d");
|
|
330
361
|
const data = parsePath(
|
|
331
|
-
hatchData.match(/([+-]?(\d+(\.\d+)?))|[MmZzLlHhVvCcSsQqTtAaBb]/g)
|
|
362
|
+
hatchData.match(/([+-]?(\d+(\.\d+)?))|[MmZzLlHhVvCcSsQqTtAaBb]/g),
|
|
332
363
|
);
|
|
333
364
|
const len = data.length;
|
|
334
|
-
const startsWithM = data[0] ===
|
|
365
|
+
const startsWithM = data[0] === "M";
|
|
335
366
|
const relative = data[0].toLowerCase() === data[0];
|
|
336
367
|
const point = new Point(0, 0);
|
|
337
368
|
let yOffset = getYDistance(hatchpath);
|
|
@@ -342,23 +373,26 @@
|
|
|
342
373
|
|
|
343
374
|
// The offset must be positive
|
|
344
375
|
if (yOffset <= 0) {
|
|
345
|
-
console.error(
|
|
376
|
+
console.error("y offset is non-positive");
|
|
346
377
|
return;
|
|
347
378
|
}
|
|
348
|
-
patternHeight = bbox.height - bbox.height % yOffset;
|
|
379
|
+
patternHeight = bbox.height - (bbox.height % yOffset);
|
|
349
380
|
|
|
350
381
|
const currentYPositions = generatePositions(
|
|
351
|
-
patternHeight,
|
|
382
|
+
patternHeight,
|
|
383
|
+
hatchDiag,
|
|
384
|
+
y,
|
|
385
|
+
yOffset,
|
|
352
386
|
);
|
|
353
387
|
|
|
354
|
-
currentXPositions.forEach(xPos => {
|
|
388
|
+
currentXPositions.forEach((xPos) => {
|
|
355
389
|
point.x = xPos;
|
|
356
390
|
|
|
357
391
|
if (!startsWithM && !relative) {
|
|
358
392
|
d += `M ${xPos} 0`;
|
|
359
393
|
}
|
|
360
394
|
|
|
361
|
-
currentYPositions.forEach(yPos => {
|
|
395
|
+
currentYPositions.forEach((yPos) => {
|
|
362
396
|
point.y = yPos;
|
|
363
397
|
|
|
364
398
|
if (relative) {
|
|
@@ -366,35 +400,36 @@
|
|
|
366
400
|
d += `M ${xPos} ${yPos} ${hatchData}`;
|
|
367
401
|
} else {
|
|
368
402
|
// Path is absolute, translate every point
|
|
369
|
-
d += data
|
|
370
|
-
.map(e => e.isPoint && e.isPoint() ? e.
|
|
371
|
-
.
|
|
403
|
+
d += data
|
|
404
|
+
.map((e) => (e.isPoint && e.isPoint() ? e.add(point) : e))
|
|
405
|
+
.map((e) => (e.isPoint && e.isPoint() ? e.toString() : e))
|
|
406
|
+
.reduce((acc, e) => `${acc} ${e}`, "");
|
|
372
407
|
}
|
|
373
408
|
});
|
|
374
409
|
});
|
|
375
410
|
|
|
376
411
|
// The hatchpaths are infinite, so they have no fill
|
|
377
|
-
path.style.fill =
|
|
412
|
+
path.style.fill = "none";
|
|
378
413
|
}
|
|
379
414
|
|
|
380
|
-
path.setAttribute(
|
|
415
|
+
path.setAttribute("d", d);
|
|
381
416
|
pattern.appendChild(path);
|
|
382
417
|
});
|
|
383
418
|
|
|
384
419
|
setAttributes(pattern, {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
420
|
+
id: patternId,
|
|
421
|
+
patternUnits: unitUserSpace,
|
|
422
|
+
patternContentUnits: contentUnits,
|
|
423
|
+
width: patternWidth,
|
|
424
|
+
height: patternHeight,
|
|
425
|
+
x: bbox.x,
|
|
426
|
+
y: bbox.y,
|
|
427
|
+
patternTransform: `rotate(${rotate} ${0} ${0}) ${transform}`,
|
|
393
428
|
});
|
|
394
429
|
hatch.parentElement.insertBefore(pattern, hatch);
|
|
395
430
|
|
|
396
431
|
shape.style.fill = `url(#${patternId})`;
|
|
397
|
-
shape.setAttribute(
|
|
432
|
+
shape.setAttribute("fill", `url(#${patternId})`);
|
|
398
433
|
}
|
|
399
434
|
}
|
|
400
435
|
});
|