svg-path-simplify 0.0.7 → 0.0.9

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 (38) hide show
  1. package/README.md +25 -5
  2. package/dist/svg-path-simplify.esm.js +1250 -562
  3. package/dist/svg-path-simplify.esm.min.js +1 -1
  4. package/dist/svg-path-simplify.js +4756 -4068
  5. package/dist/svg-path-simplify.min.js +1 -1
  6. package/dist/svg-path-simplify.node.js +1250 -562
  7. package/dist/svg-path-simplify.node.min.js +1 -1
  8. package/index.html +89 -29
  9. package/package.json +5 -3
  10. package/src/detect_input.js +17 -10
  11. package/src/dom-polyfill.js +29 -0
  12. package/src/dom-polyfill_back.js +22 -0
  13. package/src/index.js +10 -1
  14. package/src/pathData_simplify_cubic.js +114 -143
  15. package/src/pathData_simplify_cubic_extrapolate.js +64 -35
  16. package/src/pathSimplify-main.js +113 -165
  17. package/src/svgii/geometry.js +8 -155
  18. package/src/svgii/geometry_flatness.js +94 -0
  19. package/src/svgii/pathData_analyze.js +15 -596
  20. package/src/svgii/pathData_convert.js +26 -17
  21. package/src/svgii/pathData_interpolate.js +65 -0
  22. package/src/svgii/pathData_parse.js +25 -9
  23. package/src/svgii/pathData_parse_els.js +245 -0
  24. package/src/svgii/pathData_remove_collinear.js +33 -28
  25. package/src/svgii/pathData_remove_orphaned.js +21 -0
  26. package/src/svgii/pathData_remove_zerolength.js +17 -3
  27. package/src/svgii/pathData_reorder.js +9 -3
  28. package/src/svgii/pathData_simplify_refineCorners.js +160 -0
  29. package/src/svgii/pathData_simplify_refineExtremes.js +208 -0
  30. package/src/svgii/pathData_split.js +43 -15
  31. package/src/svgii/pathData_stringify.js +3 -12
  32. package/src/svgii/rounding.js +35 -27
  33. package/src/svgii/svg_cleanup.js +4 -1
  34. package/testSVG.js +39 -0
  35. package/src/pathData_simplify_cubic_arr.js +0 -50
  36. package/src/svgii/simplify.js +0 -248
  37. package/src/svgii/simplify_bezier.js +0 -470
  38. package/src/svgii/simplify_linetos.js +0 -93
