From 336112cec37e3c449ccfee65e5b1e6b0ae3b6a0d Mon Sep 17 00:00:00 2001 From: Nicolas Bachschmidt Date: Tue, 13 Feb 2024 19:10:55 +0100 Subject: [PATCH] Optionally convert rects with rounded corners to paths --- docs/03-plugins/convert-shape-to-path.mdx | 2 +- plugins/convertShapeToPath.js | 50 +++++++++++++++++----- test/plugins/convertShapeToPath.05.svg.txt | 2 + test/plugins/convertShapeToPath.06.svg.txt | 21 +++++++++ 4 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 test/plugins/convertShapeToPath.06.svg.txt diff --git a/docs/03-plugins/convert-shape-to-path.mdx b/docs/03-plugins/convert-shape-to-path.mdx index bc5139c89..37e36bfdf 100644 --- a/docs/03-plugins/convert-shape-to-path.mdx +++ b/docs/03-plugins/convert-shape-to-path.mdx @@ -5,7 +5,7 @@ svgo: defaultPlugin: true parameters: convertArcs: - description: If to convert <circle> and <ellipse> elements to paths. + description: If to convert <circle>, <ellipse>, and <rect> elements with rounded corners to paths. default: false floatPrecision: description: Number of decimal places to round to, using conventional rounding rules. diff --git a/plugins/convertShapeToPath.js b/plugins/convertShapeToPath.js index e91a0306b..a951539ed 100644 --- a/plugins/convertShapeToPath.js +++ b/plugins/convertShapeToPath.js @@ -31,34 +31,62 @@ export const fn = (root, params) => { if ( node.name === 'rect' && node.attributes.width != null && - node.attributes.height != null && - node.attributes.rx == null && - node.attributes.ry == null + node.attributes.height != null ) { const x = Number(node.attributes.x || '0'); const y = Number(node.attributes.y || '0'); const width = Number(node.attributes.width); const height = Number(node.attributes.height); + const rx = Math.min( + Number(node.attributes.rx || node.attributes.ry || '0'), + width / 2, + ); + const ry = Math.min( + Number(node.attributes.ry || node.attributes.rx || '0'), + height / 2, + ); // Values like '100%' compute to NaN, thus running after // cleanupNumericValues when 'px' units has already been removed. // TODO: Calculate sizes from % and non-px units if possible. - if (Number.isNaN(x - y + width - height)) return; + if (Number.isNaN(x - y + width - height + rx - ry)) return; /** * @type {PathDataItem[]} */ - const pathData = [ - { command: 'M', args: [x, y] }, - { command: 'H', args: [x + width] }, - { command: 'V', args: [y + height] }, - { command: 'H', args: [x] }, - { command: 'z', args: [] }, - ]; + var pathData; + if (rx == 0 || ry == 0) { + pathData = [ + { command: 'M', args: [x, y] }, + { command: 'H', args: [x + width] }, + { command: 'V', args: [y + height] }, + { command: 'H', args: [x] }, + { command: 'z', args: [] }, + ]; + } else if (convertArcs && rx > 0 && ry > 0) { + const w = width; + const h = height; + pathData = [ + { command: 'M', args: [x + rx, y] }, + { command: 'H', args: [x + w - rx] }, + { command: 'A', args: [rx, ry, 0, 0, 1, x + w, y + ry] }, + { command: 'V', args: [y + h - ry] }, + { command: 'A', args: [rx, ry, 0, 0, 1, x + w - rx, y + h] }, + { command: 'H', args: [x + rx] }, + { command: 'A', args: [rx, ry, 0, 0, 1, x, y + h - ry] }, + { command: 'V', args: [y + ry] }, + { command: 'A', args: [rx, ry, 0, 0, 1, x + rx, y] }, + { command: 'z', args: [] }, + ]; + } else { + return; + } node.name = 'path'; node.attributes.d = stringifyPathData({ pathData, precision }); delete node.attributes.x; delete node.attributes.y; delete node.attributes.width; delete node.attributes.height; + delete node.attributes.rx; + delete node.attributes.ry; } // convert line to path diff --git a/test/plugins/convertShapeToPath.05.svg.txt b/test/plugins/convertShapeToPath.05.svg.txt index 6f528646d..2fa51cebb 100644 --- a/test/plugins/convertShapeToPath.05.svg.txt +++ b/test/plugins/convertShapeToPath.05.svg.txt @@ -4,6 +4,7 @@ Precision should be applied to all converted shapes + @@ -15,6 +16,7 @@ Precision should be applied to all converted shapes + diff --git a/test/plugins/convertShapeToPath.06.svg.txt b/test/plugins/convertShapeToPath.06.svg.txt new file mode 100644 index 000000000..958ebd464 --- /dev/null +++ b/test/plugins/convertShapeToPath.06.svg.txt @@ -0,0 +1,21 @@ + + + + + + + + +@@@ + + + + + + + + + +@@@ + +{ "convertArcs": true }