fix(io): preserve one-pixel export fringes
This commit is contained in:
parent
945560b5a9
commit
70114ef6de
|
|
@ -80,6 +80,23 @@ function findAlphaBounds(ck: CanvasKit, canvas: Canvas, width: number, height: n
|
|||
return { minX, minY, maxX, maxY }
|
||||
}
|
||||
|
||||
const MIN_TRANSPARENT_TRIM_INSET = 2
|
||||
|
||||
function shouldTrimAlphaBounds(
|
||||
alphaBounds: NonNullable<ReturnType<typeof findAlphaBounds>>,
|
||||
width: number,
|
||||
height: number
|
||||
): boolean {
|
||||
return (
|
||||
Math.max(
|
||||
alphaBounds.minX,
|
||||
alphaBounds.minY,
|
||||
width - alphaBounds.maxX,
|
||||
height - alphaBounds.maxY
|
||||
) >= MIN_TRANSPARENT_TRIM_INSET
|
||||
)
|
||||
}
|
||||
|
||||
function renderToSurface(
|
||||
ck: CanvasKit,
|
||||
renderer: SkiaRenderer,
|
||||
|
|
@ -100,7 +117,11 @@ function renderToSurface(
|
|||
setup(canvas)
|
||||
renderer.renderSceneToCanvas(canvas, renderGraph, pageId)
|
||||
surface.flush()
|
||||
const alphaBounds = trimTransparent ? findAlphaBounds(ck, canvas, width, height) : null
|
||||
const foundAlphaBounds = trimTransparent ? findAlphaBounds(ck, canvas, width, height) : null
|
||||
const alphaBounds =
|
||||
foundAlphaBounds && shouldTrimAlphaBounds(foundAlphaBounds, width, height)
|
||||
? foundAlphaBounds
|
||||
: null
|
||||
const image = alphaBounds
|
||||
? surface.makeImageSnapshot([
|
||||
alphaBounds.minX,
|
||||
|
|
|
|||
|
|
@ -8,11 +8,71 @@ import { expectDefined } from '#tests/helpers/assert'
|
|||
|
||||
let ck: Awaited<ReturnType<typeof initCanvasKit>>
|
||||
|
||||
function rectangleCommandsBlob(x: number, y: number, width: number, height: number): Uint8Array {
|
||||
const blob = new Uint8Array(1 + 4 * 9 + 1)
|
||||
const view = new DataView(blob.buffer)
|
||||
const points = [
|
||||
{ command: 1, x, y },
|
||||
{ command: 2, x: x + width, y },
|
||||
{ command: 2, x: x + width, y: y + height },
|
||||
{ command: 2, x, y: y + height }
|
||||
]
|
||||
let offset = 0
|
||||
for (const point of points) {
|
||||
blob[offset] = point.command
|
||||
view.setFloat32(offset + 1, point.x, true)
|
||||
view.setFloat32(offset + 5, point.y, true)
|
||||
offset += 9
|
||||
}
|
||||
blob[offset] = 0
|
||||
return blob
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
ck = await initCanvasKit()
|
||||
})
|
||||
|
||||
describe('raster export', () => {
|
||||
test('keeps one-pixel transparent fringes when trimming exports', async () => {
|
||||
const graph = new SceneGraph()
|
||||
const page = graph.getPages()[0]
|
||||
const vector = graph.createNode('VECTOR', page.id, {
|
||||
width: 10,
|
||||
height: 10,
|
||||
fillGeometry: [{ commandsBlob: rectangleCommandsBlob(1, 1, 8, 8) }],
|
||||
fills: [
|
||||
{
|
||||
type: 'SOLID',
|
||||
color: { r: 0, g: 0, b: 0, a: 1 },
|
||||
opacity: 1,
|
||||
visible: true
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const surface = expectDefined(ck.MakeSurface(1, 1), 'surface')
|
||||
const renderer = new SkiaRenderer(ck, surface)
|
||||
|
||||
try {
|
||||
const png = expectDefined(
|
||||
renderNodesToImage(ck, renderer, graph, page.id, [vector.id], {
|
||||
scale: 1,
|
||||
format: 'PNG',
|
||||
trimTransparent: true
|
||||
}),
|
||||
'png'
|
||||
)
|
||||
const image = expectDefined(ck.MakeImageFromEncoded(png), 'image')
|
||||
|
||||
expect(image.width()).toBe(10)
|
||||
expect(image.height()).toBe(10)
|
||||
|
||||
image.delete()
|
||||
} finally {
|
||||
surface.delete()
|
||||
}
|
||||
})
|
||||
|
||||
test('page exports can trim transparent text padding', async () => {
|
||||
const graph = new SceneGraph()
|
||||
const page = graph.getPages()[0]
|
||||
|
|
|
|||
Loading…
Reference in a new issue