From 5683e6ac61b18a9e5bd2b9f4de525701fa99356f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar?= Date: Wed, 13 Mar 2024 01:11:47 +0100 Subject: [PATCH] =?UTF-8?q?Fix=20error=20computing=20some=20quadratic=20B?= =?UTF-8?q?=C3=A9zier=20curves=20cases=20(#115)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 35 +++++++++---------- ...update-copyright-years-in-license-file.yml | 2 +- CHANGELOG.md | 4 +++ README.md | 4 +-- dist/index.js | 2 +- lib/index.template.ts | 2 +- package-lock.json | 22 ++++++------ package.json | 6 ++-- src/index.ts | 2 +- tests/cases/bbox.ts | 22 +++++++----- 10 files changed, 55 insertions(+), 46 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fea411e..91a11d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,11 +15,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [14.x, 16.x, 18.x] + node-version: [18.x, 20.x] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Use NodeJS v${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - name: Install @@ -29,20 +29,20 @@ jobs: - name: Test run: npm test - name: Coverage - uses: coverallsapp/github-action@v1.1.2 + uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ./tests/coverage/lcov.info + file: ./tests/coverage/lcov.info lint: name: Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Use NodeJS v16 - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - name: Use NodeJS v20 + uses: actions/setup-node@v4 with: - node-version: 16.x + node-version: 20.x - name: Install run: npm ci - name: Lint @@ -57,11 +57,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 - - name: Use NodeJS v16 - uses: actions/setup-node@v3 + uses: actions/checkout@v4 + - name: Use NodeJS v20 + uses: actions/setup-node@v4 with: - node-version: 16.x + node-version: 20.x - name: Install dependencies run: npm ci - name: Build @@ -69,7 +69,7 @@ jobs: - name: Test run: npm test - name: Deploy to NPM - uses: JS-DevTools/npm-publish@v1.4.3 + uses: JS-DevTools/npm-publish@v3 with: token: ${{ secrets.NPM_TOKEN }} @@ -78,7 +78,7 @@ jobs: needs: npm runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get tag metadata id: tag run: | @@ -93,11 +93,10 @@ jobs: TAG_BODY="${TAG_BODY//$'\r'/'%0D'}" echo ::set-output name=body::$TAG_BODY - name: Create Release - uses: actions/create-release@v1.1.4 - id: create-release + uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.tag.outputs.title }} - release_name: ${{ steps.tag.outputs.title }} + name: ${{ steps.tag.outputs.title }} body: ${{ steps.tag.outputs.body }} draft: false prerelease: false diff --git a/.github/workflows/update-copyright-years-in-license-file.yml b/.github/workflows/update-copyright-years-in-license-file.yml index de7f25a..c6ee7e4 100644 --- a/.github/workflows/update-copyright-years-in-license-file.yml +++ b/.github/workflows/update-copyright-years-in-license-file.yml @@ -9,7 +9,7 @@ jobs: action-update-license-year: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: FantasticFiasco/action-update-license-year@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index ec946cc..8881ca7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 1.2.5 - 2024-03-13 + +- Fixed error computing some quadratic Bézier curves cases. + ## 1.2.4 - 2023-02-09 - Optimized proccesing of segments based on [Simple Icons] data. diff --git a/README.md b/README.md index 0fefbb6..1099713 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ SVG paths bounding box calculator. ## Install -``` +```sh npm install svg-path-bbox ``` @@ -58,7 +58,7 @@ console.log(svgPathBbox(cases[0])); ### Reference -# svgPathBbox(d : string) ⇒ [minX: number, minY: number, maxX: number, maxY: number] +# **svgPathBbox**(d : _string_) ⇒ [minX: _number_, minY: _number_, maxX: _number_, maxY: _number_] Computes the bounding box of SVG path following the [SVG 1.1 specification](https://www.w3.org/TR/SVG/paths.html). diff --git a/dist/index.js b/dist/index.js index cdb2933..e9821e4 100644 --- a/dist/index.js +++ b/dist/index.js @@ -7,7 +7,7 @@ var CBEZIER_MINMAX_EPSILON = 0.00000001; // https://github.com/kpym/SVGPathy/blob/acd1a50c626b36d81969f6e98e8602e128ba4302/lib/box.js#L89 function minmaxQ(A) { var min = Math.min(A[0], A[2]), max = Math.max(A[0], A[2]); - if (A[1] > A[0] ? A[2] >= A[1] : A[2] <= A[1]) { + if (A[1] >= A[0] ? A[2] >= A[1] : A[2] <= A[1]) { // if no extremum in ]0,1[ return [min, max]; } diff --git a/lib/index.template.ts b/lib/index.template.ts index 0815b77..0450bf8 100644 --- a/lib/index.template.ts +++ b/lib/index.template.ts @@ -13,7 +13,7 @@ function minmaxQ(A: [number, number, number]): minMax { const min = Math.min(A[0], A[2]), max = Math.max(A[0], A[2]); - if (A[1] > A[0] ? A[2] >= A[1] : A[2] <= A[1]) { + if (A[1] >= A[0] ? A[2] >= A[1] : A[2] <= A[1]) { // if no extremum in ]0,1[ return [min, max]; } diff --git a/package-lock.json b/package-lock.json index bb463a3..f81a1a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "svg-path-bbox", - "version": "1.2.4", + "version": "1.2.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "svg-path-bbox", - "version": "1.2.4", + "version": "1.2.5", "license": "BSD-3-Clause", "dependencies": { "svgpath": "^2.2.0" @@ -26,7 +26,7 @@ "eslint": "8.15.0", "eslint-config-prettier": "8.5.0", "eslint-plugin-prettier": "4.0.0", - "husky": "8.0.1", + "husky": "9.0.11", "is-ci": "3.0.1", "jest": "28.1.0", "jest-puppeteer": "6.1.0", @@ -4521,15 +4521,15 @@ } }, "node_modules/husky": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "dev": true, "bin": { - "husky": "lib/bin.js" + "husky": "bin.mjs" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" @@ -12686,9 +12686,9 @@ "dev": true }, "husky": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "dev": true }, "ieee754": { diff --git a/package.json b/package.json index f7d785d..b2bed13 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svg-path-bbox", - "version": "1.2.4", + "version": "1.2.5", "description": "Compute bounding boxes of SVG paths.", "keywords": [ "svg", @@ -32,7 +32,7 @@ "dist:create": "mkdir dist", "dist:clean": "rimraf dist", "test": "jest", - "prepare": "is-ci || husky install" + "prepare": "is-ci || husky" }, "author": { "name": "Álvaro Mondéjar Rubio", @@ -55,7 +55,7 @@ "eslint": "8.15.0", "eslint-config-prettier": "8.5.0", "eslint-plugin-prettier": "4.0.0", - "husky": "8.0.1", + "husky": "9.0.11", "is-ci": "3.0.1", "jest": "28.1.0", "jest-puppeteer": "6.1.0", diff --git a/src/index.ts b/src/index.ts index 865bdfb..b5164e3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,7 +15,7 @@ function minmaxQ(A: [number, number, number]): minMax { const min = Math.min(A[0], A[2]), max = Math.max(A[0], A[2]); - if (A[1] > A[0] ? A[2] >= A[1] : A[2] <= A[1]) { + if (A[1] >= A[0] ? A[2] >= A[1] : A[2] <= A[1]) { // if no extremum in ]0,1[ return [min, max]; } diff --git a/tests/cases/bbox.ts b/tests/cases/bbox.ts index 1680816..e20f340 100644 --- a/tests/cases/bbox.ts +++ b/tests/cases/bbox.ts @@ -65,13 +65,13 @@ export const pathologicalCases: CasesTuple = [ [ // Microsoft Excel "M23 1.5q.41 0 .7.3.3.29.3.7v19q0 .41-.3.7-.29.3-.7.3H7q-.41 0-.7-.3-.3-.29-.3-.7V18H1q-.41 0-.7-.3-.3-.29-.3-.7V7q0-.41.3-.7Q.58 6 1 6h5V2.5q0-.41.3-.7.29-.3.7-.3zM6 13.28l1.42 2.66h2.14l-2.38-3.87 2.34-3.8H7.46l-1.3 2.4-.05.08-.04.09-.64-1.28-.66-1.29H2.59l2.27 3.82-2.48 3.85h2.16zM14.25 21v-3H7.5v3zm0-4.5v-3.75H12v3.75zm0-5.25V7.5H12v3.75zm0-5.25V3H7.5v3zm8.25 15v-3h-6.75v3zm0-4.5v-3.75h-6.75v3.75zm0-5.25V7.5h-6.75v3.75zm0-5.25V3h-6.75v3Z", - [5.551115123125783e-17, 1.5, 24, 22.5], - // svg-path-bounding-box: [ 5.551115123125783e-17, 1.5, 24, 22.769499273762435 ] + [5.551115123125783e-17, 1.5, 24.000000000000096, 22.5], + // svg-path-bounding-box (outdated): [ 5.551115123125783e-17, 1.5, 24, 22.769499273762435 ] ], [ // Microsoft Exchange "M24 7.875q0 .293-.117.58t-.317.486L20.496 12l3.07 3.059q.2.199.317.486.117.287.117.58V21q0 .316-.117.586-.117.27-.322.475-.206.205-.475.322-.27.117-.586.117h-4.875q-.293 0-.58-.117t-.486-.317l-3.059-3.07-3.059 3.07q-.199.2-.486.317-.287.117-.58.117H4.5q-.316 0-.586-.117-.27-.117-.475-.322-.205-.206-.322-.475Q3 21.316 3 21v-3H.996q-.41 0-.703-.293T0 17.004V6.996q0-.41.293-.703T.996 6H3V3q0-.316.117-.586.117-.27.322-.475.206-.205.475-.322.27-.117.586-.117h4.875q.293 0 .58.117t.486.317l3.059 3.07 3.059-3.07q.199-.2.486-.317.287-.117.58-.117H22.5q.316 0 .586.117.27.117.475.322.205.206.322.475Q24 2.684 24 3zM4.5 3v3h6.504q.41 0 .703.293t.293.703V5.625L9.375 3zM3.375 15.938h5.25v-1.583h-3.41v-1.593h3.047V11.18H5.215V9.656H8.46V8.062H3.375zm19.125.187L19.875 13.5h-3.691q-.247 0-.463.094-.217.094-.375.252-.159.158-.252.375-.094.216-.094.463v3.691L17.625 21H22.5zm0-8.25V3h-4.875L13.5 7.125v2.191q0 .774-.404 1.424-.405.65-1.096.99v5.274q0 .41-.293.703t-.703.293H4.5v3h4.875l4.125-4.125v-2.191q0-.563.21-1.05.212-.486.575-.849t.85-.574Q15.62 12 16.184 12h2.191Z", - [0, 1.4999999999999962, 24, 22.5], + [0, 1.4999999999999998, 24, 22.5], // svg-path-bouding-box: [ 0, 1.4999999999999998, 24, 22.67233909145166 ] ], [ @@ -83,22 +83,22 @@ export const pathologicalCases: CasesTuple = [ [ // Microsoft OneNote "M23 1.5Q23.41 1.5 23.7 1.8 24 2.09 24 2.5V21.5Q24 21.91 23.7 22.2 23.41 22.5 23 22.5H7Q6.59 22.5 6.3 22.2 6 21.91 6 21.5V18H1Q0.59 18 0.3 17.7 0 17.41 0 17V7Q0 6.59 0.3 6.3 0.58 6 1 6H6V2.5Q6 2.09 6.3 1.8 6.59 1.5 7 1.5ZM4.56 11 7.39 15.93H9.18V8.07H7.44V13.1L4.71 8.07H2.82V15.93H4.56ZM22.5 21V18H19.5V21ZM22.5 16.5V13.5H19.5V16.5ZM22.5 12V9H19.5V12ZM22.5 7.5V3H7.5V6H11Q11.41 6 11.7 6.3 12 6.59 12 7V17Q12 17.41 11.7 17.7 11.41 18 11 18H7.5V21H18V7.5Z", - [0, 1.5, 24, 22.5], - // svg-path-bounding-box: [ 0, 1.5, 24, 22.769499273762435 ] + [0, 1.5, 24.000000000000096, 22.5], + // svg-path-bounding-box (outdated): [ 0, 1.5, 24, 22.769499273762435 ] ], [ // Microsoft Outlook "M7.88 12.04q0 .45-.11.87-.1.41-.33.74-.22.33-.58.52-.37.2-.87.2t-.85-.2q-.35-.21-.57-.55-.22-.33-.33-.75-.1-.42-.1-.86t.1-.87q.1-.43.34-.76.22-.34.59-.54.36-.2.87-.2t.86.2q.35.21.57.55.22.34.31.77.1.43.1.88zM24 12v9.38q0 .46-.33.8-.33.32-.8.32H7.13q-.46 0-.8-.33-.32-.33-.32-.8V18H1q-.41 0-.7-.3-.3-.29-.3-.7V7q0-.41.3-.7Q.58 6 1 6h6.5V2.55q0-.44.3-.75.3-.3.75-.3h12.9q.44 0 .75.3.3.3.3.75V10.85l1.24.72h.01q.1.07.18.18.07.12.07.25zm-6-8.25v3h3v-3zm0 4.5v3h3v-3zm0 4.5v1.83l3.05-1.83zm-5.25-9v3h3.75v-3zm0 4.5v3h3.75v-3zm0 4.5v2.03l2.41 1.5 1.34-.8v-2.73zM9 3.75V6h2l.13.01.12.04v-2.3zM5.98 15.98q.9 0 1.6-.3.7-.32 1.19-.86.48-.55.73-1.28.25-.74.25-1.61 0-.83-.25-1.55-.24-.71-.71-1.24t-1.15-.83q-.68-.3-1.55-.3-.92 0-1.64.3-.71.3-1.2.85-.5.54-.75 1.3-.25.74-.25 1.63 0 .85.26 1.56.26.72.74 1.23.48.52 1.17.81.69.3 1.56.3zM7.5 21h12.39L12 16.08V17q0 .41-.3.7-.29.3-.7.3H7.5zm15-.13v-7.24l-5.9 3.54Z", [ - 5.551115123125783e-17, 1.499999999999999, 24.000000000000004, + 5.551115123125783e-17, 1.4999999999999998, 24.000000000000004, 22.500000000000004, ], - // svg-path-bounding-box: [ 5.551115123125783e-17, 1.4999999999999998, 24.000000000000004, 22.727227619294418 ] + // svg-path-bounding-box: [ 5.551115123125783e-17, 1.499999999999999, 24.000000000000004, 22.727227619294418 ] ], [ // Microsoft Word "M23.004 1.5q.41 0 .703.293t.293.703v19.008q0 .41-.293.703t-.703.293H6.996q-.41 0-.703-.293T6 21.504V18H.996q-.41 0-.703-.293T0 17.004V6.996q0-.41.293-.703T.996 6H6V2.496q0-.41.293-.703t.703-.293zM6.035 11.203l1.442 4.735h1.64l1.57-7.876H9.036l-.937 4.653-1.325-4.5H5.38l-1.406 4.523-.938-4.675H1.312l1.57 7.874h1.641zM22.5 21v-3h-15v3zm0-4.5v-3.75H12v3.75zm0-5.25V7.5H12v3.75zm0-5.25V3h-15v3Z", - [0, 1.4999999999999996, 24, 22.499999999999996], + [0, 1.5, 24, 22.499999999999996], // svg-path-bounding-box: [ 0, 1.5, 24, 22.772661142370712 ] ], [ @@ -165,6 +165,12 @@ export const pathologicalCases: CasesTuple = [ [0.17800000000000005, -0.00016249501660449533, 23.82066666666666, 24], // svg-path-bounding-box: [ 0.17800000000000005, -0.00016249501660449477, 23.82066666666666, 24 ] ], + + // https://github.com/mondeja/svg-path-bbox/issues/112 + ["M90 100Q109 100 110 110L100 90", [90, 90, 110, 110]], + ["M90 100Q101 100 110 110L100 90", [90, 90, 110, 110]], + ["M90 100Q90 110 110 110L100 90", [90, 90, 110, 110]], + // svg-path-bounding-box: [ 90, 90, 110, 110 ] ]; export default [...linealCases, ...pathologicalCases];