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.
Files changed (41) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +2 -1
  3. package/dist/svg-path-simplify.esm.js +1670 -509
  4. package/dist/svg-path-simplify.esm.min.js +2 -2
  5. package/dist/svg-path-simplify.js +1671 -508
  6. package/dist/svg-path-simplify.min.js +2 -2
  7. package/dist/svg-path-simplify.pathdata.esm.js +936 -463
  8. package/dist/svg-path-simplify.pathdata.esm.min.js +2 -2
  9. package/dist/svg-path-simplify.poly.cjs +9 -8
  10. package/index.html +60 -20
  11. package/package.json +1 -1
  12. package/src/constants.js +4 -0
  13. package/src/detect_input.js +47 -29
  14. package/src/index.js +8 -0
  15. package/src/pathData_simplify_cubic.js +46 -18
  16. package/src/pathData_simplify_revertToquadratics.js +0 -1
  17. package/src/pathSimplify-main.js +81 -20
  18. package/src/pathSimplify-only-pathdata.js +7 -2
  19. package/src/pathSimplify-presets.js +14 -4
  20. package/src/svg-getAttributes.js +5 -3
  21. package/src/svgii/convert_units.js +1 -1
  22. package/src/svgii/geometry.js +140 -2
  23. package/src/svgii/geometry_bbox_element.js +1 -1
  24. package/src/svgii/geometry_deduceRadius.js +116 -27
  25. package/src/svgii/geometry_length.js +18 -2
  26. package/src/svgii/pathData_analyze.js +18 -0
  27. package/src/svgii/pathData_convert.js +188 -88
  28. package/src/svgii/pathData_fix_directions.js +10 -18
  29. package/src/svgii/pathData_reorder.js +123 -16
  30. package/src/svgii/pathData_simplify_refineCorners.js +130 -35
  31. package/src/svgii/pathData_simplify_refine_round.js +420 -0
  32. package/src/svgii/poly_normalize.js +9 -8
  33. package/src/svgii/rounding.js +112 -80
  34. package/src/svgii/svg_cleanup.js +75 -22
  35. package/src/svgii/svg_cleanup_convertPathLength.js +27 -15
  36. package/src/svgii/svg_cleanup_normalize_transforms.js +1 -1
  37. package/src/svgii/svg_cleanup_remove_els_and_atts.js +6 -1
  38. package/src/svgii/svg_el_parse_style_props.js +13 -10
  39. package/src/svgii/svg_validate.js +220 -0
  40. package/tests/testSVG.js +14 -1
  41. package/src/svgii/pathData_refine_round.js +0 -222
@@ -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
- if (input instanceof HTMLImageElement) return "img";
5
- if (input instanceof SVGElement) return "svg";
6
- if (input instanceof HTMLCanvasElement) return "canvas";
7
- if (input instanceof File) return "file";
8
- if (input instanceof ArrayBuffer) return "buffer";
9
- if (input instanceof Blob) return "blob";
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
- return 'polyArray'
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
- return 'polyComplexArray'
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
- return 'polyComplexObjectArray'
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
- return 'polyObjectArray'
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
- return "pathData"
42
-
50
+ result.inputType = "pathData"
43
51
  }
44
- //console.log(input[0], typeof input[0]);
45
- return "array";
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
- type = 'svgMarkup'
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
- type = 'json'
84
+ result.inputType = 'json'
63
85
  }
64
86
 
65
87
  else if (isSymbol) {
66
- type = 'symbol'
88
+ result.inputType = 'symbol'
67
89
  }
68
90
  else if (isPathData) {
69
- type = 'pathDataString'
91
+ result.inputType = 'pathDataString'
70
92
  }
71
93
  else if (isPolyString) {
72
- type = 'polyString'
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
- type = url || dataUrl ? "url" : "string";
100
+ result.inputType = url || dataUrl ? "url" : "string";
79
101
  }
80
102
 
81
-
82
- return type
103
+ return result
83
104
  }
84
105
 
85
- type = typeof input
86
- let constructor = input.constructor.name
87
-
88
-
106
+ result.inputType = (input.constructor.name || typeof input ).toLowerCase()
89
107
 
90
- return (constructor || type).toLowerCase();
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 + 1; error < tolerance && n < l; n++) {
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 pt = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t)
149
+ let ptI = pointAtT([comS.p0, comS.cp1, comS.cp2, comS.p], t)
147
150
 
148
151
 
149
- let dist0 = getDistManhattan(com1.p, pt)
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
- // 2nd segment mid
166
- let pt_2 = pointAtT([com2.p0, com2.cp1, com2.cp2, com2.p], 0.5)
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
- //renderPoint(markers, pt_2, 'magenta')
178
- //renderPoint(markers, ptS_2, 'green', '0.5%')
181
+ // 2nd segment mid
182
+ let ptM_seg2 = pointAtT([com2.p0, com2.cp1, com2.cp2, com2.p], 0.5)
179
183
 
180
- // 1st segment mid
181
- let pt_1 = pointAtT([com1.p0, com1.cp1, com1.cp2, com1.p], 0.5)
182
-
183
- let t2 = t * 0.5;
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
@@ -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/pathData_refine_round';
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, convertPathLength, 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, scale, scaleTo, crop, alignToOrigin, convertTransforms, keepSmaller, splitCompound } = settings;
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
- let inputType = detectInputType(input);
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
- convert_rects = true
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
- let comCount = pathData.length
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) pathData = refineRoundSegments(pathData);
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
- let comCountS = pathData.length
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.2,
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
- minifyD: 0
247
+ removeOffCanvas: true,
248
+ /*
249
+ */
240
250
  }
241
251
  }
242
252
 
@@ -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
- atts[att.name] = value
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
@@ -94,7 +94,7 @@ export function normalizeUnits(value = null, {
94
94
  scale = height / 100;
95
95
  }
96
96
  else {
97
- scale = normalizedDiagonal ? scaleRoot / 100 : 1;
97
+ scale = normalizedDiagonal ? scaleRoot / 100 : width / 100;
98
98
  }
99
99
  break;
100
100