Support addPath properly.

However this is not correctly handling the transform. To do it correctly we need to store the sub-paths in the path in their original form (not a string) and apply the transforms at render time.
This commit is contained in:
k1w1 2024-04-18 13:26:13 -07:00
parent cc6973fa1c
commit a891b0ad58
3 changed files with 114 additions and 52 deletions

View File

@ -775,6 +775,7 @@ export default (function () {
path = this.__currentDefaultPath;
}
if (path.__pathString.length > 0) {
var pathElement = this.__createPathElement();
this.__applyStyleToElement(pathElement, action);
pathElement.setAttribute("paint-order", "fill stroke markers");
@ -782,6 +783,19 @@ export default (function () {
if (path2d) {
this.__applyTransformation(pathElement);
}
}
if (path2d) {
path2d.__subPaths.forEach((subPath) => {
var pathElement = this.__createPathElement();
this.__applyStyleToElement(pathElement, action);
pathElement.setAttribute("paint-order", "fill stroke markers");
pathElement.setAttribute("d", subPath.path.__pathString);
if (subPath.transform) {
this.__applyTransformation(pathElement, this.getTransform().multiply(subPath.transform));
}
});
}
};
/**

View File

@ -22,6 +22,7 @@ export default (function () {
}
this.ctx = ctx;
this.__subPaths = []; // Array of path string/transform pairs.
this.__currentPosition = { x: undefined, y: undefined };
};
@ -29,18 +30,19 @@ export default (function () {
return this.ctx.__matrixTransform(x, y);
};
Path2D.prototype.addPath = function (path, transform) {
if (transform)
console.error("transform argument to addPath is not supported");
this.__pathString = this.__pathString + " " + path;
Path2D.prototype.addPath = function (path, transform = undefined) {
this.__subPaths.push({ path: path, transform: transform });
};
Path2D.prototype.appendPath = function (path) {
this.__pathString = this.__pathString + " " + path;
}
/**
* Closes the current path
*/
Path2D.prototype.closePath = function () {
this.addPath("Z");
this.appendPath("Z");
};
/**
@ -50,7 +52,7 @@ export default (function () {
Path2D.prototype.moveTo = function (x, y) {
// creates a new subpath with the given point
this.__currentPosition = { x: x, y: y };
this.addPath(
this.appendPath(
format("M {x} {y}", {
x: this.__matrixTransform(x, y).x,
y: this.__matrixTransform(x, y).y,
@ -64,14 +66,14 @@ export default (function () {
Path2D.prototype.lineTo = function (x, y) {
this.__currentPosition = { x: x, y: y };
if (this.__pathString.indexOf("M") > -1) {
this.addPath(
this.appendPath(
format("L {x} {y}", {
x: this.__matrixTransform(x, y).x,
y: this.__matrixTransform(x, y).y,
})
);
} else {
this.addPath(
this.appendPath(
format("M {x} {y}", {
x: this.__matrixTransform(x, y).x,
y: this.__matrixTransform(x, y).y,
@ -101,7 +103,7 @@ export default (function () {
*/
Path2D.prototype.bezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) {
this.__currentPosition = { x: x, y: y };
this.addPath(
this.appendPath(
format("C {cp1x} {cp1y} {cp2x} {cp2y} {x} {y}", {
cp1x: this.__matrixTransform(cp1x, cp1y).x,
cp1y: this.__matrixTransform(cp1x, cp1y).y,
@ -118,7 +120,7 @@ export default (function () {
*/
Path2D.prototype.quadraticCurveTo = function (cpx, cpy, x, y) {
this.__currentPosition = { x: x, y: y };
this.addPath(
this.appendPath(
format("Q {cpx} {cpy} {x} {y}", {
cpx: this.__matrixTransform(cpx, cpy).x,
cpy: this.__matrixTransform(cpx, cpy).y,
@ -180,7 +182,7 @@ export default (function () {
);
this.lineTo(startX, startY);
this.addPath(
this.appendPath(
format(
"A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}",
{
@ -370,7 +372,7 @@ export default (function () {
this.lineTo(startX, startY);
this.ctx.__transformMatrix = currentTransform;
this.addPath(
this.appendPath(
format(
"A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}",
{

View File

@ -45,4 +45,50 @@ export default function path2D(ctx) {
ctx.fill();
ctx.restore();
ctx.restore();
// Scaling path versus scaling the context.
const path2 = makePath(
ctx,
`M -10 -10
L 10 -10
L 10 10
L -10 10
Z`
);
ctx.save();
ctx.translate(25, 100);
ctx.scale(2, 1);
ctx.strokeStyle = "red";
ctx.moveTo(-10, -10);
ctx.lineTo(10, -10);
ctx.lineTo(10, 10);
ctx.lineTo(-10, 10);
ctx.closePath();
ctx.fillStyle = "grey";
ctx.fill();
ctx.scale(1 / 2, 1); // Reset scale so that stroke is not scaled.
ctx.stroke();
ctx.restore();
ctx.save();
ctx.translate(100, 100);
ctx.scale(2, 1);
ctx.fillStyle = "grey";
ctx.fill(path2);
ctx.strokeStyle = "red";
let pNext = makePath(ctx);
// add first path, transform path, twice size, move 100,10
pNext.addPath(path2, new DOMMatrix([
2, 0,
0, 1,
0,
0,
]));
ctx.scale(1 / 2, 1); // Reset scale so that stroke is not scaled.
ctx.stroke(pNext);
ctx.restore();
}