first commit

This commit is contained in:
Warunee Tamkoo 2023-09-06 14:51:44 +07:00
commit eb2f504652
32490 changed files with 5731109 additions and 0 deletions

107
node_modules/path2d-polyfill/CHANGELOG.md generated vendored Normal file
View file

@ -0,0 +1,107 @@
## [2.0.1](https://github.com/nilzona/path2d-polyfill/compare/v2.0.0...v2.0.1) (2023-01-22)
### Bug Fixes
- add browser and main fields in package.json ([82e8522](https://github.com/nilzona/path2d-polyfill/commit/82e8522b17c750cc06dbade1e7022ffea312fd5d))
## [2.0.0](https://github.com/nilzona/path2d-polyfill/compare/v1.2.3...v2.0.0) (2023-01-22)
### ⚠ BREAKING CHANGES
- target build now has the name `dist/path2d-polyfill.min.js`
- chore: null Path2D in example index.html
- Update tsconfig.json
Co-authored-by: Linus Unnebäck <linus@folkdatorn.se>
- chore: build for node and browsers
- docs: update doc example
Co-authored-by: Linus Unnebäck <linus@folkdatorn.se>
### Features
- node support with roundRect polyfill ([#43](https://github.com/nilzona/path2d-polyfill/issues/43)) ([2fffe15](https://github.com/nilzona/path2d-polyfill/commit/2fffe15a76e7adac50beacc0f9587d5b3cc71485))
## [1.2.3](https://github.com/nilzona/path2d-polyfill/compare/v1.2.2...v1.2.3) (2022-10-11)
## [1.2.2](https://github.com/nilzona/path2d-polyfill/compare/v1.2.1...v1.2.2) (2022-07-23)
undefined
### [1.2.1](https://github.com/nilzona/path2d-polyfill/compare/v1.2.0...v1.2.1) (2022-03-06)## [1.2.0](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2021-10-30)
### Bug Fixes
- fixup lint and build ([94be3cd](https://github.com/nilzona/path2d-polyfill/commit/94be3cd38a58f83efc403a58380ff3c23b4f18bf))
- sync version in package.json with tags ([e12e852](https://github.com/nilzona/path2d-polyfill/commit/e12e852ffb13034fa13efd5112c59b6b13a46013))
### [1.1.2](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2021-05-04)
### [1.1.1](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2020-11-16)
### Features
- support for isPointInPath ([605f5d1](https://github.com/nilzona/path2d-polyfill/commit/605f5d188812e472575ccbaba351b9bbc58d3677))
### Bug Fixes
- documentation readme ([5a0abaa](https://github.com/nilzona/path2d-polyfill/commit/5a0abaab6976f10c57ac83e6f6481ed425ac940e))
### [1.0.2](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2020-08-27)
### Bug Fixes
- remove unused css rule ([54e5174](https://github.com/nilzona/path2d-polyfill/commit/54e5174c64f6e84ef891d8830c828efc45c73b93))
- update badge in README.md ([483afe2](https://github.com/nilzona/path2d-polyfill/commit/483afe2b3440083bbb0c3dae74510959055d0f86))
## [1.0.0](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2020-05-27)
### [0.4.2](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2019-08-28)
### [0.4.1](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2019-04-15)
## [0.4.0](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2019-04-12)
### Features
- support ellipse commands ([#7](https://github.com/nilzona/path2d-polyfill/issues/7)) ([02af6d5](https://github.com/nilzona/path2d-polyfill/commit/02af6d55365b8ef70b8eecad88b913e71ae191b2))
### Bug Fixes
- move current position when a path is closed ([#9](https://github.com/nilzona/path2d-polyfill/issues/9)) ([ff6d2f7](https://github.com/nilzona/path2d-polyfill/commit/ff6d2f770f9895be2ac2e947697b8f76e488cb37))
### [0.3.1](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2018-09-26)
### Bug Fixes
- better checks if polyfill is needed ([bd65468](https://github.com/nilzona/path2d-polyfill/commit/bd654681662530d19a0958db22c5990424fb77f2))
## [0.3.0](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2018-09-25)
### [0.2.2](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2018-09-04)
### [0.2.1](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2018-06-05)
## [0.2.0](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2018-06-04)
### [0.1.3](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2018-05-22)
### Bug Fixes
- Avoid reference to global window ([9d3e742](https://github.com/nilzona/path2d-polyfill/commit/9d3e74241eb0652afe22d34523f10f3a3837e179))
- Remove wrong removeChild call ([123db85](https://github.com/nilzona/path2d-polyfill/commit/123db8571ff8b1b6c2fa917b513c74f8215acc37))
- Update README.md ([bcb01e1](https://github.com/nilzona/path2d-polyfill/commit/bcb01e153add2dccf95adaced13646e871086a3a))
### [0.1.1](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2018-05-18)
## [0.1.0](https://github.com/nilzona/path2d-polyfill/compare/v1.1.8...v1.2.0) (2018-05-18)
### Features
- Added examples ([261165c](https://github.com/nilzona/path2d-polyfill/commit/261165cfb0ea3a9910624f719a34a3596f1791d0))
- First version of Path2D polyfill ([a660f19](https://github.com/nilzona/path2d-polyfill/commit/a660f194f416785a40d8d7f5ad451bb54cec15c3))
- Implement addPath ([72d4228](https://github.com/nilzona/path2d-polyfill/commit/72d4228bd6c4dda64fa957ab80e49bd7c7677d8f))

21
node_modules/path2d-polyfill/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Anders Nilsson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

107
node_modules/path2d-polyfill/README.md generated vendored Normal file
View file

@ -0,0 +1,107 @@
# path2d-polyfill
[![validate](https://github.com/nilzona/path2d-polyfill/actions/workflows/validate.yaml/badge.svg)](https://github.com/nilzona/path2d-polyfill/actions/workflows/validate.yaml)
Polyfills `Path2D` api and `roundRect` for CanvasRenderingContext2D
## Usage
Add this script tag to your page to enable the feature.
```html
<script lang="javascript" src="https://cdn.jsdelivr.net/npm/path2d-polyfill/dist/path2d-polyfill.min.js"></script>
```
or install from npm
```shell
npm install --save path2d-polyfill
```
and import with module bundler e.g. webpack _before_ using the feature
```javascript
import "path2d-polyfill";
```
This will polyfill the browser's window object with Path2D features and it will also polyfill roundRect if they are missing in both CanvasRenderingContexst and Path2D.
Example of usage
```javascript
ctx.fill(new Path2D("M 80 80 A 45 45 0 0 0 125 125 L 125 80 Z"));
ctx.stroke(new Path2D("M 80 80 A 45 45 0 0 0 125 125 L 125 80 Z"));
```
## Usage in a node environment
It is possible to use this library in a node environment as well. The package exports a few functions that can be used:
- `Path2D` - class to create Path2D objects used by the polyfill methods
- `polyfillPath2D` - function that adds Path2D to a "window like" object and polyfills CanvasRenderingContext2D to use Path2D
- `polyfillRoundRect` - polyfills roundRect function on Path2D and CanvasRenderingContext2D (missing in firefox)
- `parsePath` - function for parsing an SVG path string into canvas commands
use any of these functions like:
```js
const { polyfillRoundRect } = require "path2d-polyfill";
const windowlike = { CanvasRenderingContext2D, Path2D };
polyfillRoundRect(windowLike);
// roundRect functions has now been added if they were missing
```
### usage with node-canvas
To get Path2D features with the [node-canvas library](https://github.com/Automattic/node-canvas) use the following pattern:
```js
const { createCanvas, CanvasRenderingContext2D } = require("canvas");
const { polyfillPath2D } = require("path2d-polyfill/path2d");
global.CanvasRenderingContext2D = CanvasRenderingContext2D;
polyfillPath2D(global);
// Path2D has now been added to global object
const canvas = createCanvas(200, 200);
const ctx = canvas.getContext("2d");
const p = new Path2D("M10 10 l 20 0 l 0 20 Z");
ctx.fillStyle = "green";
ctx.fill(p);
```
A working example of a node express server that serves an image drawn with canvas can be seen [here](https://gist.github.com/nilzona/e611c99336d8ea1f645bd391a459c24f)
## Support table
| Method | Supported |
| -------------------- | :-------: |
| constructor(SVGPath) | Yes |
| addPath() | Yes |
| closePath() | Yes |
| moveTo() | Yes |
| lineTo() | Yes |
| bezierCurveTo() | Yes |
| quadraticCurveTo() | Yes |
| arc() | Yes |
| ellipse() | Yes |
| rect() | Yes |
| roundRect() | Yes |
## See it in action
Clone this repo and run the following
```shell
yarn
yarn start
```
open <http://localhost:10001> to see the example page.
## Contributing
Recommended to use vscode with the prettier extension to keep formatting intact.

596
node_modules/path2d-polyfill/dist/path2d-node.cjs generated vendored Normal file
View file

@ -0,0 +1,596 @@
'use strict';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
var ARG_LENGTH = {
a: 7,
c: 6,
h: 1,
l: 2,
m: 2,
q: 4,
s: 4,
t: 2,
v: 1,
z: 0
};
var SEGMENT_PATTERN = /([astvzqmhlc])([^astvzqmhlc]*)/gi;
var NUMBER = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/gi;
function parseValues(args) {
var numbers = args.match(NUMBER);
return numbers ? numbers.map(Number) : [];
}
/**
* parse an svg path data string. Generates an Array
* of commands where each command is an Array of the
* form `[command, arg1, arg2, ...]`
*
* https://www.w3.org/TR/SVG/paths.html#PathDataGeneralInformation
* @ignore
*
* @param {string} path
* @returns {array}
*/
function parsePath(path) {
var data = [];
var p = String(path).trim();
// A path data segment (if there is one) must begin with a "moveto" command
if (p[0] !== "M" && p[0] !== "m") {
return data;
}
p.replace(SEGMENT_PATTERN, function (_, command, args) {
var theArgs = parseValues(args);
var type = command.toLowerCase();
var theCommand = command;
// overloaded moveTo
if (type === "m" && theArgs.length > 2) {
data.push(__spreadArray([theCommand], theArgs.splice(0, 2), true));
type = "l";
theCommand = theCommand === "m" ? "l" : "L";
}
// Ignore invalid commands
if (theArgs.length < ARG_LENGTH[type]) {
return "";
}
data.push(__spreadArray([theCommand], theArgs.splice(0, ARG_LENGTH[type]), true));
// The command letter can be eliminated on subsequent commands if the
// same command is used multiple times in a row (e.g., you can drop the
// second "L" in "M 100 200 L 200 100 L -100 -200" and use
// "M 100 200 L 200 100 -100 -200" instead).
while (theArgs.length >= ARG_LENGTH[type] && theArgs.length && ARG_LENGTH[type]) {
data.push(__spreadArray([theCommand], theArgs.splice(0, ARG_LENGTH[type]), true));
}
return "";
});
return data;
}
function rotatePoint(point, angle) {
var nx = point.x * Math.cos(angle) - point.y * Math.sin(angle);
var ny = point.y * Math.cos(angle) + point.x * Math.sin(angle);
point.x = nx;
point.y = ny;
}
function translatePoint(point, dx, dy) {
point.x += dx;
point.y += dy;
}
function scalePoint(point, s) {
point.x *= s;
point.y *= s;
}
/**
* Implements a browser's Path2D api
*/
var Path2D = /** @class */ (function () {
function Path2D(path) {
var _a;
this.commands = [];
if (path && path instanceof Path2D) {
(_a = this.commands).push.apply(_a, path.commands);
}
else if (path) {
this.commands = parsePath(path);
}
}
Path2D.prototype.addPath = function (path) {
var _a;
if (path && path instanceof Path2D) {
(_a = this.commands).push.apply(_a, path.commands);
}
};
Path2D.prototype.moveTo = function (x, y) {
this.commands.push(["M", x, y]);
};
Path2D.prototype.lineTo = function (x, y) {
this.commands.push(["L", x, y]);
};
Path2D.prototype.arc = function (x, y, r, start, end, ccw) {
this.commands.push(["AC", x, y, r, start, end, !!ccw]);
};
Path2D.prototype.arcTo = function (x1, y1, x2, y2, r) {
this.commands.push(["AT", x1, y1, x2, y2, r]);
};
Path2D.prototype.ellipse = function (x, y, rx, ry, angle, start, end, ccw) {
this.commands.push(["E", x, y, rx, ry, angle, start, end, !!ccw]);
};
Path2D.prototype.closePath = function () {
this.commands.push(["Z"]);
};
Path2D.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
this.commands.push(["C", cp1x, cp1y, cp2x, cp2y, x, y]);
};
Path2D.prototype.quadraticCurveTo = function (cpx, cpy, x, y) {
this.commands.push(["Q", cpx, cpy, x, y]);
};
Path2D.prototype.rect = function (x, y, width, height) {
this.commands.push(["R", x, y, width, height]);
};
Path2D.prototype.roundRect = function (x, y, width, height, radii) {
if (typeof radii === "undefined") {
this.commands.push(["RR", x, y, width, height, 0]);
}
else {
this.commands.push(["RR", x, y, width, height, radii]);
}
};
return Path2D;
}());
function buildPath(ctx, commands) {
var x = 0;
var y = 0;
var endAngle;
var startAngle;
var largeArcFlag;
var sweepFlag;
var endPoint;
var midPoint;
var angle;
var lambda;
var t1;
var t2;
var x1;
var y1;
var r;
var rx;
var ry;
var w;
var h;
var pathType;
var centerPoint;
var ccw;
var radii;
var cpx = null;
var cpy = null;
var qcpx = null;
var qcpy = null;
var startPoint = null;
var currentPoint = null;
ctx.beginPath();
for (var i = 0; i < commands.length; ++i) {
pathType = commands[i][0];
// Reset control point if command is not cubic
if (pathType !== "S" && pathType !== "s" && pathType !== "C" && pathType !== "c") {
cpx = null;
cpy = null;
}
if (pathType !== "T" && pathType !== "t" && pathType !== "Q" && pathType !== "q") {
qcpx = null;
qcpy = null;
}
var c = void 0;
switch (pathType) {
case "m":
case "M":
c = commands[i];
if (pathType === "m") {
x += c[1];
y += c[2];
}
else {
x = c[1];
y = c[2];
}
if (pathType === "M" || !startPoint) {
startPoint = { x: x, y: y };
}
ctx.moveTo(x, y);
break;
case "l":
c = commands[i];
x += c[1];
y += c[2];
ctx.lineTo(x, y);
break;
case "L":
c = commands[i];
x = c[1];
y = c[2];
ctx.lineTo(x, y);
break;
case "H":
c = commands[i];
x = c[1];
ctx.lineTo(x, y);
break;
case "h":
c = commands[i];
x += c[1];
ctx.lineTo(x, y);
break;
case "V":
c = commands[i];
y = c[1];
ctx.lineTo(x, y);
break;
case "v":
c = commands[i];
y += c[1];
ctx.lineTo(x, y);
break;
case "a":
case "A":
c = commands[i];
if (currentPoint === null) {
throw new Error("This should never happen");
}
if (pathType === "a") {
x += c[6];
y += c[7];
}
else {
x = c[6];
y = c[7];
}
rx = c[1]; // rx
ry = c[2]; // ry
angle = (c[3] * Math.PI) / 180;
largeArcFlag = !!c[4];
sweepFlag = !!c[5];
endPoint = { x: x, y: y };
// https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
midPoint = {
x: (currentPoint.x - endPoint.x) / 2,
y: (currentPoint.y - endPoint.y) / 2
};
rotatePoint(midPoint, -angle);
// radius correction
lambda = (midPoint.x * midPoint.x) / (rx * rx) + (midPoint.y * midPoint.y) / (ry * ry);
if (lambda > 1) {
lambda = Math.sqrt(lambda);
rx *= lambda;
ry *= lambda;
}
centerPoint = {
x: (rx * midPoint.y) / ry,
y: -(ry * midPoint.x) / rx
};
t1 = rx * rx * ry * ry;
t2 = rx * rx * midPoint.y * midPoint.y + ry * ry * midPoint.x * midPoint.x;
if (sweepFlag !== largeArcFlag) {
scalePoint(centerPoint, Math.sqrt((t1 - t2) / t2) || 0);
}
else {
scalePoint(centerPoint, -Math.sqrt((t1 - t2) / t2) || 0);
}
startAngle = Math.atan2((midPoint.y - centerPoint.y) / ry, (midPoint.x - centerPoint.x) / rx);
endAngle = Math.atan2(-(midPoint.y + centerPoint.y) / ry, -(midPoint.x + centerPoint.x) / rx);
rotatePoint(centerPoint, angle);
translatePoint(centerPoint, (endPoint.x + currentPoint.x) / 2, (endPoint.y + currentPoint.y) / 2);
ctx.save();
ctx.translate(centerPoint.x, centerPoint.y);
ctx.rotate(angle);
ctx.scale(rx, ry);
ctx.arc(0, 0, 1, startAngle, endAngle, !sweepFlag);
ctx.restore();
break;
case "C":
c = commands[i];
cpx = c[3]; // Last control point
cpy = c[4];
x = c[5];
y = c[6];
ctx.bezierCurveTo(c[1], c[2], cpx, cpy, x, y);
break;
case "c":
c = commands[i];
ctx.bezierCurveTo(c[1] + x, c[2] + y, c[3] + x, c[4] + y, c[5] + x, c[6] + y);
cpx = c[3] + x; // Last control point
cpy = c[4] + y;
x += c[5];
y += c[6];
break;
case "S":
c = commands[i];
if (cpx === null || cpy === null) {
cpx = x;
cpy = y;
}
ctx.bezierCurveTo(2 * x - cpx, 2 * y - cpy, c[1], c[2], c[3], c[4]);
cpx = c[1]; // last control point
cpy = c[2];
x = c[3];
y = c[4];
break;
case "s":
c = commands[i];
if (cpx === null || cpy === null) {
cpx = x;
cpy = y;
}
ctx.bezierCurveTo(2 * x - cpx, 2 * y - cpy, c[1] + x, c[2] + y, c[3] + x, c[4] + y);
cpx = c[1] + x; // last control point
cpy = c[2] + y;
x += c[3];
y += c[4];
break;
case "Q":
c = commands[i];
qcpx = c[1]; // last control point
qcpy = c[2];
x = c[3];
y = c[4];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "q":
c = commands[i];
qcpx = c[1] + x; // last control point
qcpy = c[2] + y;
x += c[3];
y += c[4];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "T":
c = commands[i];
if (qcpx === null || qcpy === null) {
qcpx = x;
qcpy = y;
}
qcpx = 2 * x - qcpx; // last control point
qcpy = 2 * y - qcpy;
x = c[1];
y = c[2];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "t":
c = commands[i];
if (qcpx === null || qcpy === null) {
qcpx = x;
qcpy = y;
}
qcpx = 2 * x - qcpx; // last control point
qcpy = 2 * y - qcpy;
x += c[1];
y += c[2];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "z":
case "Z":
if (startPoint) {
x = startPoint.x;
y = startPoint.y;
}
startPoint = null;
ctx.closePath();
break;
case "AC": // arc
c = commands[i];
x = c[1];
y = c[2];
r = c[3];
startAngle = c[4];
endAngle = c[5];
ccw = c[6];
ctx.arc(x, y, r, startAngle, endAngle, ccw);
break;
case "AT": // arcTo
c = commands[i];
x1 = c[1];
y1 = c[2];
x = c[3];
y = c[4];
r = c[5];
ctx.arcTo(x1, y1, x, y, r);
break;
case "E": // ellipse
c = commands[i];
x = c[1];
y = c[2];
rx = c[3];
ry = c[4];
angle = c[5];
startAngle = c[6];
endAngle = c[7];
ccw = c[8];
ctx.save();
ctx.translate(x, y);
ctx.rotate(angle);
ctx.scale(rx, ry);
ctx.arc(0, 0, 1, startAngle, endAngle, ccw);
ctx.restore();
break;
case "R": // rect
c = commands[i];
x = c[1];
y = c[2];
w = c[3];
h = c[4];
startPoint = { x: x, y: y };
ctx.rect(x, y, w, h);
break;
case "RR": // roundedRect
c = commands[i];
x = c[1];
y = c[2];
w = c[3];
h = c[4];
radii = c[5];
startPoint = { x: x, y: y };
ctx.roundRect(x, y, w, h, radii);
break;
}
if (!currentPoint) {
currentPoint = { x: x, y: y };
}
else {
currentPoint.x = x;
currentPoint.y = y;
}
}
}
/**
* Polyfills CanvasRenderingContext2D stroke, fill and isPointInPath so that they support Path2D objects.
* @param {WindowLike} window - window like object containing a CanvasRenderingContext2D constructor
*/
function polyfillPath2D(window) {
if (!window || !window.CanvasRenderingContext2D || window.Path2D)
return;
var CanvasRenderingContext2D = window.CanvasRenderingContext2D;
/* eslint-disable @typescript-eslint/unbound-method */
// setting unbound functions here. Make sure this is set in function call later
var cFill = CanvasRenderingContext2D.prototype.fill;
var cStroke = CanvasRenderingContext2D.prototype.stroke;
var cIsPointInPath = CanvasRenderingContext2D.prototype.isPointInPath;
/* eslint-enable @typescript-eslint/unbound-method */
CanvasRenderingContext2D.prototype.fill = function fill() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (args[0] instanceof Path2D) {
var path = args[0];
var fillRule = args[1] || "nonzero";
buildPath(this, path.commands);
cFill.apply(this, [fillRule]);
}
else {
var fillRule = args[0] || "nonzero";
return cFill.apply(this, [fillRule]);
}
};
CanvasRenderingContext2D.prototype.stroke = function stroke(path) {
if (path) {
buildPath(this, path.commands);
}
cStroke.apply(this);
};
CanvasRenderingContext2D.prototype.isPointInPath = function isPointInPath() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (args[0] instanceof Path2D) {
// first argument is a Path2D object
var path = args[0];
var x = args[1];
var y = args[2];
var fillRule = args[3] || "nonzero";
buildPath(this, path.commands);
return cIsPointInPath.apply(this, [x, y, fillRule]);
}
else {
return cIsPointInPath.apply(this, args);
}
};
window.Path2D = Path2D;
}
function roundRect(x, y, width, height, radii) {
var _this = this;
if (radii === void 0) { radii = 0; }
if (typeof radii === "number") {
// eslint-disable-next-line no-param-reassign
radii = [radii];
}
// check for range error
if (Array.isArray(radii)) {
if (radii.length === 0 || radii.length > 4) {
throw new RangeError("Failed to execute 'roundRect' on '".concat(this.constructor.name, "': ").concat(radii.length, " radii provided. Between one and four radii are necessary."));
}
radii.forEach(function (v) {
if (v < 0) {
throw new RangeError("Failed to execute 'roundRect' on '".concat(_this.constructor.name, "': Radius value ").concat(v, " is negative."));
}
});
}
else {
return;
}
if (radii.length === 1 && radii[0] === 0) {
return this.rect(x, y, width, height);
}
// set the corners
// tl = top left radius
// tr = top right radius
// br = bottom right radius
// bl = bottom left radius
var minRadius = Math.min(width, height) / 2;
var tr, br, bl;
var tl = (tr = br = bl = Math.min(minRadius, radii[0]));
if (radii.length === 2) {
tr = bl = Math.min(minRadius, radii[1]);
}
if (radii.length === 3) {
tr = bl = Math.min(minRadius, radii[1]);
br = Math.min(minRadius, radii[2]);
}
if (radii.length === 4) {
tr = Math.min(minRadius, radii[1]);
br = Math.min(minRadius, radii[2]);
bl = Math.min(minRadius, radii[3]);
}
// begin with closing current path
// this.closePath();
// let's draw the rounded rectangle
this.moveTo(x, y + height - bl);
this.arcTo(x, y, x + tl, y, tl);
this.arcTo(x + width, y, x + width, y + tr, tr);
this.arcTo(x + width, y + height, x + width - br, y + height, br);
this.arcTo(x, y + height, x, y + height - bl, bl);
// and move to rects control point for further path drawing
this.moveTo(x, y);
}
/**
* Polyfills roundRect on CanvasRenderingContext2D and Path2D
* @param {WindowLike} window - window like object containing both CanvasRenderingContext2D and Path2D constructor
*/
function polyfillRoundRect(window) {
if (!window || !window.CanvasRenderingContext2D)
return;
var CanvasRenderingContext2D = window.CanvasRenderingContext2D, Path2D = window.Path2D;
// polyfill unsupported roundRect for e.g. firefox https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect#browser_compatibility
if (CanvasRenderingContext2D && !CanvasRenderingContext2D.prototype.roundRect) {
CanvasRenderingContext2D.prototype.roundRect = roundRect;
}
if (Path2D && !Path2D.prototype.roundRect) {
Path2D.prototype.roundRect = roundRect;
}
}
exports.Path2D = Path2D;
exports.parsePath = parsePath;
exports.polyfillPath2D = polyfillPath2D;
exports.polyfillRoundRect = polyfillRoundRect;

591
node_modules/path2d-polyfill/dist/path2d-node.mjs generated vendored Normal file
View file

@ -0,0 +1,591 @@
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
var ARG_LENGTH = {
a: 7,
c: 6,
h: 1,
l: 2,
m: 2,
q: 4,
s: 4,
t: 2,
v: 1,
z: 0
};
var SEGMENT_PATTERN = /([astvzqmhlc])([^astvzqmhlc]*)/gi;
var NUMBER = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/gi;
function parseValues(args) {
var numbers = args.match(NUMBER);
return numbers ? numbers.map(Number) : [];
}
/**
* parse an svg path data string. Generates an Array
* of commands where each command is an Array of the
* form `[command, arg1, arg2, ...]`
*
* https://www.w3.org/TR/SVG/paths.html#PathDataGeneralInformation
* @ignore
*
* @param {string} path
* @returns {array}
*/
function parsePath(path) {
var data = [];
var p = String(path).trim();
// A path data segment (if there is one) must begin with a "moveto" command
if (p[0] !== "M" && p[0] !== "m") {
return data;
}
p.replace(SEGMENT_PATTERN, function (_, command, args) {
var theArgs = parseValues(args);
var type = command.toLowerCase();
var theCommand = command;
// overloaded moveTo
if (type === "m" && theArgs.length > 2) {
data.push(__spreadArray([theCommand], theArgs.splice(0, 2), true));
type = "l";
theCommand = theCommand === "m" ? "l" : "L";
}
// Ignore invalid commands
if (theArgs.length < ARG_LENGTH[type]) {
return "";
}
data.push(__spreadArray([theCommand], theArgs.splice(0, ARG_LENGTH[type]), true));
// The command letter can be eliminated on subsequent commands if the
// same command is used multiple times in a row (e.g., you can drop the
// second "L" in "M 100 200 L 200 100 L -100 -200" and use
// "M 100 200 L 200 100 -100 -200" instead).
while (theArgs.length >= ARG_LENGTH[type] && theArgs.length && ARG_LENGTH[type]) {
data.push(__spreadArray([theCommand], theArgs.splice(0, ARG_LENGTH[type]), true));
}
return "";
});
return data;
}
function rotatePoint(point, angle) {
var nx = point.x * Math.cos(angle) - point.y * Math.sin(angle);
var ny = point.y * Math.cos(angle) + point.x * Math.sin(angle);
point.x = nx;
point.y = ny;
}
function translatePoint(point, dx, dy) {
point.x += dx;
point.y += dy;
}
function scalePoint(point, s) {
point.x *= s;
point.y *= s;
}
/**
* Implements a browser's Path2D api
*/
var Path2D = /** @class */ (function () {
function Path2D(path) {
var _a;
this.commands = [];
if (path && path instanceof Path2D) {
(_a = this.commands).push.apply(_a, path.commands);
}
else if (path) {
this.commands = parsePath(path);
}
}
Path2D.prototype.addPath = function (path) {
var _a;
if (path && path instanceof Path2D) {
(_a = this.commands).push.apply(_a, path.commands);
}
};
Path2D.prototype.moveTo = function (x, y) {
this.commands.push(["M", x, y]);
};
Path2D.prototype.lineTo = function (x, y) {
this.commands.push(["L", x, y]);
};
Path2D.prototype.arc = function (x, y, r, start, end, ccw) {
this.commands.push(["AC", x, y, r, start, end, !!ccw]);
};
Path2D.prototype.arcTo = function (x1, y1, x2, y2, r) {
this.commands.push(["AT", x1, y1, x2, y2, r]);
};
Path2D.prototype.ellipse = function (x, y, rx, ry, angle, start, end, ccw) {
this.commands.push(["E", x, y, rx, ry, angle, start, end, !!ccw]);
};
Path2D.prototype.closePath = function () {
this.commands.push(["Z"]);
};
Path2D.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
this.commands.push(["C", cp1x, cp1y, cp2x, cp2y, x, y]);
};
Path2D.prototype.quadraticCurveTo = function (cpx, cpy, x, y) {
this.commands.push(["Q", cpx, cpy, x, y]);
};
Path2D.prototype.rect = function (x, y, width, height) {
this.commands.push(["R", x, y, width, height]);
};
Path2D.prototype.roundRect = function (x, y, width, height, radii) {
if (typeof radii === "undefined") {
this.commands.push(["RR", x, y, width, height, 0]);
}
else {
this.commands.push(["RR", x, y, width, height, radii]);
}
};
return Path2D;
}());
function buildPath(ctx, commands) {
var x = 0;
var y = 0;
var endAngle;
var startAngle;
var largeArcFlag;
var sweepFlag;
var endPoint;
var midPoint;
var angle;
var lambda;
var t1;
var t2;
var x1;
var y1;
var r;
var rx;
var ry;
var w;
var h;
var pathType;
var centerPoint;
var ccw;
var radii;
var cpx = null;
var cpy = null;
var qcpx = null;
var qcpy = null;
var startPoint = null;
var currentPoint = null;
ctx.beginPath();
for (var i = 0; i < commands.length; ++i) {
pathType = commands[i][0];
// Reset control point if command is not cubic
if (pathType !== "S" && pathType !== "s" && pathType !== "C" && pathType !== "c") {
cpx = null;
cpy = null;
}
if (pathType !== "T" && pathType !== "t" && pathType !== "Q" && pathType !== "q") {
qcpx = null;
qcpy = null;
}
var c = void 0;
switch (pathType) {
case "m":
case "M":
c = commands[i];
if (pathType === "m") {
x += c[1];
y += c[2];
}
else {
x = c[1];
y = c[2];
}
if (pathType === "M" || !startPoint) {
startPoint = { x: x, y: y };
}
ctx.moveTo(x, y);
break;
case "l":
c = commands[i];
x += c[1];
y += c[2];
ctx.lineTo(x, y);
break;
case "L":
c = commands[i];
x = c[1];
y = c[2];
ctx.lineTo(x, y);
break;
case "H":
c = commands[i];
x = c[1];
ctx.lineTo(x, y);
break;
case "h":
c = commands[i];
x += c[1];
ctx.lineTo(x, y);
break;
case "V":
c = commands[i];
y = c[1];
ctx.lineTo(x, y);
break;
case "v":
c = commands[i];
y += c[1];
ctx.lineTo(x, y);
break;
case "a":
case "A":
c = commands[i];
if (currentPoint === null) {
throw new Error("This should never happen");
}
if (pathType === "a") {
x += c[6];
y += c[7];
}
else {
x = c[6];
y = c[7];
}
rx = c[1]; // rx
ry = c[2]; // ry
angle = (c[3] * Math.PI) / 180;
largeArcFlag = !!c[4];
sweepFlag = !!c[5];
endPoint = { x: x, y: y };
// https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
midPoint = {
x: (currentPoint.x - endPoint.x) / 2,
y: (currentPoint.y - endPoint.y) / 2
};
rotatePoint(midPoint, -angle);
// radius correction
lambda = (midPoint.x * midPoint.x) / (rx * rx) + (midPoint.y * midPoint.y) / (ry * ry);
if (lambda > 1) {
lambda = Math.sqrt(lambda);
rx *= lambda;
ry *= lambda;
}
centerPoint = {
x: (rx * midPoint.y) / ry,
y: -(ry * midPoint.x) / rx
};
t1 = rx * rx * ry * ry;
t2 = rx * rx * midPoint.y * midPoint.y + ry * ry * midPoint.x * midPoint.x;
if (sweepFlag !== largeArcFlag) {
scalePoint(centerPoint, Math.sqrt((t1 - t2) / t2) || 0);
}
else {
scalePoint(centerPoint, -Math.sqrt((t1 - t2) / t2) || 0);
}
startAngle = Math.atan2((midPoint.y - centerPoint.y) / ry, (midPoint.x - centerPoint.x) / rx);
endAngle = Math.atan2(-(midPoint.y + centerPoint.y) / ry, -(midPoint.x + centerPoint.x) / rx);
rotatePoint(centerPoint, angle);
translatePoint(centerPoint, (endPoint.x + currentPoint.x) / 2, (endPoint.y + currentPoint.y) / 2);
ctx.save();
ctx.translate(centerPoint.x, centerPoint.y);
ctx.rotate(angle);
ctx.scale(rx, ry);
ctx.arc(0, 0, 1, startAngle, endAngle, !sweepFlag);
ctx.restore();
break;
case "C":
c = commands[i];
cpx = c[3]; // Last control point
cpy = c[4];
x = c[5];
y = c[6];
ctx.bezierCurveTo(c[1], c[2], cpx, cpy, x, y);
break;
case "c":
c = commands[i];
ctx.bezierCurveTo(c[1] + x, c[2] + y, c[3] + x, c[4] + y, c[5] + x, c[6] + y);
cpx = c[3] + x; // Last control point
cpy = c[4] + y;
x += c[5];
y += c[6];
break;
case "S":
c = commands[i];
if (cpx === null || cpy === null) {
cpx = x;
cpy = y;
}
ctx.bezierCurveTo(2 * x - cpx, 2 * y - cpy, c[1], c[2], c[3], c[4]);
cpx = c[1]; // last control point
cpy = c[2];
x = c[3];
y = c[4];
break;
case "s":
c = commands[i];
if (cpx === null || cpy === null) {
cpx = x;
cpy = y;
}
ctx.bezierCurveTo(2 * x - cpx, 2 * y - cpy, c[1] + x, c[2] + y, c[3] + x, c[4] + y);
cpx = c[1] + x; // last control point
cpy = c[2] + y;
x += c[3];
y += c[4];
break;
case "Q":
c = commands[i];
qcpx = c[1]; // last control point
qcpy = c[2];
x = c[3];
y = c[4];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "q":
c = commands[i];
qcpx = c[1] + x; // last control point
qcpy = c[2] + y;
x += c[3];
y += c[4];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "T":
c = commands[i];
if (qcpx === null || qcpy === null) {
qcpx = x;
qcpy = y;
}
qcpx = 2 * x - qcpx; // last control point
qcpy = 2 * y - qcpy;
x = c[1];
y = c[2];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "t":
c = commands[i];
if (qcpx === null || qcpy === null) {
qcpx = x;
qcpy = y;
}
qcpx = 2 * x - qcpx; // last control point
qcpy = 2 * y - qcpy;
x += c[1];
y += c[2];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "z":
case "Z":
if (startPoint) {
x = startPoint.x;
y = startPoint.y;
}
startPoint = null;
ctx.closePath();
break;
case "AC": // arc
c = commands[i];
x = c[1];
y = c[2];
r = c[3];
startAngle = c[4];
endAngle = c[5];
ccw = c[6];
ctx.arc(x, y, r, startAngle, endAngle, ccw);
break;
case "AT": // arcTo
c = commands[i];
x1 = c[1];
y1 = c[2];
x = c[3];
y = c[4];
r = c[5];
ctx.arcTo(x1, y1, x, y, r);
break;
case "E": // ellipse
c = commands[i];
x = c[1];
y = c[2];
rx = c[3];
ry = c[4];
angle = c[5];
startAngle = c[6];
endAngle = c[7];
ccw = c[8];
ctx.save();
ctx.translate(x, y);
ctx.rotate(angle);
ctx.scale(rx, ry);
ctx.arc(0, 0, 1, startAngle, endAngle, ccw);
ctx.restore();
break;
case "R": // rect
c = commands[i];
x = c[1];
y = c[2];
w = c[3];
h = c[4];
startPoint = { x: x, y: y };
ctx.rect(x, y, w, h);
break;
case "RR": // roundedRect
c = commands[i];
x = c[1];
y = c[2];
w = c[3];
h = c[4];
radii = c[5];
startPoint = { x: x, y: y };
ctx.roundRect(x, y, w, h, radii);
break;
}
if (!currentPoint) {
currentPoint = { x: x, y: y };
}
else {
currentPoint.x = x;
currentPoint.y = y;
}
}
}
/**
* Polyfills CanvasRenderingContext2D stroke, fill and isPointInPath so that they support Path2D objects.
* @param {WindowLike} window - window like object containing a CanvasRenderingContext2D constructor
*/
function polyfillPath2D(window) {
if (!window || !window.CanvasRenderingContext2D || window.Path2D)
return;
var CanvasRenderingContext2D = window.CanvasRenderingContext2D;
/* eslint-disable @typescript-eslint/unbound-method */
// setting unbound functions here. Make sure this is set in function call later
var cFill = CanvasRenderingContext2D.prototype.fill;
var cStroke = CanvasRenderingContext2D.prototype.stroke;
var cIsPointInPath = CanvasRenderingContext2D.prototype.isPointInPath;
/* eslint-enable @typescript-eslint/unbound-method */
CanvasRenderingContext2D.prototype.fill = function fill() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (args[0] instanceof Path2D) {
var path = args[0];
var fillRule = args[1] || "nonzero";
buildPath(this, path.commands);
cFill.apply(this, [fillRule]);
}
else {
var fillRule = args[0] || "nonzero";
return cFill.apply(this, [fillRule]);
}
};
CanvasRenderingContext2D.prototype.stroke = function stroke(path) {
if (path) {
buildPath(this, path.commands);
}
cStroke.apply(this);
};
CanvasRenderingContext2D.prototype.isPointInPath = function isPointInPath() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (args[0] instanceof Path2D) {
// first argument is a Path2D object
var path = args[0];
var x = args[1];
var y = args[2];
var fillRule = args[3] || "nonzero";
buildPath(this, path.commands);
return cIsPointInPath.apply(this, [x, y, fillRule]);
}
else {
return cIsPointInPath.apply(this, args);
}
};
window.Path2D = Path2D;
}
function roundRect(x, y, width, height, radii) {
var _this = this;
if (radii === void 0) { radii = 0; }
if (typeof radii === "number") {
// eslint-disable-next-line no-param-reassign
radii = [radii];
}
// check for range error
if (Array.isArray(radii)) {
if (radii.length === 0 || radii.length > 4) {
throw new RangeError("Failed to execute 'roundRect' on '".concat(this.constructor.name, "': ").concat(radii.length, " radii provided. Between one and four radii are necessary."));
}
radii.forEach(function (v) {
if (v < 0) {
throw new RangeError("Failed to execute 'roundRect' on '".concat(_this.constructor.name, "': Radius value ").concat(v, " is negative."));
}
});
}
else {
return;
}
if (radii.length === 1 && radii[0] === 0) {
return this.rect(x, y, width, height);
}
// set the corners
// tl = top left radius
// tr = top right radius
// br = bottom right radius
// bl = bottom left radius
var minRadius = Math.min(width, height) / 2;
var tr, br, bl;
var tl = (tr = br = bl = Math.min(minRadius, radii[0]));
if (radii.length === 2) {
tr = bl = Math.min(minRadius, radii[1]);
}
if (radii.length === 3) {
tr = bl = Math.min(minRadius, radii[1]);
br = Math.min(minRadius, radii[2]);
}
if (radii.length === 4) {
tr = Math.min(minRadius, radii[1]);
br = Math.min(minRadius, radii[2]);
bl = Math.min(minRadius, radii[3]);
}
// begin with closing current path
// this.closePath();
// let's draw the rounded rectangle
this.moveTo(x, y + height - bl);
this.arcTo(x, y, x + tl, y, tl);
this.arcTo(x + width, y, x + width, y + tr, tr);
this.arcTo(x + width, y + height, x + width - br, y + height, br);
this.arcTo(x, y + height, x, y + height - bl, bl);
// and move to rects control point for further path drawing
this.moveTo(x, y);
}
/**
* Polyfills roundRect on CanvasRenderingContext2D and Path2D
* @param {WindowLike} window - window like object containing both CanvasRenderingContext2D and Path2D constructor
*/
function polyfillRoundRect(window) {
if (!window || !window.CanvasRenderingContext2D)
return;
var CanvasRenderingContext2D = window.CanvasRenderingContext2D, Path2D = window.Path2D;
// polyfill unsupported roundRect for e.g. firefox https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect#browser_compatibility
if (CanvasRenderingContext2D && !CanvasRenderingContext2D.prototype.roundRect) {
CanvasRenderingContext2D.prototype.roundRect = roundRect;
}
if (Path2D && !Path2D.prototype.roundRect) {
Path2D.prototype.roundRect = roundRect;
}
}
export { Path2D, parsePath, polyfillPath2D, polyfillRoundRect };

View file

@ -0,0 +1,597 @@
(function () {
'use strict';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
var ARG_LENGTH = {
a: 7,
c: 6,
h: 1,
l: 2,
m: 2,
q: 4,
s: 4,
t: 2,
v: 1,
z: 0
};
var SEGMENT_PATTERN = /([astvzqmhlc])([^astvzqmhlc]*)/gi;
var NUMBER = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/gi;
function parseValues(args) {
var numbers = args.match(NUMBER);
return numbers ? numbers.map(Number) : [];
}
/**
* parse an svg path data string. Generates an Array
* of commands where each command is an Array of the
* form `[command, arg1, arg2, ...]`
*
* https://www.w3.org/TR/SVG/paths.html#PathDataGeneralInformation
* @ignore
*
* @param {string} path
* @returns {array}
*/
function parsePath(path) {
var data = [];
var p = String(path).trim();
// A path data segment (if there is one) must begin with a "moveto" command
if (p[0] !== "M" && p[0] !== "m") {
return data;
}
p.replace(SEGMENT_PATTERN, function (_, command, args) {
var theArgs = parseValues(args);
var type = command.toLowerCase();
var theCommand = command;
// overloaded moveTo
if (type === "m" && theArgs.length > 2) {
data.push(__spreadArray([theCommand], theArgs.splice(0, 2), true));
type = "l";
theCommand = theCommand === "m" ? "l" : "L";
}
// Ignore invalid commands
if (theArgs.length < ARG_LENGTH[type]) {
return "";
}
data.push(__spreadArray([theCommand], theArgs.splice(0, ARG_LENGTH[type]), true));
// The command letter can be eliminated on subsequent commands if the
// same command is used multiple times in a row (e.g., you can drop the
// second "L" in "M 100 200 L 200 100 L -100 -200" and use
// "M 100 200 L 200 100 -100 -200" instead).
while (theArgs.length >= ARG_LENGTH[type] && theArgs.length && ARG_LENGTH[type]) {
data.push(__spreadArray([theCommand], theArgs.splice(0, ARG_LENGTH[type]), true));
}
return "";
});
return data;
}
function rotatePoint(point, angle) {
var nx = point.x * Math.cos(angle) - point.y * Math.sin(angle);
var ny = point.y * Math.cos(angle) + point.x * Math.sin(angle);
point.x = nx;
point.y = ny;
}
function translatePoint(point, dx, dy) {
point.x += dx;
point.y += dy;
}
function scalePoint(point, s) {
point.x *= s;
point.y *= s;
}
/**
* Implements a browser's Path2D api
*/
var Path2D = /** @class */ (function () {
function Path2D(path) {
var _a;
this.commands = [];
if (path && path instanceof Path2D) {
(_a = this.commands).push.apply(_a, path.commands);
}
else if (path) {
this.commands = parsePath(path);
}
}
Path2D.prototype.addPath = function (path) {
var _a;
if (path && path instanceof Path2D) {
(_a = this.commands).push.apply(_a, path.commands);
}
};
Path2D.prototype.moveTo = function (x, y) {
this.commands.push(["M", x, y]);
};
Path2D.prototype.lineTo = function (x, y) {
this.commands.push(["L", x, y]);
};
Path2D.prototype.arc = function (x, y, r, start, end, ccw) {
this.commands.push(["AC", x, y, r, start, end, !!ccw]);
};
Path2D.prototype.arcTo = function (x1, y1, x2, y2, r) {
this.commands.push(["AT", x1, y1, x2, y2, r]);
};
Path2D.prototype.ellipse = function (x, y, rx, ry, angle, start, end, ccw) {
this.commands.push(["E", x, y, rx, ry, angle, start, end, !!ccw]);
};
Path2D.prototype.closePath = function () {
this.commands.push(["Z"]);
};
Path2D.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
this.commands.push(["C", cp1x, cp1y, cp2x, cp2y, x, y]);
};
Path2D.prototype.quadraticCurveTo = function (cpx, cpy, x, y) {
this.commands.push(["Q", cpx, cpy, x, y]);
};
Path2D.prototype.rect = function (x, y, width, height) {
this.commands.push(["R", x, y, width, height]);
};
Path2D.prototype.roundRect = function (x, y, width, height, radii) {
if (typeof radii === "undefined") {
this.commands.push(["RR", x, y, width, height, 0]);
}
else {
this.commands.push(["RR", x, y, width, height, radii]);
}
};
return Path2D;
}());
function buildPath(ctx, commands) {
var x = 0;
var y = 0;
var endAngle;
var startAngle;
var largeArcFlag;
var sweepFlag;
var endPoint;
var midPoint;
var angle;
var lambda;
var t1;
var t2;
var x1;
var y1;
var r;
var rx;
var ry;
var w;
var h;
var pathType;
var centerPoint;
var ccw;
var radii;
var cpx = null;
var cpy = null;
var qcpx = null;
var qcpy = null;
var startPoint = null;
var currentPoint = null;
ctx.beginPath();
for (var i = 0; i < commands.length; ++i) {
pathType = commands[i][0];
// Reset control point if command is not cubic
if (pathType !== "S" && pathType !== "s" && pathType !== "C" && pathType !== "c") {
cpx = null;
cpy = null;
}
if (pathType !== "T" && pathType !== "t" && pathType !== "Q" && pathType !== "q") {
qcpx = null;
qcpy = null;
}
var c = void 0;
switch (pathType) {
case "m":
case "M":
c = commands[i];
if (pathType === "m") {
x += c[1];
y += c[2];
}
else {
x = c[1];
y = c[2];
}
if (pathType === "M" || !startPoint) {
startPoint = { x: x, y: y };
}
ctx.moveTo(x, y);
break;
case "l":
c = commands[i];
x += c[1];
y += c[2];
ctx.lineTo(x, y);
break;
case "L":
c = commands[i];
x = c[1];
y = c[2];
ctx.lineTo(x, y);
break;
case "H":
c = commands[i];
x = c[1];
ctx.lineTo(x, y);
break;
case "h":
c = commands[i];
x += c[1];
ctx.lineTo(x, y);
break;
case "V":
c = commands[i];
y = c[1];
ctx.lineTo(x, y);
break;
case "v":
c = commands[i];
y += c[1];
ctx.lineTo(x, y);
break;
case "a":
case "A":
c = commands[i];
if (currentPoint === null) {
throw new Error("This should never happen");
}
if (pathType === "a") {
x += c[6];
y += c[7];
}
else {
x = c[6];
y = c[7];
}
rx = c[1]; // rx
ry = c[2]; // ry
angle = (c[3] * Math.PI) / 180;
largeArcFlag = !!c[4];
sweepFlag = !!c[5];
endPoint = { x: x, y: y };
// https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
midPoint = {
x: (currentPoint.x - endPoint.x) / 2,
y: (currentPoint.y - endPoint.y) / 2
};
rotatePoint(midPoint, -angle);
// radius correction
lambda = (midPoint.x * midPoint.x) / (rx * rx) + (midPoint.y * midPoint.y) / (ry * ry);
if (lambda > 1) {
lambda = Math.sqrt(lambda);
rx *= lambda;
ry *= lambda;
}
centerPoint = {
x: (rx * midPoint.y) / ry,
y: -(ry * midPoint.x) / rx
};
t1 = rx * rx * ry * ry;
t2 = rx * rx * midPoint.y * midPoint.y + ry * ry * midPoint.x * midPoint.x;
if (sweepFlag !== largeArcFlag) {
scalePoint(centerPoint, Math.sqrt((t1 - t2) / t2) || 0);
}
else {
scalePoint(centerPoint, -Math.sqrt((t1 - t2) / t2) || 0);
}
startAngle = Math.atan2((midPoint.y - centerPoint.y) / ry, (midPoint.x - centerPoint.x) / rx);
endAngle = Math.atan2(-(midPoint.y + centerPoint.y) / ry, -(midPoint.x + centerPoint.x) / rx);
rotatePoint(centerPoint, angle);
translatePoint(centerPoint, (endPoint.x + currentPoint.x) / 2, (endPoint.y + currentPoint.y) / 2);
ctx.save();
ctx.translate(centerPoint.x, centerPoint.y);
ctx.rotate(angle);
ctx.scale(rx, ry);
ctx.arc(0, 0, 1, startAngle, endAngle, !sweepFlag);
ctx.restore();
break;
case "C":
c = commands[i];
cpx = c[3]; // Last control point
cpy = c[4];
x = c[5];
y = c[6];
ctx.bezierCurveTo(c[1], c[2], cpx, cpy, x, y);
break;
case "c":
c = commands[i];
ctx.bezierCurveTo(c[1] + x, c[2] + y, c[3] + x, c[4] + y, c[5] + x, c[6] + y);
cpx = c[3] + x; // Last control point
cpy = c[4] + y;
x += c[5];
y += c[6];
break;
case "S":
c = commands[i];
if (cpx === null || cpy === null) {
cpx = x;
cpy = y;
}
ctx.bezierCurveTo(2 * x - cpx, 2 * y - cpy, c[1], c[2], c[3], c[4]);
cpx = c[1]; // last control point
cpy = c[2];
x = c[3];
y = c[4];
break;
case "s":
c = commands[i];
if (cpx === null || cpy === null) {
cpx = x;
cpy = y;
}
ctx.bezierCurveTo(2 * x - cpx, 2 * y - cpy, c[1] + x, c[2] + y, c[3] + x, c[4] + y);
cpx = c[1] + x; // last control point
cpy = c[2] + y;
x += c[3];
y += c[4];
break;
case "Q":
c = commands[i];
qcpx = c[1]; // last control point
qcpy = c[2];
x = c[3];
y = c[4];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "q":
c = commands[i];
qcpx = c[1] + x; // last control point
qcpy = c[2] + y;
x += c[3];
y += c[4];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "T":
c = commands[i];
if (qcpx === null || qcpy === null) {
qcpx = x;
qcpy = y;
}
qcpx = 2 * x - qcpx; // last control point
qcpy = 2 * y - qcpy;
x = c[1];
y = c[2];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "t":
c = commands[i];
if (qcpx === null || qcpy === null) {
qcpx = x;
qcpy = y;
}
qcpx = 2 * x - qcpx; // last control point
qcpy = 2 * y - qcpy;
x += c[1];
y += c[2];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "z":
case "Z":
if (startPoint) {
x = startPoint.x;
y = startPoint.y;
}
startPoint = null;
ctx.closePath();
break;
case "AC": // arc
c = commands[i];
x = c[1];
y = c[2];
r = c[3];
startAngle = c[4];
endAngle = c[5];
ccw = c[6];
ctx.arc(x, y, r, startAngle, endAngle, ccw);
break;
case "AT": // arcTo
c = commands[i];
x1 = c[1];
y1 = c[2];
x = c[3];
y = c[4];
r = c[5];
ctx.arcTo(x1, y1, x, y, r);
break;
case "E": // ellipse
c = commands[i];
x = c[1];
y = c[2];
rx = c[3];
ry = c[4];
angle = c[5];
startAngle = c[6];
endAngle = c[7];
ccw = c[8];
ctx.save();
ctx.translate(x, y);
ctx.rotate(angle);
ctx.scale(rx, ry);
ctx.arc(0, 0, 1, startAngle, endAngle, ccw);
ctx.restore();
break;
case "R": // rect
c = commands[i];
x = c[1];
y = c[2];
w = c[3];
h = c[4];
startPoint = { x: x, y: y };
ctx.rect(x, y, w, h);
break;
case "RR": // roundedRect
c = commands[i];
x = c[1];
y = c[2];
w = c[3];
h = c[4];
radii = c[5];
startPoint = { x: x, y: y };
ctx.roundRect(x, y, w, h, radii);
break;
}
if (!currentPoint) {
currentPoint = { x: x, y: y };
}
else {
currentPoint.x = x;
currentPoint.y = y;
}
}
}
/**
* Polyfills CanvasRenderingContext2D stroke, fill and isPointInPath so that they support Path2D objects.
* @param {WindowLike} window - window like object containing a CanvasRenderingContext2D constructor
*/
function polyfillPath2D(window) {
if (!window || !window.CanvasRenderingContext2D || window.Path2D)
return;
var CanvasRenderingContext2D = window.CanvasRenderingContext2D;
/* eslint-disable @typescript-eslint/unbound-method */
// setting unbound functions here. Make sure this is set in function call later
var cFill = CanvasRenderingContext2D.prototype.fill;
var cStroke = CanvasRenderingContext2D.prototype.stroke;
var cIsPointInPath = CanvasRenderingContext2D.prototype.isPointInPath;
/* eslint-enable @typescript-eslint/unbound-method */
CanvasRenderingContext2D.prototype.fill = function fill() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (args[0] instanceof Path2D) {
var path = args[0];
var fillRule = args[1] || "nonzero";
buildPath(this, path.commands);
cFill.apply(this, [fillRule]);
}
else {
var fillRule = args[0] || "nonzero";
return cFill.apply(this, [fillRule]);
}
};
CanvasRenderingContext2D.prototype.stroke = function stroke(path) {
if (path) {
buildPath(this, path.commands);
}
cStroke.apply(this);
};
CanvasRenderingContext2D.prototype.isPointInPath = function isPointInPath() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (args[0] instanceof Path2D) {
// first argument is a Path2D object
var path = args[0];
var x = args[1];
var y = args[2];
var fillRule = args[3] || "nonzero";
buildPath(this, path.commands);
return cIsPointInPath.apply(this, [x, y, fillRule]);
}
else {
return cIsPointInPath.apply(this, args);
}
};
window.Path2D = Path2D;
}
function roundRect(x, y, width, height, radii) {
var _this = this;
if (radii === void 0) { radii = 0; }
if (typeof radii === "number") {
// eslint-disable-next-line no-param-reassign
radii = [radii];
}
// check for range error
if (Array.isArray(radii)) {
if (radii.length === 0 || radii.length > 4) {
throw new RangeError("Failed to execute 'roundRect' on '".concat(this.constructor.name, "': ").concat(radii.length, " radii provided. Between one and four radii are necessary."));
}
radii.forEach(function (v) {
if (v < 0) {
throw new RangeError("Failed to execute 'roundRect' on '".concat(_this.constructor.name, "': Radius value ").concat(v, " is negative."));
}
});
}
else {
return;
}
if (radii.length === 1 && radii[0] === 0) {
return this.rect(x, y, width, height);
}
// set the corners
// tl = top left radius
// tr = top right radius
// br = bottom right radius
// bl = bottom left radius
var minRadius = Math.min(width, height) / 2;
var tr, br, bl;
var tl = (tr = br = bl = Math.min(minRadius, radii[0]));
if (radii.length === 2) {
tr = bl = Math.min(minRadius, radii[1]);
}
if (radii.length === 3) {
tr = bl = Math.min(minRadius, radii[1]);
br = Math.min(minRadius, radii[2]);
}
if (radii.length === 4) {
tr = Math.min(minRadius, radii[1]);
br = Math.min(minRadius, radii[2]);
bl = Math.min(minRadius, radii[3]);
}
// begin with closing current path
// this.closePath();
// let's draw the rounded rectangle
this.moveTo(x, y + height - bl);
this.arcTo(x, y, x + tl, y, tl);
this.arcTo(x + width, y, x + width, y + tr, tr);
this.arcTo(x + width, y + height, x + width - br, y + height, br);
this.arcTo(x, y + height, x, y + height - bl, bl);
// and move to rects control point for further path drawing
this.moveTo(x, y);
}
/**
* Polyfills roundRect on CanvasRenderingContext2D and Path2D
* @param {WindowLike} window - window like object containing both CanvasRenderingContext2D and Path2D constructor
*/
function polyfillRoundRect(window) {
if (!window || !window.CanvasRenderingContext2D)
return;
var CanvasRenderingContext2D = window.CanvasRenderingContext2D, Path2D = window.Path2D;
// polyfill unsupported roundRect for e.g. firefox https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect#browser_compatibility
if (CanvasRenderingContext2D && !CanvasRenderingContext2D.prototype.roundRect) {
CanvasRenderingContext2D.prototype.roundRect = roundRect;
}
if (Path2D && !Path2D.prototype.roundRect) {
Path2D.prototype.roundRect = roundRect;
}
}
polyfillPath2D(window);
polyfillRoundRect(window);
})();

View file

@ -0,0 +1,592 @@
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
var ARG_LENGTH = {
a: 7,
c: 6,
h: 1,
l: 2,
m: 2,
q: 4,
s: 4,
t: 2,
v: 1,
z: 0
};
var SEGMENT_PATTERN = /([astvzqmhlc])([^astvzqmhlc]*)/gi;
var NUMBER = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/gi;
function parseValues(args) {
var numbers = args.match(NUMBER);
return numbers ? numbers.map(Number) : [];
}
/**
* parse an svg path data string. Generates an Array
* of commands where each command is an Array of the
* form `[command, arg1, arg2, ...]`
*
* https://www.w3.org/TR/SVG/paths.html#PathDataGeneralInformation
* @ignore
*
* @param {string} path
* @returns {array}
*/
function parsePath(path) {
var data = [];
var p = String(path).trim();
// A path data segment (if there is one) must begin with a "moveto" command
if (p[0] !== "M" && p[0] !== "m") {
return data;
}
p.replace(SEGMENT_PATTERN, function (_, command, args) {
var theArgs = parseValues(args);
var type = command.toLowerCase();
var theCommand = command;
// overloaded moveTo
if (type === "m" && theArgs.length > 2) {
data.push(__spreadArray([theCommand], theArgs.splice(0, 2), true));
type = "l";
theCommand = theCommand === "m" ? "l" : "L";
}
// Ignore invalid commands
if (theArgs.length < ARG_LENGTH[type]) {
return "";
}
data.push(__spreadArray([theCommand], theArgs.splice(0, ARG_LENGTH[type]), true));
// The command letter can be eliminated on subsequent commands if the
// same command is used multiple times in a row (e.g., you can drop the
// second "L" in "M 100 200 L 200 100 L -100 -200" and use
// "M 100 200 L 200 100 -100 -200" instead).
while (theArgs.length >= ARG_LENGTH[type] && theArgs.length && ARG_LENGTH[type]) {
data.push(__spreadArray([theCommand], theArgs.splice(0, ARG_LENGTH[type]), true));
}
return "";
});
return data;
}
function rotatePoint(point, angle) {
var nx = point.x * Math.cos(angle) - point.y * Math.sin(angle);
var ny = point.y * Math.cos(angle) + point.x * Math.sin(angle);
point.x = nx;
point.y = ny;
}
function translatePoint(point, dx, dy) {
point.x += dx;
point.y += dy;
}
function scalePoint(point, s) {
point.x *= s;
point.y *= s;
}
/**
* Implements a browser's Path2D api
*/
var Path2D = /** @class */ (function () {
function Path2D(path) {
var _a;
this.commands = [];
if (path && path instanceof Path2D) {
(_a = this.commands).push.apply(_a, path.commands);
}
else if (path) {
this.commands = parsePath(path);
}
}
Path2D.prototype.addPath = function (path) {
var _a;
if (path && path instanceof Path2D) {
(_a = this.commands).push.apply(_a, path.commands);
}
};
Path2D.prototype.moveTo = function (x, y) {
this.commands.push(["M", x, y]);
};
Path2D.prototype.lineTo = function (x, y) {
this.commands.push(["L", x, y]);
};
Path2D.prototype.arc = function (x, y, r, start, end, ccw) {
this.commands.push(["AC", x, y, r, start, end, !!ccw]);
};
Path2D.prototype.arcTo = function (x1, y1, x2, y2, r) {
this.commands.push(["AT", x1, y1, x2, y2, r]);
};
Path2D.prototype.ellipse = function (x, y, rx, ry, angle, start, end, ccw) {
this.commands.push(["E", x, y, rx, ry, angle, start, end, !!ccw]);
};
Path2D.prototype.closePath = function () {
this.commands.push(["Z"]);
};
Path2D.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
this.commands.push(["C", cp1x, cp1y, cp2x, cp2y, x, y]);
};
Path2D.prototype.quadraticCurveTo = function (cpx, cpy, x, y) {
this.commands.push(["Q", cpx, cpy, x, y]);
};
Path2D.prototype.rect = function (x, y, width, height) {
this.commands.push(["R", x, y, width, height]);
};
Path2D.prototype.roundRect = function (x, y, width, height, radii) {
if (typeof radii === "undefined") {
this.commands.push(["RR", x, y, width, height, 0]);
}
else {
this.commands.push(["RR", x, y, width, height, radii]);
}
};
return Path2D;
}());
function buildPath(ctx, commands) {
var x = 0;
var y = 0;
var endAngle;
var startAngle;
var largeArcFlag;
var sweepFlag;
var endPoint;
var midPoint;
var angle;
var lambda;
var t1;
var t2;
var x1;
var y1;
var r;
var rx;
var ry;
var w;
var h;
var pathType;
var centerPoint;
var ccw;
var radii;
var cpx = null;
var cpy = null;
var qcpx = null;
var qcpy = null;
var startPoint = null;
var currentPoint = null;
ctx.beginPath();
for (var i = 0; i < commands.length; ++i) {
pathType = commands[i][0];
// Reset control point if command is not cubic
if (pathType !== "S" && pathType !== "s" && pathType !== "C" && pathType !== "c") {
cpx = null;
cpy = null;
}
if (pathType !== "T" && pathType !== "t" && pathType !== "Q" && pathType !== "q") {
qcpx = null;
qcpy = null;
}
var c = void 0;
switch (pathType) {
case "m":
case "M":
c = commands[i];
if (pathType === "m") {
x += c[1];
y += c[2];
}
else {
x = c[1];
y = c[2];
}
if (pathType === "M" || !startPoint) {
startPoint = { x: x, y: y };
}
ctx.moveTo(x, y);
break;
case "l":
c = commands[i];
x += c[1];
y += c[2];
ctx.lineTo(x, y);
break;
case "L":
c = commands[i];
x = c[1];
y = c[2];
ctx.lineTo(x, y);
break;
case "H":
c = commands[i];
x = c[1];
ctx.lineTo(x, y);
break;
case "h":
c = commands[i];
x += c[1];
ctx.lineTo(x, y);
break;
case "V":
c = commands[i];
y = c[1];
ctx.lineTo(x, y);
break;
case "v":
c = commands[i];
y += c[1];
ctx.lineTo(x, y);
break;
case "a":
case "A":
c = commands[i];
if (currentPoint === null) {
throw new Error("This should never happen");
}
if (pathType === "a") {
x += c[6];
y += c[7];
}
else {
x = c[6];
y = c[7];
}
rx = c[1]; // rx
ry = c[2]; // ry
angle = (c[3] * Math.PI) / 180;
largeArcFlag = !!c[4];
sweepFlag = !!c[5];
endPoint = { x: x, y: y };
// https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
midPoint = {
x: (currentPoint.x - endPoint.x) / 2,
y: (currentPoint.y - endPoint.y) / 2
};
rotatePoint(midPoint, -angle);
// radius correction
lambda = (midPoint.x * midPoint.x) / (rx * rx) + (midPoint.y * midPoint.y) / (ry * ry);
if (lambda > 1) {
lambda = Math.sqrt(lambda);
rx *= lambda;
ry *= lambda;
}
centerPoint = {
x: (rx * midPoint.y) / ry,
y: -(ry * midPoint.x) / rx
};
t1 = rx * rx * ry * ry;
t2 = rx * rx * midPoint.y * midPoint.y + ry * ry * midPoint.x * midPoint.x;
if (sweepFlag !== largeArcFlag) {
scalePoint(centerPoint, Math.sqrt((t1 - t2) / t2) || 0);
}
else {
scalePoint(centerPoint, -Math.sqrt((t1 - t2) / t2) || 0);
}
startAngle = Math.atan2((midPoint.y - centerPoint.y) / ry, (midPoint.x - centerPoint.x) / rx);
endAngle = Math.atan2(-(midPoint.y + centerPoint.y) / ry, -(midPoint.x + centerPoint.x) / rx);
rotatePoint(centerPoint, angle);
translatePoint(centerPoint, (endPoint.x + currentPoint.x) / 2, (endPoint.y + currentPoint.y) / 2);
ctx.save();
ctx.translate(centerPoint.x, centerPoint.y);
ctx.rotate(angle);
ctx.scale(rx, ry);
ctx.arc(0, 0, 1, startAngle, endAngle, !sweepFlag);
ctx.restore();
break;
case "C":
c = commands[i];
cpx = c[3]; // Last control point
cpy = c[4];
x = c[5];
y = c[6];
ctx.bezierCurveTo(c[1], c[2], cpx, cpy, x, y);
break;
case "c":
c = commands[i];
ctx.bezierCurveTo(c[1] + x, c[2] + y, c[3] + x, c[4] + y, c[5] + x, c[6] + y);
cpx = c[3] + x; // Last control point
cpy = c[4] + y;
x += c[5];
y += c[6];
break;
case "S":
c = commands[i];
if (cpx === null || cpy === null) {
cpx = x;
cpy = y;
}
ctx.bezierCurveTo(2 * x - cpx, 2 * y - cpy, c[1], c[2], c[3], c[4]);
cpx = c[1]; // last control point
cpy = c[2];
x = c[3];
y = c[4];
break;
case "s":
c = commands[i];
if (cpx === null || cpy === null) {
cpx = x;
cpy = y;
}
ctx.bezierCurveTo(2 * x - cpx, 2 * y - cpy, c[1] + x, c[2] + y, c[3] + x, c[4] + y);
cpx = c[1] + x; // last control point
cpy = c[2] + y;
x += c[3];
y += c[4];
break;
case "Q":
c = commands[i];
qcpx = c[1]; // last control point
qcpy = c[2];
x = c[3];
y = c[4];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "q":
c = commands[i];
qcpx = c[1] + x; // last control point
qcpy = c[2] + y;
x += c[3];
y += c[4];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "T":
c = commands[i];
if (qcpx === null || qcpy === null) {
qcpx = x;
qcpy = y;
}
qcpx = 2 * x - qcpx; // last control point
qcpy = 2 * y - qcpy;
x = c[1];
y = c[2];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "t":
c = commands[i];
if (qcpx === null || qcpy === null) {
qcpx = x;
qcpy = y;
}
qcpx = 2 * x - qcpx; // last control point
qcpy = 2 * y - qcpy;
x += c[1];
y += c[2];
ctx.quadraticCurveTo(qcpx, qcpy, x, y);
break;
case "z":
case "Z":
if (startPoint) {
x = startPoint.x;
y = startPoint.y;
}
startPoint = null;
ctx.closePath();
break;
case "AC": // arc
c = commands[i];
x = c[1];
y = c[2];
r = c[3];
startAngle = c[4];
endAngle = c[5];
ccw = c[6];
ctx.arc(x, y, r, startAngle, endAngle, ccw);
break;
case "AT": // arcTo
c = commands[i];
x1 = c[1];
y1 = c[2];
x = c[3];
y = c[4];
r = c[5];
ctx.arcTo(x1, y1, x, y, r);
break;
case "E": // ellipse
c = commands[i];
x = c[1];
y = c[2];
rx = c[3];
ry = c[4];
angle = c[5];
startAngle = c[6];
endAngle = c[7];
ccw = c[8];
ctx.save();
ctx.translate(x, y);
ctx.rotate(angle);
ctx.scale(rx, ry);
ctx.arc(0, 0, 1, startAngle, endAngle, ccw);
ctx.restore();
break;
case "R": // rect
c = commands[i];
x = c[1];
y = c[2];
w = c[3];
h = c[4];
startPoint = { x: x, y: y };
ctx.rect(x, y, w, h);
break;
case "RR": // roundedRect
c = commands[i];
x = c[1];
y = c[2];
w = c[3];
h = c[4];
radii = c[5];
startPoint = { x: x, y: y };
ctx.roundRect(x, y, w, h, radii);
break;
}
if (!currentPoint) {
currentPoint = { x: x, y: y };
}
else {
currentPoint.x = x;
currentPoint.y = y;
}
}
}
/**
* Polyfills CanvasRenderingContext2D stroke, fill and isPointInPath so that they support Path2D objects.
* @param {WindowLike} window - window like object containing a CanvasRenderingContext2D constructor
*/
function polyfillPath2D(window) {
if (!window || !window.CanvasRenderingContext2D || window.Path2D)
return;
var CanvasRenderingContext2D = window.CanvasRenderingContext2D;
/* eslint-disable @typescript-eslint/unbound-method */
// setting unbound functions here. Make sure this is set in function call later
var cFill = CanvasRenderingContext2D.prototype.fill;
var cStroke = CanvasRenderingContext2D.prototype.stroke;
var cIsPointInPath = CanvasRenderingContext2D.prototype.isPointInPath;
/* eslint-enable @typescript-eslint/unbound-method */
CanvasRenderingContext2D.prototype.fill = function fill() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (args[0] instanceof Path2D) {
var path = args[0];
var fillRule = args[1] || "nonzero";
buildPath(this, path.commands);
cFill.apply(this, [fillRule]);
}
else {
var fillRule = args[0] || "nonzero";
return cFill.apply(this, [fillRule]);
}
};
CanvasRenderingContext2D.prototype.stroke = function stroke(path) {
if (path) {
buildPath(this, path.commands);
}
cStroke.apply(this);
};
CanvasRenderingContext2D.prototype.isPointInPath = function isPointInPath() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (args[0] instanceof Path2D) {
// first argument is a Path2D object
var path = args[0];
var x = args[1];
var y = args[2];
var fillRule = args[3] || "nonzero";
buildPath(this, path.commands);
return cIsPointInPath.apply(this, [x, y, fillRule]);
}
else {
return cIsPointInPath.apply(this, args);
}
};
window.Path2D = Path2D;
}
function roundRect(x, y, width, height, radii) {
var _this = this;
if (radii === void 0) { radii = 0; }
if (typeof radii === "number") {
// eslint-disable-next-line no-param-reassign
radii = [radii];
}
// check for range error
if (Array.isArray(radii)) {
if (radii.length === 0 || radii.length > 4) {
throw new RangeError("Failed to execute 'roundRect' on '".concat(this.constructor.name, "': ").concat(radii.length, " radii provided. Between one and four radii are necessary."));
}
radii.forEach(function (v) {
if (v < 0) {
throw new RangeError("Failed to execute 'roundRect' on '".concat(_this.constructor.name, "': Radius value ").concat(v, " is negative."));
}
});
}
else {
return;
}
if (radii.length === 1 && radii[0] === 0) {
return this.rect(x, y, width, height);
}
// set the corners
// tl = top left radius
// tr = top right radius
// br = bottom right radius
// bl = bottom left radius
var minRadius = Math.min(width, height) / 2;
var tr, br, bl;
var tl = (tr = br = bl = Math.min(minRadius, radii[0]));
if (radii.length === 2) {
tr = bl = Math.min(minRadius, radii[1]);
}
if (radii.length === 3) {
tr = bl = Math.min(minRadius, radii[1]);
br = Math.min(minRadius, radii[2]);
}
if (radii.length === 4) {
tr = Math.min(minRadius, radii[1]);
br = Math.min(minRadius, radii[2]);
bl = Math.min(minRadius, radii[3]);
}
// begin with closing current path
// this.closePath();
// let's draw the rounded rectangle
this.moveTo(x, y + height - bl);
this.arcTo(x, y, x + tl, y, tl);
this.arcTo(x + width, y, x + width, y + tr, tr);
this.arcTo(x + width, y + height, x + width - br, y + height, br);
this.arcTo(x, y + height, x, y + height - bl, bl);
// and move to rects control point for further path drawing
this.moveTo(x, y);
}
/**
* Polyfills roundRect on CanvasRenderingContext2D and Path2D
* @param {WindowLike} window - window like object containing both CanvasRenderingContext2D and Path2D constructor
*/
function polyfillRoundRect(window) {
if (!window || !window.CanvasRenderingContext2D)
return;
var CanvasRenderingContext2D = window.CanvasRenderingContext2D, Path2D = window.Path2D;
// polyfill unsupported roundRect for e.g. firefox https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect#browser_compatibility
if (CanvasRenderingContext2D && !CanvasRenderingContext2D.prototype.roundRect) {
CanvasRenderingContext2D.prototype.roundRect = roundRect;
}
if (Path2D && !Path2D.prototype.roundRect) {
Path2D.prototype.roundRect = roundRect;
}
}
polyfillPath2D(window);
polyfillRoundRect(window);

File diff suppressed because one or more lines are too long

81
node_modules/path2d-polyfill/package.json generated vendored Normal file
View file

@ -0,0 +1,81 @@
{
"name": "path2d-polyfill",
"version": "2.0.1",
"description": "Polyfills Path2D api for canvas rendering",
"scripts": {
"build": "rm -rf dist/* && rollup -c",
"start": "rollup -c -w",
"lint": "eslint .",
"check-types": "tsc --noEmit",
"test": "ts-mocha test/*.spec.ts",
"test:watch": "ts-mocha --watch test/*.spec.ts",
"test:coverage": "nyc --reporter=html --reporter=text --reporter=text-summary yarn test",
"format:check": "prettier --check \"./**\"",
"format:write": "prettier --write \"./**\"",
"prepare": "husky install",
"release": "release-it"
},
"main": "dist/path2d-node.cjs",
"browser": "dist/path2d-polyfill.min.js",
"exports": {
"node": {
"import": "./dist/path2d-node.mjs",
"require": "./dist/path2d-node.cjs"
},
"development": "./dist/path2d-polyfill.dev.js",
"module": "./dist/path2d-polyfill.esm.js",
"default": "./dist/path2d-polyfill.min.js"
},
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "git+https://github.com/nilzona/path2d-polyfill.git"
},
"keywords": [
"Path2D",
"polyfill",
"canvas",
"roundRect"
],
"author": "nilzona",
"license": "MIT",
"bugs": {
"url": "https://github.com/nilzona/path2d-polyfill/issues"
},
"homepage": "https://github.com/nilzona/path2d-polyfill#readme",
"devDependencies": {
"@commitlint/cli": "17.3.0",
"@commitlint/config-conventional": "17.3.0",
"@release-it/conventional-changelog": "5.1.1",
"@rollup/plugin-terser": "0.2.1",
"@rollup/plugin-typescript": "10.0.1",
"@types/chai": "^4.3.4",
"@types/mocha": "^10.0.1",
"@types/sinon": "^10.0.13",
"@types/sinon-chai": "^3.2.9",
"@typescript-eslint/eslint-plugin": "5.48.0",
"@typescript-eslint/parser": "5.48.0",
"chai": "4.3.7",
"eslint": "8.31.0",
"eslint-config-prettier": "8.6.0",
"husky": "8.0.2",
"lint-staged": "13.1.0",
"mocha": "10.2.0",
"nyc": "15.1.0",
"prettier": "2.8.1",
"release-it": "15.6.0",
"rollup": "3.9.1",
"rollup-plugin-livereload": "2.0.5",
"rollup-plugin-serve": "2.0.2",
"sinon": "15.0.1",
"sinon-chai": "3.7.0",
"ts-mocha": "^10.0.0",
"typescript": "^4.9.4"
},
"dependencies": {},
"engines": {
"node": ">=8"
}
}