diff --git a/packages/core/src/io/formats/svg/paths.ts b/packages/core/src/io/formats/svg/paths.ts index 85d7f9a5a..3e8ecb0ac 100644 --- a/packages/core/src/io/formats/svg/paths.ts +++ b/packages/core/src/io/formats/svg/paths.ts @@ -5,6 +5,7 @@ import type { SceneNode, VectorNetwork, VectorSegment, VectorVertex } from '#cor const CMD_CLOSE = 0 const CMD_MOVE_TO = 1 const CMD_LINE_TO = 2 +const CMD_QUAD_TO = 3 const CMD_CUBIC_TO = 4 export function round(n: number, decimals = 2): number { @@ -38,6 +39,15 @@ export function geometryBlobToSVGPath(blob: Uint8Array): string { parts.push(`L${x} ${y}`) break } + case CMD_QUAD_TO: { + const x1 = round(dv.getFloat32(o, true)) + const y1 = round(dv.getFloat32(o + 4, true)) + const x = round(dv.getFloat32(o + 8, true)) + const y = round(dv.getFloat32(o + 12, true)) + o += 16 + parts.push(`Q${x1} ${y1} ${x} ${y}`) + break + } case CMD_CUBIC_TO: { const x1 = round(dv.getFloat32(o, true)) const y1 = round(dv.getFloat32(o + 4, true)) diff --git a/packages/core/src/vector/index.ts b/packages/core/src/vector/index.ts index bcf096b0d..f0ee290c0 100644 --- a/packages/core/src/vector/index.ts +++ b/packages/core/src/vector/index.ts @@ -279,6 +279,7 @@ function addLoopToPath( const CMD_CLOSE = 0 const CMD_MOVE_TO = 1 const CMD_LINE_TO = 2 +const CMD_QUAD_TO = 3 const CMD_CUBIC_TO = 4 export function geometryBlobToPath( @@ -311,6 +312,15 @@ export function geometryBlobToPath( path.lineTo(x, y) break } + case CMD_QUAD_TO: { + const x1 = dv.getFloat32(o, true) + const y1 = dv.getFloat32(o + 4, true) + const x = dv.getFloat32(o + 8, true) + const y = dv.getFloat32(o + 12, true) + o += 16 + path.quadTo(x1, y1, x, y) + break + } case CMD_CUBIC_TO: { const x1 = dv.getFloat32(o, true) const y1 = dv.getFloat32(o + 4, true) diff --git a/tests/engine/io/svg/export/paths.test.ts b/tests/engine/io/svg/export/paths.test.ts index a610f166c..81e316b6e 100644 --- a/tests/engine/io/svg/export/paths.test.ts +++ b/tests/engine/io/svg/export/paths.test.ts @@ -39,6 +39,18 @@ describe('geometryBlobToSVGPath()', () => { expect(geometryBlobToSVGPath(blob)).toBe('M10 20L30 40Z') }) + test('quadratic bezier', () => { + const blob = makeBlobWithFloats([ + { cmd: 1, floats: [0, 0] }, + { cmd: 3, floats: [10, 0, 30, 30] }, + { cmd: 0 } + ]) + const result = geometryBlobToSVGPath(blob) + expect(result).toContain('M0 0') + expect(result).toContain('Q10 0 30 30') + expect(result).toContain('Z') + }) + test('cubic bezier', () => { const blob = makeBlobWithFloats([ { cmd: 1, floats: [0, 0] },