From d313b8084d6f9dce5962ed64cc966cd78427d45b Mon Sep 17 00:00:00 2001 From: LongYinan Date: Thu, 26 Aug 2021 10:09:20 +0800 Subject: [PATCH] fix: transform state between save/restore --- .cargo/config.toml | 23 +- .eslintrc.yml | 2 +- .github/workflows/CI.yaml | 4 +- __test__/canvas-class.spec.ts | 3 +- __test__/regression.spec.ts | 61 +- .../transform-with-radial-gradient-x.png | Bin 0 -> 29498 bytes .../transform-with-radial-gradient.png | Bin 0 -> 17156 bytes depot_tools | 2 +- index.html | 25 +- index.js | 93 ++- package.json | 3 + pnpm-lock.yaml | 536 ++++++------ rust-toolchain | 2 +- scripts/build-skia.js | 38 +- skia | 2 +- skia-c/skia_c.cpp | 107 ++- skia-c/skia_c.hpp | 30 +- src/ctx.rs | 787 +++++++++--------- src/error.rs | 4 + src/font.rs | 10 - src/global_fonts.rs | 1 - src/gradient.rs | 38 +- src/image.rs | 1 - src/lib.rs | 41 +- src/path.rs | 181 ++-- src/pattern.rs | 2 - src/sk.rs | 373 +++++---- src/state.rs | 4 + 28 files changed, 1243 insertions(+), 1130 deletions(-) create mode 100644 __test__/snapshots/transform-with-radial-gradient-x.png create mode 100644 __test__/snapshots/transform-with-radial-gradient.png diff --git a/.cargo/config.toml b/.cargo/config.toml index fccc48ee..1d637b8d 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,18 +1,37 @@ +[target.x86_64-apple-darwin] +# ivybridge provided by Github Actions +rustflags = ["-C", "target-cpu=ivybridge"] + [target.x86_64-pc-windows-msvc] -rustflags = ["-C", "link-args=/NODEFAULTLIB:libcmt.lib"] +rustflags = ["-C", "link-args=/NODEFAULTLIB:libcmt.lib", "-C", "target-cpu=haswell"] + +[target.x86_64-unknown-linux-gnu] +rustflags = ["-C", "target-cpu=haswell"] + +[target.aarch64-apple-darwin] +rustflags = ["-C", "target-cpu=apple-a14"] [target.aarch64-unknown-linux-gnu] linker = "aarch64-linux-gnu-gcc" +rustflags = ["-C", "target-cpu=cortex-a57"] [target.armv7-unknown-linux-gnueabihf] linker = "arm-linux-gnueabihf-gcc" +rustflags = ["-C", "target-cpu=cortex-a7"] [target.x86_64-unknown-linux-musl] rustflags = [ "-C", "target-feature=-crt-static", + "-C", + "target-cpu=haswell", ] [target.aarch64-unknown-linux-musl] linker = "aarch64-linux-musl-gcc" -rustflags = ["-C", "target-feature=-crt-static"] +rustflags = [ + "-C", + "target-feature=-crt-static", + "-C", + "target-cpu=cortex-a57", +] diff --git a/.eslintrc.yml b/.eslintrc.yml index 0176dc11..7e9f4f5b 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -26,7 +26,7 @@ rules: 'space-before-function-paren': 0 'no-useless-constructor': 0 'no-undef': 2 - 'no-console': [2, { allow: ['error', 'warn', 'info', 'assert'] }] + 'no-console': [2, { allow: ['error', 'warn', 'info', 'assert', 'time', 'timeEnd'] }] 'comma-dangle': ['error', 'only-multiline'] 'no-unused-vars': 0 'no-var': 2 diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index f47bfb82..3c4a30c1 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -23,7 +23,9 @@ jobs: settings: - host: macos-latest target: 'x86_64-apple-darwin' - build: pnpm build + build: | + rustc --print target-cpus + pnpm build downloadTarget: '' - host: windows-latest build: pnpm build diff --git a/__test__/canvas-class.spec.ts b/__test__/canvas-class.spec.ts index 01bb9183..d56c4465 100644 --- a/__test__/canvas-class.spec.ts +++ b/__test__/canvas-class.spec.ts @@ -1,7 +1,8 @@ import test from 'ava' +import { omit } from 'lodash' import { createCanvas, Canvas } from '../index' test('Canvas constructor should be equal to createCanvas', (t) => { - t.deepEqual(createCanvas(200, 100), new Canvas(200, 100)) + t.deepEqual(omit(createCanvas(200, 100), 'getContext'), omit(new Canvas(200, 100), 'getContext')) }) diff --git a/__test__/regression.spec.ts b/__test__/regression.spec.ts index 7ff15290..5643e8d9 100644 --- a/__test__/regression.spec.ts +++ b/__test__/regression.spec.ts @@ -1,19 +1,8 @@ -import ava, { TestInterface } from 'ava' +import test from 'ava' -import { createCanvas, Canvas, SKRSContext2D } from '../index' +import { createCanvas } from '../index' import { snapshotImage } from './image-snapshot' -const test = ava as TestInterface<{ - canvas: Canvas - ctx: SKRSContext2D -}> - -test.beforeEach((t) => { - const canvas = createCanvas(512, 512) - t.context.canvas = canvas - t.context.ctx = canvas.getContext('2d')! -}) - test('transform-with-state', async (t) => { const canvas = createCanvas(256, 256) const ctx = canvas.getContext('2d') @@ -40,3 +29,49 @@ test('transform-with-state', async (t) => { ctx.restore() await snapshotImage(t, { canvas, ctx }) }) + +test('transform-with-radial-gradient', async (t) => { + const canvas = createCanvas(256, 256) + const ctx = canvas.getContext('2d') + ctx.translate(128.5, 128.5) + ctx.scale(1, 1) + ctx.clearRect(-128, -128, 256, 256) + ctx.beginPath() + ctx.save() + ctx.transform(1, 0, 0, 0.9090909090909091, 0, 0) + ctx.arc(0, 0, 110, 0, 6.283185307179586, false) + ctx.restore() + ctx.save() + const p = ctx.createRadialGradient(0.5, 0.5, 0, 0.2, 0.4, 0.5) + p.addColorStop(1, 'rgba(0, 0, 255, 1)') + p.addColorStop(0, 'rgba(200, 200, 200, 0)') + ctx.fillStyle = p + ctx.transform(220, 0, 0, 200, -110, -100) + ctx.transform(1, 0, 0, 1, 0, 0) + ctx.fill() + ctx.restore() + await snapshotImage(t, { canvas, ctx }) +}) + +test('transform-with-radial-gradient-x', async (t) => { + const canvas = createCanvas(400, 282) + const ctx = canvas.getContext('2d') + ctx.translate(200.5, 141.5) + ctx.scale(1, 1) + ctx.clearRect(-181.5, -128, 363, 256) + ctx.beginPath() + ctx.save() + ctx.transform(1, 0, 0, 0.5555555555555556, 0, 0) + ctx.arc(0, 0, 180, 0, 6.283185307179586, false) + ctx.restore() + ctx.save() + const p = ctx.createRadialGradient(0.5, 0.5, 0, 0.5, 0.5, 0.5) + p.addColorStop(1, 'rgba(0, 0, 255, 1)') + p.addColorStop(0, 'rgba(200, 200, 200, 0)') + ctx.fillStyle = p + ctx.transform(360, 0, 0, 200, -180, -100) + ctx.transform(1, 0, 0, 1, 0, 0) + ctx.fill() + ctx.restore() + await snapshotImage(t, { canvas, ctx }) +}) diff --git a/__test__/snapshots/transform-with-radial-gradient-x.png b/__test__/snapshots/transform-with-radial-gradient-x.png new file mode 100644 index 0000000000000000000000000000000000000000..00ba3a6f9cdd60e957c09ca79488b42a7a37821d GIT binary patch literal 29498 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[-b7BT;>nt+88VJ3(*cl- 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 literal 0 HcmV?d00001 diff --git a/depot_tools b/depot_tools index 74ef838a..984ce942 160000 --- a/depot_tools +++ b/depot_tools @@ -1 +1 @@ -Subproject commit 74ef838a40d8fecac485416f1a1fb07f9aeb6fd1 +Subproject commit 984ce942a4b1a5a559a5b07b9c0b29b228cd070d diff --git a/index.html b/index.html index 2da4b37f..dc345e77 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ + Canvas @@ -27,6 +28,7 @@ + diff --git a/index.js b/index.js index 38387af3..d420283a 100644 --- a/index.js +++ b/index.js @@ -14,6 +14,7 @@ const { loadBinding } = require('@node-rs/helper') const { CanvasRenderingContext2D, CanvasElement, + createContext, SVGCanvas, Path2D, ImageData, @@ -160,44 +161,60 @@ Path2D.prototype.getFillTypeString = function getFillTypeString() { function createCanvas(width, height, flag) { const isSvgBackend = typeof flag !== 'undefined' const canvasElement = isSvgBackend ? new SVGCanvas(width, height) : new CanvasElement(width, height) - const ctx = isSvgBackend - ? new CanvasRenderingContext2D(width, height, GlobalFontsSingleton, flag) - : new CanvasRenderingContext2D(width, height, GlobalFontsSingleton) - - // napi can not define writable: true but enumerable: false property - Object.defineProperty(ctx, '_fillStyle', { - value: '#000', - configurable: false, - enumerable: false, - writable: true, - }) - - Object.defineProperty(ctx, '_strokeStyle', { - value: '#000', - configurable: false, - enumerable: false, - writable: true, - }) - - Object.defineProperty(ctx, 'createImageData', { - value: function createImageData(widthOrImage, height) { - if (widthOrImage instanceof ImageData) { - return new ImageData(widthOrImage.width, widthOrImage.height) - } - return new ImageData(widthOrImage, height) - }, - configurable: false, - enumerable: false, - writable: false, - }) - - Object.defineProperty(canvasElement, 'ctx', { - value: ctx, - enumerable: false, - configurable: false, - }) - - ctx.canvas = canvasElement + + let ctx + canvasElement.getContext = function getContext(type, attr) { + if (type !== '2d') { + throw new Error('Unsupported type') + } + ctx = ctx + ? ctx + : isSvgBackend + ? new CanvasRenderingContext2D(this.width, this.height, GlobalFontsSingleton, flag) + : new CanvasRenderingContext2D(this.width, this.height, GlobalFontsSingleton) + if (attr) { + createContext(ctx, this.width, this.height, attr) + } else { + createContext(ctx, this.width, this.height) + } + + // napi can not define writable: true but enumerable: false property + Object.defineProperty(ctx, '_fillStyle', { + value: '#000', + configurable: false, + enumerable: false, + writable: true, + }) + + Object.defineProperty(ctx, '_strokeStyle', { + value: '#000', + configurable: false, + enumerable: false, + writable: true, + }) + + Object.defineProperty(ctx, 'createImageData', { + value: function createImageData(widthOrImage, height) { + if (widthOrImage instanceof ImageData) { + return new ImageData(widthOrImage.width, widthOrImage.height) + } + return new ImageData(widthOrImage, height) + }, + configurable: false, + enumerable: false, + writable: false, + }) + + Object.defineProperty(canvasElement, 'ctx', { + value: ctx, + enumerable: false, + configurable: false, + }) + + ctx.canvas = canvasElement + + return ctx + } return canvasElement } diff --git a/package.json b/package.json index fbc488a8..a6695080 100644 --- a/package.json +++ b/package.json @@ -69,11 +69,13 @@ "@napi-rs/cli": "^1.2.0", "@octokit/rest": "^18.9.0", "@swc-node/register": "^1.3.3", + "@types/lodash": "^4.14.172", "@typescript-eslint/eslint-plugin": "^4.29.0", "@typescript-eslint/parser": "^4.29.0", "ava": "^3.15.0", "benny": "^3.6.15", "canvas": "^2.8.0", + "canvaskit-wasm": "^0.29.0", "chalk": "^4.1.2", "conventional-changelog-cli": "^2.1.1", "eslint": "^7.32.0", @@ -83,6 +85,7 @@ "eslint-plugin-sonarjs": "^0.10.0", "husky": "^7.0.1", "lint-staged": "^11.1.2", + "lodash": "^4.17.21", "npm-run-all": "^4.1.5", "pinst": "^2.1.6", "png.js": "^0.2.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a260486f..c3806c3b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,11 +9,13 @@ specifiers: '@node-rs/helper': ^1.2.1 '@octokit/rest': ^18.9.0 '@swc-node/register': ^1.3.3 + '@types/lodash': ^4.14.172 '@typescript-eslint/eslint-plugin': ^4.29.0 '@typescript-eslint/parser': ^4.29.0 ava: ^3.15.0 benny: ^3.6.15 canvas: ^2.8.0 + canvaskit-wasm: ^0.29.0 chalk: ^4.1.2 conventional-changelog-cli: ^2.1.1 eslint: ^7.32.0 @@ -23,6 +25,7 @@ specifiers: eslint-plugin-sonarjs: ^0.10.0 husky: ^7.0.1 lint-staged: ^11.1.2 + lodash: ^4.17.21 npm-run-all: ^4.1.5 pinst: ^2.1.6 png.js: ^0.2.1 @@ -39,30 +42,33 @@ devDependencies: '@jimp/custom': 0.16.1 '@jimp/jpeg': 0.16.1_@jimp+custom@0.16.1 '@jimp/png': 0.16.1_@jimp+custom@0.16.1 - '@napi-rs/cli': 1.2.1 - '@octokit/rest': 18.10.0 - '@swc-node/register': 1.3.4 - '@typescript-eslint/eslint-plugin': 4.30.0_8a8a2d3eaa9257455a03c16dce5f55b3 - '@typescript-eslint/parser': 4.30.0_eslint@7.32.0+typescript@4.4.2 + '@napi-rs/cli': 1.2.0 + '@octokit/rest': 18.9.0 + '@swc-node/register': 1.3.3 + '@types/lodash': 4.14.172 + '@typescript-eslint/eslint-plugin': 4.29.0_48ea228fa0647506aa803d17f48b59f7 + '@typescript-eslint/parser': 4.29.0_eslint@7.32.0+typescript@4.3.5 ava: 3.15.0 benny: 3.6.15 canvas: 2.8.0 + canvaskit-wasm: 0.29.0 chalk: 4.1.2 conventional-changelog-cli: 2.1.1 eslint: 7.32.0 eslint-config-prettier: 8.3.0_eslint@7.32.0 - eslint-plugin-import: 2.24.2_eslint@7.32.0 + eslint-plugin-import: 2.23.4_eslint@7.32.0 eslint-plugin-prettier: 4.0.0_5a48a349ffec60f5257b5f148f5199c3 eslint-plugin-sonarjs: 0.10.0_eslint@7.32.0 - husky: 7.0.2 + husky: 7.0.1 lint-staged: 11.1.2 + lodash: 4.17.21 npm-run-all: 4.1.5 pinst: 2.1.6 png.js: 0.2.1 prettier: 2.3.2 putasset: 5.0.3 - skia-canvas: 0.9.25 - typescript: 4.4.2 + skia-canvas: 0.9.23 + typescript: 4.3.5 packages: @@ -108,8 +114,8 @@ packages: '@babel/highlight': 7.14.5 dev: true - /@babel/helper-validator-identifier/7.14.9: - resolution: {integrity: sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==} + /@babel/helper-validator-identifier/7.14.8: + resolution: {integrity: sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==} engines: {node: '>=6.9.0'} dev: true @@ -117,13 +123,13 @@ packages: resolution: {integrity: sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.14.9 + '@babel/helper-validator-identifier': 7.14.8 chalk: 2.4.2 js-tokens: 4.0.0 dev: true - /@babel/runtime/7.15.3: - resolution: {integrity: sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==} + /@babel/runtime/7.14.8: + resolution: {integrity: sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.13.9 @@ -143,7 +149,7 @@ packages: ajv: 6.12.6 debug: 4.3.2 espree: 7.3.1 - globals: 13.11.0 + globals: 13.10.0 ignore: 4.0.6 import-fresh: 3.3.0 js-yaml: 3.14.1 @@ -176,7 +182,7 @@ packages: /@jimp/core/0.16.1: resolution: {integrity: sha512-la7kQia31V6kQ4q1kI/uLimu8FXx7imWVajDGtwUG8fzePLWDFJyZl0fdIXVCL1JW2nBcRHidUot6jvlRDi2+g==} dependencies: - '@babel/runtime': 7.15.3 + '@babel/runtime': 7.14.8 '@jimp/utils': 0.16.1 any-base: 1.1.0 buffer: 5.7.1 @@ -192,7 +198,7 @@ packages: /@jimp/custom/0.16.1: resolution: {integrity: sha512-DNUAHNSiUI/j9hmbatD6WN/EBIyeq4AO0frl5ETtt51VN1SvE4t4v83ZA/V6ikxEf3hxLju4tQ5Pc3zmZkN/3A==} dependencies: - '@babel/runtime': 7.15.3 + '@babel/runtime': 7.14.8 '@jimp/core': 0.16.1 dev: true @@ -201,7 +207,7 @@ packages: peerDependencies: '@jimp/custom': '>=0.3.5' dependencies: - '@babel/runtime': 7.15.3 + '@babel/runtime': 7.14.8 '@jimp/custom': 0.16.1 '@jimp/utils': 0.16.1 jpeg-js: 0.4.2 @@ -212,7 +218,7 @@ packages: peerDependencies: '@jimp/custom': '>=0.3.5' dependencies: - '@babel/runtime': 7.15.3 + '@babel/runtime': 7.14.8 '@jimp/custom': 0.16.1 '@jimp/utils': 0.16.1 pngjs: 3.4.0 @@ -221,7 +227,7 @@ packages: /@jimp/utils/0.16.1: resolution: {integrity: sha512-8fULQjB0x4LzUSiSYG6ZtQl355sZjxbv8r9PPAuYHzS9sGiSHJQavNqK/nKnpDsVkU88/vRGcE7t3nMU0dEnVw==} dependencies: - '@babel/runtime': 7.15.3 + '@babel/runtime': 7.14.8 regenerator-runtime: 0.13.9 dev: true @@ -237,13 +243,13 @@ packages: npmlog: 4.1.2 rimraf: 3.0.2 semver: 7.3.5 - tar: 6.1.11 + tar: 6.1.2 transitivePeerDependencies: - supports-color dev: true - /@napi-rs/cli/1.2.1: - resolution: {integrity: sha512-7FoYn1JSK5rTIG9KcKfYnZL/O0UjUMMuzZCXd//bJdkLw0Xx9EqQJs1X/Mg4KqywJYb79LDfxRMiJRSukPGDNw==} + /@napi-rs/cli/1.2.0: + resolution: {integrity: sha512-yr6zm0ZTPLfWAggWb6Wncf2gEfUI++jkzRJsRbRX3parUXrOPgipVTBh1kQFaib4Oq2GK8ydrlAzQFPOsREDKw==} engines: {node: '>= 10'} hasBin: true dev: true @@ -274,21 +280,21 @@ packages: engines: {node: '>= 8'} dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.12.0 + fastq: 1.11.1 dev: true /@octokit/auth-token/2.4.5: resolution: {integrity: sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA==} dependencies: - '@octokit/types': 6.26.0 + '@octokit/types': 6.24.0 dev: true /@octokit/core/2.5.4: resolution: {integrity: sha512-HCp8yKQfTITYK+Nd09MHzAlP1v3Ii/oCohv0/TW9rhSLvzb98BOVs2QmVYuloE6a3l6LsfyGIwb6Pc4ycgWlIQ==} dependencies: '@octokit/auth-token': 2.4.5 - '@octokit/graphql': 4.8.0 - '@octokit/request': 5.6.1 + '@octokit/graphql': 4.6.4 + '@octokit/request': 5.6.0 '@octokit/types': 5.5.0 before-after-hook: 2.2.2 universal-user-agent: 5.0.0 @@ -298,10 +304,10 @@ packages: resolution: {integrity: sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==} dependencies: '@octokit/auth-token': 2.4.5 - '@octokit/graphql': 4.8.0 - '@octokit/request': 5.6.1 + '@octokit/graphql': 4.6.4 + '@octokit/request': 5.6.0 '@octokit/request-error': 2.1.0 - '@octokit/types': 6.26.0 + '@octokit/types': 6.22.0 before-after-hook: 2.2.2 universal-user-agent: 6.0.0 dev: true @@ -309,39 +315,43 @@ packages: /@octokit/endpoint/6.0.12: resolution: {integrity: sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==} dependencies: - '@octokit/types': 6.26.0 + '@octokit/types': 6.24.0 is-plain-object: 5.0.0 universal-user-agent: 6.0.0 dev: true - /@octokit/graphql/4.8.0: - resolution: {integrity: sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==} + /@octokit/graphql/4.6.4: + resolution: {integrity: sha512-SWTdXsVheRmlotWNjKzPOb6Js6tjSqA2a8z9+glDJng0Aqjzti8MEWOtuT8ZSu6wHnci7LZNuarE87+WJBG4vg==} dependencies: - '@octokit/request': 5.6.1 - '@octokit/types': 6.26.0 + '@octokit/request': 5.6.0 + '@octokit/types': 6.24.0 universal-user-agent: 6.0.0 dev: true - /@octokit/openapi-types/10.0.0: - resolution: {integrity: sha512-k1iO2zKuEjjRS1EJb4FwSLk+iF6EGp+ZV0OMRViQoWhQ1fZTk9hg1xccZII5uyYoiqcbC73MRBmT45y1vp2PPg==} + /@octokit/openapi-types/9.2.0: + resolution: {integrity: sha512-c4A1Xm0At+ypvBfEETREu519wLncJYQXvY+dBGg/V5YA51eg5EwdDsPPfcOMG0cuXscqRvsIgIySTmTJUdcTNA==} dev: true - /@octokit/plugin-paginate-rest/2.16.0_@octokit+core@2.5.4: - resolution: {integrity: sha512-8YYzALPMvEZ35kgy5pdYvQ22Roz+BIuEaedO575GwE2vb/ACDqQn0xQrTJR4tnZCJn7pi8+AWPVjrFDaERIyXQ==} + /@octokit/openapi-types/9.4.0: + resolution: {integrity: sha512-rKRkXikOJgDNImPl49IJuECLVXjj+t4qOXHhl8SBjMQCGGp1w4m5Ud/0kfdUx+zCpTvBN8vaOUDF4nnboZoOtQ==} + dev: true + + /@octokit/plugin-paginate-rest/2.14.0_@octokit+core@2.5.4: + resolution: {integrity: sha512-S2uEu2uHeI7Vf+Lvj8tv3O5/5TCAa8GHS0dUQN7gdM7vKA6ZHAbR6HkAVm5yMb1mbedLEbxOuQ+Fa0SQ7tCDLA==} peerDependencies: '@octokit/core': '>=2' dependencies: '@octokit/core': 2.5.4 - '@octokit/types': 6.26.0 + '@octokit/types': 6.22.0 dev: true - /@octokit/plugin-paginate-rest/2.16.0_@octokit+core@3.5.1: - resolution: {integrity: sha512-8YYzALPMvEZ35kgy5pdYvQ22Roz+BIuEaedO575GwE2vb/ACDqQn0xQrTJR4tnZCJn7pi8+AWPVjrFDaERIyXQ==} + /@octokit/plugin-paginate-rest/2.14.0_@octokit+core@3.5.1: + resolution: {integrity: sha512-S2uEu2uHeI7Vf+Lvj8tv3O5/5TCAa8GHS0dUQN7gdM7vKA6ZHAbR6HkAVm5yMb1mbedLEbxOuQ+Fa0SQ7tCDLA==} peerDependencies: '@octokit/core': '>=2' dependencies: '@octokit/core': 3.5.1 - '@octokit/types': 6.26.0 + '@octokit/types': 6.22.0 dev: true /@octokit/plugin-request-log/1.0.4_@octokit+core@2.5.4: @@ -367,30 +377,30 @@ packages: deprecation: 2.3.1 dev: true - /@octokit/plugin-rest-endpoint-methods/5.9.0_@octokit+core@3.5.1: - resolution: {integrity: sha512-Rz67pg+rEJq2Qn/qfHsMiBoP7GL5NDn8Gg0ezGznZ745Ixn1gPusZYZqCXNhICYrIZaVXmusNP0iwPdphJneqQ==} + /@octokit/plugin-rest-endpoint-methods/5.7.0_@octokit+core@3.5.1: + resolution: {integrity: sha512-G7sgccWRYQMwcHJXkDY/sDxbXeKiZkFQqUtzBCwmrzCNj2GQf3VygQ4T/BFL2crLVpIbenkE/c0ErhYOte2MPw==} peerDependencies: '@octokit/core': '>=3' dependencies: '@octokit/core': 3.5.1 - '@octokit/types': 6.26.0 + '@octokit/types': 6.24.0 deprecation: 2.3.1 dev: true /@octokit/request-error/2.1.0: resolution: {integrity: sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==} dependencies: - '@octokit/types': 6.26.0 + '@octokit/types': 6.24.0 deprecation: 2.3.1 once: 1.4.0 dev: true - /@octokit/request/5.6.1: - resolution: {integrity: sha512-Ls2cfs1OfXaOKzkcxnqw5MR6drMA/zWX/LIS/p8Yjdz7QKTPQLMsB3R+OvoxE6XnXeXEE2X7xe4G4l4X0gRiKQ==} + /@octokit/request/5.6.0: + resolution: {integrity: sha512-4cPp/N+NqmaGQwbh3vUsYqokQIzt7VjsgTYVXiwpUP2pxd5YiZB2XuTedbb0SPtv9XS7nzAKjAuQxmY8/aZkiA==} dependencies: '@octokit/endpoint': 6.0.12 '@octokit/request-error': 2.1.0 - '@octokit/types': 6.26.0 + '@octokit/types': 6.24.0 is-plain-object: 5.0.0 node-fetch: 2.6.1 universal-user-agent: 6.0.0 @@ -400,36 +410,42 @@ packages: resolution: {integrity: sha512-4jTmn8WossTUaLfNDfXk4fVJgbz5JgZE8eCs4BvIb52lvIH8rpVMD1fgRCrHbSd6LRPE5JFZSfAEtszrOq3ZFQ==} dependencies: '@octokit/core': 2.5.4 - '@octokit/plugin-paginate-rest': 2.16.0_@octokit+core@2.5.4 + '@octokit/plugin-paginate-rest': 2.14.0_@octokit+core@2.5.4 '@octokit/plugin-request-log': 1.0.4_@octokit+core@2.5.4 '@octokit/plugin-rest-endpoint-methods': 3.17.0 dev: true - /@octokit/rest/18.10.0: - resolution: {integrity: sha512-esHR5OKy38bccL/sajHqZudZCvmv4yjovMJzyXlphaUo7xykmtOdILGJ3aAm0mFHmMLmPFmDMJXf39cAjNJsrw==} + /@octokit/rest/18.9.0: + resolution: {integrity: sha512-VrmrE8gjpuOoDAGjrQq2j9ZhOE6LxaqxaQg0yMrrEnnQZy2ZcAnr5qbVfKsMF0up/48PRV/VFS/2GSMhA7nTdA==} dependencies: '@octokit/core': 3.5.1 - '@octokit/plugin-paginate-rest': 2.16.0_@octokit+core@3.5.1 + '@octokit/plugin-paginate-rest': 2.14.0_@octokit+core@3.5.1 '@octokit/plugin-request-log': 1.0.4_@octokit+core@3.5.1 - '@octokit/plugin-rest-endpoint-methods': 5.9.0_@octokit+core@3.5.1 + '@octokit/plugin-rest-endpoint-methods': 5.7.0_@octokit+core@3.5.1 dev: true /@octokit/types/4.1.10: resolution: {integrity: sha512-/wbFy1cUIE5eICcg0wTKGXMlKSbaAxEr00qaBXzscLXpqhcwgXeS6P8O0pkysBhRfyjkKjJaYrvR1ExMO5eOXQ==} dependencies: - '@types/node': 16.7.10 + '@types/node': 16.4.9 dev: true /@octokit/types/5.5.0: resolution: {integrity: sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ==} dependencies: - '@types/node': 16.7.10 + '@types/node': 16.4.9 + dev: true + + /@octokit/types/6.22.0: + resolution: {integrity: sha512-Y8GR0BJHQDpO09qw/ZQpN+DXrFzCWaE0pvK4frDm3zJ+h99AktsFfBoDazbCtHxiL8d0jD8xRH4BeynlKLeChg==} + dependencies: + '@octokit/openapi-types': 9.2.0 dev: true - /@octokit/types/6.26.0: - resolution: {integrity: sha512-RDxZBAFMtqs1ZPnbUu1e7ohPNfoNhTiep4fErY7tZs995BeHu369Vsh5woMIaFbllRWEZBfvTCS4hvDnMPiHrA==} + /@octokit/types/6.24.0: + resolution: {integrity: sha512-MfEimJeQ8AV1T2nI5kOfHqsqPHaAnG0Dw3MVoHSEsEq6iLKx2N91o+k2uAgXhPYeSE76LVBqjgTShnFFgNwe0A==} dependencies: - '@octokit/openapi-types': 10.0.0 + '@octokit/openapi-types': 9.4.0 dev: true /@sindresorhus/is/0.14.0: @@ -441,18 +457,18 @@ packages: resolution: {integrity: sha512-H424sTzhvgc+mKm9E4C115UYKgegM4LeX5F1UPBGTvLs4KSS9eU/wH0sly7+mUk0I8QZjjn3NgtWLAE8NxM37Q==} engines: {node: '>= 10'} dependencies: - '@swc/core': 1.2.83 + '@swc/core': 1.2.70 dev: true - /@swc-node/register/1.3.4: - resolution: {integrity: sha512-clv43MpAfjtVWzSVyEF4uR+r3yA1HQg7y4mwonC/nHteFSr8hlYr36hKr7lJZehTCTFNwdqai9Ly+Qa6nB8cWg==} + /@swc-node/register/1.3.3: + resolution: {integrity: sha512-aGMJYVkOY/66Bz6wWH/Ldtg0X0G+/z0FshoxBM2yTrv7NlPESfTiXk61oevByGxxTWueHyYdXfftqhNI2Sig5Q==} dependencies: '@swc-node/core': 1.5.1 '@swc-node/sourcemap-support': 0.1.8 chalk: 4.1.2 debug: 4.3.2 pirates: 4.0.1 - typescript: 4.4.2 + typescript: 4.3.5 transitivePeerDependencies: - supports-color dev: true @@ -463,132 +479,120 @@ packages: source-map-support: 0.5.19 dev: true - /@swc/core-android-arm64/1.2.83: - resolution: {integrity: sha512-pODboMBvwplgfPU7/LVAJdIlt/9lttd8cMUwxSykMo/lFaP5J5SyiBauL1UzFEe6eGpN4WPhlF3H+tTz1uWBwg==} + /@swc/core-android-arm64/1.2.70: + resolution: {integrity: sha512-Zq7lBQ8L+LtcwYbkZFHDiosVW/1wa4QTxvSIeA4YWVRWogWAp73MQm1aaRsq+LLCu/7W7a0j3t61y64dxgyvDg==} engines: {node: '>=10'} cpu: [arm64] os: [android] - requiresBuild: true dev: true optional: true - /@swc/core-darwin-arm64/1.2.83: - resolution: {integrity: sha512-/RadmNG6w8ouXsqEFMgjUZL1pxiodkAMTLuKxzKgGb8C+cJYYzrMrJAhuRaVF56/tbI0f7HjGtVYPIUyj7PO/Q==} + /@swc/core-darwin-arm64/1.2.70: + resolution: {integrity: sha512-QoxAyCg08W6U3eUJ2M36OX+pdqFV9vDwevtySoEPjBZegsKrBqNzCwyRbxst/TUkgm9yycv++yexvl1aPMVf3g==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - requiresBuild: true dev: true optional: true - /@swc/core-darwin-x64/1.2.83: - resolution: {integrity: sha512-SuMQOzMPv79EqHbvkL29KuAfvxADpEgzVndg/w3rjfT2xHHRBZSbcpTWZ2mXYZeddM3+JG2OrHH55RixUH+r9Q==} + /@swc/core-darwin-x64/1.2.70: + resolution: {integrity: sha512-uxXvQWih1PewtATjENXgWeqPM+AWBAL6JYpRVLf92ZR2Tj/G1XmX3szCgnGNA0Vx+gt1Iw5mu2RZIixmT/hNXg==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - requiresBuild: true dev: true optional: true - /@swc/core-freebsd-x64/1.2.83: - resolution: {integrity: sha512-2s7L71s3OgrXbjujPY37OuA0FuTtoevTz8Ce40HkvfcOArTi92gN6WZu55ZtUIwFq3U/hH0oE0Po86JOO/ArVg==} + /@swc/core-freebsd-x64/1.2.70: + resolution: {integrity: sha512-o3TE3d0aA/+PFIw2e1UcCvnuvteE+V1jBqbvqqs8joX2fcTA+7SHHEx7KCbt6Ui885Dp60H6FclUZCBoh5RoZw==} engines: {node: '>=10'} cpu: [x64] os: [freebsd] - requiresBuild: true dev: true optional: true - /@swc/core-linux-arm-gnueabihf/1.2.83: - resolution: {integrity: sha512-RwONngFb7BG+6o9Hi+EuE7dT0d/PtlZyV9DdeAP++uuem9I6vyuXmI3IqtpeRU731wW4gLvlRKLp/EV63sjoSA==} + /@swc/core-linux-arm-gnueabihf/1.2.70: + resolution: {integrity: sha512-1rt4aDMIH5VcHsRmMeX7fuWIzJn9pfIwae+yz0MBVEiMKgYS26swNjJNN+3k37MXEATfDFynCDFSidjc0wrKQA==} engines: {node: '>=10'} cpu: [arm] os: [linux] - requiresBuild: true dev: true optional: true - /@swc/core-linux-arm64-gnu/1.2.83: - resolution: {integrity: sha512-BM4cbI4X74eul6ix0PBsJ7sSkIbcHX9P6J3fAoT6CmYeS4gADGB4n1ktw5GYkXhaiVRVK9KVUXEqpfxBTpCXXQ==} + /@swc/core-linux-arm64-gnu/1.2.70: + resolution: {integrity: sha512-psdyNMpEWiGyUETdSJTBba7mZ0pLY2DRqiBfCEd7roIESJ3ZBoDhMvexu7P9rFUH0EGYFfowmxeFTLGvw74omQ==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - requiresBuild: true dev: true optional: true - /@swc/core-linux-arm64-musl/1.2.83: - resolution: {integrity: sha512-XDuxnA/rRMLOAAOCjyPlDdzFUrWuD3Xp+m5dHQi80VqpfLGxYeVZebUYfpEtWGI1K4UPQLx+gTk2ssVG5avWKA==} + /@swc/core-linux-arm64-musl/1.2.70: + resolution: {integrity: sha512-JamkRFw+Rw2UX7lg4QhvqU5oW8jppvM46EA+b97JFDFMAlByMASXbLblJ2R/As+6BaIttYqqRr++UJbhZf5vpw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - requiresBuild: true dev: true optional: true - /@swc/core-linux-x64-gnu/1.2.83: - resolution: {integrity: sha512-FaA5O2V0I8X6UuBua7a4ufGh/r9I00aXvoMcb2yrxyzyApgh2VvLfCj3DaiQIYR44QV7dQm/RII1KsJnX6XpDw==} + /@swc/core-linux-x64-gnu/1.2.70: + resolution: {integrity: sha512-/jGVV+A5NtI1gKHSp5hvfj1vdGNQWC2MutLr0t5dAOZ0Ij6YpTY1YTnN8tvVFwPwMVFP9Ly/wkG9YJt/f/T5TQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] - requiresBuild: true dev: true optional: true - /@swc/core-linux-x64-musl/1.2.83: - resolution: {integrity: sha512-BYNqN7cmN+TazrUrhGrY9IYbT2+l4UqFEZX/M5iWfFzpvHmGeeacvD4qxC1iAh99dqGHn7rsPM3QVK9lyDlLSw==} + /@swc/core-linux-x64-musl/1.2.70: + resolution: {integrity: sha512-k+Sa5DwkPexeNoHPkSm3dhKwPnnmqfNalu6mygDRVAwATVoEHEAxYEwFM3DQjTfBMLGyW5T6aWaKZOseEhLJUg==} engines: {node: '>=10'} cpu: [x64] os: [linux] - requiresBuild: true dev: true optional: true - /@swc/core-win32-arm64-msvc/1.2.83: - resolution: {integrity: sha512-tMzWXwcwTsBQ0eVXrwai+Q/aiBZR1sDWpYDD1KINRIYWxTASJ0PLySbLyZdEFfxxPvqOY1gslnWLjPwa1frTkg==} + /@swc/core-win32-arm64-msvc/1.2.70: + resolution: {integrity: sha512-RAdskZSUU2/K8JS8fPNgNqxZHxX2JvKYcq4IXoQ1zKkwsAkdm8jIx9YXIXWSynttckPF1Nid1Ij8tPGkZaZn8w==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - requiresBuild: true dev: true optional: true - /@swc/core-win32-ia32-msvc/1.2.83: - resolution: {integrity: sha512-ft1kSw8b09Lmyg7xXn7n99GYMr7CCFzWXB8800kjOb+9jsIN73Sn86I3TVldAeIdJZbeuTYU8J7cxhcJcnmmOA==} + /@swc/core-win32-ia32-msvc/1.2.70: + resolution: {integrity: sha512-rbTQWfKzU+R8AQsdKgnmxmesoE6s3+n0I1B/hv5HI/HOHwXhaPotoRK//wreYWXGuUwZmRBXwMm0ATOWKK0/uA==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - requiresBuild: true dev: true optional: true - /@swc/core-win32-x64-msvc/1.2.83: - resolution: {integrity: sha512-HraOOGDp0dI4+yQ7DxW44FBGSa7CDKG+oviiu2ieXyFjnMqyI3AS5jD27O7g7WKQ1RvKky8M6PxFMz9w3P8HJQ==} + /@swc/core-win32-x64-msvc/1.2.70: + resolution: {integrity: sha512-co4zKgF8HdngnI0y+OzUtE0MCWAHBA26dBaM/G71y6OBvFWBx//uw6/GU0x6rLIR4p3EXW2Sj4ze6VsCicYXqQ==} engines: {node: '>=10'} cpu: [x64] os: [win32] - requiresBuild: true dev: true optional: true - /@swc/core/1.2.83: - resolution: {integrity: sha512-Ao5XziabPGXBcwyDF8NRZcp7ySZBsjrV1aDyVe2Rdb44VaJ8Q0jN7QjYlc4zOikcwgi1BF05YgvMykMfB0qKMA==} + /@swc/core/1.2.70: + resolution: {integrity: sha512-OnV4chCPqIybPTEC2jRMCuIOm/6keFUw37tpqL8hJ9+r8n44SGg2lheWaqQrFko9UDg0nwTR4Go5h4U0u5PkFw==} engines: {node: '>=10'} dependencies: '@node-rs/helper': 1.2.1 optionalDependencies: - '@swc/core-android-arm64': 1.2.83 - '@swc/core-darwin-arm64': 1.2.83 - '@swc/core-darwin-x64': 1.2.83 - '@swc/core-freebsd-x64': 1.2.83 - '@swc/core-linux-arm-gnueabihf': 1.2.83 - '@swc/core-linux-arm64-gnu': 1.2.83 - '@swc/core-linux-arm64-musl': 1.2.83 - '@swc/core-linux-x64-gnu': 1.2.83 - '@swc/core-linux-x64-musl': 1.2.83 - '@swc/core-win32-arm64-msvc': 1.2.83 - '@swc/core-win32-ia32-msvc': 1.2.83 - '@swc/core-win32-x64-msvc': 1.2.83 + '@swc/core-android-arm64': 1.2.70 + '@swc/core-darwin-arm64': 1.2.70 + '@swc/core-darwin-x64': 1.2.70 + '@swc/core-freebsd-x64': 1.2.70 + '@swc/core-linux-arm-gnueabihf': 1.2.70 + '@swc/core-linux-arm64-gnu': 1.2.70 + '@swc/core-linux-arm64-musl': 1.2.70 + '@swc/core-linux-x64-gnu': 1.2.70 + '@swc/core-linux-x64-musl': 1.2.70 + '@swc/core-win32-arm64-msvc': 1.2.70 + '@swc/core-win32-ia32-msvc': 1.2.70 + '@swc/core-win32-x64-msvc': 1.2.70 dev: true /@szmarczak/http-timer/1.1.2: @@ -598,20 +602,20 @@ packages: defer-to-connect: 1.1.3 dev: true - /@types/json-schema/7.0.9: - resolution: {integrity: sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==} + /@types/json-schema/7.0.8: + resolution: {integrity: sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==} dev: true - /@types/json5/0.0.29: - resolution: {integrity: sha1-7ihweulOEdK4J7y+UnC86n8+ce4=} + /@types/lodash/4.14.172: + resolution: {integrity: sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw==} dev: true /@types/minimist/1.2.2: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true - /@types/node/16.7.10: - resolution: {integrity: sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA==} + /@types/node/16.4.9: + resolution: {integrity: sha512-HXhRf581nCItzn8yevv4LYt+bJ5cBbDBAJExbDPMeU/2n5/j0ZemGpayahFBP4xL7RseaCLASLD9i9AYyDe7Nw==} dev: true /@types/normalize-package-data/2.4.1: @@ -622,8 +626,8 @@ packages: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} dev: true - /@typescript-eslint/eslint-plugin/4.30.0_8a8a2d3eaa9257455a03c16dce5f55b3: - resolution: {integrity: sha512-NgAnqk55RQ/SD+tZFD9aPwNSeHmDHHe5rtUyhIq0ZeCWZEvo4DK9rYz7v9HDuQZFvn320Ot+AikaCKMFKLlD0g==} + /@typescript-eslint/eslint-plugin/4.29.0_48ea228fa0647506aa803d17f48b59f7: + resolution: {integrity: sha512-eiREtqWRZ8aVJcNru7cT/AMVnYd9a2UHsfZT8MR1dW3UUEg6jDv9EQ9Cq4CUPZesyQ58YUpoAADGv71jY8RwgA==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: '@typescript-eslint/parser': ^4.0.0 @@ -633,30 +637,30 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/experimental-utils': 4.30.0_eslint@7.32.0+typescript@4.4.2 - '@typescript-eslint/parser': 4.30.0_eslint@7.32.0+typescript@4.4.2 - '@typescript-eslint/scope-manager': 4.30.0 + '@typescript-eslint/experimental-utils': 4.29.0_eslint@7.32.0+typescript@4.3.5 + '@typescript-eslint/parser': 4.29.0_eslint@7.32.0+typescript@4.3.5 + '@typescript-eslint/scope-manager': 4.29.0 debug: 4.3.2 eslint: 7.32.0 functional-red-black-tree: 1.0.1 regexpp: 3.2.0 semver: 7.3.5 - tsutils: 3.21.0_typescript@4.4.2 - typescript: 4.4.2 + tsutils: 3.21.0_typescript@4.3.5 + typescript: 4.3.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/experimental-utils/4.30.0_eslint@7.32.0+typescript@4.4.2: - resolution: {integrity: sha512-K8RNIX9GnBsv5v4TjtwkKtqMSzYpjqAQg/oSphtxf3xxdt6T0owqnpojztjjTcatSteH3hLj3t/kklKx87NPqw==} + /@typescript-eslint/experimental-utils/4.29.0_eslint@7.32.0+typescript@4.3.5: + resolution: {integrity: sha512-FpNVKykfeaIxlArLUP/yQfv/5/3rhl1ov6RWgud4OgbqWLkEq7lqgQU9iiavZRzpzCRQV4XddyFz3wFXdkiX9w==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: eslint: '*' dependencies: - '@types/json-schema': 7.0.9 - '@typescript-eslint/scope-manager': 4.30.0 - '@typescript-eslint/types': 4.30.0 - '@typescript-eslint/typescript-estree': 4.30.0_typescript@4.4.2 + '@types/json-schema': 7.0.8 + '@typescript-eslint/scope-manager': 4.29.0 + '@typescript-eslint/types': 4.29.0 + '@typescript-eslint/typescript-estree': 4.29.0_typescript@4.3.5 eslint: 7.32.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0_eslint@7.32.0 @@ -665,8 +669,8 @@ packages: - typescript dev: true - /@typescript-eslint/parser/4.30.0_eslint@7.32.0+typescript@4.4.2: - resolution: {integrity: sha512-HJ0XuluSZSxeboLU7Q2VQ6eLlCwXPBOGnA7CqgBnz2Db3JRQYyBDJgQnop6TZ+rsbSx5gEdWhw4rE4mDa1FnZg==} + /@typescript-eslint/parser/4.29.0_eslint@7.32.0+typescript@4.3.5: + resolution: {integrity: sha512-+92YRNHFdXgq+GhWQPT2bmjX09X7EH36JfgN2/4wmhtwV/HPxozpCNst8jrWcngLtEVd/4zAwA6BKojAlf+YqA==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 @@ -675,31 +679,31 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 4.30.0 - '@typescript-eslint/types': 4.30.0 - '@typescript-eslint/typescript-estree': 4.30.0_typescript@4.4.2 + '@typescript-eslint/scope-manager': 4.29.0 + '@typescript-eslint/types': 4.29.0 + '@typescript-eslint/typescript-estree': 4.29.0_typescript@4.3.5 debug: 4.3.2 eslint: 7.32.0 - typescript: 4.4.2 + typescript: 4.3.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager/4.30.0: - resolution: {integrity: sha512-VJ/jAXovxNh7rIXCQbYhkyV2Y3Ac/0cVHP/FruTJSAUUm4Oacmn/nkN5zfWmWFEanN4ggP0vJSHOeajtHq3f8A==} + /@typescript-eslint/scope-manager/4.29.0: + resolution: {integrity: sha512-HPq7XAaDMM3DpmuijxLV9Io8/6pQnliiXMQUcAdjpJJSR+fdmbD/zHCd7hMkjJn04UQtCQBtshgxClzg6NIS2w==} engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} dependencies: - '@typescript-eslint/types': 4.30.0 - '@typescript-eslint/visitor-keys': 4.30.0 + '@typescript-eslint/types': 4.29.0 + '@typescript-eslint/visitor-keys': 4.29.0 dev: true - /@typescript-eslint/types/4.30.0: - resolution: {integrity: sha512-YKldqbNU9K4WpTNwBqtAerQKLLW/X2A/j4yw92e3ZJYLx+BpKLeheyzoPfzIXHfM8BXfoleTdiYwpsvVPvHrDw==} + /@typescript-eslint/types/4.29.0: + resolution: {integrity: sha512-2YJM6XfWfi8pgU2HRhTp7WgRw78TCRO3dOmSpAvIQ8MOv4B46JD2chnhpNT7Jq8j0APlIbzO1Bach734xxUl4A==} engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} dev: true - /@typescript-eslint/typescript-estree/4.30.0_typescript@4.4.2: - resolution: {integrity: sha512-6WN7UFYvykr/U0Qgy4kz48iGPWILvYL34xXJxvDQeiRE018B7POspNRVtAZscWntEPZpFCx4hcz/XBT+erenfg==} + /@typescript-eslint/typescript-estree/4.29.0_typescript@4.3.5: + resolution: {integrity: sha512-8ZpNHDIOyqzzgZrQW9+xQ4k5hM62Xy2R4RPO3DQxMc5Rq5QkCdSpk/drka+DL9w6sXNzV5nrdlBmf8+x495QXQ==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: typescript: '*' @@ -707,23 +711,23 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 4.30.0 - '@typescript-eslint/visitor-keys': 4.30.0 + '@typescript-eslint/types': 4.29.0 + '@typescript-eslint/visitor-keys': 4.29.0 debug: 4.3.2 globby: 11.0.4 is-glob: 4.0.1 semver: 7.3.5 - tsutils: 3.21.0_typescript@4.4.2 - typescript: 4.4.2 + tsutils: 3.21.0_typescript@4.3.5 + typescript: 4.3.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/visitor-keys/4.30.0: - resolution: {integrity: sha512-pNaaxDt/Ol/+JZwzP7MqWc8PJQTUhZwoee/PVlQ+iYoYhagccvoHnC9e4l+C/krQYYkENxznhVSDwClIbZVxRw==} + /@typescript-eslint/visitor-keys/4.29.0: + resolution: {integrity: sha512-LoaofO1C/jAJYs0uEpYMXfHboGXzOJeV118X4OsZu9f7rG7Pr9B3+4HTU8+err81rADa4xfQmAxnRnPAI2jp+Q==} engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} dependencies: - '@typescript-eslint/types': 4.30.0 + '@typescript-eslint/types': 4.29.0 eslint-visitor-keys: 2.1.0 dev: true @@ -899,9 +903,9 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.1.3 - es-abstract: 1.18.5 + es-abstract: 1.18.4 get-intrinsic: 1.1.1 - is-string: 1.0.7 + is-string: 1.0.6 dev: true /array-union/2.1.0: @@ -915,7 +919,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.1.3 - es-abstract: 1.18.5 + es-abstract: 1.18.4 dev: true /arrgv/1.0.2: @@ -1153,12 +1157,16 @@ packages: requiresBuild: true dependencies: '@mapbox/node-pre-gyp': 1.0.5 - nan: 2.15.0 + nan: 2.14.2 simple-get: 3.1.0 transitivePeerDependencies: - supports-color dev: true + /canvaskit-wasm/0.29.0: + resolution: {integrity: sha512-apI00O3O8DI9+at9O9M6aTmGL4gD1XNs4L+L5X2FXggmpf/+YaftuqsWeYeoy0OpbzltF6Seu26FXoLXLXxxWg==} + dev: true + /chalk/2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -1300,8 +1308,8 @@ packages: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: true - /colorette/1.3.0: - resolution: {integrity: sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==} + /colorette/1.2.2: + resolution: {integrity: sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==} dev: true /commander/6.2.1: @@ -1348,7 +1356,7 @@ packages: engines: {node: '>=8'} dependencies: dot-prop: 5.3.0 - graceful-fs: 4.2.8 + graceful-fs: 4.2.6 make-dir: 3.1.0 unique-string: 2.0.0 write-file-atomic: 3.0.3 @@ -1415,7 +1423,7 @@ packages: git-remote-origin-url: 2.0.0 git-semver-tags: 4.1.1 lodash: 4.17.21 - normalize-package-data: 3.0.3 + normalize-package-data: 3.0.2 q: 1.5.1 read-pkg: 3.0.0 read-pkg-up: 3.0.0 @@ -1529,12 +1537,12 @@ packages: engines: {node: '>= 4'} dev: true - /core-util-is/1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + /core-util-is/1.0.2: + resolution: {integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=} dev: true - /cosmiconfig/7.0.1: - resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} + /cosmiconfig/7.0.0: + resolution: {integrity: sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==} engines: {node: '>=10'} dependencies: '@types/parse-json': 4.0.0 @@ -1681,7 +1689,7 @@ packages: engines: {node: '>=10'} dependencies: globby: 11.0.4 - graceful-fs: 4.2.8 + graceful-fs: 4.2.6 is-glob: 4.0.1 is-path-cwd: 2.2.0 is-path-inside: 3.0.3 @@ -1777,8 +1785,8 @@ packages: is-arrayish: 0.2.1 dev: true - /es-abstract/1.18.5: - resolution: {integrity: sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==} + /es-abstract/1.18.4: + resolution: {integrity: sha512-xjDAPJRxKc1uoTkdW8MEk7Fq/2bzz3YoCADYniDV7+KITCUdu9c90fj1aKI7nEZFZxRrHlDo3wtma/C6QkhlXQ==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 @@ -1788,10 +1796,10 @@ packages: has: 1.0.3 has-symbols: 1.0.2 internal-slot: 1.0.3 - is-callable: 1.2.4 + is-callable: 1.2.3 is-negative-zero: 2.0.1 - is-regex: 1.1.4 - is-string: 1.0.7 + is-regex: 1.1.3 + is-string: 1.0.6 object-inspect: 1.11.0 object-keys: 1.1.1 object.assign: 4.1.2 @@ -1804,8 +1812,8 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} dependencies: - is-callable: 1.2.4 - is-date-object: 1.0.5 + is-callable: 1.2.3 + is-date-object: 1.0.4 is-symbol: 1.0.4 dev: true @@ -1843,23 +1851,23 @@ packages: eslint: 7.32.0 dev: true - /eslint-import-resolver-node/0.3.6: - resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==} + /eslint-import-resolver-node/0.3.4: + resolution: {integrity: sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==} dependencies: - debug: 3.2.7 + debug: 2.6.9 resolve: 1.20.0 dev: true - /eslint-module-utils/2.6.2: - resolution: {integrity: sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==} + /eslint-module-utils/2.6.1: + resolution: {integrity: sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==} engines: {node: '>=4'} dependencies: debug: 3.2.7 pkg-dir: 2.0.0 dev: true - /eslint-plugin-import/2.24.2_eslint@7.32.0: - resolution: {integrity: sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q==} + /eslint-plugin-import/2.23.4_eslint@7.32.0: + resolution: {integrity: sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==} engines: {node: '>=4'} peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 @@ -1869,17 +1877,17 @@ packages: debug: 2.6.9 doctrine: 2.1.0 eslint: 7.32.0 - eslint-import-resolver-node: 0.3.6 - eslint-module-utils: 2.6.2 + eslint-import-resolver-node: 0.3.4 + eslint-module-utils: 2.6.1 find-up: 2.1.0 has: 1.0.3 - is-core-module: 2.6.0 + is-core-module: 2.5.0 minimatch: 3.0.4 object.values: 1.1.4 pkg-up: 2.0.0 read-pkg-up: 3.0.0 resolve: 1.20.0 - tsconfig-paths: 3.11.0 + tsconfig-paths: 3.10.1 dev: true /eslint-plugin-prettier/4.0.0_5a48a349ffec60f5257b5f148f5199c3: @@ -1968,7 +1976,7 @@ packages: file-entry-cache: 6.0.1 functional-red-black-tree: 1.0.1 glob-parent: 5.1.2 - globals: 13.11.0 + globals: 13.10.0 ignore: 4.0.6 import-fresh: 3.3.0 imurmurhash: 0.1.4 @@ -2095,8 +2103,8 @@ packages: resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} dev: true - /fastq/1.12.0: - resolution: {integrity: sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==} + /fastq/1.11.1: + resolution: {integrity: sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==} dependencies: reusify: 1.0.4 dev: true @@ -2170,7 +2178,7 @@ packages: engines: {node: '>=10'} dependencies: at-least-node: 1.0.0 - graceful-fs: 4.2.8 + graceful-fs: 4.2.6 jsonfile: 6.1.0 universalify: 2.0.0 dev: true @@ -2190,7 +2198,6 @@ packages: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - requiresBuild: true dev: true optional: true @@ -2329,8 +2336,8 @@ packages: process: 0.11.10 dev: true - /globals/13.11.0: - resolution: {integrity: sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==} + /globals/13.10.0: + resolution: {integrity: sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 @@ -2365,8 +2372,8 @@ packages: url-parse-lax: 3.0.0 dev: true - /graceful-fs/4.2.8: - resolution: {integrity: sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==} + /graceful-fs/4.2.6: + resolution: {integrity: sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==} dev: true /handlebars/4.7.7: @@ -2406,13 +2413,6 @@ packages: engines: {node: '>= 0.4'} dev: true - /has-tostringtag/1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.2 - dev: true - /has-unicode/2.0.1: resolution: {integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=} dev: true @@ -2459,8 +2459,8 @@ packages: engines: {node: '>=10.17.0'} dev: true - /husky/7.0.2: - resolution: {integrity: sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==} + /husky/7.0.1: + resolution: {integrity: sha512-gceRaITVZ+cJH9sNHqx5tFwbzlLCVxtVZcusME8JYQ8Edy5mpGDOqD8QBCdMhpyo9a+JXddnujQ4rpY2Ff9SJA==} engines: {node: '>=12'} hasBin: true dev: true @@ -2554,10 +2554,8 @@ packages: resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} dev: true - /is-bigint/1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.1 + /is-bigint/1.0.2: + resolution: {integrity: sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==} dev: true /is-binary-path/2.1.0: @@ -2567,16 +2565,15 @@ packages: binary-extensions: 2.2.0 dev: true - /is-boolean-object/1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + /is-boolean-object/1.1.1: + resolution: {integrity: sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - has-tostringtag: 1.0.0 dev: true - /is-callable/1.2.4: - resolution: {integrity: sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==} + /is-callable/1.2.3: + resolution: {integrity: sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==} engines: {node: '>= 0.4'} dev: true @@ -2587,17 +2584,15 @@ packages: ci-info: 2.0.0 dev: true - /is-core-module/2.6.0: - resolution: {integrity: sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==} + /is-core-module/2.5.0: + resolution: {integrity: sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==} dependencies: has: 1.0.3 dev: true - /is-date-object/1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + /is-date-object/1.0.4: + resolution: {integrity: sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==} engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 dev: true /is-error/2.2.2: @@ -2660,11 +2655,9 @@ packages: engines: {node: '>=10'} dev: true - /is-number-object/1.0.6: - resolution: {integrity: sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==} + /is-number-object/1.0.5: + resolution: {integrity: sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==} engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 dev: true /is-number/7.0.0: @@ -2706,12 +2699,12 @@ packages: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} dev: true - /is-regex/1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + /is-regex/1.1.3: + resolution: {integrity: sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - has-tostringtag: 1.0.0 + has-symbols: 1.0.2 dev: true /is-regexp/1.0.0: @@ -2729,11 +2722,9 @@ packages: engines: {node: '>=8'} dev: true - /is-string/1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + /is-string/1.0.6: + resolution: {integrity: sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==} engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 dev: true /is-symbol/1.0.4: @@ -2834,8 +2825,9 @@ packages: lodash.get: 4.4.2 dev: true - /json5/1.0.1: - resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} + /json5/2.2.0: + resolution: {integrity: sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==} + engines: {node: '>=6'} hasBin: true dependencies: minimist: 1.2.5 @@ -2846,7 +2838,7 @@ packages: dependencies: universalify: 2.0.0 optionalDependencies: - graceful-fs: 4.2.8 + graceful-fs: 4.2.6 dev: true /jsonparse/1.3.1: @@ -2896,11 +2888,11 @@ packages: chalk: 4.1.2 cli-truncate: 2.1.0 commander: 7.2.0 - cosmiconfig: 7.0.1 + cosmiconfig: 7.0.0 debug: 4.3.2 enquirer: 2.3.6 execa: 5.1.1 - listr2: 3.11.1_enquirer@2.3.6 + listr2: 3.11.0_enquirer@2.3.6 log-symbols: 4.1.0 micromatch: 4.0.4 normalize-path: 3.0.0 @@ -2911,14 +2903,14 @@ packages: - supports-color dev: true - /listr2/3.11.1_enquirer@2.3.6: - resolution: {integrity: sha512-ZXQvQfmH9iWLlb4n3hh31yicXDxlzB0pE7MM1zu6kgbVL4ivEsO4H8IPh4E682sC8RjnYO9anose+zT52rrpyg==} + /listr2/3.11.0_enquirer@2.3.6: + resolution: {integrity: sha512-XLJVe2JgXCyQTa3FbSv11lkKExYmEyA4jltVo8z4FX10Vt1Yj8IMekBfwim0BSOM9uj1QMTJvDQQpHyuPbB/dQ==} engines: {node: '>=10.0.0'} peerDependencies: enquirer: '>= 2.3.0 < 3' dependencies: cli-truncate: 2.1.0 - colorette: 1.3.0 + colorette: 1.2.2 enquirer: 2.3.6 log-update: 4.0.0 p-map: 4.0.0 @@ -2944,7 +2936,7 @@ packages: resolution: {integrity: sha1-L19Fq5HjMhYjT9U62rZo607AmTs=} engines: {node: '>=4'} dependencies: - graceful-fs: 4.2.8 + graceful-fs: 4.2.6 parse-json: 4.0.0 pify: 3.0.0 strip-bom: 3.0.0 @@ -2954,7 +2946,7 @@ packages: resolution: {integrity: sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==} engines: {node: '>=6'} dependencies: - graceful-fs: 4.2.8 + graceful-fs: 4.2.6 parse-json: 4.0.0 pify: 4.0.1 strip-bom: 3.0.0 @@ -3125,7 +3117,7 @@ packages: decamelize-keys: 1.1.0 hard-rejection: 2.1.0 minimist-options: 4.1.0 - normalize-package-data: 3.0.3 + normalize-package-data: 3.0.2 read-pkg-up: 7.0.1 redent: 3.0.0 trim-newlines: 3.0.1 @@ -3268,8 +3260,8 @@ packages: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: true - /nan/2.15.0: - resolution: {integrity: sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==} + /nan/2.14.2: + resolution: {integrity: sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==} dev: true /natural-compare/1.4.0: @@ -3311,12 +3303,12 @@ packages: validate-npm-package-license: 3.0.4 dev: true - /normalize-package-data/3.0.3: - resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + /normalize-package-data/3.0.2: + resolution: {integrity: sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==} engines: {node: '>=10'} dependencies: hosted-git-info: 4.0.2 - is-core-module: 2.6.0 + resolve: 1.20.0 semver: 7.3.5 validate-npm-package-license: 3.0.4 dev: true @@ -3405,7 +3397,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.1.3 - es-abstract: 1.18.5 + es-abstract: 1.18.4 dev: true /once/1.4.0: @@ -3573,8 +3565,8 @@ packages: xml2js: 0.4.23 dev: true - /parse-headers/2.0.4: - resolution: {integrity: sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==} + /parse-headers/2.0.3: + resolution: {integrity: sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==} dev: true /parse-json/4.0.0: @@ -3892,7 +3884,7 @@ packages: /readable-stream/2.3.7: resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} dependencies: - core-util-is: 1.0.3 + core-util-is: 1.0.2 inherits: 2.0.4 isarray: 1.0.0 process-nextick-args: 2.0.1 @@ -3986,7 +3978,7 @@ packages: /resolve/1.20.0: resolution: {integrity: sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==} dependencies: - is-core-module: 2.6.0 + is-core-module: 2.5.0 path-parse: 1.0.7 dev: true @@ -4141,8 +4133,8 @@ packages: simple-concat: 1.0.1 dev: true - /skia-canvas/0.9.25: - resolution: {integrity: sha512-Txgo8F1MW5BiqLr2QO4r4SP5bJ2agF0ehx5B53DaMqtq9pVh/OhP94uGZhKn9ps1A5xCEb+ocQ0TWmkzOSWCAA==} + /skia-canvas/0.9.23: + resolution: {integrity: sha512-IIzhCiH9v2odyCfeUOuPdgAkruMSrwjnvN4FjJfn1rtW1RHC5Yqdmivno0YcYaS4UB0OwFBxkcxep0j8jQQ6HA==} requiresBuild: true dependencies: '@mapbox/node-pre-gyp': 1.0.5 @@ -4193,7 +4185,7 @@ packages: resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.10 + spdx-license-ids: 3.0.9 dev: true /spdx-exceptions/2.3.0: @@ -4204,11 +4196,11 @@ packages: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} dependencies: spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.10 + spdx-license-ids: 3.0.9 dev: true - /spdx-license-ids/3.0.10: - resolution: {integrity: sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==} + /spdx-license-ids/3.0.9: + resolution: {integrity: sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==} dev: true /split/1.0.1: @@ -4282,7 +4274,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.1.3 - es-abstract: 1.18.5 + es-abstract: 1.18.4 dev: true /string.prototype.trimend/1.0.4: @@ -4410,8 +4402,8 @@ packages: strip-ansi: 6.0.0 dev: true - /tar/6.1.11: - resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} + /tar/6.1.2: + resolution: {integrity: sha512-EwKEgqJ7nJoS+s8QfLYVGMDmAsj+StbI2AM/RTHeUSsOw6Z8bwNBRv5z3CY0m7laC5qUAqruLX5AhMuc5deY3Q==} engines: {node: '>= 10'} dependencies: chownr: 2.0.0 @@ -4502,11 +4494,10 @@ packages: engines: {node: '>=6'} dev: true - /tsconfig-paths/3.11.0: - resolution: {integrity: sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==} + /tsconfig-paths/3.10.1: + resolution: {integrity: sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q==} dependencies: - '@types/json5': 0.0.29 - json5: 1.0.1 + json5: 2.2.0 minimist: 1.2.5 strip-bom: 3.0.0 dev: true @@ -4515,14 +4506,14 @@ packages: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} dev: true - /tsutils/3.21.0_typescript@4.4.2: + /tsutils/3.21.0_typescript@4.3.5: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 - typescript: 4.4.2 + typescript: 4.3.5 dev: true /type-check/0.4.0: @@ -4573,8 +4564,8 @@ packages: is-typedarray: 1.0.0 dev: true - /typescript/4.4.2: - resolution: {integrity: sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==} + /typescript/4.3.5: + resolution: {integrity: sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==} engines: {node: '>=4.2.0'} hasBin: true dev: true @@ -4583,7 +4574,6 @@ packages: resolution: {integrity: sha512-JhS3hmcVaXlp/xSo3PKY5R0JqKs5M3IV+exdLHW99qKvKivPO4Z8qbej6mte17SOPqAOVMjt/XGgWacnFSzM3g==} engines: {node: '>=0.8.0'} hasBin: true - requiresBuild: true dev: true optional: true @@ -4686,10 +4676,10 @@ packages: /which-boxed-primitive/1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.6 - is-string: 1.0.7 + is-bigint: 1.0.2 + is-boolean-object: 1.1.1 + is-number-object: 1.0.5 + is-string: 1.0.6 is-symbol: 1.0.4 dev: true @@ -4778,7 +4768,7 @@ packages: dependencies: global: 4.4.0 is-function: 1.0.2 - parse-headers: 2.0.4 + parse-headers: 2.0.3 xtend: 4.0.2 dev: true diff --git a/rust-toolchain b/rust-toolchain index b22a7746..f1fe3380 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2021-07-29 \ No newline at end of file +nightly-2021-09-08 \ No newline at end of file diff --git a/scripts/build-skia.js b/scripts/build-skia.js index 021778b4..d9b6ee45 100644 --- a/scripts/build-skia.js +++ b/scripts/build-skia.js @@ -28,6 +28,9 @@ const CC = PLATFORM_NAME === 'win32' ? '\\"clang-cl\\"' : '"clang"' const CXX = PLATFORM_NAME === 'win32' ? '\\"clang-cl\\"' : '"clang++"' let ExtraCflagsCC = '' let ExtraSkiaBuildFlag = '' +let ExtraCflags +let ExtraLdFlags +let ExtraAsmFlags const GN_ARGS = [ `is_official_build=false`, @@ -115,20 +118,16 @@ switch (PLATFORM_NAME) { throw new TypeError(`Don't support ${PLATFORM_NAME} for now`) } -let ExtraCflags -let ExtraLdFlags -let ExtraAsmFlags - switch (TARGET_TRIPLE) { case 'aarch64-unknown-linux-gnu': ExtraSkiaBuildFlag += ' target_cpu="arm64" target_os="linux"' ExtraCflags = - '"--target=aarch64-unknown-linux-gnu", "--sysroot=/usr/aarch64-linux-gnu", "--gcc-toolchain=aarch64-linux-gnu-gcc-10", "-B/usr/aarch64-linux-gnu/bin", "-I/usr/aarch64-linux-gnu/include/c++/10", "-I/usr/aarch64-linux-gnu/include/c++/10/aarch64-linux-gnu"' + '"--target=aarch64-unknown-linux-gnu", "--sysroot=/usr/aarch64-linux-gnu", "--gcc-toolchain=aarch64-linux-gnu-gcc-10", "-B/usr/aarch64-linux-gnu/bin", "-I/usr/aarch64-linux-gnu/include/c++/10", "-I/usr/aarch64-linux-gnu/include/c++/10/aarch64-linux-gnu", "-march=armv8-a"' ExtraCflagsCC += - ', "--target=aarch64-unknown-linux-gnu", "--sysroot=/usr/aarch64-linux-gnu", "--gcc-toolchain=aarch64-linux-gnu-gcc-10", "-B/usr/aarch64-linux-gnu/bin", "-I/usr/aarch64-linux-gnu/include/c++/10", "-I/usr/aarch64-linux-gnu/include/c++/10/aarch64-linux-gnu"' + ', "--target=aarch64-unknown-linux-gnu", "--sysroot=/usr/aarch64-linux-gnu", "--gcc-toolchain=aarch64-linux-gnu-gcc-10", "-B/usr/aarch64-linux-gnu/bin", "-I/usr/aarch64-linux-gnu/include/c++/10", "-I/usr/aarch64-linux-gnu/include/c++/10/aarch64-linux-gnu", "-march=armv8-a"' ExtraLdFlags = '"--target=aarch64-unknown-linux-gnu", "-B/usr/aarch64-linux-gnu/bin", "-L/usr/aarch64-linux-gnu/lib", "-L/usr/lib/gcc-cross/aarch64-linux-gnu/10"' - ExtraAsmFlags = '"--sysroot=/usr/aarch64-linux-gnu", "--target=aarch64-unknown-linux-gnu"' + ExtraAsmFlags = '"--sysroot=/usr/aarch64-linux-gnu", "--target=aarch64-unknown-linux-gnu", "-march=armv8-a"' GN_ARGS.push( `extra_ldflags=[${ExtraLdFlags}]`, @@ -141,12 +140,13 @@ switch (TARGET_TRIPLE) { case 'aarch64-unknown-linux-musl': ExtraSkiaBuildFlag += ' target_cpu="arm64" target_os="linux"' ExtraCflags = - '"--target=aarch64-unknown-linux-musl", "--sysroot=/aarch64-linux-musl-cross/aarch64-linux-musl", "--gcc-toolchain=aarch64-linux-musl-gcc", "-B/aarch64-linux-musl-cross/aarch64-linux-musl/bin", "-I/aarch64-linux-musl-cross/aarch64-linux-musl/include/c++/10.2.1", "-I/aarch64-linux-musl-cross/aarch64-linux-musl/include/c++/10.2.1/aarch64-linux-musl"' + '"--target=aarch64-unknown-linux-musl", "--sysroot=/aarch64-linux-musl-cross/aarch64-linux-musl", "--gcc-toolchain=aarch64-linux-musl-gcc", "-B/aarch64-linux-musl-cross/aarch64-linux-musl/bin", "-I/aarch64-linux-musl-cross/aarch64-linux-musl/include/c++/10.2.1", "-I/aarch64-linux-musl-cross/aarch64-linux-musl/include/c++/10.2.1/aarch64-linux-musl", "-march=armv8-a"' ExtraCflagsCC += - ', "--target=aarch64-unknown-linux-musl", "--sysroot=/aarch64-linux-musl-cross/aarch64-linux-musl", "--gcc-toolchain=aarch64-linux-musl-gcc", "-B/aarch64-linux-musl-cross/aarch64-linux-musl/bin", "-I/aarch64-linux-musl-cross/aarch64-linux-musl/include/c++/10.2.1", "-I/aarch64-linux-musl-cross/aarch64-linux-musl/include/c++/10.2.1/aarch64-linux-musl"' + ', "--target=aarch64-unknown-linux-musl", "--sysroot=/aarch64-linux-musl-cross/aarch64-linux-musl", "--gcc-toolchain=aarch64-linux-musl-gcc", "-B/aarch64-linux-musl-cross/aarch64-linux-musl/bin", "-I/aarch64-linux-musl-cross/aarch64-linux-musl/include/c++/10.2.1", "-I/aarch64-linux-musl-cross/aarch64-linux-musl/include/c++/10.2.1/aarch64-linux-musl", "-march=armv8-a"' ExtraLdFlags = '"--target=aarch64-unknown-linux-musl", "--sysroot=/aarch64-linux-musl-cross/usr", "-B/aarch64-linux-musl-cross/usr/aarch64-linux-musl/bin", "-L/aarch64-linux-musl-cross/usr/aarch64-linux-musl/lib", "-L/aarch64-linux-musl-cross/usr/lib/gcc/aarch64-linux-musl/10.2.1"' - ExtraAsmFlags = '"--sysroot=/aarch64-linux-musl-cross/aarch64-linux-musl", "--target=aarch64-unknown-linux-musl"' + ExtraAsmFlags = + '"--sysroot=/aarch64-linux-musl-cross/aarch64-linux-musl", "--target=aarch64-unknown-linux-musl", "-march=armv8-a"' GN_ARGS.push( `extra_ldflags=[${ExtraLdFlags}]`, `ar="aarch64-linux-musl-ar"`, @@ -158,13 +158,13 @@ switch (TARGET_TRIPLE) { case 'armv7-unknown-linux-gnueabihf': ExtraSkiaBuildFlag += ' target_cpu="armv7a" target_os="linux"' ExtraCflags = - '"--target=arm-unknown-linux-gnueabihf", "--sysroot=/usr/arm-linux-gnueabihf", "--gcc-toolchain=arm-linux-gnueabihf-gcc-10", "-B/usr/arm-linux-gnueabihf/bin", "-I/usr/arm-linux-gnueabihf/include/c++/10", "-I/usr/arm-linux-gnueabihf/include/c++/10/arm-linux-gnueabihf"' + '"--target=arm-unknown-linux-gnueabihf", "--sysroot=/usr/arm-linux-gnueabihf", "--gcc-toolchain=arm-linux-gnueabihf-gcc-10", "-B/usr/arm-linux-gnueabihf/bin", "-I/usr/arm-linux-gnueabihf/include/c++/10", "-I/usr/arm-linux-gnueabihf/include/c++/10/arm-linux-gnueabihf", "-march=armv7-a", "-mthumb"' ExtraCflagsCC += - ', "--target=arm-unknown-linux-gnueabihf", "--sysroot=/usr/arm-linux-gnueabihf", "--gcc-toolchain=arm-linux-gnueabihf-gcc-10", "-B/usr/arm-linux-gnueabihf/bin", "-I/usr/arm-linux-gnueabihf/include/c++/10", "-I/usr/arm-linux-gnueabihf/include/c++/10/arm-linux-gnueabihf"' + ', "--target=arm-unknown-linux-gnueabihf", "--sysroot=/usr/arm-linux-gnueabihf", "--gcc-toolchain=arm-linux-gnueabihf-gcc-10", "-B/usr/arm-linux-gnueabihf/bin", "-I/usr/arm-linux-gnueabihf/include/c++/10", "-I/usr/arm-linux-gnueabihf/include/c++/10/arm-linux-gnueabihf", "-march=armv7-a", "-mthumb"' ExtraLdFlags = '"--target=arm-unknown-linux-gnueabihf", "-B/usr/arm-linux-gnueabihf/bin", "-L/usr/arm-linux-gnueabihf/lib", "-L/usr/lib/gcc-cross/arm-linux-gnueabihf/10"' ExtraAsmFlags = - '"--sysroot=/usr/arm-linux-gnueabihf", "--target=arm-unknown-linux-gnueabihf", "-march=armv7-a", "-mfpu=neon", "-mthumb"' + '"--sysroot=/usr/arm-linux-gnueabihf", "--target=arm-unknown-linux-gnueabihf", "-march=armv7-a", "-mthumb"' GN_ARGS.push( `extra_ldflags=[${ExtraLdFlags}]`, @@ -195,6 +195,14 @@ switch (TARGET_TRIPLE) { ExtraSkiaBuildFlag += ` target_cpu="arm64" ndk="${ANDROID_NDK_HOME}"` break case '': + // native compile for x86_64 systems + // enable AVX2 + // No macOS here, because Github Actions provide ivybridge CPU on macOS, which does not support AVX2 + if (PLATFORM_NAME === 'win32') { + ExtraCflagsCC += ',\\"-march=haswell\\"' + } else if (PLATFORM_NAME === 'linux') { + ExtraCflagsCC += ',"-march=haswell"' + } break default: throw new TypeError(`[${TARGET_TRIPLE}] is not a valid target`) @@ -235,4 +243,8 @@ if (process.env.GN_EXE) { writeFileSync(ninjaToolchain, ninjaToolchainContent.replace('python3', 'python')) } +console.time('Build Skia') + exec(`ninja -C ${OUTPUT_PATH}`) + +console.timeEnd('Build Skia') diff --git a/skia b/skia index 975fcdd7..68eae500 160000 --- a/skia +++ b/skia @@ -1 +1 @@ -Subproject commit 975fcdd755dfc5d57cddbb25857e0c4ac29abe98 +Subproject commit 68eae500785ccc74f49bafeb93a5d632277661c8 diff --git a/skia-c/skia_c.cpp b/skia-c/skia_c.cpp index e230c132..ecc08bcf 100644 --- a/skia-c/skia_c.cpp +++ b/skia-c/skia_c.cpp @@ -217,14 +217,14 @@ extern "C" CANVAS_CAST->clear(static_cast(color)); } - void skiac_canvas_set_transform(skiac_canvas *c_canvas, skiac_transform c_ts) + void skiac_canvas_set_transform(skiac_canvas *c_canvas, skiac_matrix *c_matrix) { - CANVAS_CAST->setMatrix(conv_from_transform(c_ts)); + CANVAS_CAST->setMatrix(*MATRIX_CAST); } - void skiac_canvas_concat(skiac_canvas *c_canvas, skiac_transform c_ts) + void skiac_canvas_concat(skiac_canvas *c_canvas, skiac_matrix *c_matrix) { - CANVAS_CAST->concat(conv_from_transform(c_ts)); + CANVAS_CAST->concat(*MATRIX_CAST); } void skiac_canvas_scale(skiac_canvas *c_canvas, float sx, float sy) @@ -481,6 +481,11 @@ extern "C" CANVAS_CAST->restore(); } + void skiac_canvas_reset(skiac_canvas *c_canvas) + { + CANVAS_CAST->restoreToCount(1); + } + void skiac_canvas_write_pixels(skiac_canvas *c_canvas, int width, int height, uint8_t *pixels, size_t row_bytes, int x, int y) { auto info = SkImageInfo::Make(width, height, SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kUnpremul_SkAlphaType); @@ -658,10 +663,10 @@ extern "C" PATH_CAST->swap(*other); } - void skiac_add_path(skiac_path *c_path, skiac_path *other_path, skiac_transform c_transform) + void skiac_add_path(skiac_path *c_path, skiac_path *other_path, skiac_matrix *c_matrix) { auto path = PATH_CAST; - path->addPath(*reinterpret_cast(other_path), conv_from_transform(c_transform), SkPath::AddPathMode::kExtend_AddPathMode); + path->addPath(*reinterpret_cast(other_path), *MATRIX_CAST, SkPath::AddPathMode::kExtend_AddPathMode); } bool skiac_path_op(skiac_path *c_path_one, skiac_path *c_path_two, int op) @@ -822,13 +827,14 @@ extern "C" PATH_CAST->addCircle(x, y, r); } - void skiac_path_transform(skiac_path *c_path, skiac_transform c_transform) + skiac_path *skiac_path_transform(skiac_path *c_path, skiac_matrix *c_matrix) { - SkMatrix matrix = conv_from_transform(c_transform); - PATH_CAST->transform(matrix, SkApplyPerspectiveClip::kYes); + auto new_path = new SkPath(); + PATH_CAST->transform(*MATRIX_CAST, new_path, SkApplyPerspectiveClip::kYes); + return reinterpret_cast(new_path); } - void skiac_path_transform_matrix(skiac_path *c_path, skiac_matrix *c_matrix) + void skiac_path_transform_self(skiac_path *c_path, skiac_matrix *c_matrix) { SkMatrix matrix = *reinterpret_cast(c_matrix); PATH_CAST->transform(matrix, SkApplyPerspectiveClip::kYes); @@ -943,7 +949,6 @@ extern "C" { const SkPoint startPoint = {c_start_point.x, c_start_point.y}; const SkPoint endPoint = {c_end_point.x, c_end_point.y}; - const auto ts = conv_from_transform(c_ts); auto shader = SkGradientShader::MakeTwoPointConical( startPoint, start_radius, @@ -954,7 +959,7 @@ extern "C" count, (SkTileMode)tile_mode, flags, - &ts) + nullptr) .release(); if (shader) @@ -1039,6 +1044,63 @@ extern "C" return reinterpret_cast(new SkMatrix()); } + skiac_matrix *skiac_matrix_new(float a, float b, float c, float d, float e, float f) + { + auto m = new SkMatrix(SkMatrix::MakeAll(a, b, c, d, e, f, 0, 0, 1)); + return reinterpret_cast(m); + } + + skiac_matrix *skiac_matrix_from_ts(const skiac_transform *c_ts) + { + auto matrix = conv_from_transform(*c_ts); + auto m = new SkMatrix(matrix); + return reinterpret_cast(m); + } + + skiac_matrix *skiac_matrix_create_rotated(float rotation, float x, float y) + { + auto matrix = new SkMatrix(); + matrix->setRotate(rotation, x, y); + return reinterpret_cast(matrix); + } + + skiac_matrix *skiac_matrix_create_translated(float x, float y) + { + auto matrix = new SkMatrix(); + matrix->setTranslate(x, y); + return reinterpret_cast(matrix); + } + + skiac_matrix *skiac_matrix_concat(skiac_matrix *c_matrix, skiac_matrix *other) + { + auto m = SkMatrix::Concat(*MATRIX_CAST, *reinterpret_cast(other)); + auto r = new SkMatrix(m); + return reinterpret_cast(r); + } + + skiac_matrix *skiac_matrix_multiply(skiac_matrix *c_matrix, skiac_matrix *other) + { + auto m = *MATRIX_CAST; + auto o = *reinterpret_cast(other); + auto r = new SkMatrix(o * m); + return reinterpret_cast(r); + } + + void skiac_matrix_map_points(skiac_matrix *c_matrix, float x1, float y1, float x2, float y2, skiac_mapped_point *mapped_point) + { + SkPoint dst[2]; + auto p1 = SkPoint::Make(x1, y1); + auto p2 = SkPoint::Make(x2, y2); + SkPoint src[] = {p1, p2}; + MATRIX_CAST->mapPoints(src, dst, 2); + auto dp1 = dst[0]; + auto dp2 = dst[1]; + mapped_point->x1 = dp1.fX; + mapped_point->y1 = dp1.fY; + mapped_point->x2 = dp2.fX; + mapped_point->y2 = dp2.fY; + } + skiac_matrix *skiac_matrix_clone(skiac_matrix *c_matrix) { return reinterpret_cast(new SkMatrix(*MATRIX_CAST)); @@ -1049,11 +1111,32 @@ extern "C" MATRIX_CAST->preTranslate(dx, dy); } + void skiac_matrix_pre_concat(skiac_matrix *c_matrix, skiac_matrix *other) + { + MATRIX_CAST->preConcat(*reinterpret_cast(other)); + } + + void skiac_matrix_pre_scale(skiac_matrix *c_matrix, float sx, float sy) + { + MATRIX_CAST->preScale(sx, sy); + } + + void skiac_matrix_pre_concat_transform(skiac_matrix *c_matrix, skiac_transform c_ts) + { + auto ts = conv_from_transform(c_ts); + MATRIX_CAST->preConcat(ts); + } + void skiac_matrix_pre_rotate(skiac_matrix *c_matrix, float degrees) { MATRIX_CAST->preRotate(degrees); } + void skiac_matrix_pre_rotate_x_y(skiac_matrix *c_matrix, float degrees, float x, float y) + { + MATRIX_CAST->preRotate(degrees, x, y); + } + bool skiac_matrix_invert(skiac_matrix *c_matrix, skiac_matrix *inverse) { return MATRIX_CAST->invert(reinterpret_cast(inverse)); diff --git a/skia-c/skia_c.hpp b/skia-c/skia_c.hpp index 89b6b2e1..44a7cac8 100644 --- a/skia-c/skia_c.hpp +++ b/skia-c/skia_c.hpp @@ -187,6 +187,14 @@ struct skiac_sk_data skiac_data *data; }; +struct skiac_mapped_point +{ + float x1; + float y1; + float x2; + float y2; +}; + extern "C" { @@ -214,8 +222,8 @@ extern "C" // Canvas void skiac_canvas_clear(skiac_canvas *c_canvas, uint32_t color); - void skiac_canvas_set_transform(skiac_canvas *c_canvas, skiac_transform c_ts); - void skiac_canvas_concat(skiac_canvas *c_canvas, skiac_transform c_ts); + void skiac_canvas_set_transform(skiac_canvas *c_canvas, skiac_matrix *c_matrix); + void skiac_canvas_concat(skiac_canvas *c_canvas, skiac_matrix *c_matrix); void skiac_canvas_scale(skiac_canvas *c_canvas, float sx, float sy); void skiac_canvas_translate(skiac_canvas *c_canvas, float dx, float dy); void skiac_canvas_rotate(skiac_canvas *c_canvas, float degrees); @@ -271,6 +279,7 @@ extern "C" void skiac_canvas_clip_path(skiac_canvas *c_canvas, skiac_path *c_path); void skiac_canvas_save(skiac_canvas *c_canvas); void skiac_canvas_restore(skiac_canvas *c_canvas); + void skiac_canvas_reset(skiac_canvas *c_canvas); void skiac_canvas_write_pixels(skiac_canvas *c_canvas, int width, int height, uint8_t *pixels, size_t row_bytes, int x, int y); void skiac_canvas_write_pixels_dirty(skiac_canvas *c_canvas, int width, int height, uint8_t *pixels, size_t row_bytes, size_t length, float x, float y, float dirty_x, float dirty_y, float dirty_width, float dirty_height); @@ -303,7 +312,7 @@ extern "C" skiac_path *skiac_path_from_svg(char *svg_path); skiac_path *skiac_path_clone(skiac_path *c_path); void skiac_path_swap(skiac_path *c_path, skiac_path *other_path); - void skiac_add_path(skiac_path *c_path, skiac_path *other_path, skiac_transform c_transform); + void skiac_add_path(skiac_path *c_path, skiac_path *other_path, skiac_matrix *c_matrix); bool skiac_path_op(skiac_path *c_path_one, skiac_path *c_path_two, int op); void skiac_path_to_svg_string(skiac_path *c_path, skiac_string *c_string); bool skiac_path_simplify(skiac_path *c_path); @@ -328,8 +337,8 @@ extern "C" void skiac_path_close(skiac_path *c_path); void skiac_path_add_rect(skiac_path *c_path, float l, float t, float r, float b); void skiac_path_add_circle(skiac_path *c_path, float x, float y, float r); - void skiac_path_transform(skiac_path *c_path, skiac_transform c_transform); - void skiac_path_transform_matrix(skiac_path *c_path, skiac_matrix *c_matrix); + skiac_path *skiac_path_transform(skiac_path *c_path, skiac_matrix *c_matrix); + void skiac_path_transform_self(skiac_path *c_path, skiac_matrix *c_matrix); bool skiac_path_is_empty(skiac_path *c_path); bool skiac_path_hit_test(skiac_path *c_path, float x, float y, int type); bool skiac_path_stroke_hit_test(skiac_path *c_path, float x, float y, float stroke_w); @@ -377,9 +386,20 @@ extern "C" // Matrix skiac_matrix *skiac_matrix_create(); + skiac_matrix *skiac_matrix_new(float a, float b, float c, float d, float e, float f); + skiac_matrix *skiac_matrix_from_ts(const skiac_transform *c_ts); + skiac_matrix *skiac_matrix_create_rotated(float rotation, float x, float y); + skiac_matrix *skiac_matrix_create_translated(float x, float y); + skiac_matrix *skiac_matrix_concat(skiac_matrix *c_matrix, skiac_matrix *other); + skiac_matrix *skiac_matrix_multiply(skiac_matrix *c_matrix, skiac_matrix *other); skiac_matrix *skiac_matrix_clone(skiac_matrix *c_matrix); + void skiac_matrix_map_points(skiac_matrix *c_matrix, float x1, float y1, float x2, float y2, skiac_mapped_point *mapped_point); void skiac_matrix_pre_translate(skiac_matrix *c_matrix, float dx, float dy); + void skiac_matrix_pre_concat(skiac_matrix *c_matrix, skiac_matrix *other); + void skiac_matrix_pre_scale(skiac_matrix *c_matrix, float sx, float sy); + void skiac_matrix_pre_concat_transform(skiac_matrix *c_matrix, skiac_transform c_ts); void skiac_matrix_pre_rotate(skiac_matrix *c_matrix, float degrees); + void skiac_matrix_pre_rotate_x_y(skiac_matrix *c_matrix, float degrees, float x, float y); bool skiac_matrix_invert(skiac_matrix *c_matrix, skiac_matrix *inverse); skiac_transform skiac_matrix_to_transform(skiac_matrix *c_matrix); void skiac_matrix_destroy(skiac_matrix *c_matrix); diff --git a/src/ctx.rs b/src/ctx.rs index 5fe41619..16b4794c 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -1,4 +1,4 @@ -use std::convert::{TryFrom, TryInto}; +use std::convert::TryFrom; use std::f32::consts::PI; use std::mem; use std::rc::Rc; @@ -30,7 +30,6 @@ pub(crate) enum ImageOrCanvas { } impl ImageOrCanvas { - #[inline] pub(crate) fn get_image(&mut self) -> Option<&mut Image> { match self { Self::Image(i) => Some(i), @@ -44,6 +43,7 @@ pub struct Context { path: Path, pub alpha: bool, pub(crate) states: Vec, + state: Context2dRenderingState, pub font_collection: Rc, pub width: u32, pub height: u32, @@ -51,7 +51,6 @@ pub struct Context { } impl Context { - #[inline(always)] pub fn create_js_class(env: &Env) -> Result { env.define_class( "CanvasRenderingContext2D", @@ -162,7 +161,6 @@ impl Context { ) } - #[inline(always)] pub fn new_svg( width: u32, height: u32, @@ -172,12 +170,12 @@ impl Context { let (surface, stream) = Surface::new_svg(width, height, AlphaType::Unpremultiplied, svg_export_flag) .ok_or_else(|| Error::from_reason("Create skia svg surface failed".to_owned()))?; - let states = vec![Context2dRenderingState::default()]; Ok(Context { surface, alpha: true, path: Path::new(), - states, + states: vec![], + state: Context2dRenderingState::default(), font_collection: font_collection.clone(), width, height, @@ -185,16 +183,15 @@ impl Context { }) } - #[inline(always)] pub fn new(width: u32, height: u32, font_collection: &mut Rc) -> Result { let surface = Surface::new_rgba(width, height) .ok_or_else(|| Error::from_reason("Create skia surface failed".to_owned()))?; - let states = vec![Context2dRenderingState::default()]; Ok(Context { surface, alpha: true, path: Path::new(), - states, + states: vec![], + state: Context2dRenderingState::default(), font_collection: font_collection.clone(), width, height, @@ -202,7 +199,48 @@ impl Context { }) } - #[inline(always)] + pub fn arc( + &mut self, + center_x: f32, + center_y: f32, + radius: f32, + start_angle: f32, + end_angle: f32, + from_end: bool, + ) { + self + .path + .arc(center_x, center_y, radius, start_angle, end_angle, from_end); + } + + pub fn ellipse( + &mut self, + x: f32, + y: f32, + radius_x: f32, + radius_y: f32, + rotation: f32, + start_angle: f32, + end_angle: f32, + ccw: bool, + ) { + self.path.ellipse( + x, + y, + radius_x, + radius_y, + rotation, + start_angle, + end_angle, + ccw, + ); + } + + pub fn begin_path(&mut self) { + let mut new_sub_path = Path::new(); + self.path.swap(&mut new_sub_path); + } + pub fn clip(&mut self, path: Option<&mut Path>, fill_rule: FillType) { let clip = match path { Some(path) => path, @@ -212,26 +250,25 @@ impl Context { self.surface.canvas.set_clip_path(clip); } - #[inline(always)] pub fn save(&mut self) { - self.surface.save(); - self.states.push(self.states.last().unwrap().clone()); + self.surface.canvas.save(); + self.states.push(self.state.clone()); } - #[inline(always)] pub fn restore(&mut self) { - self.surface.restore(); - if self.states.len() > 1 { - mem::drop(self.states.pop().unwrap()); + if let Some(s) = self.states.pop() { + self.path.transform_self(&self.state.transform); + self.surface.canvas.restore(); + self.path.transform_self(&s.transform.invert().unwrap()); + self.state = s; } } - #[inline(always)] pub fn stroke_rect(&mut self, x: f32, y: f32, w: f32, h: f32) -> result::Result<(), SkError> { let stroke_paint = self.stroke_paint()?; if let Some(shadow_paint) = self.shadow_blur_paint(&stroke_paint) { let surface = &mut self.surface; - let last_state = self.states.last().unwrap(); + let last_state = &self.state; surface.save(); Self::apply_shadow_offset_matrix( surface, @@ -247,7 +284,54 @@ impl Context { Ok(()) } - #[inline(always)] + pub fn translate(&mut self, x: f32, y: f32) { + let s = &mut self.state; + let inverse = Matrix::translated(-x, -y); + self.path.transform_self(&inverse); + s.transform.pre_translate(x, y); + self.surface.canvas.set_transform(&s.transform); + } + + pub fn transform(&mut self, ts: Matrix) -> result::Result<(), SkError> { + let s = &mut self.state; + self.path.transform_self( + &ts + .invert() + .ok_or_else(|| SkError::InvalidTransform(ts.clone()))?, + ); + s.transform = ts.multiply(&s.transform); + self.surface.set_transform(&s.transform); + Ok(()) + } + + pub fn rotate(&mut self, angle: f32) { + let s = &mut self.state; + let degrees = angle as f32 / PI * 180f32; + let inverse = Matrix::rotated(-angle, 0.0, 0.0); + self.path.transform_self(&inverse); + s.transform.pre_rotate(degrees); + self.surface.canvas.set_transform(&s.transform); + } + + pub fn scale(&mut self, x: f32, y: f32) { + let s = &mut self.state; + let mut inverse = Matrix::identity(); + inverse.pre_scale(1f32 / x, 1f32 / y); + self.path.transform_self(&inverse); + s.transform.pre_scale(x, y); + self.surface.canvas.set_transform(&s.transform); + } + + pub fn set_transform(&mut self, ts: Matrix) { + self.surface.canvas.set_transform(&ts); + self.state.transform = ts; + } + + pub fn reset_transform(&mut self) { + self.surface.canvas.reset_transform(); + self.state.transform = Matrix::identity(); + } + pub fn stroke_text( &mut self, text: &str, @@ -260,12 +344,11 @@ impl Context { Ok(()) } - #[inline(always)] pub fn fill_rect(&mut self, x: f32, y: f32, w: f32, h: f32) -> result::Result<(), SkError> { let fill_paint = self.fill_paint()?; if let Some(shadow_paint) = self.shadow_blur_paint(&fill_paint) { let surface = &mut self.surface; - let last_state = self.states.last().unwrap(); + let last_state = &self.state; surface.save(); Self::apply_shadow_offset_matrix( surface, @@ -281,7 +364,6 @@ impl Context { Ok(()) } - #[inline(always)] pub fn fill_text( &mut self, text: &str, @@ -294,13 +376,15 @@ impl Context { Ok(()) } - #[inline(always)] - pub fn stroke(&mut self, path: Option<&Path>) -> Result<()> { - let p = path.unwrap_or(&self.path); + pub fn stroke(&mut self, path: Option<&mut Path>) -> Result<()> { + let last_state = &self.state; + let p = match path { + Some(path) => path, + None => &self.path, + }; let stroke_paint = self.stroke_paint()?; if let Some(shadow_paint) = self.shadow_blur_paint(&stroke_paint) { let surface = &mut self.surface; - let last_state = self.states.last().unwrap(); surface.save(); Self::apply_shadow_offset_matrix( surface, @@ -315,12 +399,12 @@ impl Context { Ok(()) } - #[inline(always)] pub fn fill( &mut self, path: Option<&mut Path>, fill_rule: FillType, ) -> result::Result<(), SkError> { + let last_state = &self.state; let p = if let Some(p) = path { p.set_fill_type(fill_rule); p @@ -331,27 +415,25 @@ impl Context { let fill_paint = self.fill_paint()?; if let Some(shadow_paint) = self.shadow_blur_paint(&fill_paint) { let surface = &mut self.surface; - let last_state = self.states.last().unwrap(); surface.save(); Self::apply_shadow_offset_matrix( surface, last_state.shadow_offset_x, last_state.shadow_offset_y, )?; - self.surface.canvas.draw_path(p, &shadow_paint); - self.surface.restore(); + surface.canvas.draw_path(p, &shadow_paint); + surface.restore(); mem::drop(shadow_paint); } self.surface.draw_path(p, &fill_paint); Ok(()) } - #[inline(always)] pub fn fill_paint(&self) -> result::Result { - let current_paint = &self.states.last().unwrap().paint; + let last_state = &self.state; + let current_paint = &last_state.paint; let mut paint = current_paint.clone(); paint.set_style(PaintStyle::Fill); - let last_state = self.states.last().unwrap(); let alpha = current_paint.get_alpha(); match &last_state.fill_style { Pattern::Color(c, _) => { @@ -360,8 +442,8 @@ impl Context { paint.set_color(color.red, color.green, color.blue, color.alpha); } Pattern::Gradient(g) => { - let current_transform = self.surface.canvas.get_transform(); - let shader = g.get_shader(¤t_transform)?; + let current_transform = &last_state.transform; + let shader = g.get_shader(current_transform.get_transform())?; paint.set_color(0, 0, 0, alpha); paint.set_shader(&shader); } @@ -383,12 +465,11 @@ impl Context { Ok(paint) } - #[inline(always)] fn stroke_paint(&self) -> result::Result { - let current_paint = &self.states.last().unwrap().paint; + let last_state = &self.state; + let current_paint = &last_state.paint; let mut paint = current_paint.clone(); paint.set_style(PaintStyle::Stroke); - let last_state = self.states.last().unwrap(); let global_alpha = current_paint.get_alpha(); match &last_state.stroke_style { Pattern::Color(c, _) => { @@ -397,8 +478,8 @@ impl Context { paint.set_color(color.red, color.green, color.blue, color.alpha); } Pattern::Gradient(g) => { - let current_transform = self.surface.canvas.get_transform(); - let shader = g.get_shader(¤t_transform)?; + let current_transform = &last_state.transform; + let shader = g.get_shader(current_transform.get_transform())?; paint.set_color(0, 0, 0, global_alpha); paint.set_shader(&shader); } @@ -420,10 +501,9 @@ impl Context { Ok(paint) } - #[inline(always)] fn drop_shadow_paint(&self, paint: &Paint) -> Option { let alpha = paint.get_alpha(); - let last_state = self.states.last().unwrap(); + let last_state = &self.state; let shadow_color = &last_state.shadow_color; let mut shadow_alpha = shadow_color.alpha; shadow_alpha = ((shadow_alpha as f32) * (alpha as f32 / 255.0)) as u8; @@ -454,10 +534,9 @@ impl Context { Some(drop_shadow_paint) } - #[inline(always)] fn shadow_blur_paint(&self, paint: &Paint) -> Option { let alpha = paint.get_alpha(); - let last_state = self.states.last().unwrap(); + let last_state = &self.state; let shadow_color = &last_state.shadow_color; let mut shadow_alpha = shadow_color.alpha; shadow_alpha = ((shadow_alpha as f32) * (alpha as f32 / 255.0)) as u8; @@ -483,7 +562,6 @@ impl Context { Some(drop_shadow_paint) } - #[inline(always)] fn draw_image( &mut self, image: &Image, @@ -520,7 +598,6 @@ impl Context { Ok(()) } - #[inline(always)] fn draw_text( &mut self, text: &str, @@ -529,7 +606,7 @@ impl Context { max_width: f32, paint: &Paint, ) -> result::Result<(), SkError> { - let state = self.states.last().unwrap(); + let state = &self.state; let weight = state.font_style.weight; let stretch = state.font_style.stretch; let slant = state.font_style.style; @@ -575,9 +652,8 @@ impl Context { Ok(()) } - #[inline(always)] fn get_line_metrics(&mut self, text: &str) -> result::Result { - let state = self.states.last().unwrap(); + let state = &self.state; let fill_paint = self.fill_paint()?; let weight = state.font_style.weight; let stretch = state.font_style.stretch; @@ -598,7 +674,6 @@ impl Context { Ok(line_metrics) } - #[inline(always)] fn apply_shadow_offset_matrix( surface: &mut Surface, shadow_offset_x: f32, @@ -608,19 +683,19 @@ impl Context { let invert = current_transform .invert() .ok_or_else(|| SkError::Generic("Invert matrix failed".to_owned()))?; - surface.canvas.concat(invert.into_transform()); + surface.canvas.concat(&invert); let mut shadow_offset = current_transform.clone(); shadow_offset.pre_translate(shadow_offset_x, shadow_offset_y); - surface.canvas.concat(shadow_offset.into_transform()); - surface.canvas.concat(current_transform.into_transform()); + surface.canvas.concat(&shadow_offset); + surface.canvas.concat(¤t_transform); Ok(()) } } #[js_function(4)] fn context_2d_constructor(ctx: CallContext) -> Result { - let width: u32 = ctx.get::(0)?.try_into()?; - let height: u32 = ctx.get::(1)?.try_into()?; + let width = ctx.get::(0)?.get_uint32()?; + let height = ctx.get::(1)?.get_uint32()?; let font_collection_js = ctx.get::(2)?; let font_collection = ctx.env.unwrap::>(&font_collection_js)?; @@ -645,24 +720,16 @@ fn context_2d_constructor(ctx: CallContext) -> Result { fn arc(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let center_x: f64 = ctx.get::(0)?.try_into()?; - let center_y: f64 = ctx.get::(1)?.try_into()?; - let radius: f64 = ctx.get::(2)?.try_into()?; - let start_angle: f64 = ctx.get::(3)?.try_into()?; - let end_angle: f64 = ctx.get::(4)?.try_into()?; - let from_end = if ctx.length == 6 { - ctx.get::(5)?.get_value()? - } else { - false - }; - context_2d.path.arc( - center_x as f32, - center_y as f32, - radius as f32, - start_angle as f32, - end_angle as f32, - from_end, - ); + let center_x = ctx.get::(0)?.get_double()? as f32; + let center_y = ctx.get::(1)?.get_double()? as f32; + let radius = ctx.get::(2)?.get_double()? as f32; + let start_angle = ctx.get::(3)?.get_double()? as f32; + let end_angle = ctx.get::(4)?.get_double()? as f32; + let from_end = ctx + .get::(5) + .and_then(|js_bool| js_bool.get_value()) + .unwrap_or(false); + context_2d.arc(center_x, center_y, radius, start_angle, end_angle, from_end); ctx.env.get_undefined() } @@ -671,19 +738,15 @@ fn arc_to(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let ctrl_x: f64 = ctx.get::(0)?.try_into()?; - let ctrl_y: f64 = ctx.get::(1)?.try_into()?; - let to_x: f64 = ctx.get::(2)?.try_into()?; - let to_y: f64 = ctx.get::(3)?.try_into()?; - let radius: f64 = ctx.get::(4)?.try_into()?; + let ctrl_x = ctx.get::(0)?.get_double()? as f32; + let ctrl_y = ctx.get::(1)?.get_double()? as f32; + let to_x = ctx.get::(2)?.get_double()? as f32; + let to_y = ctx.get::(3)?.get_double()? as f32; + let radius = ctx.get::(4)?.get_double()? as f32; - context_2d.path.arc_to_tangent( - ctrl_x as f32, - ctrl_y as f32, - to_x as f32, - to_y as f32, - radius as f32, - ); + context_2d + .path + .arc_to_tangent(ctrl_x, ctrl_y, to_x, to_y, radius); ctx.env.get_undefined() } @@ -691,11 +754,7 @@ fn arc_to(ctx: CallContext) -> Result { fn begin_path(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - - let mut new_sub_path = Path::new(); - - context_2d.path.swap(&mut new_sub_path); - + context_2d.begin_path(); ctx.env.get_undefined() } @@ -704,21 +763,14 @@ fn bezier_curve_to(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let cp1x: f64 = ctx.get::(0)?.try_into()?; - let cp1y: f64 = ctx.get::(1)?.try_into()?; - let cp2x: f64 = ctx.get::(2)?.try_into()?; - let cp2y: f64 = ctx.get::(3)?.try_into()?; - let x: f64 = ctx.get::(4)?.try_into()?; - let y: f64 = ctx.get::(5)?.try_into()?; + let cp1x = ctx.get::(0)?.get_double()? as f32; + let cp1y = ctx.get::(1)?.get_double()? as f32; + let cp2x = ctx.get::(2)?.get_double()? as f32; + let cp2y = ctx.get::(3)?.get_double()? as f32; + let x = ctx.get::(4)?.get_double()? as f32; + let y = ctx.get::(5)?.get_double()? as f32; - context_2d.path.cubic_to( - cp1x as f32, - cp1y as f32, - cp2x as f32, - cp2y as f32, - x as f32, - y as f32, - ); + context_2d.path.cubic_to(cp1x, cp1y, cp2x, cp2y, x, y); ctx.env.get_undefined() } @@ -728,14 +780,12 @@ fn quadratic_curve_to(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let cpx: f64 = ctx.get::(0)?.try_into()?; - let cpy: f64 = ctx.get::(1)?.try_into()?; - let x: f64 = ctx.get::(2)?.try_into()?; - let y: f64 = ctx.get::(3)?.try_into()?; + let cpx = ctx.get::(0)?.get_double()? as f32; + let cpy = ctx.get::(1)?.get_double()? as f32; + let x = ctx.get::(2)?.get_double()? as f32; + let y = ctx.get::(3)?.get_double()? as f32; - context_2d - .path - .quad_to(cpx as f32, cpy as f32, x as f32, y as f32); + context_2d.path.quad_to(cpx, cpy, x, y); ctx.env.get_undefined() } @@ -767,10 +817,10 @@ fn rect(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; - let width: f64 = ctx.get::(2)?.try_into()?; - let height: f64 = ctx.get::(3)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; + let width = ctx.get::(2)?.get_double()? as f32; + let height = ctx.get::(3)?.get_double()? as f32; context_2d .path @@ -835,9 +885,8 @@ fn rotate(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let angle: f64 = ctx.get::(0)?.try_into()?; - context_2d.path.transform(&Transform::rotate(-angle as f32)); - context_2d.surface.canvas.rotate(angle as f32 / PI * 180f32); + let angle = ctx.get::(0)?.get_double()? as f32; + context_2d.rotate(angle); ctx.env.get_undefined() } @@ -845,53 +894,48 @@ fn rotate(ctx: CallContext) -> Result { fn clear_rect(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; - let width: f64 = ctx.get::(2)?.try_into()?; - let height: f64 = ctx.get::(3)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; + let width = ctx.get::(2)?.get_double()? as f32; + let height = ctx.get::(3)?.get_double()? as f32; let mut paint = Paint::new(); paint.set_style(PaintStyle::Fill); paint.set_color(0, 0, 0, 0); paint.set_stroke_miter(10.0); paint.set_blend_mode(BlendMode::Clear); - context_2d - .surface - .draw_rect(x as f32, y as f32, width as f32, height as f32, &paint); + context_2d.surface.draw_rect(x, y, width, height, &paint); ctx.env.get_undefined() } #[js_function(4)] fn create_linear_gradient(ctx: CallContext) -> Result { - let x0: f64 = ctx.get::(0)?.try_into()?; - let y0: f64 = ctx.get::(1)?.try_into()?; - let x1: f64 = ctx.get::(2)?.try_into()?; - let y1: f64 = ctx.get::(3)?.try_into()?; - let linear_gradient = - CanvasGradient::create_linear_gradient(x0 as f32, y0 as f32, x1 as f32, y1 as f32); + let x0 = ctx.get::(0)?.get_double()? as f32; + let y0 = ctx.get::(1)?.get_double()? as f32; + let x1 = ctx.get::(2)?.get_double()? as f32; + let y1 = ctx.get::(3)?.get_double()? as f32; + let linear_gradient = CanvasGradient::create_linear_gradient(x0, y0, x1, y1); linear_gradient.into_js_instance(ctx.env) } #[js_function(6)] fn create_radial_gradient(ctx: CallContext) -> Result { - let x0: f64 = ctx.get::(0)?.try_into()?; - let y0: f64 = ctx.get::(1)?.try_into()?; - let r0: f64 = ctx.get::(2)?.try_into()?; - let x1: f64 = ctx.get::(3)?.try_into()?; - let y1: f64 = ctx.get::(4)?.try_into()?; - let r1: f64 = ctx.get::(5)?.try_into()?; - let radial_gradient = CanvasGradient::create_radial_gradient( - x0 as f32, y0 as f32, r0 as f32, x1 as f32, y1 as f32, r1 as f32, - ); + let x0 = ctx.get::(0)?.get_double()? as f32; + let y0 = ctx.get::(1)?.get_double()? as f32; + let r0 = ctx.get::(2)?.get_double()? as f32; + let x1 = ctx.get::(3)?.get_double()? as f32; + let y1 = ctx.get::(4)?.get_double()? as f32; + let r1 = ctx.get::(5)?.get_double()? as f32; + let radial_gradient = CanvasGradient::create_radial_gradient(x0, y0, r0, x1, y1, r1); radial_gradient.into_js_instance(ctx.env) } #[js_function(3)] fn create_conic_gradient(ctx: CallContext) -> Result { - let r: f64 = ctx.get::(0)?.try_into()?; - let x: f64 = ctx.get::(1)?.try_into()?; - let y: f64 = ctx.get::(2)?.try_into()?; - let conic_gradient = CanvasGradient::create_conic_gradient(x as f32, y as f32, r as f32); + let r = ctx.get::(0)?.get_double()? as f32; + let x = ctx.get::(1)?.get_double()? as f32; + let y = ctx.get::(2)?.get_double()? as f32; + let conic_gradient = CanvasGradient::create_conic_gradient(x, y, r); conic_gradient.into_js_instance(ctx.env) } @@ -1044,31 +1088,27 @@ fn is_point_in_path(ctx: CallContext) -> Result { let result; if ctx.length == 2 { - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; - result = context_2d - .path - .hit_test(y as f32, x as f32, FillType::Winding); + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; + result = context_2d.path.hit_test(y, x, FillType::Winding); ctx.env.get_boolean(result) } else if ctx.length == 3 { let input = ctx.get::(0)?; match input.get_type()? { ValueType::Number => { - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; let fill_rule_js = ctx.get::(2)?.into_utf8()?; - result = context_2d.path.hit_test( - y as f32, - x as f32, - FillType::from_str(fill_rule_js.as_str()?)?, - ); + result = context_2d + .path + .hit_test(y, x, FillType::from_str(fill_rule_js.as_str()?)?); } ValueType::Object => { - let x: f64 = ctx.get::(1)?.try_into()?; - let y: f64 = ctx.get::(2)?.try_into()?; + let x = ctx.get::(1)?.get_double()? as f32; + let y = ctx.get::(2)?.get_double()? as f32; let path_js = ctx.get::(0)?; let path = ctx.env.unwrap::(&path_js)?; - result = path.hit_test(x as f32, y as f32, FillType::Winding); + result = path.hit_test(x, y, FillType::Winding); } _ => { return Err(Error::new( @@ -1081,14 +1121,10 @@ fn is_point_in_path(ctx: CallContext) -> Result { } else if ctx.length == 4 { let path_js = ctx.get::(0)?; let path = ctx.env.unwrap::(&path_js)?; - let x: f64 = ctx.get::(1)?.try_into()?; - let y: f64 = ctx.get::(2)?.try_into()?; + let x = ctx.get::(1)?.get_double()? as f32; + let y = ctx.get::(2)?.get_double()? as f32; let fill_rule_js = ctx.get::(3)?.into_utf8()?; - result = path.hit_test( - y as f32, - x as f32, - FillType::from_str(fill_rule_js.as_str()?)?, - ); + result = path.hit_test(y, x, FillType::from_str(fill_rule_js.as_str()?)?); ctx.env.get_boolean(result) } else { Err(Error::new( @@ -1105,20 +1141,18 @@ fn is_point_in_stroke(ctx: CallContext) -> Result { let mut result = false; if ctx.length == 2 { - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; - let stroke_w = context_2d.states.last().unwrap().paint.get_stroke_width() as f32; - result = context_2d - .path - .stroke_hit_test(x as f32, y as f32, stroke_w); + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; + let stroke_w = context_2d.state.paint.get_stroke_width(); + result = context_2d.path.stroke_hit_test(x, y, stroke_w); } else if ctx.length == 3 { let path_js = ctx.get::(0)?; let path = ctx.env.unwrap::(&path_js)?; - let x: f64 = ctx.get::(1)?.try_into()?; - let y: f64 = ctx.get::(2)?.try_into()?; - let stroke_w = context_2d.states.last().unwrap().paint.get_stroke_width() as f32; - result = path.stroke_hit_test(x as f32, y as f32, stroke_w); + let x = ctx.get::(1)?.get_double()? as f32; + let y = ctx.get::(2)?.get_double()? as f32; + let stroke_w = context_2d.state.paint.get_stroke_width(); + result = path.stroke_hit_test(x, y, stroke_w); } ctx.env.get_boolean(result) } @@ -1127,27 +1161,27 @@ fn is_point_in_stroke(ctx: CallContext) -> Result { fn ellipse(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; - let radius_x: f64 = ctx.get::(2)?.try_into()?; - let radius_y: f64 = ctx.get::(3)?.try_into()?; - let rotation: f64 = ctx.get::(4)?.try_into()?; - let start_angle: f64 = ctx.get::(5)?.try_into()?; - let end_angle: f64 = ctx.get::(6)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; + let radius_x = ctx.get::(2)?.get_double()? as f32; + let radius_y = ctx.get::(3)?.get_double()? as f32; + let rotation = ctx.get::(4)?.get_double()? as f32; + let start_angle = ctx.get::(5)?.get_double()? as f32; + let end_angle = ctx.get::(6)?.get_double()? as f32; let from_end = if ctx.length == 8 { ctx.get::(7)?.get_value()? } else { false }; - context_2d.path.ellipse( - x as f32, - y as f32, - radius_x as f32, - radius_y as f32, - rotation as f32, - start_angle as f32, - end_angle as f32, + context_2d.ellipse( + x, + y, + radius_x, + radius_y, + rotation, + start_angle, + end_angle, from_end, ); ctx.env.get_undefined() @@ -1158,10 +1192,10 @@ fn line_to(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; - context_2d.path.line_to(x as f32, y as f32); + context_2d.path.line_to(x, y); ctx.env.get_undefined() } @@ -1208,10 +1242,10 @@ fn move_to(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; - context_2d.path.move_to(x as f32, y as f32); + context_2d.path.move_to(x, y); ctx.env.get_undefined() } @@ -1220,13 +1254,8 @@ fn move_to(ctx: CallContext) -> Result { fn set_miter_limit(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let miter: f64 = ctx.get::(0)?.try_into()?; - context_2d - .states - .last_mut() - .unwrap() - .paint - .set_stroke_miter(miter as f32); + let miter = ctx.get::(0)?.get_double()? as f32; + context_2d.state.paint.set_stroke_miter(miter); ctx.env.get_undefined() } @@ -1237,20 +1266,20 @@ fn get_miter_limit(ctx: CallContext) -> Result { ctx .env - .create_double(context_2d.states.last().unwrap().paint.get_stroke_miter() as f64) + .create_double(context_2d.state.paint.get_stroke_miter() as f64) } #[js_function(4)] fn stroke_rect(ctx: CallContext) -> Result { - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; - let w: f64 = ctx.get::(2)?.try_into()?; - let h: f64 = ctx.get::(3)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; + let w = ctx.get::(2)?.get_double()? as f32; + let h = ctx.get::(3)?.get_double()? as f32; let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - context_2d.stroke_rect(x as f32, y as f32, w as f32, h as f32)?; + context_2d.stroke_rect(x, y, w, h)?; ctx.env.get_undefined() } @@ -1258,8 +1287,8 @@ fn stroke_rect(ctx: CallContext) -> Result { #[js_function(4)] fn stroke_text(ctx: CallContext) -> Result { let text = ctx.get::(0)?.into_utf8()?; - let x: f64 = ctx.get::(1)?.try_into()?; - let y: f64 = ctx.get::(2)?.try_into()?; + let x = ctx.get::(1)?.get_double()? as f32; + let y = ctx.get::(2)?.get_double()? as f32; let max_width = if ctx.length == 3 { MAX_TEXT_WIDTH } else { @@ -1268,22 +1297,22 @@ fn stroke_text(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - context_2d.stroke_text(text.as_str()?, x as f32, y as f32, max_width)?; + context_2d.stroke_text(text.as_str()?, x, y, max_width)?; ctx.env.get_undefined() } #[js_function(4)] fn fill_rect(ctx: CallContext) -> Result { - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; - let w: f64 = ctx.get::(2)?.try_into()?; - let h: f64 = ctx.get::(3)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; + let w = ctx.get::(2)?.get_double()? as f32; + let h = ctx.get::(3)?.get_double()? as f32; let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - context_2d.fill_rect(x as f32, y as f32, w as f32, h as f32)?; + context_2d.fill_rect(x, y, w, h)?; ctx.env.get_undefined() } @@ -1291,8 +1320,8 @@ fn fill_rect(ctx: CallContext) -> Result { #[js_function(4)] fn fill_text(ctx: CallContext) -> Result { let text = ctx.get::(0)?.into_utf8()?; - let x: f64 = ctx.get::(1)?.try_into()?; - let y: f64 = ctx.get::(2)?.try_into()?; + let x = ctx.get::(1)?.get_double()? as f32; + let y = ctx.get::(2)?.get_double()? as f32; let max_width = if ctx.length == 3 { MAX_TEXT_WIDTH } else { @@ -1301,7 +1330,7 @@ fn fill_text(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - context_2d.fill_text(text.as_str()?, x as f32, y as f32, max_width)?; + context_2d.fill_text(text.as_str()?, x, y, max_width)?; ctx.env.get_undefined() } @@ -1310,10 +1339,10 @@ fn fill_text(ctx: CallContext) -> Result { fn get_image_data(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let x: u32 = ctx.get::(0)?.try_into()?; - let y: u32 = ctx.get::(1)?.try_into()?; - let width: u32 = ctx.get::(2)?.try_into()?; - let height: u32 = ctx.get::(3)?.try_into()?; + let x = ctx.get::(0)?.get_uint32()?; + let y = ctx.get::(1)?.get_uint32()?; + let width = ctx.get::(2)?.get_uint32()?; + let height = ctx.get::(3)?.get_uint32()?; let pixels = context_2d .surface .read_pixels(x, y, width, height) @@ -1335,7 +1364,7 @@ fn get_line_dash(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let line_dash_list = &context_2d.states.last().unwrap().line_dash_list; + let line_dash_list = &context_2d.state.line_dash_list; let mut arr = ctx.env.create_array_with_length(line_dash_list.len())?; @@ -1352,56 +1381,56 @@ fn put_image_data(ctx: CallContext) -> Result { let image_data_js = ctx.get::(0)?; let image_data = ctx.env.unwrap::(&image_data_js)?; - let dx: u32 = ctx.get::(1)?.try_into()?; - let dy: u32 = ctx.get::(2)?.try_into()?; + let dx = ctx.get::(1)?.get_uint32()?; + let dy = ctx.get::(2)?.get_uint32()?; if ctx.length == 3 { context_2d.surface.canvas.write_pixels(image_data, dx, dy); } else { - let mut dirty_x: f64 = ctx.get::(3)?.try_into()?; + let mut dirty_x = ctx.get::(3)?.get_double()? as f32; let mut dirty_y = if ctx.length >= 5 { - ctx.get::(4)?.try_into()? + ctx.get::(4)?.get_double()? as f32 } else { - 0f64 + 0.0f32 }; let mut dirty_width = if ctx.length >= 6 { - ctx.get::(5)?.try_into()? + ctx.get::(5)?.get_double()? as f32 } else { - image_data.width as f64 + image_data.width as f32 }; let mut dirty_height = if ctx.length == 7 { - ctx.get::(6)?.try_into()? + ctx.get::(6)?.get_double()? as f32 } else { - image_data.height as f64 + image_data.height as f32 }; // as per https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-putimagedata - if dirty_width < 0f64 { + if dirty_width < 0f32 { dirty_x += dirty_width; dirty_width = dirty_width.abs(); } - if dirty_height < 0f64 { + if dirty_height < 0f32 { dirty_y += dirty_height; dirty_height = dirty_height.abs(); } - if dirty_x < 0f64 { + if dirty_x < 0f32 { dirty_width += dirty_x; - dirty_x = 0f64; + dirty_x = 0f32; } - if dirty_y < 0f64 { + if dirty_y < 0f32 { dirty_height += dirty_y; - dirty_y = 0f64; + dirty_y = 0f32; } - if dirty_width <= 0f64 || dirty_height <= 0f64 { + if dirty_width <= 0f32 || dirty_height <= 0f32 { return ctx.env.get_undefined(); } - let inverted = context_2d.surface.canvas.get_transform().invert(); + let inverted = context_2d.surface.canvas.get_transform_matrix().invert(); context_2d.surface.canvas.save(); if let Some(inverted) = inverted { - context_2d.surface.canvas.concat(inverted); + context_2d.surface.canvas.concat(&inverted); }; context_2d.surface.canvas.write_pixels_dirty( image_data, - dx, - dy, + dx as f32, + dy as f32, dirty_x, dirty_y, dirty_width, @@ -1418,7 +1447,7 @@ fn set_global_alpha(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let alpha: f64 = ctx.get::(0)?.try_into()?; + let alpha = ctx.get::(0)?.get_double()? as f32; if !(0.0..=1.0).contains(&alpha) { return Err(Error::new( @@ -1430,12 +1459,7 @@ fn set_global_alpha(ctx: CallContext) -> Result { )); } - context_2d - .states - .last_mut() - .unwrap() - .paint - .set_alpha((alpha * 255.0) as u8); + context_2d.state.paint.set_alpha((alpha * 255.0) as u8); ctx.env.get_undefined() } @@ -1446,7 +1470,7 @@ fn get_global_alpha(ctx: CallContext) -> Result { ctx .env - .create_double((context_2d.states.last().unwrap().paint.get_alpha() as f64) / 255.0) + .create_double((context_2d.state.paint.get_alpha() as f64) / 255.0) } #[js_function(1)] @@ -1456,9 +1480,7 @@ fn set_global_composite_operation(ctx: CallContext) -> Result { let blend_string = ctx.get::(0)?.into_utf8()?; context_2d - .states - .last_mut() - .unwrap() + .state .paint .set_blend_mode(BlendMode::from_str(blend_string.as_str()?).map_err(Error::from)?); @@ -1470,15 +1492,9 @@ fn get_global_composite_operation(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - ctx.env.create_string( - context_2d - .states - .last() - .unwrap() - .paint - .get_blend_mode() - .as_str(), - ) + ctx + .env + .create_string(context_2d.state.paint.get_blend_mode().as_str()) } #[js_function(1)] @@ -1487,11 +1503,7 @@ fn set_image_smoothing_enabled(ctx: CallContext) -> Result { let context_2d = ctx.env.unwrap::(&this)?; let enabled = ctx.get::(0)?; - context_2d - .states - .last_mut() - .unwrap() - .image_smoothing_enabled = enabled.get_value()?; + context_2d.state.image_smoothing_enabled = enabled.get_value()?; ctx.env.get_undefined() } @@ -1503,7 +1515,7 @@ fn get_image_smoothing_enabled(ctx: CallContext) -> Result { ctx .env - .get_boolean(context_2d.states.last().unwrap().image_smoothing_enabled) + .get_boolean(context_2d.state.image_smoothing_enabled) } #[js_function(1)] @@ -1512,11 +1524,8 @@ fn set_image_smoothing_quality(ctx: CallContext) -> Result { let context_2d = ctx.env.unwrap::(&this)?; let quality = ctx.get::(0)?.into_utf8()?; - context_2d - .states - .last_mut() - .unwrap() - .image_smoothing_quality = FilterQuality::from_str(quality.as_str()?).map_err(Error::from)?; + context_2d.state.image_smoothing_quality = + FilterQuality::from_str(quality.as_str()?).map_err(Error::from)?; ctx.env.get_undefined() } @@ -1526,14 +1535,9 @@ fn get_image_smoothing_quality(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - ctx.env.create_string( - context_2d - .states - .last() - .unwrap() - .image_smoothing_quality - .as_str(), - ) + ctx + .env + .create_string(context_2d.state.image_smoothing_quality.as_str()) } #[js_function] @@ -1542,7 +1546,7 @@ fn get_current_transform(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let current_transform = context_2d.surface.canvas.get_transform(); + let current_transform = context_2d.state.transform.get_transform(); transform_object.set_named_property("a", ctx.env.create_double(current_transform.a as f64)?)?; transform_object.set_named_property("b", ctx.env.create_double(current_transform.b as f64)?)?; @@ -1560,33 +1564,33 @@ fn set_current_transform(ctx: CallContext) -> Result { let transform = if ctx.length == 1 { let transform_object = ctx.get::(0)?; - let a: f64 = transform_object + let a = transform_object .get_named_property::("a")? - .try_into()?; - let b: f64 = transform_object + .get_double()? as f32; + let b = transform_object .get_named_property::("b")? - .try_into()?; - let c: f64 = transform_object + .get_double()? as f32; + let c = transform_object .get_named_property::("c")? - .try_into()?; - let d: f64 = transform_object + .get_double()? as f32; + let d = transform_object .get_named_property::("d")? - .try_into()?; - let e: f64 = transform_object + .get_double()? as f32; + let e = transform_object .get_named_property::("e")? - .try_into()?; - let f: f64 = transform_object + .get_double()? as f32; + let f = transform_object .get_named_property::("f")? - .try_into()?; - Transform::new(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32) + .get_double()? as f32; + Matrix::new(a, c, e, b, d, f) } else if ctx.length == 6 { - let a: f64 = ctx.get::(0)?.try_into()?; - let b: f64 = ctx.get::(1)?.try_into()?; - let c: f64 = ctx.get::(2)?.try_into()?; - let d: f64 = ctx.get::(3)?.try_into()?; - let e: f64 = ctx.get::(4)?.try_into()?; - let f: f64 = ctx.get::(5)?.try_into()?; - Transform::new(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32) + let a = ctx.get::(0)?.get_double()? as f32; + let b = ctx.get::(1)?.get_double()? as f32; + let c = ctx.get::(2)?.get_double()? as f32; + let d = ctx.get::(3)?.get_double()? as f32; + let e = ctx.get::(4)?.get_double()? as f32; + let f = ctx.get::(5)?.get_double()? as f32; + Matrix::new(a, c, e, b, d, f) } else { return Err(Error::new( Status::InvalidArg, @@ -1594,20 +1598,20 @@ fn set_current_transform(ctx: CallContext) -> Result { )); }; - context_2d.surface.canvas.set_transform(transform); + context_2d.set_transform(transform); ctx.env.get_undefined() } #[js_function(2)] fn scale(ctx: CallContext) -> Result { - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - context_2d.surface.canvas.scale(x as f32, y as f32); + context_2d.scale(x, y); ctx.env.get_undefined() } @@ -1626,13 +1630,13 @@ fn set_line_dash(ctx: CallContext) -> Result { vec![0f32; len] }; for idx in 0..len { - let dash_value: f64 = dash.get_element::(idx as u32)?.try_into()?; + let dash_value: f32 = dash.get_element::(idx as u32)?.get_double()? as f32; dash_list[idx] = dash_value as f32; if is_odd { dash_list[idx + len] = dash_value as f32; } } - context_2d.states.last_mut().unwrap().line_dash_list = dash_list; + context_2d.state.line_dash_list = dash_list; ctx.env.get_undefined() } @@ -1649,45 +1653,35 @@ fn stroke(ctx: CallContext) -> Result { Some(path) }; - context_2d.stroke(path.as_deref())?; + context_2d.stroke(path)?; ctx.env.get_undefined() } #[js_function(2)] fn translate(ctx: CallContext) -> Result { - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - - let mut inverted = Matrix::identity(); - inverted.pre_translate(-x as f32, -y as f32); - context_2d.path.transform_matrix(&inverted); - context_2d.surface.canvas.translate(x as f32, y as f32); - + context_2d.translate(x, y); ctx.env.get_undefined() } #[js_function(6)] fn transform(ctx: CallContext) -> Result { - let a: f64 = ctx.get::(0)?.try_into()?; - let b: f64 = ctx.get::(1)?.try_into()?; - let c: f64 = ctx.get::(2)?.try_into()?; - let d: f64 = ctx.get::(3)?.try_into()?; - let e: f64 = ctx.get::(4)?.try_into()?; - let f: f64 = ctx.get::(5)?.try_into()?; + let a = ctx.get::(0)?.get_double()? as f32; + let b = ctx.get::(1)?.get_double()? as f32; + let c = ctx.get::(2)?.get_double()? as f32; + let d = ctx.get::(3)?.get_double()? as f32; + let e = ctx.get::(4)?.get_double()? as f32; + let f = ctx.get::(5)?.get_double()? as f32; let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - - let new_transform = Transform::new(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32); - let inverted = new_transform - .invert() - .ok_or_else(|| Error::new(Status::InvalidArg, "Invalid transform".to_owned()))?; - context_2d.path.transform(&inverted); - context_2d.surface.canvas.concat(new_transform); + let ts = Matrix::new(a, c, e, b, d, f); + context_2d.transform(ts)?; ctx.env.get_undefined() } @@ -1696,7 +1690,7 @@ fn reset_transform(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - context_2d.surface.canvas.reset_transform(); + context_2d.reset_transform(); ctx.env.get_undefined() } @@ -1705,15 +1699,9 @@ fn get_line_cap(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - ctx.env.create_string( - context_2d - .states - .last() - .unwrap() - .paint - .get_stroke_cap() - .as_str(), - ) + ctx + .env + .create_string(context_2d.state.paint.get_stroke_cap().as_str()) } #[js_function(1)] @@ -1725,9 +1713,7 @@ fn set_line_cap(ctx: CallContext) -> Result { let context_2d = ctx.env.unwrap::(&this)?; context_2d - .states - .last_mut() - .unwrap() + .state .paint .set_stroke_cap(StrokeCap::from_str(line_cap.as_str()?)?); @@ -1741,18 +1727,17 @@ fn get_line_dash_offset(ctx: CallContext) -> Result { ctx .env - .create_double(context_2d.states.last_mut().unwrap().line_dash_offset as f64) + .create_double(context_2d.state.line_dash_offset as f64) } #[js_function(1)] fn set_line_dash_offset(ctx: CallContext) -> Result { - let line_offset_number = ctx.get::(0)?; - let offset: f64 = line_offset_number.get_double()?; + let line_offset = ctx.get::(0)?.get_double()? as f32; let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - context_2d.states.last_mut().unwrap().line_dash_offset = offset as f32; + context_2d.state.line_dash_offset = line_offset as f32; ctx.env.get_undefined() } @@ -1762,15 +1747,9 @@ fn get_line_join(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - ctx.env.create_string( - context_2d - .states - .last() - .unwrap() - .paint - .get_stroke_join() - .as_str(), - ) + ctx + .env + .create_string(context_2d.state.paint.get_stroke_join().as_str()) } #[js_function(1)] @@ -1782,9 +1761,7 @@ fn set_line_join(ctx: CallContext) -> Result { let context_2d = ctx.env.unwrap::(&this)?; context_2d - .states - .last_mut() - .unwrap() + .state .paint .set_stroke_join(StrokeJoin::from_str(line_join.as_str()?)?); @@ -1798,22 +1775,17 @@ fn get_line_width(ctx: CallContext) -> Result { ctx .env - .create_double(context_2d.states.last().unwrap().paint.get_stroke_width() as f64) + .create_double(context_2d.state.paint.get_stroke_width() as f64) } #[js_function(1)] fn set_line_width(ctx: CallContext) -> Result { - let width: f64 = ctx.get::(0)?.try_into()?; + let width = ctx.get::(0)?.get_double()? as f32; let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - context_2d - .states - .last_mut() - .unwrap() - .paint - .set_stroke_width(width as f32); + context_2d.state.paint.set_stroke_width(width as f32); ctx.env.get_undefined() } @@ -1822,20 +1794,17 @@ fn set_line_width(ctx: CallContext) -> Result { fn set_fill_style(ctx: CallContext) -> Result { let mut this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let js_fill_style = ctx.get::(0)?; - let last_state = context_2d.states.last_mut().unwrap(); - - match js_fill_style.get_type()? { + let p = match js_fill_style.get_type()? { ValueType::String => { let js_color = unsafe { js_fill_style.cast::() }.into_utf8()?; - last_state.fill_style = Pattern::from_color(js_color.as_str()?)?; + Pattern::from_color(js_color.as_str()?)? } ValueType::Object => { let fill_object = unsafe { js_fill_style.cast::() }; let pattern = ctx.env.unwrap::(&fill_object)?; - last_state.fill_style = pattern.clone(); + pattern.clone() } _ => { return Err(Error::new( @@ -1843,7 +1812,9 @@ fn set_fill_style(ctx: CallContext) -> Result { "Invalid fillStyle".to_string(), )) } - } + }; + + context_2d.state.fill_style = p; this.set_named_property("_fillStyle", js_fill_style)?; @@ -1861,9 +1832,7 @@ fn get_font(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - ctx - .env - .create_string(context_2d.states.last().unwrap().font.as_str()) + ctx.env.create_string(context_2d.state.font.as_str()) } #[js_function(1)] @@ -1871,7 +1840,7 @@ fn set_font(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let last_state = context_2d.states.last_mut().unwrap(); + let last_state = &mut context_2d.state; let font_style = ctx.get::(0)?.into_utf8()?.into_owned()?; last_state.font_style = Font::new(font_style.as_str()).map_err(|e| Error::new(Status::InvalidArg, format!("{}", e)))?; @@ -1885,7 +1854,7 @@ fn get_text_direction(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let last_state = context_2d.states.last().unwrap(); + let last_state = &context_2d.state; ctx.env.create_string(last_state.text_direction.as_str()) } @@ -1895,7 +1864,7 @@ fn set_text_direction(ctx: CallContext) -> Result { let context_2d = ctx.env.unwrap::(&this)?; let direction = ctx.get::(0)?.into_utf8()?; let text_direction = TextDirection::from_str(direction.as_str()?)?; - let last_state = context_2d.states.last_mut().unwrap(); + let last_state = &mut context_2d.state; last_state.text_direction = text_direction; ctx.env.get_undefined() } @@ -1906,7 +1875,7 @@ fn set_stroke_style(ctx: CallContext) -> Result { let context_2d = ctx.env.unwrap::(&this)?; let js_stroke_style = ctx.get::(0)?; - let last_state = context_2d.states.last_mut().unwrap(); + let last_state = &mut context_2d.state; match js_stroke_style.get_type()? { ValueType::String => { @@ -1942,19 +1911,19 @@ fn get_stroke_style(ctx: CallContext) -> Result { fn get_shadow_blur(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let last_state = context_2d.states.last_mut().unwrap(); + let last_state = &mut context_2d.state; ctx.env.create_double(last_state.shadow_blur as f64) } #[js_function(1)] fn set_shadow_blur(ctx: CallContext) -> Result { - let blur: f64 = ctx.get::(0)?.try_into()?; + let blur = ctx.get::(0)?.get_double()? as f32; let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - context_2d.states.last_mut().unwrap().shadow_blur = blur as f32; + context_2d.state.shadow_blur = blur; ctx.env.get_undefined() } @@ -1964,14 +1933,9 @@ fn get_shadow_color(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - ctx.env.create_string( - context_2d - .states - .last() - .unwrap() - .shadow_color_string - .as_str(), - ) + ctx + .env + .create_string(context_2d.state.shadow_color_string.as_str()) } #[js_function(1)] @@ -1982,7 +1946,7 @@ fn set_shadow_color(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let last_state = context_2d.states.last_mut().unwrap(); + let last_state = &mut context_2d.state; let shadow_color_str = shadow_color.as_str()?; last_state.shadow_color_string = shadow_color_str.to_owned(); @@ -2013,20 +1977,20 @@ fn set_shadow_color(ctx: CallContext) -> Result { fn get_shadow_offset_x(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let last_state = context_2d.states.last_mut().unwrap(); + let last_state = &mut context_2d.state; ctx.env.create_double(last_state.shadow_offset_x as f64) } #[js_function(1)] fn set_shadow_offset_x(ctx: CallContext) -> Result { - let offset: f64 = ctx.get::(0)?.try_into()?; + let offset: f32 = ctx.get::(0)?.get_double()? as f32; let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let last_state = context_2d.states.last_mut().unwrap(); + let last_state = &mut context_2d.state; - last_state.shadow_offset_x = offset as f32; + last_state.shadow_offset_x = offset; ctx.env.get_undefined() } @@ -2035,20 +1999,20 @@ fn set_shadow_offset_x(ctx: CallContext) -> Result { fn get_shadow_offset_y(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let last_state = context_2d.states.last_mut().unwrap(); + let last_state = &mut context_2d.state; ctx.env.create_double(last_state.shadow_offset_y as f64) } #[js_function(1)] fn set_shadow_offset_y(ctx: CallContext) -> Result { - let offset: f64 = ctx.get::(0)?.try_into()?; + let offset = ctx.get::(0)?.get_double()? as f32; let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - let last_state = context_2d.states.last_mut().unwrap(); + let last_state = &mut context_2d.state; - last_state.shadow_offset_y = offset as f32; + last_state.shadow_offset_y = offset; ctx.env.get_undefined() } @@ -2058,7 +2022,7 @@ fn set_text_align(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - context_2d.states.last_mut().unwrap().text_align = + context_2d.state.text_align = TextAlign::from_str(ctx.get::(0)?.into_utf8()?.as_str()?)?; ctx.env.get_undefined() } @@ -2068,17 +2032,14 @@ fn get_text_align(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - ctx - .env - .create_string(context_2d.states.last().unwrap().text_align.as_str()) + ctx.env.create_string(context_2d.state.text_align.as_str()) } #[js_function(1)] fn set_text_baseline(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let context_2d = ctx.env.unwrap::(&this)?; - - context_2d.states.last_mut().unwrap().text_baseline = + context_2d.state.text_baseline = TextBaseline::from_str(ctx.get::(0)?.into_utf8()?.as_str()?)?; ctx.env.get_undefined() } @@ -2090,7 +2051,7 @@ fn get_text_baseline(ctx: CallContext) -> Result { ctx .env - .create_string(context_2d.states.last().unwrap().text_baseline.as_str()) + .create_string(context_2d.state.text_baseline.as_str()) } pub enum ContextData { diff --git a/src/error.rs b/src/error.rs index 8b3dfd26..b894d609 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,7 @@ use thiserror::Error; +use crate::sk::Matrix; + #[derive(Error, Debug)] pub enum SkError { #[error("[`{0}`] is not valid Blend value")] @@ -20,6 +22,8 @@ pub enum SkError { StringToStrokeJoinError(String), #[error("[`{0}`] is not valid SvgExportFlag value")] U32ToStrokeJoinError(u32), + #[error("[`{0}`] is not valid transform")] + InvalidTransform(Matrix), #[error("[`{0}`]")] Generic(String), } diff --git a/src/font.rs b/src/font.rs index 3ff2656a..395cdd67 100644 --- a/src/font.rs +++ b/src/font.rs @@ -53,7 +53,6 @@ impl Default for Font { } impl Font { - #[inline] pub fn new(font_rules: &str) -> Result { let font_regexp = FONT_REGEXP.get_or_init(init_font_regexp); let default_font = Font::default(); @@ -121,7 +120,6 @@ impl Font { } } -#[inline] // [ [ <'font-style'> || || <'font-weight'> || <'font-stretch'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-barwhere = [ normal | small-caps ] pub(crate) fn init_font_regexp() -> Regex { Regex::new( @@ -152,7 +150,6 @@ pub enum FontStyle { } impl FontStyle { - #[inline] pub fn as_str(&self) -> &str { match *self { Self::Italic => "italic", @@ -165,7 +162,6 @@ impl FontStyle { impl FromStr for FontStyle { type Err = ParseError; - #[inline] fn from_str(s: &str) -> Result { match s { "normal" => Ok(Self::Normal), @@ -185,7 +181,6 @@ pub enum FontVariant { impl FromStr for FontVariant { type Err = ParseError; - #[inline] fn from_str(s: &str) -> Result { match s { "normal" => Ok(Self::Normal), @@ -210,7 +205,6 @@ pub enum FontStretch { } impl From for FontStretch { - #[inline] fn from(value: i32) -> Self { match value { 1 => FontStretch::UltraCondensed, @@ -228,7 +222,6 @@ impl From for FontStretch { } impl FontStretch { - #[inline] pub fn as_str(&self) -> &str { match *self { FontStretch::UltraCondensed => "ultra-condensed", @@ -244,7 +237,6 @@ impl FontStretch { } } -#[inline] // https://drafts.csswg.org/css-fonts-4/#propdef-font-weight fn parse_font_weight(weight: &str) -> Option { match weight { @@ -265,7 +257,6 @@ fn parse_font_weight(weight: &str) -> Option { } } -#[inline] fn parse_font_stretch(stretch: &str) -> Option { match stretch { "ultra-condensed" | "50%" => Some(FontStretch::UltraCondensed), @@ -281,7 +272,6 @@ fn parse_font_stretch(stretch: &str) -> Option { } } -#[inline] fn parse_size_px(size: f32, unit: &str) -> f32 { let mut size_px = size; match unit { diff --git a/src/global_fonts.rs b/src/global_fonts.rs index d7006531..b2b4e967 100644 --- a/src/global_fonts.rs +++ b/src/global_fonts.rs @@ -80,7 +80,6 @@ fn load_fonts(ctx: CallContext) -> Result { .create_uint32(load_fonts_from_dir(font_collection, dir.as_str()?)) } -#[inline(always)] fn load_fonts_from_dir>( font_collection: &mut Rc, dir: P, diff --git a/src/gradient.rs b/src/gradient.rs index 7040638f..c5cea2c0 100644 --- a/src/gradient.rs +++ b/src/gradient.rs @@ -17,7 +17,6 @@ pub enum CanvasGradient { } impl CanvasGradient { - #[inline(always)] pub fn into_js_instance(self, env: &Env) -> Result { let gradient_class = env.define_class( "Gradient", @@ -30,7 +29,6 @@ impl CanvasGradient { Ok(instance) } - #[inline(always)] pub fn create_linear_gradient(x0: f32, y0: f32, x1: f32, y1: f32) -> Self { let linear_gradient = LinearGradient { start_point: (x0, y0), @@ -45,7 +43,6 @@ impl CanvasGradient { Self::Linear(linear_gradient) } - #[inline(always)] pub fn create_radial_gradient(x0: f32, y0: f32, r0: f32, x1: f32, y1: f32, r1: f32) -> Self { let radial_gradient = RadialGradient { start: (x0, y0), @@ -62,7 +59,6 @@ impl CanvasGradient { Self::Radial(radial_gradient) } - #[inline(always)] pub fn create_conic_gradient(x: f32, y: f32, r: f32) -> Self { Self::Conic(ConicGradient { center: (x, y), @@ -76,7 +72,6 @@ impl CanvasGradient { }) } - #[inline(always)] pub fn add_color_stop(&mut self, offset: f32, color: Color) { let (stops, colors) = match self { Self::Linear(linear_gradient) => ( @@ -110,7 +105,6 @@ impl CanvasGradient { } } - #[inline(always)] /// Transform is [3 x 3] matrix, but stored in 2d array: /// | A B C | /// | D E F | @@ -118,10 +112,7 @@ impl CanvasGradient { /// [0 -> A, 1 -> B, 2 -> C, 3 -> D, 4 -> E, 5 -> F, 6 -> 0, 7 -> 0, 8 -> 1 ] /// [lineargradient.js](skia/modules/canvaskit/htmlcanvas/lineargradient.js) /// [radialgradient.js](skia/modules/canvaskit/htmlcanvas/radialgradient.js) - pub(crate) fn get_shader( - &self, - current_transform: &Transform, - ) -> result::Result { + pub(crate) fn get_shader(&self, current_transform: Transform) -> result::Result { match self { Self::Linear(ref linear_gradient) => Ok( Shader::new_linear_gradient(&LinearGradient { @@ -131,23 +122,19 @@ impl CanvasGradient { }) .ok_or_else(|| SkError::Generic("Get shader of linear gradient failed".to_owned()))?, ), + // Note, Skia has a different notion of a "radial" gradient. + // Skia has a twoPointConical gradient that is the same as the + // canvas's RadialGradient. Self::Radial(ref radial_gradient) => { - let r1 = radial_gradient.start_radius; - let r2 = radial_gradient.end_radius; - - let sx = current_transform.a; - let sy = current_transform.d; - let scale_factor = (f32::abs(sx) + f32::abs(sy)) / 2f32; - - let sr1 = r1 * scale_factor; - let sr2 = r2 * scale_factor; - + // From the spec: "The points in the linear gradient must be transformed + // as described by the current transformation matrix when rendering." + let base = radial_gradient.base.clone(); let new_radial_gradient = RadialGradient { start: radial_gradient.start, end: radial_gradient.end, - start_radius: sr1, - end_radius: sr2, - base: radial_gradient.base.clone(), + start_radius: radial_gradient.start_radius, + end_radius: radial_gradient.end_radius, + base, }; Ok( @@ -158,9 +145,8 @@ impl CanvasGradient { Self::Conic(ref conic_gradient) => { let (x, y) = conic_gradient.center; let r = conic_gradient.radius; - - let sx = current_transform.a; - let sy = current_transform.d; + let sx = current_transform.c; + let sy = current_transform.b; let scale_factor = (f32::abs(sx) + f32::abs(sy)) / 2f32; let sr = r * scale_factor; let new_conic_gradient = ConicGradient { diff --git a/src/image.rs b/src/image.rs index 8966bbef..2979fbe4 100644 --- a/src/image.rs +++ b/src/image.rs @@ -134,7 +134,6 @@ pub(crate) struct Image { } impl Image { - #[inline(always)] pub(crate) fn regenerate_bitmap_if_need(&mut self, data: D) where D: AsRef<[u8]>, diff --git a/src/lib.rs b/src/lib.rs index 6cabe137..02a75757 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,6 @@ extern crate napi_derive; #[macro_use] extern crate serde_derive; -use std::convert::TryInto; use std::mem; use napi::*; @@ -48,7 +47,6 @@ fn init(mut exports: JsObject, env: Env) -> Result<()> { "CanvasElement", canvas_element_constructor, &[ - Property::new(&env, "getContext")?.with_method(get_context), Property::new(&env, "encode")?.with_method(encode), Property::new(&env, "encodeSync")?.with_method(encode_sync), Property::new(&env, "toBuffer")?.with_method(to_buffer), @@ -62,10 +60,7 @@ fn init(mut exports: JsObject, env: Env) -> Result<()> { let svg_canvas_element = env.define_class( "SVGCanvas", canvas_element_constructor, - &[ - Property::new(&env, "getContext")?.with_method(get_context), - Property::new(&env, "getContent")?.with_method(get_content), - ], + &[Property::new(&env, "getContent")?.with_method(get_content)], )?; let canvas_rendering_context2d = ctx::Context::create_js_class(&env)?; @@ -102,6 +97,8 @@ fn init(mut exports: JsObject, env: Env) -> Result<()> { exports.create_named_method("convertSVGTextToPath", svg::convert_svg_text_to_path)?; + exports.create_named_method("createContext", create_context)?; + // pre init font regexp FONT_REGEXP.get_or_init(init_font_regexp); Ok(()) @@ -118,34 +115,21 @@ fn canvas_element_constructor(ctx: CallContext) -> Result { ctx.env.get_undefined() } -#[js_function(2)] -fn get_context(ctx: CallContext) -> Result { - let context_type = ctx.get::(0)?.into_utf8()?; - if context_type.as_str()? != "2d" { - return Err(Error::new( - Status::InvalidArg, - "Only supports 2d context".to_owned(), - )); - } - - let this = ctx.this_unchecked::(); - let ctx_js = this.get_named_property_unchecked::("ctx")?; - let context_2d = ctx.env.unwrap::(&ctx_js)?; +#[js_function(4)] +fn create_context(ctx: CallContext) -> Result { + let context_2d_object = ctx.get::(0)?; + let context_2d = ctx.env.unwrap::(&context_2d_object)?; - if ctx.length == 2 { - let attrs = ctx.get::(1)?; + if ctx.length == 4 { + let w = ctx.get::(1)?.get_double()?; + let h = ctx.get::(2)?.get_double()?; + let attrs = ctx.get::(3)?; let alpha = attrs .get_named_property_unchecked::("alpha")? .get_value()?; if !alpha { let mut fill_paint = context_2d.fill_paint()?; fill_paint.set_color(255, 255, 255, 255); - let w: f64 = this - .get_named_property_unchecked::("width")? - .try_into()?; - let h: f64 = this - .get_named_property_unchecked::("height")? - .try_into()?; context_2d.alpha = false; context_2d .surface @@ -153,7 +137,7 @@ fn get_context(ctx: CallContext) -> Result { } } - Ok(ctx_js) + ctx.env.get_undefined() } #[js_function(2)] @@ -337,7 +321,6 @@ fn get_content(ctx: CallContext) -> Result { } } -#[inline] fn get_data_ref(ctx: &CallContext, mime: &str, quality: u8) -> Result { let this = ctx.this_unchecked::(); let ctx_js = this.get_named_property::("ctx")?; diff --git a/src/path.rs b/src/path.rs index 4b6cb65a..90b2672c 100644 --- a/src/path.rs +++ b/src/path.rs @@ -1,11 +1,8 @@ -use std::convert::TryInto; - use napi::*; use crate::sk::*; impl Path { - #[inline(always)] pub fn create_js_class(env: &Env) -> Result { env.define_class( "Path2D", @@ -84,29 +81,29 @@ fn add_path(ctx: CallContext) -> Result { let sub_path = ctx.env.unwrap::(&sub_path_obj)?; let transform = if ctx.length == 2 { let transform_object = ctx.get::(1)?; - let a: f64 = transform_object + let a = transform_object .get_named_property::("a")? - .try_into()?; - let b: f64 = transform_object + .get_double()? as f32; + let b = transform_object .get_named_property::("b")? - .try_into()?; - let c: f64 = transform_object + .get_double()? as f32; + let c = transform_object .get_named_property::("c")? - .try_into()?; - let d: f64 = transform_object + .get_double()? as f32; + let d = transform_object .get_named_property::("d")? - .try_into()?; - let e: f64 = transform_object + .get_double()? as f32; + let e = transform_object .get_named_property::("e")? - .try_into()?; - let f: f64 = transform_object + .get_double()? as f32; + let f = transform_object .get_named_property::("f")? - .try_into()?; - Transform::new(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32) + .get_double()? as f32; + Matrix::new(a, c, e, b, d, f) } else { - Default::default() + Matrix::identity() }; - path_2d.add_path(sub_path, transform); + path_2d.add_path(sub_path, &transform); ctx.env.get_undefined() } @@ -124,10 +121,10 @@ fn close_path(ctx: CallContext) -> Result { fn move_to(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let path_2d = ctx.env.unwrap::(&this)?; - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; - path_2d.move_to(x as f32, y as f32); + path_2d.move_to(x, y); ctx.env.get_undefined() } @@ -136,10 +133,10 @@ fn move_to(ctx: CallContext) -> Result { fn line_to(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let path_2d = ctx.env.unwrap::(&this)?; - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; - path_2d.line_to(x as f32, y as f32); + path_2d.line_to(x, y); ctx.env.get_undefined() } @@ -148,21 +145,14 @@ fn line_to(ctx: CallContext) -> Result { fn bezier_curve_to(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let path_2d = ctx.env.unwrap::(&this)?; - let cp1x: f64 = ctx.get::(0)?.try_into()?; - let cp1y: f64 = ctx.get::(1)?.try_into()?; - let cp2x: f64 = ctx.get::(2)?.try_into()?; - let cp2y: f64 = ctx.get::(3)?.try_into()?; - let x: f64 = ctx.get::(4)?.try_into()?; - let y: f64 = ctx.get::(5)?.try_into()?; - - path_2d.cubic_to( - cp1x as f32, - cp1y as f32, - cp2x as f32, - cp2y as f32, - x as f32, - y as f32, - ); + let cp1x = ctx.get::(0)?.get_double()? as f32; + let cp1y = ctx.get::(1)?.get_double()? as f32; + let cp2x = ctx.get::(2)?.get_double()? as f32; + let cp2y = ctx.get::(3)?.get_double()? as f32; + let x = ctx.get::(4)?.get_double()? as f32; + let y = ctx.get::(5)?.get_double()? as f32; + + path_2d.cubic_to(cp1x, cp1y, cp2x, cp2y, x, y); ctx.env.get_undefined() } @@ -171,12 +161,12 @@ fn bezier_curve_to(ctx: CallContext) -> Result { fn quadratic_curve_to(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let path_2d = ctx.env.unwrap::(&this)?; - let cpx: f64 = ctx.get::(0)?.try_into()?; - let cpy: f64 = ctx.get::(1)?.try_into()?; - let x: f64 = ctx.get::(2)?.try_into()?; - let y: f64 = ctx.get::(3)?.try_into()?; + let cpx = ctx.get::(0)?.get_double()? as f32; + let cpy = ctx.get::(1)?.get_double()? as f32; + let x = ctx.get::(2)?.get_double()? as f32; + let y = ctx.get::(3)?.get_double()? as f32; - path_2d.quad_to(cpx as f32, cpy as f32, x as f32, y as f32); + path_2d.quad_to(cpx, cpy, x, y); ctx.env.get_undefined() } @@ -185,24 +175,17 @@ fn quadratic_curve_to(ctx: CallContext) -> Result { fn arc(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let path_2d = ctx.env.unwrap::(&this)?; - let center_x: f64 = ctx.get::(0)?.try_into()?; - let center_y: f64 = ctx.get::(1)?.try_into()?; - let radius: f64 = ctx.get::(2)?.try_into()?; - let start_angle: f64 = ctx.get::(3)?.try_into()?; - let end_angle: f64 = ctx.get::(4)?.try_into()?; + let center_x = ctx.get::(0)?.get_double()? as f32; + let center_y = ctx.get::(1)?.get_double()? as f32; + let radius = ctx.get::(2)?.get_double()? as f32; + let start_angle = ctx.get::(3)?.get_double()? as f32; + let end_angle = ctx.get::(4)?.get_double()? as f32; let from_end = if ctx.length == 6 { ctx.get::(5)?.get_value()? } else { false }; - path_2d.arc( - center_x as f32, - center_y as f32, - radius as f32, - start_angle as f32, - end_angle as f32, - from_end, - ); + path_2d.arc(center_x, center_y, radius, start_angle, end_angle, from_end); ctx.env.get_undefined() } @@ -211,19 +194,13 @@ fn arc_to(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let path_2d = ctx.env.unwrap::(&this)?; - let ctrl_x: f64 = ctx.get::(0)?.try_into()?; - let ctrl_y: f64 = ctx.get::(1)?.try_into()?; - let to_x: f64 = ctx.get::(2)?.try_into()?; - let to_y: f64 = ctx.get::(3)?.try_into()?; - let radius: f64 = ctx.get::(4)?.try_into()?; - - path_2d.arc_to_tangent( - ctrl_x as f32, - ctrl_y as f32, - to_x as f32, - to_y as f32, - radius as f32, - ); + let ctrl_x = ctx.get::(0)?.get_double()? as f32; + let ctrl_y = ctx.get::(1)?.get_double()? as f32; + let to_x = ctx.get::(2)?.get_double()? as f32; + let to_y = ctx.get::(3)?.get_double()? as f32; + let radius = ctx.get::(4)?.get_double()? as f32; + + path_2d.arc_to_tangent(ctrl_x, ctrl_y, to_x, to_y, radius); ctx.env.get_undefined() } @@ -231,13 +208,13 @@ fn arc_to(ctx: CallContext) -> Result { fn ellipse(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let path_2d = ctx.env.unwrap::(&this)?; - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; - let radius_x: f64 = ctx.get::(2)?.try_into()?; - let radius_y: f64 = ctx.get::(3)?.try_into()?; - let rotation: f64 = ctx.get::(4)?.try_into()?; - let start_angle: f64 = ctx.get::(5)?.try_into()?; - let end_angle: f64 = ctx.get::(6)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; + let radius_x = ctx.get::(2)?.get_double()? as f32; + let radius_y = ctx.get::(3)?.get_double()? as f32; + let rotation = ctx.get::(4)?.get_double()? as f32; + let start_angle = ctx.get::(5)?.get_double()? as f32; + let end_angle = ctx.get::(6)?.get_double()? as f32; let from_end = if ctx.length == 8 { ctx.get::(7)?.get_value()? @@ -245,13 +222,13 @@ fn ellipse(ctx: CallContext) -> Result { false }; path_2d.ellipse( - x as f32, - y as f32, - radius_x as f32, - radius_y as f32, - rotation as f32, - start_angle as f32, - end_angle as f32, + x, + y, + radius_x, + radius_y, + rotation, + start_angle, + end_angle, from_end, ); ctx.env.get_undefined() @@ -261,10 +238,10 @@ fn ellipse(ctx: CallContext) -> Result { fn rect(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); let path_2d = ctx.env.unwrap::(&this)?; - let x: f64 = ctx.get::(0)?.try_into()?; - let y: f64 = ctx.get::(1)?.try_into()?; - let width: f64 = ctx.get::(2)?.try_into()?; - let height: f64 = ctx.get::(3)?.try_into()?; + let x = ctx.get::(0)?.get_double()? as f32; + let y = ctx.get::(1)?.get_double()? as f32; + let width = ctx.get::(2)?.get_double()? as f32; + let height = ctx.get::(3)?.get_double()? as f32; path_2d.add_rect(x as f32, y as f32, width as f32, height as f32); @@ -381,27 +358,27 @@ fn transform(ctx: CallContext) -> Result { let this: JsObject = ctx.this_unchecked(); let path_2d = ctx.env.unwrap::(&this)?; let transform_object = ctx.get::(0)?; - let a: f64 = transform_object + let a = transform_object .get_named_property::("a")? - .get_double()?; - let b: f64 = transform_object + .get_double()? as f32; + let b = transform_object .get_named_property::("b")? - .get_double()?; - let c: f64 = transform_object + .get_double()? as f32; + let c = transform_object .get_named_property::("c")? - .get_double()?; - let d: f64 = transform_object + .get_double()? as f32; + let d = transform_object .get_named_property::("d")? - .get_double()?; - let e: f64 = transform_object + .get_double()? as f32; + let e = transform_object .get_named_property::("e")? - .get_double()?; - let f: f64 = transform_object + .get_double()? as f32; + let f = transform_object .get_named_property::("f")? - .get_double()?; - let trans = Transform::new(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32); + .get_double()? as f32; + let trans = Matrix::new(a, c, e, b, d, f); - path_2d.transform(&trans); + path_2d.transform_self(&trans); Ok(this) } diff --git a/src/pattern.rs b/src/pattern.rs index db4a6542..4d0b98ad 100644 --- a/src/pattern.rs +++ b/src/pattern.rs @@ -12,14 +12,12 @@ pub enum Pattern { } impl Default for Pattern { - #[inline] fn default() -> Self { Self::Color(RGBA::new(0, 0, 0, 255), "#000".to_owned()) } } impl Pattern { - #[inline(always)] pub fn from_color(color_str: &str) -> Result { let mut parser_input = ParserInput::new(color_str); let mut parser = Parser::new(&mut parser_input); diff --git a/src/sk.rs b/src/sk.rs index 3b843f60..3b3ba477 100644 --- a/src/sk.rs +++ b/src/sk.rs @@ -197,6 +197,15 @@ mod ffi { _unused: [u8; 0], } + #[repr(C)] + #[derive(Debug, Clone, Copy)] + pub struct skiac_mapped_point { + pub x1: f32, + pub y1: f32, + pub x2: f32, + pub y2: f32, + } + pub type SkiacFontCollectionGetFamily = Option; @@ -268,9 +277,9 @@ mod ffi { // SkCanvas pub fn skiac_canvas_clear(canvas: *mut skiac_canvas, color: u32); - pub fn skiac_canvas_set_transform(canvas: *mut skiac_canvas, ts: skiac_transform); + pub fn skiac_canvas_set_transform(canvas: *mut skiac_canvas, ts: *mut skiac_matrix); - pub fn skiac_canvas_concat(canvas: *mut skiac_canvas, ts: skiac_transform); + pub fn skiac_canvas_concat(canvas: *mut skiac_canvas, ts: *mut skiac_matrix); pub fn skiac_canvas_scale(canvas: *mut skiac_canvas, sx: f32, sy: f32); @@ -367,6 +376,8 @@ mod ffi { pub fn skiac_canvas_restore(canvas: *mut skiac_canvas); + pub fn skiac_canvas_reset(canvas: *mut skiac_canvas); + pub fn skiac_canvas_write_pixels( canvas: *mut skiac_canvas, width: i32, @@ -456,7 +467,7 @@ mod ffi { pub fn skiac_add_path( c_path: *mut skiac_path, other_path: *mut skiac_path, - c_matrix: skiac_transform, + c_matrix: *mut skiac_matrix, ); pub fn skiac_path_op(c_path_one: *mut skiac_path, c_path_two: *mut skiac_path, op: i32) @@ -539,9 +550,12 @@ mod ffi { pub fn skiac_path_add_circle(path: *mut skiac_path, x: f32, y: f32, r: f32); - pub fn skiac_path_transform(path: *mut skiac_path, matrix: skiac_transform); + pub fn skiac_path_transform( + path: *mut skiac_path, + matrix: *mut skiac_matrix, + ) -> *mut skiac_path; - pub fn skiac_path_transform_matrix(path: *mut skiac_path, matrix: *mut skiac_matrix); + pub fn skiac_path_transform_self(path: *mut skiac_path, matrix: *mut skiac_matrix); pub fn skiac_path_is_empty(path: *mut skiac_path) -> bool; @@ -603,12 +617,47 @@ mod ffi { pub fn skiac_matrix_create() -> *mut skiac_matrix; + pub fn skiac_matrix_new(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> *mut skiac_matrix; + + pub fn skiac_matrix_from_ts(ts: *mut skiac_transform) -> *mut skiac_matrix; + + pub fn skiac_matrix_concat( + ts: *mut skiac_matrix, + other: *mut skiac_matrix, + ) -> *mut skiac_matrix; + + pub fn skiac_matrix_multiply( + ts: *mut skiac_matrix, + other: *mut skiac_matrix, + ) -> *mut skiac_matrix; + + pub fn skiac_matrix_create_rotated(rotation: f32, x: f32, y: f32) -> *mut skiac_matrix; + + pub fn skiac_matrix_create_translated(x: f32, y: f32) -> *mut skiac_matrix; + pub fn skiac_matrix_clone(matrix: *mut skiac_matrix) -> *mut skiac_matrix; + pub fn skiac_matrix_map_points( + c_matrix: *mut skiac_matrix, + x1: f32, + y1: f32, + x2: f32, + y2: f32, + mapped_point: *mut skiac_mapped_point, + ); + + pub fn skiac_matrix_pre_concat_transform(matrix: *mut skiac_matrix, ts: skiac_transform); + pub fn skiac_matrix_pre_translate(matrix: *mut skiac_matrix, dx: f32, dy: f32); + pub fn skiac_matrix_pre_concat(matrix: *mut skiac_matrix, other: *mut skiac_matrix); + + pub fn skiac_matrix_pre_scale(matrix: *mut skiac_matrix, sx: f32, sy: f32); + pub fn skiac_matrix_pre_rotate(matrix: *mut skiac_matrix, degrees: f32); + pub fn skiac_matrix_pre_rotate_x_y(matrix: *mut skiac_matrix, degrees: f32, x: f32, y: f32); + pub fn skiac_matrix_invert(matrix: *mut skiac_matrix, inverse: *mut skiac_matrix) -> bool; pub fn skiac_matrix_to_transform(matrix: *mut skiac_matrix) -> skiac_transform; @@ -1093,14 +1142,12 @@ pub enum FilterQuality { } impl Default for FilterQuality { - #[inline] fn default() -> Self { FilterQuality::Low } } impl FilterQuality { - #[inline] pub fn as_str(&self) -> &'static str { match self { Self::High => "high", @@ -1114,7 +1161,6 @@ impl FilterQuality { impl FromStr for FilterQuality { type Err = SkError; - #[inline] fn from_str(s: &str) -> Result { match s { "low" => Ok(Self::Low), @@ -1158,7 +1204,6 @@ pub enum PathOp { } impl From for PathOp { - #[inline] fn from(value: i32) -> Self { match value { 0 => Self::Difference, @@ -1183,7 +1228,6 @@ pub enum TextAlign { } impl TextAlign { - #[inline] pub fn as_str(&self) -> &str { match self { Self::Start => "start", @@ -1197,7 +1241,6 @@ impl TextAlign { } impl Default for TextAlign { - #[inline] fn default() -> Self { Self::Start } @@ -1206,7 +1249,6 @@ impl Default for TextAlign { impl FromStr for TextAlign { type Err = SkError; - #[inline] fn from_str(s: &str) -> Result { match s { "center" => Ok(TextAlign::Center), @@ -1240,7 +1282,6 @@ impl Default for TextBaseline { impl FromStr for TextBaseline { type Err = SkError; - #[inline] fn from_str(s: &str) -> Result { match s { "top" => Ok(Self::Top), @@ -1255,7 +1296,6 @@ impl FromStr for TextBaseline { } impl TextBaseline { - #[inline] pub fn as_str(&self) -> &'static str { match self { Self::Bottom => "bottom", @@ -1269,7 +1309,6 @@ impl TextBaseline { } impl ToString for TextBaseline { - #[inline] fn to_string(&self) -> String { self.as_str().to_owned() } @@ -1286,7 +1325,6 @@ pub enum TextDirection { impl FromStr for TextDirection { type Err = SkError; - #[inline] fn from_str(s: &str) -> Result { match s { "inherit" | "ltr" => Ok(Self::Ltr), @@ -1297,7 +1335,6 @@ impl FromStr for TextDirection { } impl TextDirection { - #[inline] pub fn as_str(&self) -> &str { match self { &Self::Inherit | &Self::Ltr => "ltr", @@ -1305,7 +1342,6 @@ impl TextDirection { } } - #[inline] pub fn as_sk_direction(&self) -> i32 { match self { &Self::Inherit | &Self::Ltr => 1, @@ -1315,7 +1351,6 @@ impl TextDirection { } impl Default for TextDirection { - #[inline] fn default() -> Self { Self::Inherit } @@ -1349,7 +1384,6 @@ pub enum SvgExportFlag { impl TryFrom for SvgExportFlag { type Error = SkError; - #[inline] fn try_from(value: u32) -> Result { match value { 0x01 => Ok(Self::ConvertTextToPaths), @@ -1366,12 +1400,10 @@ pub struct Surface { } impl Surface { - #[inline] pub fn new_rgba(width: u32, height: u32) -> Option { unsafe { Self::from_ptr(ffi::skiac_surface_create_rgba(width as i32, height as i32)) } } - #[inline] pub fn new_rgba_premultiplied(width: u32, height: u32) -> Option { unsafe { Self::from_ptr(ffi::skiac_surface_create_rgba_premultiplied( @@ -1381,7 +1413,6 @@ impl Surface { } } - #[inline] pub fn new_svg( width: u32, height: u32, @@ -1414,7 +1445,6 @@ impl Surface { )) } - #[inline] unsafe fn from_ptr(ptr: *mut ffi::skiac_surface) -> Option { if ptr.is_null() { None @@ -1426,12 +1456,10 @@ impl Surface { } } - #[inline] pub fn copy_rgba(&self, x: u32, y: u32, width: u32, height: u32) -> Option { unsafe { Self::from_ptr(ffi::skiac_surface_copy_rgba(self.ptr, x, y, width, height)) } } - #[inline] pub fn try_clone(&self) -> Option { unsafe { Self::from_ptr(ffi::skiac_surface_copy_rgba( @@ -1444,23 +1472,19 @@ impl Surface { } } - #[inline] pub fn save_png(&self, path: &str) -> bool { let c_path = std::ffi::CString::new(path).unwrap(); unsafe { ffi::skiac_surface_save(self.ptr, c_path.as_ptr()) } } - #[inline] pub fn width(&self) -> u32 { unsafe { ffi::skiac_surface_get_width(self.ptr) as u32 } } - #[inline] pub fn height(&self) -> u32 { unsafe { ffi::skiac_surface_get_height(self.ptr) as u32 } } - #[inline] pub fn alpha_type(&self) -> AlphaType { let kind = unsafe { ffi::skiac_surface_get_alpha_type(self.ptr) }; match kind { @@ -1472,7 +1496,6 @@ impl Surface { } } - #[inline] pub fn read_pixels(&self, x: u32, y: u32, width: u32, height: u32) -> Option> { let mut result = vec![0; (width * height * 4) as usize]; let status = unsafe { @@ -1492,7 +1515,6 @@ impl Surface { } } - #[inline] pub fn data(&self) -> Option { unsafe { let mut data = ffi::skiac_surface_data { @@ -1511,7 +1533,6 @@ impl Surface { } } - #[inline] pub fn svg(&self, width: f32, height: f32, flag: SvgExportFlag) -> Option { let mut data = ffi::skiac_sk_data { ptr: ptr::null_mut(), @@ -1535,7 +1556,6 @@ impl Surface { } } - #[inline] pub fn data_mut(&mut self) -> Option { unsafe { let mut data = ffi::skiac_surface_data { @@ -1553,12 +1573,10 @@ impl Surface { } } - #[inline] pub(crate) fn reference(&self) -> SurfaceRef { SurfaceRef(self.ptr) } - #[inline] pub(crate) fn get_bitmap(&self) -> Bitmap { let mut bitmap_info = ffi::skiac_bitmap_info { bitmap: ptr::null_mut(), @@ -1573,21 +1591,18 @@ impl Surface { impl std::ops::Deref for Surface { type Target = Canvas; - #[inline] fn deref(&self) -> &Self::Target { &self.canvas } } impl std::ops::DerefMut for Surface { - #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.canvas } } impl Drop for Surface { - #[inline] fn drop(&mut self) { unsafe { ffi::skiac_surface_destroy(self.ptr); @@ -1599,7 +1614,6 @@ impl Drop for Surface { pub struct SurfaceRef(*mut ffi::skiac_surface); impl SurfaceRef { - #[inline] pub fn png_data(&self) -> Option { unsafe { let mut data = ffi::skiac_sk_data { @@ -1617,7 +1631,6 @@ impl SurfaceRef { } } - #[inline] pub fn data(&self) -> Option<(*const u8, usize)> { let mut data = ffi::skiac_surface_data { ptr: ptr::null_mut(), @@ -1631,7 +1644,6 @@ impl SurfaceRef { } } - #[inline] pub fn encode_data(&self, format: SkEncodedImageFormat, quality: u8) -> Option { unsafe { let mut data = ffi::skiac_sk_data { @@ -1649,7 +1661,6 @@ impl SurfaceRef { } } - #[inline] pub fn svg(&self, width: f32, height: f32, flag: SvgExportFlag) -> Option { let mut data = ffi::skiac_sk_data { ptr: ptr::null_mut(), @@ -1684,7 +1695,6 @@ pub struct SurfaceData<'a> { impl<'a> Deref for SurfaceData<'a> { type Target = [u8]; - #[inline] fn deref(&self) -> &[u8] { self.slice } @@ -1697,7 +1707,6 @@ pub struct SurfaceDataMut<'a> { impl<'a> Deref for SurfaceDataMut<'a> { type Target = [u8]; - #[inline] fn deref(&self) -> &[u8] { self.slice } @@ -1722,7 +1731,6 @@ unsafe impl Send for SkiaDataRef {} unsafe impl Sync for SkiaDataRef {} impl<'a> DerefMut for SurfaceDataMut<'a> { - #[inline] fn deref_mut(&mut self) -> &mut [u8] { self.slice } @@ -1744,7 +1752,6 @@ impl fmt::Debug for Color { } impl Color { - #[inline] pub fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Color { Color((a as u32) << 24 | (r as u32) << 16 | (g as u32) << 8 | (b as u32)) } @@ -1754,14 +1761,12 @@ impl Color { pub struct Canvas(*mut ffi::skiac_canvas); impl Canvas { - #[inline] pub fn clear(&mut self) { unsafe { ffi::skiac_canvas_clear(self.0, 0); } } - #[inline] pub fn fill(&mut self, r: u8, g: u8, b: u8, a: u8) { unsafe { ffi::skiac_canvas_clear( @@ -1771,66 +1776,56 @@ impl Canvas { } } - #[inline] - pub fn set_transform(&mut self, ts: Transform) { + pub fn set_transform(&mut self, ts: &Matrix) { unsafe { - ffi::skiac_canvas_set_transform(self.0, ts.into()); + ffi::skiac_canvas_set_transform(self.0, ts.0); } } - #[inline] - pub fn concat(&mut self, ts: Transform) { + pub fn concat(&mut self, ts: &Matrix) { unsafe { - ffi::skiac_canvas_concat(self.0, ts.into()); + ffi::skiac_canvas_concat(self.0, ts.0); } } - #[inline] pub fn scale(&mut self, sx: f32, sy: f32) { unsafe { ffi::skiac_canvas_scale(self.0, sx, sy); } } - #[inline] pub fn translate(&mut self, dx: f32, dy: f32) { unsafe { ffi::skiac_canvas_translate(self.0, dx, dy); } } - #[inline] pub fn rotate(&mut self, degrees: f32) { unsafe { ffi::skiac_canvas_rotate(self.0, degrees); } } - #[inline] pub fn get_transform(&self) -> Transform { unsafe { ffi::skiac_canvas_get_total_transform(self.0).into() } } - #[inline] pub fn get_transform_matrix(&self) -> Matrix { Matrix(unsafe { ffi::skiac_canvas_get_total_transform_matrix(self.0) }) } - #[inline] pub fn reset_transform(&mut self) { unsafe { ffi::skiac_canvas_reset_transform(self.0); } } - #[inline] pub fn draw_color(&mut self, r: f32, g: f32, b: f32, a: f32) { unsafe { ffi::skiac_canvas_draw_color(self.0, r, g, b, a); } } - #[inline] pub fn draw_image( &mut self, image: *mut ffi::skiac_bitmap, @@ -1851,21 +1846,18 @@ impl Canvas { } } - #[inline] pub fn draw_path(&mut self, path: &Path, paint: &Paint) { unsafe { ffi::skiac_canvas_draw_path(self.0, path.0, paint.0); } } - #[inline] pub fn draw_rect(&mut self, x: f32, y: f32, w: f32, h: f32, paint: &Paint) { unsafe { ffi::skiac_canvas_draw_rect(self.0, x, y, w, h, paint.0); } } - #[inline] pub fn draw_text( &mut self, text: &str, @@ -1909,7 +1901,6 @@ impl Canvas { } } - #[inline] pub fn get_line_metrics( &self, text: &str, @@ -1953,7 +1944,6 @@ impl Canvas { line_metrics } - #[inline] pub fn draw_surface( &mut self, surface: &Surface, @@ -1976,7 +1966,6 @@ impl Canvas { } } - #[inline] pub fn draw_surface_rect( &mut self, surface: &Surface, @@ -2007,35 +1996,36 @@ impl Canvas { } } - #[inline] pub fn set_clip_rect(&mut self, x: f32, y: f32, w: f32, h: f32) { unsafe { ffi::skiac_canvas_clip_rect(self.0, x, y, w, h); } } - #[inline] pub fn set_clip_path(&mut self, path: &Path) { unsafe { ffi::skiac_canvas_clip_path(self.0, path.0); } } - #[inline] pub fn save(&mut self) { unsafe { ffi::skiac_canvas_save(self.0); } } - #[inline] pub fn restore(&mut self) { unsafe { ffi::skiac_canvas_restore(self.0); } } - #[inline] + pub fn reset(&mut self) { + unsafe { + ffi::skiac_canvas_reset(self.0); + } + } + pub fn write_pixels(&mut self, image: &ImageData, x: u32, y: u32) { unsafe { ffi::skiac_canvas_write_pixels( @@ -2050,16 +2040,15 @@ impl Canvas { } } - #[inline] pub fn write_pixels_dirty( &mut self, image: &ImageData, - x: u32, - y: u32, - dirty_x: f64, - dirty_y: f64, - dirty_width: f64, - dirty_height: f64, + x: f32, + y: f32, + dirty_x: f32, + dirty_y: f32, + dirty_width: f32, + dirty_height: f32, ) { unsafe { ffi::skiac_canvas_write_pixels_dirty( @@ -2069,12 +2058,12 @@ impl Canvas { image.data, (image.width * 4) as usize, (image.width * image.height * 4) as usize, - x as f32, - y as f32, - dirty_x as f32, - dirty_y as f32, - dirty_width as f32, - dirty_height as f32, + x, + y, + dirty_x, + dirty_y, + dirty_width, + dirty_height, ) } } @@ -2090,126 +2079,106 @@ impl Clone for Paint { } impl Paint { - #[inline] pub fn new() -> Paint { unsafe { Paint(ffi::skiac_paint_create()) } } - #[inline] pub fn set_style(&mut self, style: PaintStyle) { unsafe { ffi::skiac_paint_set_style(self.0, style as i32); } } - #[inline] pub fn set_color(&mut self, r: u8, g: u8, b: u8, a: u8) { unsafe { ffi::skiac_paint_set_color(self.0, r, g, b, a); } } - #[inline] pub fn set_alpha(&mut self, a: u8) { unsafe { ffi::skiac_paint_set_alpha(self.0, a); } } - #[inline] pub fn get_alpha(&self) -> u8 { unsafe { ffi::skiac_paint_get_alpha(self.0) } } - #[inline] pub fn set_anti_alias(&mut self, aa: bool) { unsafe { ffi::skiac_paint_set_anti_alias(self.0, aa); } } - #[inline] pub fn set_blend_mode(&mut self, blend_mode: BlendMode) { unsafe { ffi::skiac_paint_set_blend_mode(self.0, blend_mode as i32); } } - #[inline] pub fn get_blend_mode(&self) -> BlendMode { unsafe { ffi::skiac_paint_get_blend_mode(self.0).into() } } - #[inline] pub fn set_shader(&mut self, shader: &Shader) { unsafe { ffi::skiac_paint_set_shader(self.0, shader.0); } } - #[inline] pub fn set_stroke_width(&mut self, width: f32) { unsafe { ffi::skiac_paint_set_stroke_width(self.0, width); } } - #[inline] pub fn get_stroke_width(&self) -> f32 { unsafe { ffi::skiac_paint_get_stroke_width(self.0) } } - #[inline] pub fn set_stroke_cap(&mut self, cap: StrokeCap) { unsafe { ffi::skiac_paint_set_stroke_cap(self.0, cap as i32); } } - #[inline] pub fn get_stroke_cap(&self) -> StrokeCap { StrokeCap::from_raw(unsafe { ffi::skiac_paint_get_stroke_cap(self.0) }).unwrap() } - #[inline] pub fn set_stroke_join(&mut self, join: StrokeJoin) { unsafe { ffi::skiac_paint_set_stroke_join(self.0, join as u8); } } - #[inline] pub fn get_stroke_join(&self) -> StrokeJoin { StrokeJoin::from_raw(unsafe { ffi::skiac_paint_get_stroke_join(self.0) }).unwrap() } - #[inline] pub fn set_stroke_miter(&mut self, miter: f32) { unsafe { ffi::skiac_paint_set_stroke_miter(self.0, miter as f32); } } - #[inline] pub fn get_stroke_miter(&self) -> f32 { unsafe { ffi::skiac_paint_get_stroke_miter(self.0) } } - #[inline] pub fn set_path_effect(&mut self, path_effect: &PathEffect) { unsafe { ffi::skiac_paint_set_path_effect(self.0, path_effect.0); } } - #[inline] pub fn set_mask_filter(&mut self, mask_filter: &MaskFilter) { unsafe { ffi::skiac_paint_set_mask_filter(self.0, mask_filter.0); } } - #[inline] pub fn set_image_filter(&mut self, image_filter: &ImageFilter) { unsafe { ffi::skiac_paint_set_image_filter(self.0, image_filter.0); @@ -2233,7 +2202,6 @@ impl Default for Paint { } impl Drop for Paint { - #[inline] fn drop(&mut self) { unsafe { ffi::skiac_paint_destroy(self.0) } } @@ -2253,17 +2221,14 @@ impl Clone for Path { } impl Path { - #[inline] pub fn new() -> Path { unsafe { Path(ffi::skiac_path_create()) } } - #[inline] pub fn swap(&mut self, other: &mut Path) { unsafe { ffi::skiac_path_swap(self.0, other.0) } } - #[inline] pub fn from_svg_path(path: &str) -> Option { let path_str = CString::new(path).ok()?; let p = unsafe { ffi::skiac_path_from_svg(path_str.into_raw()) }; @@ -2274,29 +2239,24 @@ impl Path { } } - #[inline] - pub fn add_path(&mut self, sub_path: &Path, transform: Transform) { - unsafe { ffi::skiac_add_path(self.0, sub_path.0, transform.into()) }; + pub fn add_path(&mut self, sub_path: &Path, transform: &Matrix) { + unsafe { ffi::skiac_add_path(self.0, sub_path.0, transform.0) }; } - #[inline] pub fn op(&self, other: &Path, op: PathOp) -> bool { unsafe { ffi::skiac_path_op(self.0, other.0, op as i32) } } - #[inline] pub fn set_fill_type(&mut self, kind: FillType) { unsafe { ffi::skiac_path_set_fill_type(self.0, kind as i32); } } - #[inline] pub fn get_fill_type(&mut self) -> i32 { unsafe { ffi::skiac_path_get_fill_type(self.0) } } - #[inline(always)] pub fn ellipse( &mut self, x: f32, @@ -2344,7 +2304,7 @@ impl Path { rotated.pre_translate(-x, -y); let unrotated = rotated.invert().unwrap(); - self.transform_matrix(&unrotated); + self.transform_self(&unrotated); // draw in 2 180 degree segments because trying to draw all 360 degrees at once // draws nothing. @@ -2366,10 +2326,9 @@ impl Path { self.arc_to(left, top, right, bottom, start_deg, sweep_deg, false); } - self.transform_matrix(&rotated); + self.transform_self(&rotated); } - #[inline(always)] pub fn arc( &mut self, center_x: f32, @@ -2391,7 +2350,6 @@ impl Path { ) } - #[inline] pub fn arc_to( &mut self, left: f32, @@ -2416,86 +2374,72 @@ impl Path { } } - #[inline] pub fn arc_to_tangent(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, radius: f32) { unsafe { ffi::skiac_path_arc_to_tangent(self.0, x1, y1, x2, y2, radius) } } - #[inline] pub fn move_to(&mut self, x: f32, y: f32) { unsafe { ffi::skiac_path_move_to(self.0, x, y); } } - #[inline] pub fn line_to(&mut self, x: f32, y: f32) { unsafe { ffi::skiac_path_line_to(self.0, x, y); } } - #[inline] pub fn cubic_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) { unsafe { ffi::skiac_path_cubic_to(self.0, x1, y1, x2, y2, x3, y3); } } - #[inline] pub fn quad_to(&mut self, cpx: f32, cpy: f32, x: f32, y: f32) { unsafe { ffi::skiac_path_quad_to(self.0, cpx, cpy, x, y); } } - #[inline] pub fn close(&mut self) { unsafe { ffi::skiac_path_close(self.0); } } - #[inline] pub fn add_rect(&mut self, l: f32, t: f32, r: f32, b: f32) { unsafe { ffi::skiac_path_add_rect(self.0, l, t, r, b); } } - #[inline] pub fn push_circle(&mut self, x: f32, y: f32, r: f32) { unsafe { ffi::skiac_path_add_circle(self.0, x, y, r); } } - #[inline] - pub fn transform(&mut self, transform: &Transform) { - unsafe { ffi::skiac_path_transform(self.0, transform.into()) }; + pub fn transform(&self, transform: &Matrix) -> Self { + Self(unsafe { ffi::skiac_path_transform(self.0, transform.0) }) } - #[inline] - pub fn transform_matrix(&mut self, matrix: &Matrix) { - unsafe { ffi::skiac_path_transform_matrix(self.0, matrix.0) }; + pub fn transform_self(&mut self, matrix: &Matrix) { + unsafe { ffi::skiac_path_transform_self(self.0, matrix.0) }; } - #[inline] pub fn is_empty(&self) -> bool { unsafe { ffi::skiac_path_is_empty(self.0) } } - #[inline] pub fn hit_test(&self, x: f32, y: f32, kind: FillType) -> bool { unsafe { ffi::skiac_path_hit_test(self.0, x, y, kind as i32) } } - #[inline] pub fn stroke_hit_test(&self, x: f32, y: f32, stroke_w: f32) -> bool { unsafe { ffi::skiac_path_stroke_hit_test(self.0, x, y, stroke_w) } } - #[inline] pub fn to_svg_string(&self) -> SkiaString { let mut string = SkiaString { ptr: ptr::null_mut(), @@ -2506,22 +2450,18 @@ impl Path { string } - #[inline] pub fn simplify(&mut self) -> bool { unsafe { ffi::skiac_path_simplify(self.0) } } - #[inline] pub fn as_winding(&mut self) -> bool { unsafe { ffi::skiac_path_as_winding(self.0) } } - #[inline] pub fn stroke(&mut self, cap: StrokeCap, join: StrokeJoin, width: f32, miter_limit: f32) -> bool { unsafe { ffi::skiac_path_stroke(self.0, cap as i32, join as u8, width, miter_limit) } } - #[inline] pub fn compute_tight_bounds(&self) -> (f32, f32, f32, f32) { let mut rect = ffi::skiac_rect { left: 0.0f32, @@ -2533,7 +2473,6 @@ impl Path { (rect.left, rect.top, rect.right, rect.bottom) } - #[inline] pub fn get_bounds(&self) -> (f32, f32, f32, f32) { let mut rect = ffi::skiac_rect { left: 0.0f32, @@ -2545,15 +2484,44 @@ impl Path { (rect.left, rect.top, rect.right, rect.bottom) } - #[inline] pub fn trim(&mut self, start: f32, end: f32, is_complement: bool) -> bool { unsafe { ffi::skiac_path_trim(self.0, start, end, is_complement) } } - #[inline] pub fn dash(&mut self, on: f32, off: f32, phase: f32) -> bool { unsafe { ffi::skiac_path_dash(self.0, on, off, phase) } } + + fn ellipse_helper(&mut self, x: f32, y: f32, rx: f32, ry: f32, start_angle: f32, end_angle: f32) { + let sweep_degrees = radians_to_degrees(end_angle - start_angle); + let start_degrees = radians_to_degrees(start_angle); + let left = x - rx; + let top = y - ry; + let right = x + rx; + let bottom = y + ry; + if almost_equal(sweep_degrees.abs(), 360.0) { + let half_sweep = sweep_degrees / 2.0; + self.arc_to(left, top, right, bottom, start_degrees, half_sweep, false); + self.arc_to( + left, + top, + right, + bottom, + start_degrees + half_sweep, + half_sweep, + false, + ); + }; + self.arc_to( + left, + top, + right, + bottom, + start_degrees, + sweep_degrees, + false, + ); + } } impl PartialEq for Path { @@ -2563,7 +2531,6 @@ impl PartialEq for Path { } impl Drop for Path { - #[inline] fn drop(&mut self) { unsafe { ffi::skiac_path_destroy(self.0); @@ -2606,7 +2573,6 @@ pub struct ConicGradient { pub struct Shader(*mut ffi::skiac_shader); impl Shader { - #[inline] pub fn new_linear_gradient(grad: &LinearGradient) -> Option { let points = [ ffi::skiac_point { @@ -2632,7 +2598,6 @@ impl Shader { } } - #[inline] pub fn new_radial_gradient(grad: &RadialGradient) -> Option { let start_point = ffi::skiac_point { x: grad.start.0, @@ -2659,7 +2624,6 @@ impl Shader { } } - #[inline] pub fn new_conic_gradient(grad: &ConicGradient) -> Option { unsafe { Self::from_ptr(ffi::skiac_shader_make_conic_gradient( @@ -2676,7 +2640,6 @@ impl Shader { } } - #[inline] pub fn new_from_surface_image( surface: &Surface, ts: Transform, @@ -2691,7 +2654,6 @@ impl Shader { } } - #[inline] pub fn from_bitmap( bitmap: *mut ffi::skiac_bitmap, repeat_x: TileMode, @@ -2707,7 +2669,6 @@ impl Shader { } } - #[inline] unsafe fn from_ptr(ptr: *mut ffi::skiac_shader) -> Option { if ptr.is_null() { None @@ -2718,7 +2679,6 @@ impl Shader { } impl Drop for Shader { - #[inline] fn drop(&mut self) { unsafe { ffi::skiac_shader_destroy(self.0); @@ -2729,7 +2689,6 @@ impl Drop for Shader { pub struct PathEffect(*mut ffi::skiac_path_effect); impl PathEffect { - #[inline] pub fn new_dash_path(intervals: &[f32], phase: f32) -> Option { unsafe { let ptr = @@ -2745,7 +2704,6 @@ impl PathEffect { } impl Drop for PathEffect { - #[inline] fn drop(&mut self) { unsafe { ffi::skiac_path_effect_destroy(self.0); @@ -2757,27 +2715,79 @@ impl Drop for PathEffect { pub struct Matrix(*mut ffi::skiac_matrix); impl Matrix { - #[inline(always)] pub fn identity() -> Self { Matrix(unsafe { ffi::skiac_matrix_create() }) } - #[inline(always)] + pub fn new(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> Self { + Self(unsafe { ffi::skiac_matrix_new(a, b, c, d, e, f) }) + } + + pub fn from_transform(ts: &Transform) -> Self { + let mut c_ts: ffi::skiac_transform = ts.into(); + Matrix(unsafe { ffi::skiac_matrix_from_ts(&mut c_ts) }) + } + + pub fn rotated(radians: f32, x: f32, y: f32) -> Self { + Matrix(unsafe { ffi::skiac_matrix_create_rotated(radians, x, y) }) + } + + pub fn translated(x: f32, y: f32) -> Self { + Matrix(unsafe { ffi::skiac_matrix_create_translated(x, y) }) + } + + pub fn map_points(&self, x1: f32, y1: f32, x2: f32, y2: f32) -> (f32, f32, f32, f32) { + let mut mapped_point = ffi::skiac_mapped_point { + x1: 0.0, + y1: 0.0, + x2: 0.0, + y2: 0.0, + }; + unsafe { ffi::skiac_matrix_map_points(self.0, x1, y1, x2, y2, &mut mapped_point) }; + ( + mapped_point.x1, + mapped_point.y1, + mapped_point.x2, + mapped_point.y2, + ) + } + pub fn pre_translate(&mut self, dx: f32, dy: f32) { unsafe { ffi::skiac_matrix_pre_translate(self.0, dx, dy) }; } - #[inline(always)] + pub fn concat(&self, other: &Matrix) -> Self { + Self(unsafe { ffi::skiac_matrix_concat(self.0, other.0) }) + } + + pub fn multiply(&self, other: &Matrix) -> Self { + Self(unsafe { ffi::skiac_matrix_multiply(self.0, other.0) }) + } + + pub fn pre_concat(&mut self, other: &Matrix) { + unsafe { ffi::skiac_matrix_pre_concat(self.0, other.0) }; + } + + pub fn pre_scale(&mut self, sx: f32, sy: f32) { + unsafe { ffi::skiac_matrix_pre_scale(self.0, sx, sy) }; + } + + pub fn pre_transform(&mut self, ts: &Transform) { + unsafe { ffi::skiac_matrix_pre_concat_transform(self.0, ts.into()) } + } + pub fn pre_rotate(&mut self, degrees: f32) { unsafe { ffi::skiac_matrix_pre_rotate(self.0, degrees) }; } - #[inline(always)] - pub fn into_transform(self) -> Transform { + pub fn pre_rotate_x_y(&mut self, degrees: f32, x: f32, y: f32) { + unsafe { ffi::skiac_matrix_pre_rotate_x_y(self.0, degrees, x, y) }; + } + + pub fn get_transform(&self) -> Transform { unsafe { ffi::skiac_matrix_to_transform(self.0) }.into() } - #[inline(always)] pub fn invert(&self) -> Option { let m = Matrix::identity(); if unsafe { ffi::skiac_matrix_invert(self.0, m.0) } { @@ -2794,6 +2804,23 @@ impl Clone for Matrix { } } +impl fmt::Debug for Matrix { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.get_transform().fmt(f) + } +} + +impl fmt::Display for Matrix { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let ts = self.get_transform(); + write!( + f, + "Matrix [{}, {}, {}, {}, {}, {}, 0, 0, 1]", + ts.a, ts.c, ts.e, ts.b, ts.d, ts.f + ) + } +} + impl Drop for Matrix { fn drop(&mut self) { unsafe { ffi::skiac_matrix_destroy(self.0) }; @@ -2811,12 +2838,10 @@ pub struct Transform { } impl Transform { - #[inline] pub fn new(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) -> Self { Transform { a, b, c, d, e, f } } - #[inline] pub fn rotate(radians: f32) -> Self { let sin_v = radians.sin(); let cos_v = radians.cos(); @@ -2831,7 +2856,6 @@ impl Transform { } } - #[inline] /// | A C E | | A/X C/X E/X | /// | B D F | -> | B/X D/X F/X | for X != 0 /// | 0 0 X | | 0 0 1 | @@ -2853,7 +2877,6 @@ impl Transform { } } - #[inline] /// | A C E | /// | B D F | /// | 0 0 1 | @@ -2894,14 +2917,12 @@ impl Default for Transform { } impl From for Transform { - #[inline] fn from(ts: ffi::skiac_transform) -> Self { Transform::new(ts.a, ts.b, ts.c, ts.d, ts.e, ts.f) } } impl From for ffi::skiac_transform { - #[inline] fn from(ts: Transform) -> Self { ffi::skiac_transform { a: ts.a, @@ -2915,7 +2936,6 @@ impl From for ffi::skiac_transform { } impl<'a> From<&'a Transform> for ffi::skiac_transform { - #[inline] fn from(ts: &'a Transform) -> Self { ffi::skiac_transform { a: ts.a, @@ -2982,7 +3002,6 @@ impl Drop for ImageFilter { pub(crate) struct Bitmap(pub(crate) ffi::skiac_bitmap_info); impl Bitmap { - #[inline] pub fn from_buffer(ptr: *mut u8, size: usize) -> Self { let mut bitmap_info = ffi::skiac_bitmap_info { bitmap: ptr::null_mut(), @@ -2995,7 +3014,6 @@ impl Bitmap { } } - #[inline] pub fn from_svg_data(data: *const u8, size: usize) -> Option { let mut bitmap_info = ffi::skiac_bitmap_info { bitmap: ptr::null_mut(), @@ -3012,7 +3030,6 @@ impl Bitmap { } } - #[inline(always)] pub fn from_svg_data_with_custom_size( data: *const u8, size: usize, @@ -3034,7 +3051,6 @@ impl Bitmap { } } - #[inline] pub fn from_image_data( ptr: *mut u8, width: usize, @@ -3081,7 +3097,6 @@ pub struct ImagePattern { } impl ImagePattern { - #[inline(always)] pub(crate) fn get_shader(&self) -> Option { Shader::from_bitmap( self.bitmap, @@ -3115,7 +3130,6 @@ pub struct LineMetrics(pub ffi::skiac_line_metrics); pub struct FontCollection(pub *mut ffi::skiac_font_collection); impl FontCollection { - #[inline] pub fn new() -> FontCollection { unsafe { let c_font_collection = ffi::skiac_font_collection_create(); @@ -3123,7 +3137,6 @@ impl FontCollection { } } - #[inline] pub fn get_families(&self) -> Vec { let mut names = Vec::new(); @@ -3173,7 +3186,6 @@ impl FontCollection { names } - #[inline] pub fn register(&self, font: &[u8], maybe_name_alias: Option<&str>) -> bool { let name_alias_ptr = match maybe_name_alias { Some(name_alias) => match CString::new(name_alias) { @@ -3187,7 +3199,6 @@ impl FontCollection { } } - #[inline] pub fn register_from_path(&self, font_path: &str, maybe_name_alias: Option<&str>) -> bool { if let Ok(fp) = CString::new(font_path) { let name_alias_ptr = match maybe_name_alias { @@ -3207,7 +3218,6 @@ impl FontCollection { } impl Drop for FontCollection { - #[inline] fn drop(&mut self) { unsafe { ffi::skiac_font_collection_destroy(self.0) } } @@ -3230,7 +3240,6 @@ pub struct FontStyleSet { pub struct SkWMemoryStream(*mut ffi::skiac_w_memory_stream); impl SkWMemoryStream { - #[inline] pub fn data(&self, w: u32, h: u32) -> SkiaDataRef { let mut data = ffi::skiac_sk_data { ptr: ptr::null_mut(), @@ -3243,7 +3252,6 @@ impl SkWMemoryStream { } impl Drop for SkWMemoryStream { - #[inline] fn drop(&mut self) { unsafe { ffi::skiac_sk_w_stream_destroy(self.0) } } @@ -3259,7 +3267,6 @@ fn almost_equal(floata: f32, floatb: f32) -> bool { (floata - floatb).abs() < 0.00001 } -#[inline(always)] pub fn sk_svg_text_to_path(svg: &[u8], fc: &FontCollection) -> Option { let mut output_data = ffi::skiac_sk_data { ptr: ptr::null_mut(), diff --git a/src/state.rs b/src/state.rs index 05fbc608..d5bf0b35 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,5 +1,7 @@ use cssparser::RGBA; +use crate::sk::Matrix; + use super::{ font::Font, pattern::Pattern, @@ -27,6 +29,7 @@ pub struct Context2dRenderingState { pub text_align: TextAlign, pub text_baseline: TextBaseline, pub text_direction: TextDirection, + pub transform: Matrix, } impl Default for Context2dRenderingState { @@ -53,6 +56,7 @@ impl Default for Context2dRenderingState { text_align: TextAlign::default(), text_baseline: TextBaseline::default(), text_direction: TextDirection::default(), + transform: Matrix::identity(), } } }