From 433dcefd646edba35b015fc4f567077a79d1d8ee Mon Sep 17 00:00:00 2001 From: Seth Falco Date: Thu, 28 Dec 2023 17:51:19 +0000 Subject: [PATCH] refactor(convertPaths): clean up plugin (#1913) --- plugins/convertPathData.js | 125 +++++++++++-------------------------- 1 file changed, 36 insertions(+), 89 deletions(-) diff --git a/plugins/convertPathData.js b/plugins/convertPathData.js index 0ee7824ea..e8d8350e1 100644 --- a/plugins/convertPathData.js +++ b/plugins/convertPathData.js @@ -15,25 +15,15 @@ exports.name = 'convertPathData'; exports.description = 'optimizes path data: writes in shorter form, applies transformations'; -/** - * @type {(data: number[]) => number[]} - */ +/** @type {(data: number[]) => number[]} */ let roundData; -/** - * @type {number | false} - */ +/** @type {number | false} */ let precision; -/** - * @type {number} - */ +/** @type {number} */ let error; -/** - * @type {number} - */ +/** @type {number} */ let arcThreshold; -/** - * @type {number} - */ +/** @type {number} */ let arcTolerance; /** @@ -393,16 +383,17 @@ function filters( params, { isSafeToUseZ, maybeHasStrokeAndLinecap, hasMarkerMid }, ) { - var stringify = data2Path.bind(null, params), - relSubpoint = [0, 0], - pathBase = [0, 0], - prev = {}; + const stringify = data2Path.bind(null, params); + const relSubpoint = [0, 0]; + const pathBase = [0, 0]; + /** @type {any} */ + let prev = {}; /** @type {Point | undefined} */ - let qControlPoint; + let prevQControlPoint; path = path.filter(function (item, index, path) { - const qPoint = qControlPoint; - qControlPoint = undefined; + const qControlPoint = prevQControlPoint; + prevQControlPoint = undefined; let command = item.command; let data = item.args; @@ -415,9 +406,8 @@ function filters( if (command === 's') { sdata = [0, 0].concat(data); - // @ts-ignore - var pdata = prev.args, - n = pdata.length; + const pdata = prev.args; + const n = pdata.length; // (-x, -y) of the prev tangent point relative to the current point sdata[0] = pdata[n - 2] - pdata[n - 4]; @@ -464,16 +454,11 @@ function filters( nextLonghand; if ( - // @ts-ignore (prev.command == 'c' && - // @ts-ignore isConvex(prev.args) && - // @ts-ignore isArcPrev(prev.args, circle)) || - // @ts-ignore (prev.command == 'a' && prev.sdata && isArcPrev(prev.sdata, circle)) ) { - // @ts-ignore arcCurves.unshift(prev); // @ts-ignore arc.base = prev.base; @@ -481,7 +466,6 @@ function filters( arc.args[5] = arc.coords[0] - arc.base[0]; // @ts-ignore arc.args[6] = arc.coords[1] - arc.base[1]; - // @ts-ignore var prevData = prev.command == 'a' ? prev.sdata : prev.args; var prevAngle = findArcAngle(prevData, { center: [ @@ -498,7 +482,7 @@ function filters( // check if next curves are fitting the arc for ( var j = index; - (next = path[++j]) && ~'cs'.indexOf(next.command); + (next = path[++j]) && 'cs'.includes(next.command); ) { var nextData = next.args; @@ -574,7 +558,6 @@ function filters( relSubpoint[0] += prevArc.args[5] - prev.args[prev.args.length - 2]; // @ts-ignore relSubpoint[1] += prevArc.args[6] - prev.args[prev.args.length - 1]; - // @ts-ignore prev.command = 'a'; // @ts-ignore prev.args = prevArc.args; @@ -588,11 +571,7 @@ function filters( item.sdata = sdata.slice(); // preserve curve data for future checks } else if (arcCurves.length - 1 - hasPrev > 0) { // filter out consumed next items - path.splice.apply( - path, - // @ts-ignore - [index + 1, arcCurves.length - 1 - hasPrev].concat(output), - ); + path.splice(index + 1, arcCurves.length - 1 - hasPrev, ...output); } if (!arc) return false; command = 'a'; @@ -679,9 +658,7 @@ function filters( data = data.slice(-2); } else if ( command === 't' && - // @ts-ignore prev.command !== 'q' && - // @ts-ignore prev.command !== 't' ) { command = 'l'; @@ -716,39 +693,29 @@ function filters( params.collapseRepeated && hasMarkerMid === false && (command === 'm' || command === 'h' || command === 'v') && - // @ts-ignore prev.command && - // @ts-ignore command == prev.command.toLowerCase() && ((command != 'h' && command != 'v') || - // @ts-ignore prev.args[0] >= 0 == data[0] >= 0) ) { - // @ts-ignore prev.args[0] += data[0]; if (command != 'h' && command != 'v') { - // @ts-ignore prev.args[1] += data[1]; } // @ts-ignore prev.coords = item.coords; - // @ts-ignore path[index] = prev; return false; } // convert curves into smooth shorthands - // @ts-ignore if (params.curveSmoothShorthands && prev.command) { // curveto if (command === 'c') { // c + c → c + s if ( - // @ts-ignore prev.command === 'c' && - // @ts-ignore Math.abs(data[0] - -(prev.args[2] - prev.args[4])) < error && - // @ts-ignore Math.abs(data[1] - -(prev.args[3] - prev.args[5])) < error ) { command = 's'; @@ -757,11 +724,8 @@ function filters( // s + c → s + s else if ( - // @ts-ignore prev.command === 's' && - // @ts-ignore Math.abs(data[0] - -(prev.args[0] - prev.args[2])) < error && - // @ts-ignore Math.abs(data[1] - -(prev.args[1] - prev.args[3])) < error ) { command = 's'; @@ -770,9 +734,7 @@ function filters( // [^cs] + c → [^cs] + s else if ( - // @ts-ignore prev.command !== 'c' && - // @ts-ignore prev.command !== 's' && Math.abs(data[0]) < error && Math.abs(data[1]) < error @@ -786,11 +748,8 @@ function filters( else if (command === 'q') { // q + q → q + t if ( - // @ts-ignore prev.command === 'q' && - // @ts-ignore Math.abs(data[0] - (prev.args[2] - prev.args[0])) < error && - // @ts-ignore Math.abs(data[1] - (prev.args[3] - prev.args[1])) < error ) { command = 't'; @@ -798,12 +757,13 @@ function filters( } // t + q → t + t - else if ( - // @ts-ignore - prev.command === 't' - ) { - // @ts-ignore - const predictedControlPoint = reflectPoint(qPoint, item.base); + else if (prev.command === 't') { + const predictedControlPoint = reflectPoint( + // @ts-ignore + qControlPoint, + // @ts-ignore + item.base, + ); const realControlPoint = [ // @ts-ignore data[0] + item.base[0], @@ -837,14 +797,12 @@ function filters( return i === 0; }) ) { - // @ts-ignore path[index] = prev; return false; } // a 25,25 -30 0,1 0,0 if (command === 'a' && data[5] === 0 && data[6] === 0) { - // @ts-ignore path[index] = prev; return false; } @@ -874,7 +832,6 @@ function filters( // z resets coordinates relSubpoint[0] = pathBase[0]; relSubpoint[1] = pathBase[1]; - // @ts-ignore if (prev.command === 'Z' || prev.command === 'z') return false; } if ( @@ -890,14 +847,14 @@ function filters( if (command === 'q') { // @ts-ignore - qControlPoint = [data[0] + item.base[0], data[1] + item.base[1]]; + prevQControlPoint = [data[0] + item.base[0], data[1] + item.base[1]]; } else if (command === 't') { - if (qPoint) { + if (qControlPoint) { // @ts-ignore - qControlPoint = reflectPoint(qPoint, item.base); + prevQControlPoint = reflectPoint(qControlPoint, item.base); } else { // @ts-ignore - qControlPoint = item.coords; + prevQControlPoint = item.coords; } } prev = item; @@ -971,8 +928,9 @@ function convertToMixed(path, params) { prev.command.charCodeAt(0) > 96 && absoluteDataStr.length == relativeDataStr.length - 1 && (data[0] < 0 || - // @ts-ignore - (/^0\./.test(data[0]) && prev.args[prev.args.length - 1] % 1)) + (Math.floor(data[0]) === 0 && + !Number.isInteger(data[0]) && + prev.args[prev.args.length - 1] % 1)) )) ) { // @ts-ignore @@ -981,7 +939,6 @@ function convertToMixed(path, params) { } prev = item; - return true; }); @@ -1098,7 +1055,6 @@ function round(data) { * * @type {(data: number[]) => boolean} */ - function isCurveStraightLine(data) { // Get line equation a·x + b·y + c = 0 coefficients a, b (c = 0) by start and end points. var i = data.length - 2, @@ -1125,7 +1081,6 @@ function isCurveStraightLine(data) { */ function calculateSagitta(data) { if (data[3] === 1) return undefined; - const [rx, ry] = data; if (Math.abs(rx - ry) > error) return undefined; const chord = Math.sqrt(data[5] ** 2 + data[6] ** 2); @@ -1138,7 +1093,6 @@ function calculateSagitta(data) { * * @type {(item: PathDataItem, data: number[]) => PathDataItem} */ - function makeLonghand(item, data) { switch (item.command) { case 's': @@ -1160,20 +1114,19 @@ function makeLonghand(item, data) { * * @type {(point1: Point, point2: Point) => number} */ - function getDistance(point1, point2) { - return Math.hypot(point1[0] - point2[0], point1[1] - point2[1]); + return Math.sqrt((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2); } /** - * Reflects point across another point + * Reflects point across another point. * - * @param {Point} input + * @param {Point} controlPoint * @param {Point} base * @returns {Point} */ -function reflectPoint(input, base) { - return [2 * base[0] - input[0], 2 * base[1] - input[1]]; +function reflectPoint(controlPoint, base) { + return [2 * base[0] - controlPoint[0], 2 * base[1] - controlPoint[1]]; } /** @@ -1183,7 +1136,6 @@ function reflectPoint(input, base) { * * @type {(curve: number[], t: number) => Point} */ - function getCubicBezierPoint(curve, t) { var sqrT = t * t, cubT = sqrT * t, @@ -1201,7 +1153,6 @@ function getCubicBezierPoint(curve, t) { * * @type {(curve: number[]) => undefined | Circle} */ - function findCircle(curve) { var midPoint = getCubicBezierPoint(curve, 1 / 2), m1 = [midPoint[0] / 2, midPoint[1] / 2], @@ -1242,7 +1193,6 @@ function findCircle(curve) { * * @type {(curve: number[], circle: Circle) => boolean} */ - function isArc(curve, circle) { var tolerance = Math.min( arcThreshold * error, @@ -1264,7 +1214,6 @@ function isArc(curve, circle) { * * @type {(curve: number[], circle: Circle) => boolean} */ - function isArcPrev(curve, circle) { return isArc(curve, { center: [circle.center[0] + curve[4], circle.center[1] + curve[5]], @@ -1277,7 +1226,6 @@ function isArcPrev(curve, circle) { * @type {(curve: number[], relCircle: Circle) => number} */ - function findArcAngle(curve, relCircle) { var x1 = -relCircle.center[0], y1 = -relCircle.center[1], @@ -1294,7 +1242,6 @@ function findArcAngle(curve, relCircle) { * * @type {(params: InternalParams, pathData: PathDataItem[]) => string} */ - function data2Path(params, pathData) { return pathData.reduce(function (pathString, item) { var strData = '';