feat: add crop and canvas resize workflows
This commit is contained in:
17
platform/browser/exportArtboardPng.test.ts
Normal file
17
platform/browser/exportArtboardPng.test.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { resolveLayerDrawImage } from "./exportArtboardPng";
|
||||
|
||||
describe("artboard PNG export", () => {
|
||||
test("draws only cropped source pixels at their retained document position", () => {
|
||||
const draw = resolveLayerDrawImage({
|
||||
id: "layer", type: "raster", name: "Layer", visible: true, locked: false, opacity: 1, assetId: "asset",
|
||||
sourceRect: { x: 10, y: 5, w: 40, h: 20 },
|
||||
transform: { position: { x: 100, y: 50 }, scale: { x: 2, y: 3 }, rotation: 0 },
|
||||
}, { w: 200, h: 100 });
|
||||
|
||||
expect(draw).toEqual({
|
||||
source: { x: 10, y: 5, w: 40, h: 20 },
|
||||
destination: { x: 120, y: 65, w: 80, h: 60 },
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2,6 +2,7 @@ import type { Artboard } from "@core/artboard";
|
||||
import type { Asset } from "@core/asset";
|
||||
import type { Rect } from "@core/geometry";
|
||||
import type { Layer } from "@core/layer";
|
||||
import type { Size } from "@core/geometry";
|
||||
import { getLayerMask } from "@core/layer-mask-utils";
|
||||
|
||||
export async function downloadArtboardPng(artboard: Artboard, assets: readonly Asset[]) {
|
||||
@@ -66,16 +67,25 @@ async function drawLayer(
|
||||
}
|
||||
|
||||
const image = await loadImage(asset.source);
|
||||
context.drawImage(
|
||||
image,
|
||||
layer.transform.position.x,
|
||||
layer.transform.position.y,
|
||||
asset.intrinsicSize.w * layer.transform.scale.x,
|
||||
asset.intrinsicSize.h * layer.transform.scale.y,
|
||||
);
|
||||
const draw = resolveLayerDrawImage(layer, asset.intrinsicSize);
|
||||
context.drawImage(image, draw.source.x, draw.source.y, draw.source.w, draw.source.h,
|
||||
draw.destination.x, draw.destination.y, draw.destination.w, draw.destination.h);
|
||||
context.restore();
|
||||
}
|
||||
|
||||
export function resolveLayerDrawImage(layer: Exclude<Layer, { type: "group" }>, intrinsicSize: Size) {
|
||||
const source = layer.sourceRect ?? { x: 0, y: 0, ...intrinsicSize };
|
||||
return {
|
||||
source,
|
||||
destination: {
|
||||
x: layer.transform.position.x + source.x * layer.transform.scale.x,
|
||||
y: layer.transform.position.y + source.y * layer.transform.scale.y,
|
||||
w: source.w * layer.transform.scale.x,
|
||||
h: source.h * layer.transform.scale.y,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function drawMaskedLayer(
|
||||
context: CanvasRenderingContext2D,
|
||||
layer: Layer,
|
||||
|
||||
Reference in New Issue
Block a user