@emasoft/svg-matrix 1.0.28 → 1.0.30
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/README.md +325 -0
- package/bin/svg-matrix.js +985 -378
- package/bin/svglinter.cjs +4172 -433
- package/bin/svgm.js +723 -180
- package/package.json +16 -4
- package/src/animation-references.js +71 -52
- package/src/arc-length.js +160 -96
- package/src/bezier-analysis.js +257 -117
- package/src/bezier-intersections.js +411 -148
- package/src/browser-verify.js +240 -100
- package/src/clip-path-resolver.js +350 -142
- package/src/convert-path-data.js +279 -134
- package/src/css-specificity.js +78 -70
- package/src/flatten-pipeline.js +751 -263
- package/src/geometry-to-path.js +511 -182
- package/src/index.js +191 -46
- package/src/inkscape-support.js +18 -7
- package/src/marker-resolver.js +278 -164
- package/src/mask-resolver.js +209 -98
- package/src/matrix.js +147 -67
- package/src/mesh-gradient.js +187 -96
- package/src/off-canvas-detection.js +201 -104
- package/src/path-analysis.js +187 -107
- package/src/path-data-plugins.js +628 -167
- package/src/path-simplification.js +0 -1
- package/src/pattern-resolver.js +125 -88
- package/src/polygon-clip.js +111 -66
- package/src/svg-boolean-ops.js +194 -118
- package/src/svg-collections.js +22 -18
- package/src/svg-flatten.js +282 -164
- package/src/svg-parser.js +427 -200
- package/src/svg-rendering-context.js +147 -104
- package/src/svg-toolbox.js +16381 -3370
- package/src/svg2-polyfills.js +93 -224
- package/src/transform-decomposition.js +46 -41
- package/src/transform-optimization.js +89 -68
- package/src/transforms2d.js +49 -16
- package/src/transforms3d.js +58 -22
- package/src/use-symbol-resolver.js +150 -110
- package/src/vector.js +67 -15
- package/src/vendor/README.md +110 -0
- package/src/vendor/inkscape-hatch-polyfill.js +401 -0
- package/src/vendor/inkscape-hatch-polyfill.min.js +8 -0
- package/src/vendor/inkscape-mesh-polyfill.js +843 -0
- package/src/vendor/inkscape-mesh-polyfill.min.js +8 -0
- package/src/verification.js +288 -124
|
@@ -27,82 +27,84 @@
|
|
|
27
27
|
* @module svg-rendering-context
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import Decimal from
|
|
31
|
-
import {
|
|
32
|
-
|
|
30
|
+
import Decimal from "decimal.js";
|
|
31
|
+
import {
|
|
32
|
+
FillRule,
|
|
33
|
+
pointInPolygonWithRule,
|
|
34
|
+
offsetPolygon as _offsetPolygon,
|
|
35
|
+
strokeToFilledPolygon,
|
|
36
|
+
} from "./svg-boolean-ops.js";
|
|
37
|
+
import * as _PolygonClip from "./polygon-clip.js";
|
|
33
38
|
|
|
34
39
|
Decimal.set({ precision: 80 });
|
|
35
40
|
|
|
36
|
-
const D = x => (x instanceof Decimal ? x : new Decimal(x));
|
|
41
|
+
const D = (x) => (x instanceof Decimal ? x : new Decimal(x));
|
|
37
42
|
|
|
38
43
|
/**
|
|
39
44
|
* Default SVG property values per SVG 1.1/2.0 specification
|
|
40
45
|
*/
|
|
41
46
|
export const SVG_DEFAULTS = {
|
|
42
47
|
// Fill properties
|
|
43
|
-
fill:
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
fill: "black",
|
|
49
|
+
"fill-rule": "nonzero",
|
|
50
|
+
"fill-opacity": 1,
|
|
46
51
|
|
|
47
52
|
// Stroke properties
|
|
48
|
-
stroke:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
stroke: "none",
|
|
54
|
+
"stroke-width": 1,
|
|
55
|
+
"stroke-linecap": "butt", // butt | round | square
|
|
56
|
+
"stroke-linejoin": "miter", // miter | round | bevel
|
|
57
|
+
"stroke-miterlimit": 4,
|
|
58
|
+
"stroke-dasharray": "none",
|
|
59
|
+
"stroke-dashoffset": 0,
|
|
60
|
+
"stroke-opacity": 1,
|
|
56
61
|
|
|
57
62
|
// Markers
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
"marker-start": "none",
|
|
64
|
+
"marker-mid": "none",
|
|
65
|
+
"marker-end": "none",
|
|
61
66
|
|
|
62
67
|
// Paint order (SVG 2)
|
|
63
|
-
|
|
68
|
+
"paint-order": "normal", // normal = fill stroke markers
|
|
64
69
|
|
|
65
70
|
// Clipping
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
"clip-path": "none",
|
|
72
|
+
"clip-rule": "nonzero",
|
|
68
73
|
|
|
69
74
|
// Masking
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
mask: "none",
|
|
76
|
+
"mask-type": "luminance", // luminance | alpha
|
|
72
77
|
|
|
73
78
|
// Opacity
|
|
74
|
-
|
|
79
|
+
opacity: 1,
|
|
75
80
|
|
|
76
81
|
// Transform
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
transform: "none",
|
|
83
|
+
"vector-effect": "none", // none | non-scaling-stroke
|
|
79
84
|
|
|
80
85
|
// Filter
|
|
81
|
-
|
|
86
|
+
filter: "none",
|
|
82
87
|
};
|
|
83
88
|
|
|
84
89
|
/**
|
|
85
90
|
* Properties that affect the geometric extent of an element
|
|
86
91
|
*/
|
|
87
92
|
export const GEOMETRY_AFFECTING_PROPERTIES = [
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
"stroke-width",
|
|
94
|
+
"stroke-linecap",
|
|
95
|
+
"stroke-linejoin",
|
|
96
|
+
"stroke-miterlimit",
|
|
97
|
+
"marker-start",
|
|
98
|
+
"marker-mid",
|
|
99
|
+
"marker-end",
|
|
100
|
+
"filter",
|
|
101
|
+
"transform",
|
|
97
102
|
];
|
|
98
103
|
|
|
99
104
|
/**
|
|
100
105
|
* Properties that affect what's considered "inside" a shape
|
|
101
106
|
*/
|
|
102
|
-
export const FILL_AFFECTING_PROPERTIES = [
|
|
103
|
-
'fill-rule',
|
|
104
|
-
'clip-rule'
|
|
105
|
-
];
|
|
107
|
+
export const FILL_AFFECTING_PROPERTIES = ["fill-rule", "clip-rule"];
|
|
106
108
|
|
|
107
109
|
/**
|
|
108
110
|
* SVG Rendering Context class
|
|
@@ -125,27 +127,29 @@ export class SVGRenderingContext {
|
|
|
125
127
|
this.properties = this._extractProperties(element, inherited);
|
|
126
128
|
|
|
127
129
|
// Parse stroke-dasharray into array
|
|
128
|
-
this.dashArray = this._parseDashArray(this.properties[
|
|
129
|
-
this.dashOffset = D(this.properties[
|
|
130
|
+
this.dashArray = this._parseDashArray(this.properties["stroke-dasharray"]);
|
|
131
|
+
this.dashOffset = D(this.properties["stroke-dashoffset"] || 0);
|
|
130
132
|
|
|
131
133
|
// Parse marker references
|
|
132
134
|
this.markers = {
|
|
133
|
-
start: this._parseMarkerRef(this.properties[
|
|
134
|
-
mid: this._parseMarkerRef(this.properties[
|
|
135
|
-
end: this._parseMarkerRef(this.properties[
|
|
135
|
+
start: this._parseMarkerRef(this.properties["marker-start"]),
|
|
136
|
+
mid: this._parseMarkerRef(this.properties["marker-mid"]),
|
|
137
|
+
end: this._parseMarkerRef(this.properties["marker-end"]),
|
|
136
138
|
};
|
|
137
139
|
|
|
138
140
|
// Determine if element has visible fill
|
|
139
|
-
this.hasFill =
|
|
140
|
-
|
|
141
|
+
this.hasFill =
|
|
142
|
+
this.properties.fill !== "none" && this.properties["fill-opacity"] > 0;
|
|
141
143
|
|
|
142
144
|
// Determine if element has visible stroke
|
|
143
|
-
this.hasStroke =
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
this.hasStroke =
|
|
146
|
+
this.properties.stroke !== "none" &&
|
|
147
|
+
D(this.properties["stroke-width"]).gt(0) &&
|
|
148
|
+
this.properties["stroke-opacity"] > 0;
|
|
146
149
|
|
|
147
150
|
// Determine if element has markers
|
|
148
|
-
this.hasMarkers =
|
|
151
|
+
this.hasMarkers =
|
|
152
|
+
this.markers.start || this.markers.mid || this.markers.end;
|
|
149
153
|
}
|
|
150
154
|
|
|
151
155
|
/**
|
|
@@ -172,10 +176,16 @@ export class SVGRenderingContext {
|
|
|
172
176
|
}
|
|
173
177
|
|
|
174
178
|
// Convert numeric properties
|
|
175
|
-
const numericProps = [
|
|
176
|
-
|
|
179
|
+
const numericProps = [
|
|
180
|
+
"stroke-width",
|
|
181
|
+
"stroke-miterlimit",
|
|
182
|
+
"stroke-dashoffset",
|
|
183
|
+
"opacity",
|
|
184
|
+
"fill-opacity",
|
|
185
|
+
"stroke-opacity",
|
|
186
|
+
];
|
|
177
187
|
for (const prop of numericProps) {
|
|
178
|
-
if (typeof props[prop] ===
|
|
188
|
+
if (typeof props[prop] === "string") {
|
|
179
189
|
const parsed = parseFloat(props[prop]);
|
|
180
190
|
if (!isNaN(parsed)) {
|
|
181
191
|
props[prop] = parsed;
|
|
@@ -194,9 +204,9 @@ export class SVGRenderingContext {
|
|
|
194
204
|
const props = {};
|
|
195
205
|
if (!style) return props;
|
|
196
206
|
|
|
197
|
-
const declarations = style.split(
|
|
207
|
+
const declarations = style.split(";");
|
|
198
208
|
for (const decl of declarations) {
|
|
199
|
-
const [prop, value] = decl.split(
|
|
209
|
+
const [prop, value] = decl.split(":").map((s) => s.trim());
|
|
200
210
|
if (prop && value) {
|
|
201
211
|
props[prop] = value;
|
|
202
212
|
}
|
|
@@ -209,10 +219,13 @@ export class SVGRenderingContext {
|
|
|
209
219
|
* @private
|
|
210
220
|
*/
|
|
211
221
|
_parseDashArray(dasharray) {
|
|
212
|
-
if (!dasharray || dasharray ===
|
|
222
|
+
if (!dasharray || dasharray === "none") return null;
|
|
213
223
|
|
|
214
|
-
const parts = dasharray
|
|
215
|
-
|
|
224
|
+
const parts = dasharray
|
|
225
|
+
.toString()
|
|
226
|
+
.split(/[\s,]+/)
|
|
227
|
+
.filter((s) => s);
|
|
228
|
+
const values = parts.map((s) => D(parseFloat(s)));
|
|
216
229
|
|
|
217
230
|
// Per SVG spec, if odd number of values, duplicate the array
|
|
218
231
|
if (values.length % 2 === 1) {
|
|
@@ -226,7 +239,7 @@ export class SVGRenderingContext {
|
|
|
226
239
|
* @private
|
|
227
240
|
*/
|
|
228
241
|
_parseMarkerRef(value) {
|
|
229
|
-
if (!value || value ===
|
|
242
|
+
if (!value || value === "none") return null;
|
|
230
243
|
const match = value.match(/url\(#?([^)]+)\)/);
|
|
231
244
|
return match ? match[1] : null;
|
|
232
245
|
}
|
|
@@ -236,7 +249,7 @@ export class SVGRenderingContext {
|
|
|
236
249
|
* @returns {string} 'nonzero' or 'evenodd'
|
|
237
250
|
*/
|
|
238
251
|
get fillRule() {
|
|
239
|
-
return this.properties[
|
|
252
|
+
return this.properties["fill-rule"] || "nonzero";
|
|
240
253
|
}
|
|
241
254
|
|
|
242
255
|
/**
|
|
@@ -244,7 +257,7 @@ export class SVGRenderingContext {
|
|
|
244
257
|
* @returns {string} 'nonzero' or 'evenodd'
|
|
245
258
|
*/
|
|
246
259
|
get clipRule() {
|
|
247
|
-
return this.properties[
|
|
260
|
+
return this.properties["clip-rule"] || "nonzero";
|
|
248
261
|
}
|
|
249
262
|
|
|
250
263
|
/**
|
|
@@ -252,7 +265,7 @@ export class SVGRenderingContext {
|
|
|
252
265
|
* @returns {Decimal}
|
|
253
266
|
*/
|
|
254
267
|
get strokeWidth() {
|
|
255
|
-
return D(this.properties[
|
|
268
|
+
return D(this.properties["stroke-width"] || 0);
|
|
256
269
|
}
|
|
257
270
|
|
|
258
271
|
/**
|
|
@@ -260,7 +273,7 @@ export class SVGRenderingContext {
|
|
|
260
273
|
* @returns {string} 'butt', 'round', or 'square'
|
|
261
274
|
*/
|
|
262
275
|
get strokeLinecap() {
|
|
263
|
-
return this.properties[
|
|
276
|
+
return this.properties["stroke-linecap"] || "butt";
|
|
264
277
|
}
|
|
265
278
|
|
|
266
279
|
/**
|
|
@@ -268,7 +281,7 @@ export class SVGRenderingContext {
|
|
|
268
281
|
* @returns {string} 'miter', 'round', or 'bevel'
|
|
269
282
|
*/
|
|
270
283
|
get strokeLinejoin() {
|
|
271
|
-
return this.properties[
|
|
284
|
+
return this.properties["stroke-linejoin"] || "miter";
|
|
272
285
|
}
|
|
273
286
|
|
|
274
287
|
/**
|
|
@@ -276,7 +289,7 @@ export class SVGRenderingContext {
|
|
|
276
289
|
* @returns {Decimal}
|
|
277
290
|
*/
|
|
278
291
|
get strokeMiterlimit() {
|
|
279
|
-
return D(this.properties[
|
|
292
|
+
return D(this.properties["stroke-miterlimit"] || 4);
|
|
280
293
|
}
|
|
281
294
|
|
|
282
295
|
/**
|
|
@@ -297,12 +310,12 @@ export class SVGRenderingContext {
|
|
|
297
310
|
let extent = halfWidth;
|
|
298
311
|
|
|
299
312
|
// Miter joins can extend further
|
|
300
|
-
if (this.strokeLinejoin ===
|
|
313
|
+
if (this.strokeLinejoin === "miter") {
|
|
301
314
|
extent = halfWidth.times(this.strokeMiterlimit);
|
|
302
315
|
}
|
|
303
316
|
|
|
304
317
|
// Square linecaps extend by half stroke width beyond endpoints
|
|
305
|
-
if (this.strokeLinecap ===
|
|
318
|
+
if (this.strokeLinecap === "square") {
|
|
306
319
|
const capExtent = halfWidth;
|
|
307
320
|
if (capExtent.gt(extent)) {
|
|
308
321
|
extent = capExtent;
|
|
@@ -327,7 +340,7 @@ export class SVGRenderingContext {
|
|
|
327
340
|
x: bbox.x.minus(extent),
|
|
328
341
|
y: bbox.y.minus(extent),
|
|
329
342
|
width: bbox.width.plus(extent.times(2)),
|
|
330
|
-
height: bbox.height.plus(extent.times(2))
|
|
343
|
+
height: bbox.height.plus(extent.times(2)),
|
|
331
344
|
};
|
|
332
345
|
}
|
|
333
346
|
|
|
@@ -348,8 +361,8 @@ export class SVGRenderingContext {
|
|
|
348
361
|
|
|
349
362
|
if (markerSizes) {
|
|
350
363
|
const sizes = [markerSizes.start, markerSizes.mid, markerSizes.end]
|
|
351
|
-
.filter(s => s)
|
|
352
|
-
.map(s => D(s));
|
|
364
|
+
.filter((s) => s)
|
|
365
|
+
.map((s) => D(s));
|
|
353
366
|
if (sizes.length > 0) {
|
|
354
367
|
maxMarkerSize = Decimal.max(...sizes);
|
|
355
368
|
}
|
|
@@ -366,7 +379,7 @@ export class SVGRenderingContext {
|
|
|
366
379
|
x: bbox.x.minus(extent),
|
|
367
380
|
y: bbox.y.minus(extent),
|
|
368
381
|
width: bbox.width.plus(extent.times(2)),
|
|
369
|
-
height: bbox.height.plus(extent.times(2))
|
|
382
|
+
height: bbox.height.plus(extent.times(2)),
|
|
370
383
|
};
|
|
371
384
|
}
|
|
372
385
|
|
|
@@ -381,12 +394,12 @@ export class SVGRenderingContext {
|
|
|
381
394
|
*/
|
|
382
395
|
expandBBoxForFilter(bbox, filterDef = null) {
|
|
383
396
|
const filterRef = this.properties.filter;
|
|
384
|
-
if (!filterRef || filterRef ===
|
|
397
|
+
if (!filterRef || filterRef === "none") return bbox;
|
|
385
398
|
|
|
386
399
|
// Default filter region is 10% larger on each side (per SVG spec)
|
|
387
400
|
// filterUnits="objectBoundingBox" x="-10%" y="-10%" width="120%" height="120%"
|
|
388
|
-
let extentX = bbox.width.times(
|
|
389
|
-
let extentY = bbox.height.times(
|
|
401
|
+
let extentX = bbox.width.times("0.1");
|
|
402
|
+
let extentY = bbox.height.times("0.1");
|
|
390
403
|
|
|
391
404
|
// If filter definition provided with explicit bounds, use those
|
|
392
405
|
if (filterDef) {
|
|
@@ -398,7 +411,7 @@ export class SVGRenderingContext {
|
|
|
398
411
|
x: bbox.x.minus(extentX),
|
|
399
412
|
y: bbox.y.minus(extentY),
|
|
400
413
|
width: bbox.width.plus(extentX.times(2)),
|
|
401
|
-
height: bbox.height.plus(extentY.times(2))
|
|
414
|
+
height: bbox.height.plus(extentY.times(2)),
|
|
402
415
|
};
|
|
403
416
|
}
|
|
404
417
|
|
|
@@ -438,7 +451,7 @@ export class SVGRenderingContext {
|
|
|
438
451
|
areas.push({
|
|
439
452
|
polygon: polygon,
|
|
440
453
|
fillRule: this.fillRule,
|
|
441
|
-
type:
|
|
454
|
+
type: "fill",
|
|
442
455
|
});
|
|
443
456
|
}
|
|
444
457
|
|
|
@@ -448,14 +461,14 @@ export class SVGRenderingContext {
|
|
|
448
461
|
width: this.strokeWidth.toNumber(),
|
|
449
462
|
linecap: this.strokeLinecap,
|
|
450
463
|
linejoin: this.strokeLinejoin,
|
|
451
|
-
miterlimit: this.strokeMiterlimit.toNumber()
|
|
464
|
+
miterlimit: this.strokeMiterlimit.toNumber(),
|
|
452
465
|
});
|
|
453
466
|
|
|
454
467
|
if (strokePolygon && strokePolygon.length > 0) {
|
|
455
468
|
areas.push({
|
|
456
469
|
polygon: strokePolygon,
|
|
457
|
-
fillRule:
|
|
458
|
-
type:
|
|
470
|
+
fillRule: "nonzero", // Stroke is always nonzero
|
|
471
|
+
type: "stroke",
|
|
459
472
|
});
|
|
460
473
|
}
|
|
461
474
|
}
|
|
@@ -473,7 +486,8 @@ export class SVGRenderingContext {
|
|
|
473
486
|
isPointInRenderedArea(point, polygon) {
|
|
474
487
|
// Check fill area
|
|
475
488
|
if (this.hasFill) {
|
|
476
|
-
const fillRule =
|
|
489
|
+
const fillRule =
|
|
490
|
+
this.fillRule === "evenodd" ? FillRule.EVENODD : FillRule.NONZERO;
|
|
477
491
|
const inFill = pointInPolygonWithRule(point, polygon, fillRule);
|
|
478
492
|
if (inFill >= 0) return true;
|
|
479
493
|
}
|
|
@@ -484,11 +498,15 @@ export class SVGRenderingContext {
|
|
|
484
498
|
width: this.strokeWidth.toNumber(),
|
|
485
499
|
linecap: this.strokeLinecap,
|
|
486
500
|
linejoin: this.strokeLinejoin,
|
|
487
|
-
miterlimit: this.strokeMiterlimit.toNumber()
|
|
501
|
+
miterlimit: this.strokeMiterlimit.toNumber(),
|
|
488
502
|
});
|
|
489
503
|
|
|
490
504
|
if (strokePolygon && strokePolygon.length > 0) {
|
|
491
|
-
const inStroke = pointInPolygonWithRule(
|
|
505
|
+
const inStroke = pointInPolygonWithRule(
|
|
506
|
+
point,
|
|
507
|
+
strokePolygon,
|
|
508
|
+
FillRule.NONZERO,
|
|
509
|
+
);
|
|
492
510
|
if (inStroke >= 0) return true;
|
|
493
511
|
}
|
|
494
512
|
}
|
|
@@ -507,45 +525,51 @@ export class SVGRenderingContext {
|
|
|
507
525
|
canMergeWith(other) {
|
|
508
526
|
// Fill rules must match
|
|
509
527
|
if (this.fillRule !== other.fillRule) {
|
|
510
|
-
return { canMerge: false, reason:
|
|
528
|
+
return { canMerge: false, reason: "Different fill-rule" };
|
|
511
529
|
}
|
|
512
530
|
|
|
513
531
|
// Stroke properties must match if either has stroke
|
|
514
532
|
if (this.hasStroke || other.hasStroke) {
|
|
515
533
|
if (this.hasStroke !== other.hasStroke) {
|
|
516
|
-
return { canMerge: false, reason:
|
|
534
|
+
return { canMerge: false, reason: "Different stroke presence" };
|
|
517
535
|
}
|
|
518
536
|
|
|
519
537
|
if (!this.strokeWidth.eq(other.strokeWidth)) {
|
|
520
|
-
return { canMerge: false, reason:
|
|
538
|
+
return { canMerge: false, reason: "Different stroke-width" };
|
|
521
539
|
}
|
|
522
540
|
|
|
523
541
|
if (this.strokeLinecap !== other.strokeLinecap) {
|
|
524
|
-
return { canMerge: false, reason:
|
|
542
|
+
return { canMerge: false, reason: "Different stroke-linecap" };
|
|
525
543
|
}
|
|
526
544
|
|
|
527
545
|
if (this.strokeLinejoin !== other.strokeLinejoin) {
|
|
528
|
-
return { canMerge: false, reason:
|
|
546
|
+
return { canMerge: false, reason: "Different stroke-linejoin" };
|
|
529
547
|
}
|
|
530
548
|
}
|
|
531
549
|
|
|
532
550
|
// Neither can have markers (markers break continuity)
|
|
533
551
|
if (this.hasMarkers || other.hasMarkers) {
|
|
534
|
-
return { canMerge: false, reason:
|
|
552
|
+
return { canMerge: false, reason: "Has markers" };
|
|
535
553
|
}
|
|
536
554
|
|
|
537
555
|
// Neither can have clip-path or mask
|
|
538
|
-
if (
|
|
539
|
-
|
|
556
|
+
if (
|
|
557
|
+
this.properties["clip-path"] !== "none" ||
|
|
558
|
+
other.properties["clip-path"] !== "none"
|
|
559
|
+
) {
|
|
560
|
+
return { canMerge: false, reason: "Has clip-path" };
|
|
540
561
|
}
|
|
541
562
|
|
|
542
|
-
if (this.properties.mask !==
|
|
543
|
-
return { canMerge: false, reason:
|
|
563
|
+
if (this.properties.mask !== "none" || other.properties.mask !== "none") {
|
|
564
|
+
return { canMerge: false, reason: "Has mask" };
|
|
544
565
|
}
|
|
545
566
|
|
|
546
567
|
// Neither can have filter
|
|
547
|
-
if (
|
|
548
|
-
|
|
568
|
+
if (
|
|
569
|
+
this.properties.filter !== "none" ||
|
|
570
|
+
other.properties.filter !== "none"
|
|
571
|
+
) {
|
|
572
|
+
return { canMerge: false, reason: "Has filter" };
|
|
549
573
|
}
|
|
550
574
|
|
|
551
575
|
return { canMerge: true, reason: null };
|
|
@@ -565,8 +589,8 @@ export class SVGRenderingContext {
|
|
|
565
589
|
strokeExtent: this.getStrokeExtent().toNumber(),
|
|
566
590
|
linecap: this.strokeLinecap,
|
|
567
591
|
linejoin: this.strokeLinejoin,
|
|
568
|
-
clipPath: this.properties[
|
|
569
|
-
filter: this.properties.filter
|
|
592
|
+
clipPath: this.properties["clip-path"],
|
|
593
|
+
filter: this.properties.filter,
|
|
570
594
|
};
|
|
571
595
|
}
|
|
572
596
|
}
|
|
@@ -579,7 +603,11 @@ export class SVGRenderingContext {
|
|
|
579
603
|
* @param {Map} defsMap - Definitions map
|
|
580
604
|
* @returns {SVGRenderingContext}
|
|
581
605
|
*/
|
|
582
|
-
export function createRenderingContext(
|
|
606
|
+
export function createRenderingContext(
|
|
607
|
+
element,
|
|
608
|
+
inherited = {},
|
|
609
|
+
defsMap = null,
|
|
610
|
+
) {
|
|
583
611
|
return new SVGRenderingContext(element, inherited, defsMap);
|
|
584
612
|
}
|
|
585
613
|
|
|
@@ -594,11 +622,26 @@ export function getInheritedProperties(element) {
|
|
|
594
622
|
|
|
595
623
|
// Inheritable properties per SVG spec
|
|
596
624
|
const inheritableProps = [
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
625
|
+
"fill",
|
|
626
|
+
"fill-rule",
|
|
627
|
+
"fill-opacity",
|
|
628
|
+
"stroke",
|
|
629
|
+
"stroke-width",
|
|
630
|
+
"stroke-linecap",
|
|
631
|
+
"stroke-linejoin",
|
|
632
|
+
"stroke-miterlimit",
|
|
633
|
+
"stroke-dasharray",
|
|
634
|
+
"stroke-dashoffset",
|
|
635
|
+
"stroke-opacity",
|
|
636
|
+
"marker-start",
|
|
637
|
+
"marker-mid",
|
|
638
|
+
"marker-end",
|
|
639
|
+
"clip-rule",
|
|
640
|
+
"opacity",
|
|
641
|
+
"font-family",
|
|
642
|
+
"font-size",
|
|
643
|
+
"font-style",
|
|
644
|
+
"font-weight",
|
|
602
645
|
];
|
|
603
646
|
|
|
604
647
|
let current = element.parentNode;
|
|
@@ -623,5 +666,5 @@ export default {
|
|
|
623
666
|
GEOMETRY_AFFECTING_PROPERTIES,
|
|
624
667
|
FILL_AFFECTING_PROPERTIES,
|
|
625
668
|
createRenderingContext,
|
|
626
|
-
getInheritedProperties
|
|
669
|
+
getInheritedProperties,
|
|
627
670
|
};
|