From 8d21d05f2524883eda6e0c1257afcea944cfc7d3 Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Sat, 16 May 2026 18:43:24 +0300 Subject: [PATCH] fix(clipboard): convert quadratic beziers to cubic instead of flattening to lines --- .../src/kiwi/node-change/path-commands.ts | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/packages/core/src/kiwi/node-change/path-commands.ts b/packages/core/src/kiwi/node-change/path-commands.ts index f207e19c6..1b657f1ff 100644 --- a/packages/core/src/kiwi/node-change/path-commands.ts +++ b/packages/core/src/kiwi/node-change/path-commands.ts @@ -12,33 +12,54 @@ export function encodePathCommandsBlob(commands: OutlineCommand[], scale = 1): U new DataView(buf).setFloat32(0, (value ?? 0) / scale, true) bytes.push(...new Uint8Array(buf)) } + const negY = (v: number | undefined) => (v === undefined ? undefined : -v) + + let curX = 0 + let curY = 0 for (const command of commands) { switch (command.type) { case 'M': bytes.push(CMD_MOVE_TO) pushFloat(command.x) - pushFloat(command.y === undefined ? undefined : -command.y) + pushFloat(negY(command.y)) + curX = command.x ?? 0 + curY = command.y ?? 0 break case 'L': bytes.push(CMD_LINE_TO) pushFloat(command.x) - pushFloat(command.y === undefined ? undefined : -command.y) + pushFloat(negY(command.y)) + curX = command.x ?? 0 + curY = command.y ?? 0 break case 'C': bytes.push(CMD_CUBIC_TO) pushFloat(command.x1) - pushFloat(command.y1 === undefined ? undefined : -command.y1) + pushFloat(negY(command.y1)) pushFloat(command.x2) - pushFloat(command.y2 === undefined ? undefined : -command.y2) + pushFloat(negY(command.y2)) pushFloat(command.x) - pushFloat(command.y === undefined ? undefined : -command.y) + pushFloat(negY(command.y)) + curX = command.x ?? 0 + curY = command.y ?? 0 break - case 'Q': - bytes.push(CMD_LINE_TO) - pushFloat(command.x) - pushFloat(command.y === undefined ? undefined : -command.y) + case 'Q': { + const qx1 = command.x1 ?? 0 + const qy1 = command.y1 ?? 0 + const qx = command.x ?? 0 + const qy = command.y ?? 0 + bytes.push(CMD_CUBIC_TO) + pushFloat(curX + (2 / 3) * (qx1 - curX)) + pushFloat(negY(curY + (2 / 3) * (qy1 - curY))) + pushFloat(qx + (2 / 3) * (qx1 - qx)) + pushFloat(negY(qy + (2 / 3) * (qy1 - qy))) + pushFloat(qx) + pushFloat(negY(qy)) + curX = qx + curY = qy break + } case 'Z': bytes.push(CMD_CLOSE) break