fix: png-exporting does not preserve angles correctly for flipped images (#6085)

* fix: png-exporting does not preserve angles correctly for flipped images

* refactor related code

* simplify further and comment
This commit is contained in:
David Luzar 2023-01-08 16:22:04 +01:00 committed by GitHub
parent 40d53d9231
commit 809d5ba17f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 28 deletions

View File

@ -713,22 +713,8 @@ const drawElementFromCanvas = (
const cx = ((x1 + x2) / 2 + renderConfig.scrollX) * window.devicePixelRatio;
const cy = ((y1 + y2) / 2 + renderConfig.scrollY) * window.devicePixelRatio;
const _isPendingImageElement = isPendingImageElement(element, renderConfig);
const scaleXFactor =
"scale" in elementWithCanvas.element && !_isPendingImageElement
? elementWithCanvas.element.scale[0]
: 1;
const scaleYFactor =
"scale" in elementWithCanvas.element && !_isPendingImageElement
? elementWithCanvas.element.scale[1]
: 1;
context.save();
context.scale(
(1 / window.devicePixelRatio) * scaleXFactor,
(1 / window.devicePixelRatio) * scaleYFactor,
);
context.scale(1 / window.devicePixelRatio, 1 / window.devicePixelRatio);
const boundTextElement = getBoundTextElement(element);
if (isArrowElement(element) && boundTextElement) {
@ -793,7 +779,7 @@ const drawElementFromCanvas = (
zoom,
);
context.translate(cx * scaleXFactor, cy * scaleYFactor);
context.translate(cx, cy);
context.drawImage(
tempCanvas,
(-(x2 - x1) / 2) * window.devicePixelRatio - offsetX / zoom - padding,
@ -802,15 +788,30 @@ const drawElementFromCanvas = (
tempCanvas.height / zoom,
);
} else {
context.translate(cx * scaleXFactor, cy * scaleYFactor);
// we translate context to element center so that rotation and scale
// originates from the element center
context.translate(cx, cy);
context.rotate(element.angle * scaleXFactor * scaleYFactor);
context.rotate(element.angle);
if (
"scale" in elementWithCanvas.element &&
!isPendingImageElement(element, renderConfig)
) {
context.scale(
elementWithCanvas.element.scale[0],
elementWithCanvas.element.scale[1],
);
}
// revert afterwards we don't have account for it during drawing
context.translate(-cx, -cy);
context.drawImage(
elementWithCanvas.canvas!,
(-(x2 - x1) / 2) * window.devicePixelRatio -
(x1 + renderConfig.scrollX) * window.devicePixelRatio -
(padding * elementWithCanvas.canvasZoom) / elementWithCanvas.canvasZoom,
(-(y2 - y1) / 2) * window.devicePixelRatio -
(y1 + renderConfig.scrollY) * window.devicePixelRatio -
(padding * elementWithCanvas.canvasZoom) / elementWithCanvas.canvasZoom,
elementWithCanvas.canvas!.width / elementWithCanvas.canvasZoom,
elementWithCanvas.canvas!.height / elementWithCanvas.canvasZoom,
@ -905,9 +906,6 @@ export const renderElement = (
}
context.save();
context.translate(cx, cy);
if (element.type === "image") {
context.scale(element.scale[0], element.scale[1]);
}
if (shouldResetImageFilter(element, renderConfig)) {
context.filter = "none";
@ -973,6 +971,12 @@ export const renderElement = (
);
} else {
context.rotate(element.angle);
if (element.type === "image") {
// note: scale must be applied *after* rotating
context.scale(element.scale[0], element.scale[1]);
}
context.translate(-shiftX, -shiftY);
drawElementOnCanvas(element, rc, context, renderConfig);
}

View File

@ -41,8 +41,8 @@ export const centerScrollOn = ({
zoom: Zoom;
}) => {
return {
scrollX: (viewportDimensions.width / 2) * (1 / zoom.value) - scenePoint.x,
scrollY: (viewportDimensions.height / 2) * (1 / zoom.value) - scenePoint.y,
scrollX: viewportDimensions.width / 2 / zoom.value - scenePoint.x,
scrollY: viewportDimensions.height / 2 / zoom.value - scenePoint.y,
};
};

View File

@ -352,9 +352,8 @@ export const viewportCoordsToSceneCoords = (
scrollY: number;
},
) => {
const invScale = 1 / zoom.value;
const x = (clientX - offsetLeft) * invScale - scrollX;
const y = (clientY - offsetTop) * invScale - scrollY;
const x = (clientX - offsetLeft) / zoom.value - scrollX;
const y = (clientY - offsetTop) / zoom.value - scrollY;
return { x, y };
};