package/testSVG.js ADDED
@@ -0,0 +1,39 @@
1
+ // add suport for DOM manipulations
2
+ import { DOMParser, parseHTML } from 'linkedom';
3
+ //import { XMLSerializerPoly, DOMParserPoly } from 'svg-path-simplify/dom_polyfills.js';
4
+ import { svgPathSimplify } from 'svg-path-simplify';
5
+
6
+
7
+
8
+
9
+ let svgMarkup =
10
+ `<?xml version="1.0" encoding="utf-8"?>
11
+ <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
12
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
13
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100px"
14
+ height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
15
+ <g id="garamond">
16
+ <path id="path1" d="M16.2 125.7 L16.2 125.7 Q12.1 125.7 8.4 123.8 Q4.6 122 2.3 119.1 Q0 116.2 0.2 113.1 L0.2 113.1 L0.4 112.6 Q2.2 111.2 5 109.3 Q7.8 107.4 11.4 105.1 Q15 102.8 19.1 100.4 L19.1 100.4 L19.2 99.5 Q16.8 98.1 15.5 94.7 Q14.1 91.3 14.1 86.7 L14.1 86.7 Q14.1 81.1 16 75.5 Q17.9 70 21.1 65.5 Q24.2 61 28.1 58.3 Q32 55.6 35.9 55.6 L35.9 55.6 L46.1 57.2 L47.2 54.7 L47.7 54.6 L50.8 56.1 L51.6 57 Q49.2 61.4 47.6 65.1 Q45.9 68.9 45 72 Q44 75.1 43.7 77.8 L43.7 77.8 Q43.4 80.3 43.2 83.7 Q43 87.1 42.8 90.6 Q42.6 94.2 42.5 97.1 Q42.3 100.1 42.1 101.6 L42.1 101.6 Q41.7 105.1 40 108.5 Q38.2 112 35.6 115.1 Q32.9 118.2 29.7 120.6 Q26.5 123 23 124.3 Q19.5 125.7 16.2 125.7 ZM19.5 119.9 L19.5 119.9 Q25.9 119.9 30.4 115.3 Q34.9 110.7 35.9 102.7 L35.9 102.7 L38.4 82 L37.6 81.8 Q34.5 87.5 32.3 91 Q30 94.6 28 96.8 Q25.9 99 23.5 100.8 L23.5 100.8 Q20.4 103.1 16.8 105.3 Q13.2 107.6 10.7 109.4 Q8.1 111.3 8.1 112.3 L8.1 112.3 Q8.1 114 9.9 115.8 Q11.6 117.5 14.3 118.7 Q16.9 119.9 19.5 119.9 ZM24.8 92.9 L24.8 92.9 Q26.3 92.9 29 89.4 Q31.6 86 35.2 79.5 Q38.7 73.1 42.9 64.1 L42.9 64.1 Q40.9 63.1 39.1 62.4 Q37.2 61.7 35.7 61.3 Q34.1 61 32.8 61 L32.8 61 Q29.8 61 27.1 64 Q24.4 67.1 22.7 71.9 Q21 76.7 21 82 L21 82 Q21 86.3 22.2 89.6 Q23.3 92.9 24.8 92.9 Z "/>
17
+ </g>
18
+ </svg>`
19
+
20
+
21
+ /*
22
+ */
23
+ let document = new DOMParser().parseFromString(svgMarkup, 'image/svg+xml');
24
+ let svg = document.querySelector('svg');
25
+ let path = svg.querySelector('path');
26
+ let d = path.getAttribute('d')
27
+
28
+ let markup = document.toString()
29
+ markup = new XMLSerializer().serializeToString(svg)
30
+
31
+ console.log(markup);
32
+
33
+ /*
34
+ // try to simplify
35
+ let svgOpt = svgPathSimplify(svgMarkup);
36
+
37
+ // simplified pathData
38
+ console.log(svgOpt)
39
+ */
@@ -1,50 +0,0 @@
1
- import { getDistance, getSquareDistance, checkLineIntersection, pointAtT, getDistAv } from "./svgii/geometry";
2
- import { getBezierArea, getPolygonArea } from "./svgii/geometry_area";
3
- import { renderPoint } from "./svgii/visualize";
4
-
5
- export function combineCubicArray(commands = [], threshold = 0.05) {
6
-
7
-
8
- let [comF, comM, comE] = commands;
9
-
10
- commands.forEach(com => {
11
- let area = getBezierArea([com.p0, com.cp1, com.cp2, com.p], true)
12
- com.area = area
13
- })
14
-
15
- // sort by area
16
- let commandsFiltered = JSON.parse(JSON.stringify(commands)).sort((a,b)=>b.area-a.area )
17
-
18
- let comL = commandsFiltered[0]
19
-
20
- // find largest segment
21
- //let area2 = getBezierArea(comF)
22
-
23
- console.log('area1', commands, commandsFiltered);
24
-
25
- // largest segment
26
- comM = commandsFiltered[0]
27
-
28
-
29
- //let segLargest =
30
- let pt_mid = pointAtT([comM.p0, comM.cp1, comM.cp2, comM.p], 0.5, false, true)
31
-
32
- let seg1_cp2 = pt_mid.cpts[2]
33
- let seg2_cp1 = pt_mid.cpts[3]
34
- renderPoint(markers, seg1_cp2, 'orange')
35
- renderPoint(markers, seg2_cp1, 'cyan')
36
-
37
-
38
- console.log('comM', pt_mid);
39
-
40
- renderPoint(markers, comF.p0, 'green')
41
- renderPoint(markers, comL.p, 'purple')
42
- //renderPoint(markers, comE.cp2, 'orange')
43
-
44
- renderPoint(markers, pt_mid, 'magenta')
45
- //let ptI_1 = checkLineIntersection(comF)
46
-
47
-
48
- return commands;
49
- }
50
-
@@ -1,248 +0,0 @@
1
-
2
- /**
3
- * split path data into chunks
4
- * to detect subsequent cubic segments
5
- * that could be combined
6
- */
7
-
8
- //import { splitSubpaths, shiftSvgStartingPoint } from "./convert_segments";
9
- import { shiftSvgStartingPoint } from "./pathData_reorder.js";
10
- import { splitSubpaths, getPathDataPlusChunks } from './pathData_split.js';
11
-
12
- import { getAngle, bezierhasExtreme, getPathDataVertices } from "./geometry";
13
- import { renderPoint, renderPath } from "./visualize";
14
-
15
-
16
- //import { optimizeStartingPoints } from './cleanup.js';
17
- //import { getPathDataVertices, getPointOnEllipse, pointAtT, checkLineIntersection, getDistance, interpolate } from './geometry.js';
18
-
19
- import { getPolygonArea, getPathArea, getRelativeAreaDiff } from './geometry_area.js';
20
- import { getPathDataBBox, getPolyBBox } from './geometry_bbox.js';
21
-
22
- import { optimizeStartingPoints, cleanUpPathData } from './pathdata_cleanup.js';
23
-
24
- import { pathDataArcsToCubics, pathDataQuadraticToCubic, quadratic2Cubic, pathDataToRelative, pathDataToAbsolute, pathDataToLonghands, pathDataToShorthands, pathDataToQuadratic, cubicToQuad, arcToBezier, pathDataToVerbose, convertArrayPathData, revertPathDataToArray, combineArcs, replaceCubicsByArcs } from './pathData_convert.js';
25
-
26
- import {unitePolygon} from './simplify_polygon.js';
27
-
28
- import { simplifyBezierSequence } from './simplify_bezier.js';
29
- //import { simplifyBezierSequence } from './simplify_bezier_back16_working.js';
30
- //import { simplifyBezierSequence } from './simplify_bezier_back17_working.js';
31
-
32
-
33
-
34
- import { simplifyLinetoSequence } from './simplify_linetos.js';
35
- import { analyzePathData } from "./pathData_anylyse.js";
36
- import { scalePathData } from "./pathData_scale.js";
37
- //import { analyzePathData } from "./pathData_anylyse_back1.js";
38
-
39
-
40
-
41
- export function simplifyPathData(pathData, tolerance = 3, keepDetails = true, forceCubic = false, cubicToArc = true, multipass = false, debug = false) {
42
-
43
- ///devcomment
44
-
45
- //console.log('forceCubic simplifyPathData', forceCubic);
46
-
47
- // unoptimized area
48
- let area0 = getPathArea(pathData);
49
-
50
- // get bbox for adjustment scaling
51
- let bb = getPathDataBBox(pathData);
52
- //console.log('bb', bb);
53
-
54
- let dimA = (bb.width + bb.height) / 2;
55
- let scale = dimA < 10 ? 100 / dimA : 1;
56
-
57
- // scale small paths
58
- if (scale != 1) pathData = scalePathData(pathData, scale, scale)
59
-
60
- // remove zero length commands and shift starting point
61
- let addExtremes = true;
62
- addExtremes = false;
63
-
64
- let removeFinalLineto = false
65
- let startToTop = true;
66
- //tolerance = 5;
67
-
68
- // show chunks
69
- //debug = true
70
-
71
- /**
72
- * optimize starting point
73
- * remove zero length segments
74
- */
75
- pathData = cleanUpPathData(pathData, addExtremes, removeFinalLineto, startToTop, debug)
76
-
77
-
78
- // get verbose pathdata properties
79
- let pathDataPlus = analyzePathData(pathData);
80
-
81
- // add chunks to path object
82
- let pathDataPlusChunks = getPathDataPlusChunks(pathDataPlus, debug);
83
-
84
- // create simplified pathData
85
- let pathDataSimple = [];
86
-
87
- // loop sup path
88
- for (let s = 0, l = pathDataPlusChunks.length; l && s < l; s++) {
89
- let sub = pathDataPlusChunks[s];
90
- let { chunks, dimA, area } = sub;
91
-
92
- let thresh = dimA * 0.1
93
- let len = chunks.length;
94
- let simplified;
95
- //console.log('sub', chunks);
96
-
97
- //forceCubic = true
98
-
99
- for (let i = 0; i < len; i++) {
100
- let chunk = chunks[i];
101
- let type = chunk[0].type;
102
-
103
- // try to convert cubic to quadratic
104
-
105
- //forceCubic = true
106
-
107
- if (!forceCubic && chunk.length === 1 && type === 'C') {
108
- simplified = simplifyBezierSequence(chunk);
109
- pathDataSimple.push(...simplified);
110
- //console.log('simplified cubic to quadratic', simplified);
111
- continue;
112
- }
113
-
114
- // nothing to combine
115
- if (chunk.length < 2) {
116
- pathDataSimple.push(...chunk);
117
- //console.log('simple',chunk );
118
- continue;
119
- }
120
-
121
- // simplify linetos
122
- if (type === 'L' && chunk.length > 1) {
123
- //simplified = simplifyLinetoSequence(chunk, thresh);
124
- //console.log('lineto');
125
- simplified = simplifyLinetoSequence(chunk);
126
- pathDataSimple.push(...simplified);
127
- }
128
-
129
- // Béziers
130
- else if (chunk.length > 1 && (type === 'C' || type === 'Q')) {
131
- //console.log('hasCubics');
132
- if (chunk.length) {
133
-
134
- multipass = false
135
- //multipass = true
136
-
137
- let directionChange = chunk[0].directionChange;
138
- //directionChange = false
139
-
140
- /**
141
- * prevent too aggressive simplification
142
- * e.g for quadratic glyphs
143
- * by splitting large chunks in two
144
- */
145
- //keepDetails = false
146
-
147
- //(directionChange && chunk.length > 4) || (!directionChange && chunk.length > 4)
148
- if (keepDetails && (chunk.length > 4) && !multipass) {
149
- let split = Math.ceil((chunk.length - 1) / 2)
150
- let chunk1 = chunk.slice(0, split)
151
- let chunk2 = chunk.slice(split)
152
- //console.log('chunk:', chunk);
153
- //renderPoint(svg1,chunk[0].p0, 'magenta' )
154
-
155
- //console.log('forceCubic keepDetails', forceCubic);
156
- let simplified1 = simplifyBezierSequence(chunk1, tolerance, keepDetails, forceCubic);
157
- let simplified2 = simplifyBezierSequence(chunk2, tolerance, keepDetails, forceCubic);
158
-
159
- pathDataSimple.push(...simplified1, ...simplified2);
160
- }
161
-
162
- else {
163
- simplified = simplifyBezierSequence(chunk, tolerance, keepDetails, forceCubic);
164
- pathDataSimple.push(...simplified);
165
- }
166
- }
167
- }
168
-
169
- // No match, keep original commands
170
- else {
171
- //chunk.forEach(com => pathDataSimple.push({ type: com.type, values: com.values }));
172
- pathDataSimple.push(...chunk);
173
- }
174
- }
175
- }
176
-
177
-
178
- /**
179
- * try to replace cubics
180
- * to arcs
181
- */
182
- //cubicToArc = false;
183
- if (cubicToArc) {
184
- //console.log();
185
- pathDataSimple = replaceCubicsByArcs(pathDataSimple, tolerance * 0.5);
186
-
187
- // combine adjacent arcs
188
- pathDataSimple = combineArcs(pathDataSimple);
189
-
190
- console.log('arcs', pathDataSimple);
191
- }
192
-
193
-
194
- // rescale small paths
195
- if (scale != 1) pathDataSimple = scalePathData(pathDataSimple, 1 / scale, 1 / scale)
196
-
197
-
198
- /**
199
- * final area check
200
- * fallback to original if difference is too large
201
- */
202
- /*
203
- let areaS = getPathArea(pathDataSimple);
204
- let areaDiff = getRelativeAreaDiff(area0, areaS)
205
-
206
- if (areaDiff > tolerance) {
207
- //pathDataSimple = pathData;
208
- //console.log('take original', pathDataSimple);
209
- }
210
- */
211
-
212
-
213
- /**
214
- * final optimization
215
- * simplify adjacent linetos
216
- * optimize start points
217
- * we done it before
218
- * but we need to apply this again to
219
- * avoid unnecessary close linetos
220
- */
221
-
222
- // prefer first lineto to allow implicit closing linetos by "Z"
223
- removeFinalLineto = true;
224
- startToTop = false;
225
- addExtremes = false;
226
- debug = false;
227
-
228
- pathDataSimple = cleanUpPathData(pathDataSimple, addExtremes, removeFinalLineto, startToTop, debug)
229
- console.log('pathDataSimple post', pathDataSimple);
230
-
231
- return pathDataSimple;
232
- }
233
-
234
-
235
-
236
-
237
-
238
-
239
-
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248
-