svg-path-simplify 0.4.3 → 0.4.5
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/CHANGELOG.md +21 -0
- package/README.md +2 -1
- package/dist/svg-path-simplify.esm.js +1670 -509
- package/dist/svg-path-simplify.esm.min.js +2 -2
- package/dist/svg-path-simplify.js +1671 -508
- package/dist/svg-path-simplify.min.js +2 -2
- package/dist/svg-path-simplify.pathdata.esm.js +936 -463
- package/dist/svg-path-simplify.pathdata.esm.min.js +2 -2
- package/dist/svg-path-simplify.poly.cjs +9 -8
- package/index.html +60 -20
- package/package.json +1 -1
- package/src/constants.js +4 -0
- package/src/detect_input.js +47 -29
- package/src/index.js +8 -0
- package/src/pathData_simplify_cubic.js +46 -18
- package/src/pathData_simplify_revertToquadratics.js +0 -1
- package/src/pathSimplify-main.js +81 -20
- package/src/pathSimplify-only-pathdata.js +7 -2
- package/src/pathSimplify-presets.js +14 -4
- package/src/svg-getAttributes.js +5 -3
- package/src/svgii/convert_units.js +1 -1
- package/src/svgii/geometry.js +140 -2
- package/src/svgii/geometry_bbox_element.js +1 -1
- package/src/svgii/geometry_deduceRadius.js +116 -27
- package/src/svgii/geometry_length.js +18 -2
- package/src/svgii/pathData_analyze.js +18 -0
- package/src/svgii/pathData_convert.js +188 -88
- package/src/svgii/pathData_fix_directions.js +10 -18
- package/src/svgii/pathData_reorder.js +123 -16
- package/src/svgii/pathData_simplify_refineCorners.js +130 -35
- package/src/svgii/pathData_simplify_refine_round.js +420 -0
- package/src/svgii/poly_normalize.js +9 -8
- package/src/svgii/rounding.js +112 -80
- package/src/svgii/svg_cleanup.js +75 -22
- package/src/svgii/svg_cleanup_convertPathLength.js +27 -15
- package/src/svgii/svg_cleanup_normalize_transforms.js +1 -1
- package/src/svgii/svg_cleanup_remove_els_and_atts.js +6 -1
- package/src/svgii/svg_el_parse_style_props.js +13 -10
- package/src/svgii/svg_validate.js +220 -0
- package/tests/testSVG.js +14 -1
- package/src/svgii/pathData_refine_round.js +0 -222
package/src/detect_input.js
CHANGED
|
@@ -1,48 +1,57 @@
|
|
|
1
|
+
import { dummySVG, svgNs } from "./constants";
|
|
2
|
+
import { validateSVG } from "./svgii/svg_validate";
|
|
3
|
+
|
|
1
4
|
export function detectInputType(input) {
|
|
2
5
|
let type = 'string';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
let log = '';
|
|
7
|
+
let isValid = true;
|
|
8
|
+
|
|
9
|
+
let result = {
|
|
10
|
+
inputType:'',
|
|
11
|
+
isValid:true,
|
|
12
|
+
fileReport:{},
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
11
16
|
if (Array.isArray(input)) {
|
|
12
17
|
|
|
18
|
+
result.inputType = "array";
|
|
19
|
+
|
|
20
|
+
|
|
13
21
|
// nested array
|
|
14
22
|
if (Array.isArray(input[0])) {
|
|
15
23
|
//console.log('is array', input[0], input[0][0])
|
|
16
24
|
|
|
17
25
|
if (input[0].length === 2) {
|
|
18
26
|
//console.log('is single poly value array')
|
|
19
|
-
|
|
27
|
+
result.inputType = 'polyArray'
|
|
20
28
|
}
|
|
21
29
|
|
|
22
30
|
else if (Array.isArray(input[0][0]) && input[0][0].length === 2) {
|
|
23
31
|
//console.log('is complex poly point value array', input[0][0])
|
|
24
|
-
|
|
32
|
+
result.inputType = 'polyComplexArray'
|
|
25
33
|
}
|
|
26
34
|
else if (input[0][0].x !== undefined && input[0][0].y !== undefined) {
|
|
27
35
|
//console.log('is nested point object array')
|
|
28
|
-
|
|
36
|
+
result.inputType = 'polyComplexObjectArray'
|
|
29
37
|
}
|
|
38
|
+
//return result
|
|
30
39
|
}
|
|
31
40
|
|
|
32
41
|
// is point array
|
|
33
42
|
else if (input[0].x !== undefined && input[0].y !== undefined) {
|
|
34
43
|
//console.log('is nested point object array')
|
|
35
|
-
|
|
44
|
+
result.inputType = 'polyObjectArray'
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
// path data array
|
|
39
48
|
else if (input[0]?.type && input[0]?.values
|
|
40
49
|
) {
|
|
41
|
-
|
|
42
|
-
|
|
50
|
+
result.inputType = "pathData"
|
|
43
51
|
}
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
return result;
|
|
46
55
|
}
|
|
47
56
|
|
|
48
57
|
if (typeof input === "string") {
|
|
@@ -55,39 +64,48 @@ export function detectInputType(input) {
|
|
|
55
64
|
//console.log('isNumberJson', isJson);
|
|
56
65
|
|
|
57
66
|
if (isSVG) {
|
|
58
|
-
|
|
67
|
+
let validate = validateSVG(input);
|
|
68
|
+
({isValid, log} = validate) ;
|
|
69
|
+
if(!isValid){
|
|
70
|
+
//input = dummySVG
|
|
71
|
+
result.inputType = 'invalid'
|
|
72
|
+
result.isValid=false,
|
|
73
|
+
//result.log = JSON.stringify(log, null, ' ')
|
|
74
|
+
result.log = log
|
|
75
|
+
}else{
|
|
76
|
+
result.inputType = 'svgMarkup'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
result.fileReport = validate.fileReport
|
|
80
|
+
|
|
59
81
|
}
|
|
60
82
|
|
|
61
83
|
else if (isJson) {
|
|
62
|
-
|
|
84
|
+
result.inputType = 'json'
|
|
63
85
|
}
|
|
64
86
|
|
|
65
87
|
else if (isSymbol) {
|
|
66
|
-
|
|
88
|
+
result.inputType = 'symbol'
|
|
67
89
|
}
|
|
68
90
|
else if (isPathData) {
|
|
69
|
-
|
|
91
|
+
result.inputType = 'pathDataString'
|
|
70
92
|
}
|
|
71
93
|
else if (isPolyString) {
|
|
72
|
-
|
|
94
|
+
result.inputType = 'polyString'
|
|
73
95
|
}
|
|
74
96
|
|
|
75
97
|
else {
|
|
76
98
|
let url = /^(file:|https?:\/\/|\/|\.\/|\.\.\/)/.test(input);
|
|
77
99
|
let dataUrl = input.startsWith('data:image');
|
|
78
|
-
|
|
100
|
+
result.inputType = url || dataUrl ? "url" : "string";
|
|
79
101
|
}
|
|
80
102
|
|
|
81
|
-
|
|
82
|
-
return type
|
|
103
|
+
return result
|
|
83
104
|
}
|
|
84
105
|
|
|
85
|
-
|
|
86
|
-
let constructor = input.constructor.name
|
|
87
|
-
|
|
88
|
-
|
|
106
|
+
result.inputType = (input.constructor.name || typeof input ).toLowerCase()
|
|
89
107
|
|
|
90
|
-
return
|
|
108
|
+
return result;
|
|
91
109
|
}
|
|
92
110
|
|
|
93
111
|
|
package/src/index.js
CHANGED
|
@@ -44,11 +44,19 @@ export{getElementTransform as getElementTransform};
|
|
|
44
44
|
import {getViewBox} from './svg_getViewbox.js';
|
|
45
45
|
export{getViewBox as getViewBox};
|
|
46
46
|
|
|
47
|
+
import { validateSVG } from './svgii/svg_validate.js';
|
|
48
|
+
export { validateSVG as validateSVG};
|
|
49
|
+
import { detectInputType } from './detect_input.js';
|
|
50
|
+
export { detectInputType as detectInputType};
|
|
51
|
+
|
|
52
|
+
|
|
47
53
|
|
|
48
54
|
// IIFE
|
|
49
55
|
if (typeof window !== 'undefined') {
|
|
50
56
|
window.svgPathSimplify = svgPathSimplify;
|
|
51
57
|
window.getElementTransform = getElementTransform;
|
|
58
|
+
window.validateSVG = validateSVG;
|
|
59
|
+
window.detectInputType = detectInputType;
|
|
52
60
|
//window.simplifyPolySchneider = simplifyPolySchneider;
|
|
53
61
|
//window.getPathDataFromEl = getPathDataFromEl;
|
|
54
62
|
//window.parsePathDataString = parsePathDataString;
|
|
@@ -56,7 +56,7 @@ export function simplifyPathDataCubic(pathData, {
|
|
|
56
56
|
error += com.error;
|
|
57
57
|
|
|
58
58
|
// find next candidates
|
|
59
|
-
for (let n = i +
|
|
59
|
+
for (let n = i + offset; error < tolerance && n < l; n++) {
|
|
60
60
|
let comN = pathData[n]
|
|
61
61
|
|
|
62
62
|
if (comN.type !== 'C' ||
|
|
@@ -66,6 +66,7 @@ export function simplifyPathDataCubic(pathData, {
|
|
|
66
66
|
(keepExtremes && com.extreme)
|
|
67
67
|
)
|
|
68
68
|
) {
|
|
69
|
+
|
|
69
70
|
break
|
|
70
71
|
}
|
|
71
72
|
|
|
@@ -73,6 +74,7 @@ export function simplifyPathDataCubic(pathData, {
|
|
|
73
74
|
|
|
74
75
|
// failure - could not be combined - exit loop
|
|
75
76
|
if (combined.length > 1) {
|
|
77
|
+
//renderPoint(markers, com.p, 'orange', '1%', '0.5')
|
|
76
78
|
break
|
|
77
79
|
}
|
|
78
80
|
|
|
@@ -86,6 +88,7 @@ export function simplifyPathDataCubic(pathData, {
|
|
|
86
88
|
|
|
87
89
|
// return combined
|
|
88
90
|
com = combined[0]
|
|
91
|
+
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
//console.log('tests', log, offset);
|
|
@@ -143,10 +146,10 @@ export function combineCubicPairs(com1, com2, {
|
|
|
143
146
|
let comS = getExtrapolatedCommand(com1, com2, t)
|
|
144
147
|
|
|
145
148
|
// test new point-at-t against original mid segment starting point
|
|
146
|
-
let
|
|
149
|
+
let ptI = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t)
|
|
147
150
|
|
|
148
151
|
|
|
149
|
-
let dist0 = getDistManhattan(com1.p,
|
|
152
|
+
let dist0 = getDistManhattan(com1.p, ptI)
|
|
150
153
|
let dist1 = 0, dist2 = 0;
|
|
151
154
|
let close = dist0 < maxDist;
|
|
152
155
|
let success = false;
|
|
@@ -162,32 +165,42 @@ export function combineCubicPairs(com1, com2, {
|
|
|
162
165
|
* to prevent distortions
|
|
163
166
|
*/
|
|
164
167
|
|
|
165
|
-
//
|
|
166
|
-
let
|
|
168
|
+
// 1st segment mid
|
|
169
|
+
let ptM_seg1 = pointAtT([com1.p0, com1.cp1, com1.cp2, com1.p], 0.5)
|
|
170
|
+
|
|
171
|
+
let t2 = t * 0.5;
|
|
172
|
+
// combined interpolated mid point
|
|
173
|
+
let ptI_seg1 = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t2)
|
|
174
|
+
dist1 = getDistManhattan(ptM_seg1, ptI_seg1)
|
|
167
175
|
|
|
168
|
-
// simplified path
|
|
169
|
-
let t3 = (1 + t) * 0.5;
|
|
170
|
-
let ptS_2 = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t3)
|
|
171
|
-
dist1 = getDistManhattan(pt_2, ptS_2)
|
|
172
176
|
|
|
173
177
|
error += dist1;
|
|
174
178
|
|
|
175
179
|
if (dist1 < maxDist) {
|
|
176
180
|
|
|
177
|
-
//
|
|
178
|
-
|
|
181
|
+
// 2nd segment mid
|
|
182
|
+
let ptM_seg2 = pointAtT([com2.p0, com2.cp1, com2.cp2, com2.p], 0.5)
|
|
179
183
|
|
|
180
|
-
//
|
|
181
|
-
let
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
let ptS_1 = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t2)
|
|
185
|
-
dist2 = getDistManhattan(pt_1, ptS_1)
|
|
184
|
+
// simplified path
|
|
185
|
+
let t3 = (1 + t) * 0.5;
|
|
186
|
+
let ptI_seg2 = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t3)
|
|
187
|
+
dist2 = getDistManhattan(ptM_seg2, ptI_seg2)
|
|
186
188
|
|
|
187
189
|
error += dist2;
|
|
188
190
|
|
|
189
191
|
if (error < maxDist) success = true;
|
|
190
192
|
|
|
193
|
+
|
|
194
|
+
/*
|
|
195
|
+
renderPoint(markers, ptM_seg1, 'cyan')
|
|
196
|
+
renderPoint(markers, pt, 'orange', '1.5%', '1')
|
|
197
|
+
renderPoint(markers, ptM_seg2, 'orange')
|
|
198
|
+
|
|
199
|
+
renderPoint(markers, com1.p, 'green')
|
|
200
|
+
//renderPoint(markers, com2.p, 'green')
|
|
201
|
+
renderPoint(markers, ptI_seg1, 'purple')
|
|
202
|
+
*/
|
|
203
|
+
|
|
191
204
|
}
|
|
192
205
|
|
|
193
206
|
} // end 1st try
|
|
@@ -203,11 +216,26 @@ export function combineCubicPairs(com1, com2, {
|
|
|
203
216
|
|
|
204
217
|
comS.dimA = getDistManhattan(comS.p0, comS.p);
|
|
205
218
|
comS.type = 'C';
|
|
219
|
+
|
|
206
220
|
comS.extreme = com2.extreme;
|
|
207
221
|
comS.directionChange = com2.directionChange;
|
|
208
|
-
//comS.directionChange = com1.directionChange ? true : (com2.directionChange);
|
|
209
222
|
comS.corner = com2.corner;
|
|
210
223
|
|
|
224
|
+
|
|
225
|
+
if (comS.extreme || comS.corner) {
|
|
226
|
+
//renderPoint(markers, comS.p)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/*
|
|
230
|
+
comS.extreme = com1.extreme;
|
|
231
|
+
comS.directionChange = com1.directionChange;
|
|
232
|
+
comS.corner = com1.corner;
|
|
233
|
+
*/
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
//comS.directionChange = com1.directionChange ? true : (com2.directionChange);
|
|
238
|
+
|
|
211
239
|
comS.values = [comS.cp1.x, comS.cp1.y, comS.cp2.x, comS.cp2.y, comS.p.x, comS.p.y]
|
|
212
240
|
|
|
213
241
|
// relative error
|
|
@@ -6,7 +6,6 @@ export function pathDataRevertCubicToQuadratic(pathData, tolerance=1) {
|
|
|
6
6
|
let com = pathData[c]
|
|
7
7
|
let { type, values, p0, cp1 = null, cp2 = null, p = null } = com;
|
|
8
8
|
if (type === 'C') {
|
|
9
|
-
//console.log(com);
|
|
10
9
|
let comQ = revertCubicQuadratic(p0, cp1, cp2, p, tolerance)
|
|
11
10
|
if (comQ.type === 'Q') {
|
|
12
11
|
comQ.extreme = com.extreme
|
package/src/pathSimplify-main.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { detectInputType } from './detect_input';
|
|
2
2
|
import { simplifyPathDataCubic } from './pathData_simplify_cubic';
|
|
3
|
-
import { getDistManhattan, getDistance, getPathDataVertices, interpolate, pointAtT, reducePoints, svgArcToCenterParam, toParametricAngle } from './svgii/geometry';
|
|
3
|
+
import { getDistManhattan, getDistance, getPathDataVertices, getSquareDistance, interpolate, pointAtT, reducePoints, svgArcToCenterParam, toParametricAngle } from './svgii/geometry';
|
|
4
4
|
import { getPolyBBox } from './svgii/geometry_bbox';
|
|
5
5
|
import { analyzePathData, getPathDataVerbose } from './svgii/pathData_analyze';
|
|
6
6
|
import { normalizePathData, parsePathDataNormalized, convertPathData } from './svgii/pathData_convert';
|
|
@@ -16,7 +16,7 @@ import { detectAccuracy, roundPathData, roundTo } from './svgii/rounding';
|
|
|
16
16
|
import { refineAdjacentExtremes } from './svgii/pathData_simplify_refineExtremes';
|
|
17
17
|
import { cleanUpSVG, removeEmptySVGEls } from './svgii/svg_cleanup';
|
|
18
18
|
import { refineRoundedCorners } from './svgii/pathData_simplify_refineCorners';
|
|
19
|
-
import { refineRoundSegments } from './svgii/
|
|
19
|
+
import { refineRoundSegments, simplifyAdjacentRound } from './svgii/pathData_simplify_refine_round';
|
|
20
20
|
import { refineClosingCommand } from './svgii/pathData_remove_short';
|
|
21
21
|
import { scalePathData } from './svgii/pathData_transform_scale';
|
|
22
22
|
import { getViewBox } from './svg_getViewbox';
|
|
@@ -32,7 +32,7 @@ import { normalizePoly, polyPtsToArray } from './svgii/poly_normalize';
|
|
|
32
32
|
import { simplifyPolyRD } from './simplify_poly_radial_distance';
|
|
33
33
|
import { simplifyPolyRDP, simplifyPolyRDP__, simplifyRDP_rel } from './simplify_poly_RDP';
|
|
34
34
|
import { getEllipseLengthLG, getLegendreGaussValues, getLength, waArr_global } from './svgii/geometry_length';
|
|
35
|
-
import { deg2rad } from './constants';
|
|
35
|
+
import { deg2rad, dummySVG } from './constants';
|
|
36
36
|
import { getPathDataLength } from './svgii/pathData_getLength';
|
|
37
37
|
import { stringifySVG } from './string_helpers';
|
|
38
38
|
import { presetSettings, settingsDefaults } from './pathSimplify-presets';
|
|
@@ -55,21 +55,54 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
let { getObject = false, removeComments, removeOffCanvas, unGroup, mergePaths, removeElements, removeDimensions, removeIds, removeClassNames, omitNamespace, cleanUpStrokes, addViewBox, addDimensions, removePrologue, removeHidden, removeUnused, cleanupDefs, cleanupClip, cleanupSVGAtts, removeNameSpaced, removeNameSpacedAtts, attributesToGroup, minifyRgbColors, stylesToAttributes, fixHref, legacyHref, allowMeta, allowDataAtts, allowAriaAtts,
|
|
58
|
+
let { getObject = false, removeComments, removeOffCanvas, unGroup, mergePaths, removeElements, removeDimensions, removeIds, removeClassNames, omitNamespace, cleanUpStrokes, addViewBox, addDimensions, removePrologue, removeHidden, removeUnused, cleanupDefs, cleanupClip, cleanupSVGAtts, removeNameSpaced, removeNameSpacedAtts, attributesToGroup, minifyRgbColors, stylesToAttributes, fixHref, legacyHref, allowMeta, allowDataAtts, allowAriaAtts, removeSVGAttributes, removeElAttributes, shapesToPaths, shapeConvert, convertShapes, simplifyBezier, optimizeOrder, autoClose, removeZeroLength, refineClosing, removeColinear, flatBezierToLinetos, revertToQuadratics, refineExtremes, simplifyCorners, fixDirections, keepExtremes, keepCorners, keepInflections, addExtremes, reversePath, toAbsolute, toRelative, toMixed, toShorthands, toLonghands, quadraticToCubic, arcToCubic, cubicToArc, lineToCubic, decimals, autoAccuracy, minifyD, tolerance, toPolygon, smoothPoly, polyFormat, precisionPoly, simplifyRD, simplifyRDP, harmonizeCpts, removeOrphanSubpaths, simplifyRound, simplifyQuadraticCorners, scale, scaleTo, crop, alignToOrigin, convertTransforms, keepSmaller, splitCompound, convertPathLength, toAbsoluteUnits } = settings;
|
|
59
59
|
|
|
60
60
|
//toAbsolute = !toRelative;
|
|
61
61
|
|
|
62
62
|
// clamp tolerance and scale
|
|
63
63
|
tolerance = Math.max(0.1, tolerance);
|
|
64
64
|
scale = Math.max(0.001, scale)
|
|
65
|
-
if(fixDirections) keepSmaller = false;
|
|
65
|
+
if (fixDirections) keepSmaller = false;
|
|
66
66
|
if (scale !== 1 || scaleTo || crop || alignToOrigin) {
|
|
67
67
|
convertTransforms = true;
|
|
68
68
|
settings.convertTransforms = true
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
/**
|
|
73
|
+
* intercept
|
|
74
|
+
* invalid inputs
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
let inputDetection = detectInputType(input);
|
|
78
|
+
let { inputType, log } = inputDetection
|
|
79
|
+
|
|
80
|
+
// invalid file
|
|
81
|
+
if (inputType === 'invalid' || input === dummySVG) {
|
|
82
|
+
// return dummy SVG to continue processing
|
|
83
|
+
//input = dummySVG;
|
|
84
|
+
//inputType = 'invalid';
|
|
85
|
+
|
|
86
|
+
//console.warn(`Input is not valid!\n ${log}`);
|
|
87
|
+
//console.log(input);
|
|
88
|
+
//return false
|
|
89
|
+
|
|
90
|
+
let report = {
|
|
91
|
+
original: 0,
|
|
92
|
+
new: 0,
|
|
93
|
+
saved: 0,
|
|
94
|
+
svgSize: 0,
|
|
95
|
+
svgSizeOpt: 0,
|
|
96
|
+
compression: 0,
|
|
97
|
+
decimals: 0,
|
|
98
|
+
invalid: true
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return { svg: dummySVG, d: '', polys: [], report, pathDataPlusArr: [], pathDataPlusArr_global: [], inputType: 'invalid', dOriginal: '' };
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
73
106
|
let svg = '';
|
|
74
107
|
let svgSize = 0;
|
|
75
108
|
let svgSizeOpt = 0;
|
|
@@ -81,12 +114,12 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
81
114
|
|
|
82
115
|
// pathdata superset array - containing additional data
|
|
83
116
|
let pathDataPlusArr_global = []
|
|
84
|
-
let paths = []
|
|
117
|
+
let paths = [];
|
|
85
118
|
let isPoly = false;
|
|
86
|
-
let polys = []
|
|
87
|
-
let poly = []
|
|
119
|
+
let polys = [];
|
|
120
|
+
let poly = [];
|
|
88
121
|
let dStr = '';
|
|
89
|
-
let dOriginal = ''
|
|
122
|
+
let dOriginal = '';
|
|
90
123
|
|
|
91
124
|
/**
|
|
92
125
|
* normalize input
|
|
@@ -204,10 +237,7 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
204
237
|
// convert all shapes to paths
|
|
205
238
|
if (shapesToPaths) {
|
|
206
239
|
shapeConvert = 'toPaths'
|
|
207
|
-
|
|
208
|
-
convert_ellipses = true
|
|
209
|
-
convert_poly = true
|
|
210
|
-
convert_lines = true
|
|
240
|
+
convertShapes = ['rect', 'polygon', 'polyline', 'line', 'circle', 'ellipse']
|
|
211
241
|
}
|
|
212
242
|
|
|
213
243
|
//console.log('shapesToPaths', shapesToPaths, 'shapeConvert', shapeConvert, convert_rects, convert_ellipses, convert_poly);
|
|
@@ -255,6 +285,9 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
255
285
|
}
|
|
256
286
|
//console.log('pathOptions', pathOptions);
|
|
257
287
|
|
|
288
|
+
let comCount = 0
|
|
289
|
+
let comCountS = 0
|
|
290
|
+
|
|
258
291
|
|
|
259
292
|
for (let i = 0, l = paths.length; l && i < l; i++) {
|
|
260
293
|
|
|
@@ -264,6 +297,12 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
264
297
|
let dN = ''
|
|
265
298
|
let isPoly = false;
|
|
266
299
|
|
|
300
|
+
// disable reordering for elements with stroke dash-array
|
|
301
|
+
if (el && (el.hasAttribute('stroke-dasharray') || el.hasAttribute('stroke-dashoffset'))) {
|
|
302
|
+
optimizeOrder = false;
|
|
303
|
+
//optimizeClosePath=false;
|
|
304
|
+
}
|
|
305
|
+
|
|
267
306
|
// if polygon we already heave absolute coordinates
|
|
268
307
|
//let isPolyPath = !mode && isPoly && Array.isArray(d)
|
|
269
308
|
//let pathData = !isPolyPath ? parsePathDataNormalized(d, { quadraticToCubic, arcToCubic }) : d;
|
|
@@ -306,7 +345,7 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
306
345
|
}
|
|
307
346
|
|
|
308
347
|
// count commands for evaluation
|
|
309
|
-
|
|
348
|
+
comCount += pathData.length
|
|
310
349
|
|
|
311
350
|
if (!isPoly && removeOrphanSubpaths) pathData = removeOrphanedM(pathData);
|
|
312
351
|
|
|
@@ -463,7 +502,6 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
463
502
|
|
|
464
503
|
|
|
465
504
|
|
|
466
|
-
|
|
467
505
|
// simplify beziers
|
|
468
506
|
let { pathData, bb, dimA } = pathDataPlus;
|
|
469
507
|
|
|
@@ -498,12 +536,14 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
498
536
|
//pathData = removeZeroLengthLinetos(pathData);
|
|
499
537
|
|
|
500
538
|
let threshold = (bb.width + bb.height) * 0.1
|
|
501
|
-
pathData = refineRoundedCorners(pathData, { threshold, tolerance })
|
|
539
|
+
pathData = refineRoundedCorners(pathData, { threshold, tolerance, simplifyQuadraticCorners })
|
|
502
540
|
}
|
|
503
541
|
|
|
504
542
|
// refine round segment sequences
|
|
505
|
-
if (simplifyRound)
|
|
506
|
-
|
|
543
|
+
if (simplifyRound) {
|
|
544
|
+
pathData = refineRoundSegments(pathData);
|
|
545
|
+
pathData = simplifyAdjacentRound(pathData);
|
|
546
|
+
}
|
|
507
547
|
|
|
508
548
|
// simplify to quadratics
|
|
509
549
|
if (revertToQuadratics) pathData = pathDataRevertCubicToQuadratic(pathData, tolerance);
|
|
@@ -550,7 +590,25 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
550
590
|
|
|
551
591
|
// prefer top to bottom priority for portrait aspect ratios
|
|
552
592
|
if (optimizeOrder) {
|
|
593
|
+
/*
|
|
553
594
|
pathDataPlusArr = isPortrait ? pathDataPlusArr.sort((a, b) => a.bb.y - b.bb.y || a.bb.x - b.bb.x) : pathDataPlusArr.sort((a, b) => a.bb.x - b.bb.x || a.bb.y - b.bb.y)
|
|
595
|
+
*/
|
|
596
|
+
|
|
597
|
+
// add missin bbox
|
|
598
|
+
pathDataPlusArr.forEach(p => {
|
|
599
|
+
if (p.bb.x === undefined) {
|
|
600
|
+
p.bb = getPolyBBox(getPathDataVertices(p.pathData))
|
|
601
|
+
}
|
|
602
|
+
})
|
|
603
|
+
|
|
604
|
+
try {
|
|
605
|
+
pathDataPlusArr = pathDataPlusArr.sort((a, b) => +a.bb.x.toFixed(2) - (+b.bb.x.toFixed(2)) || a.bb.y - b.bb.y);
|
|
606
|
+
//console.log(pathDataPlusArr);
|
|
607
|
+
|
|
608
|
+
} catch {
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
|
|
554
612
|
}
|
|
555
613
|
|
|
556
614
|
|
|
@@ -623,7 +681,7 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
623
681
|
|
|
624
682
|
|
|
625
683
|
// compare command count
|
|
626
|
-
|
|
684
|
+
comCountS += pathData.length
|
|
627
685
|
|
|
628
686
|
let dOpt = pathDataToD(pathData, minifyD)
|
|
629
687
|
//svgSizeOpt = new Blob([dOpt]).size;
|
|
@@ -706,6 +764,9 @@ export function svgPathSimplify(input = '', settings = {}) {
|
|
|
706
764
|
|
|
707
765
|
|
|
708
766
|
report = {
|
|
767
|
+
original: comCount,
|
|
768
|
+
new: comCountS,
|
|
769
|
+
saved: comCount - comCountS,
|
|
709
770
|
svgSize,
|
|
710
771
|
svgSizeOpt,
|
|
711
772
|
compression,
|
|
@@ -13,10 +13,11 @@ import { pathDataToD } from './svgii/pathData_stringify';
|
|
|
13
13
|
import { detectAccuracy } from './svgii/rounding';
|
|
14
14
|
import { refineAdjacentExtremes } from './svgii/pathData_simplify_refineExtremes';
|
|
15
15
|
import { refineRoundedCorners } from './svgii/pathData_simplify_refineCorners';
|
|
16
|
-
import { refineRoundSegments } from './svgii/pathData_refine_round';
|
|
16
|
+
//import { refineRoundSegments } from './svgii/pathData_refine_round';
|
|
17
17
|
import { refineClosingCommand } from './svgii/pathData_remove_short';
|
|
18
18
|
import { pathDataRevertCubicToQuadratic } from './pathData_simplify_revertToquadratics';
|
|
19
19
|
import { pathDataLineToCubic } from './svgii/pathData_line_to_cubic';
|
|
20
|
+
import { refineRoundSegments } from './svgii/pathData_simplify_refine_round';
|
|
20
21
|
|
|
21
22
|
//import { installDOMPolyfills } from './dom-polyfill';
|
|
22
23
|
|
|
@@ -97,7 +98,11 @@ export function simplifyPathData(input = '', {
|
|
|
97
98
|
let yArr = []
|
|
98
99
|
|
|
99
100
|
// mode:0 – single path
|
|
100
|
-
let inputType = detectInputType(input)
|
|
101
|
+
//let inputType = detectInputType(input)
|
|
102
|
+
let inputDetection = detectInputType(input);
|
|
103
|
+
let {inputType, log} = inputDetection
|
|
104
|
+
|
|
105
|
+
|
|
101
106
|
if (inputType === 'pathDataString') {
|
|
102
107
|
d = input
|
|
103
108
|
} else if (inputType === 'polyString') {
|
|
@@ -30,6 +30,7 @@ export let settingsDefaults = {
|
|
|
30
30
|
allowAriaAtts: true,
|
|
31
31
|
//pathlength conversion
|
|
32
32
|
convertPathLength: false,
|
|
33
|
+
toAbsoluteUnits: false,
|
|
33
34
|
|
|
34
35
|
// custom removal
|
|
35
36
|
removeElements: [],
|
|
@@ -61,6 +62,7 @@ export let settingsDefaults = {
|
|
|
61
62
|
revertToQuadratics: true,
|
|
62
63
|
refineExtremes: false,
|
|
63
64
|
simplifyCorners: false,
|
|
65
|
+
simplifyQuadraticCorners: false,
|
|
64
66
|
keepExtremes: true,
|
|
65
67
|
keepCorners: true,
|
|
66
68
|
keepInflections: false,
|
|
@@ -121,7 +123,7 @@ for (let prop in settingsDefaults) {
|
|
|
121
123
|
let isArray = Array.isArray(val)
|
|
122
124
|
|
|
123
125
|
if (isBoolean) val = false
|
|
124
|
-
else if (!isArray && isNum) val = val===1 ? 1 : (prop==='decimals'? -1 : 0);
|
|
126
|
+
else if (!isArray && isNum) val = val === 1 ? 1 : (prop === 'decimals' ? -1 : 0);
|
|
125
127
|
else if (isArray) val = []
|
|
126
128
|
settingsNull[prop] = val;
|
|
127
129
|
}
|
|
@@ -153,10 +155,14 @@ export const presetSettings = {
|
|
|
153
155
|
...settingsDefaults,
|
|
154
156
|
...{
|
|
155
157
|
keepSmaller: false,
|
|
158
|
+
convertPathLength:true,
|
|
156
159
|
toRelative: true,
|
|
157
160
|
toMixed: true,
|
|
158
161
|
toShorthands: true,
|
|
159
162
|
//fixHref: true,
|
|
163
|
+
allowMeta:true,
|
|
164
|
+
allowDataAtts:true,
|
|
165
|
+
allowAriaAtts:true,
|
|
160
166
|
legacyHref: true,
|
|
161
167
|
addViewBox: true,
|
|
162
168
|
addDimensions: true,
|
|
@@ -224,19 +230,23 @@ export const presetSettings = {
|
|
|
224
230
|
high: {
|
|
225
231
|
...settingsDefaults,
|
|
226
232
|
...{
|
|
227
|
-
tolerance: 1.
|
|
233
|
+
tolerance: 1.1,
|
|
228
234
|
toMixed: true,
|
|
229
235
|
refineExtremes: true,
|
|
230
236
|
simplifyCorners: true,
|
|
237
|
+
simplifyQuadraticCorners: true,
|
|
238
|
+
removeOrphanSubpaths: true,
|
|
231
239
|
simplifyRound: true,
|
|
232
240
|
removeClassNames: true,
|
|
233
241
|
cubicToArc: true,
|
|
242
|
+
minifyD: 0,
|
|
234
243
|
removeComments: true,
|
|
235
244
|
removeHidden: true,
|
|
236
|
-
removeOffCanvas: true,
|
|
237
245
|
addViewBox: true,
|
|
238
246
|
removeDimensions: true,
|
|
239
|
-
|
|
247
|
+
removeOffCanvas: true,
|
|
248
|
+
/*
|
|
249
|
+
*/
|
|
240
250
|
}
|
|
241
251
|
}
|
|
242
252
|
|
package/src/svg-getAttributes.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { normalizeUnits } from "./svgii/convert_units";
|
|
2
2
|
|
|
3
3
|
export function getElementAtts(el, {x=0, y=0, width=0, height=0}={}){
|
|
4
|
-
let attributes = [...el.attributes];
|
|
4
|
+
//let attributes = [...el.attributes];
|
|
5
|
+
let attributes = [...el.attributes].map(att=>att.name);
|
|
5
6
|
|
|
6
7
|
let atts={};
|
|
7
8
|
attributes.forEach(att=>{
|
|
8
|
-
let value = normalizeUnits(att.nodeValue, {x, y, width, height});
|
|
9
|
-
|
|
9
|
+
//let value = normalizeUnits(att.nodeValue, {x, y, width, height});
|
|
10
|
+
let value = normalizeUnits(el.getAttribute(att), {x, y, width, height});
|
|
11
|
+
atts[att] = value
|
|
10
12
|
})
|
|
11
13
|
|
|
12
14
|
return atts
|