diff --git a/packages/core/src/canvas/fills.ts b/packages/core/src/canvas/fills.ts index b9daea9b1..ddd63cdfb 100644 --- a/packages/core/src/canvas/fills.ts +++ b/packages/core/src/canvas/fills.ts @@ -104,6 +104,17 @@ function makeGradientLocalMatrix( ]) } +export function linearGradientEndpoints( + width: number, + height: number, + transform: NonNullable +) { + return { + start: { x: (transform.m00 + transform.m02) * width, y: (transform.m10 + transform.m12) * height }, + end: { x: transform.m02 * width, y: transform.m12 * height } + } +} + export function applyGradientFill( r: SkiaRenderer, fill: Fill, @@ -135,10 +146,11 @@ export function applyGradientFill( const h = node.height if (fill.type === 'GRADIENT_LINEAR') { - const startX = t.m02 * w - const startY = t.m12 * h - const endX = (t.m00 + t.m02) * w - const endY = (t.m10 + t.m12) * h + const { start, end } = linearGradientEndpoints(w, h, t) + const startX = start.x + const startY = start.y + const endX = end.x + const endY = end.y const shader = r.ck.Shader.MakeLinearGradient( [startX, startY], [endX, endY], diff --git a/tests/engine/render/canvas/gradient.test.ts b/tests/engine/render/canvas/gradient.test.ts new file mode 100644 index 000000000..013f76642 --- /dev/null +++ b/tests/engine/render/canvas/gradient.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, test } from 'bun:test' + +import { linearGradientEndpoints } from '#core/canvas/fills' + +describe('canvas gradients', () => { + test('maps figma linear gradient start color to transformed x-axis endpoint', () => { + const endpoints = linearGradientEndpoints(188, 270, { + m00: 0, + m01: 1, + m02: 0, + m10: -1, + m11: 0, + m12: 1 + }) + + expect(endpoints.start).toEqual({ x: 0, y: 0 }) + expect(endpoints.end).toEqual({ x: 0, y: 270 }) + }) +})