mirror of
https://github.com/penpot/penpot-exporter-figma-plugin.git
synced 2024-12-22 05:33:02 -05:00
Vectors - Pen & pencil (#35)
* path shapes * add polygon node * wip vector * implement translation of commands and paths * vectors and polygon * strokes * star * deformed shapes * simplify star * simplify star * fix transformers --------- Co-authored-by: Alex Sánchez <sion333@gmail.com>
This commit is contained in:
parent
cfbd196872
commit
73ccf83657
25 changed files with 303 additions and 16 deletions
20
package-lock.json
generated
20
package-lock.json
generated
|
@ -11,7 +11,8 @@
|
|||
"dependencies": {
|
||||
"react": "^18.2",
|
||||
"react-dom": "^18.2",
|
||||
"slugify": "^1.6"
|
||||
"slugify": "^1.6",
|
||||
"svg-path-commander": "^2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@figma/eslint-plugin-figma-plugins": "^0.15",
|
||||
|
@ -2013,6 +2014,11 @@
|
|||
"@swc/counter": "^0.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@thednp/dommatrix": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@thednp/dommatrix/-/dommatrix-2.0.6.tgz",
|
||||
"integrity": "sha512-DXQq4Rs/akYzeXYGkNy3KiJ4JoD8+SYr1QRWTXtAGoZ0+vJcyBt0aeqA1K4CxPaBaIfKdOTE+Te1HV9sAQ4I4A=="
|
||||
},
|
||||
"node_modules/@trivago/prettier-plugin-sort-imports": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz",
|
||||
|
@ -6482,6 +6488,18 @@
|
|||
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/svg-path-commander": {
|
||||
"version": "2.0.9",
|
||||
"resolved": "https://registry.npmjs.org/svg-path-commander/-/svg-path-commander-2.0.9.tgz",
|
||||
"integrity": "sha512-VfRLznHewlpQvuahtBK0MT/PlWAapbTx8RSytqgaVwD3US2keKcc3WYYlBBk4vIOR+jB3nQu/NAVlWHKlo0Fjw==",
|
||||
"dependencies": {
|
||||
"@thednp/dommatrix": "^2.0.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16",
|
||||
"pnpm": ">=8.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svg-tags": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
"dependencies": {
|
||||
"react": "^18.2",
|
||||
"react-dom": "^18.2",
|
||||
"slugify": "^1.6"
|
||||
"slugify": "^1.6",
|
||||
"svg-path-commander": "^2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@figma/eslint-plugin-figma-plugins": "^0.15",
|
||||
|
|
|
@ -2,8 +2,10 @@ export * from './transformDocumentNode';
|
|||
export * from './transformEllipseNode';
|
||||
export * from './transformFrameNode';
|
||||
export * from './transformGroupNode';
|
||||
export * from './transformImageNode';
|
||||
export * from './transformPageNode';
|
||||
export * from './transformPolygonNode';
|
||||
export * from './transformRectangleNode';
|
||||
export * from './transformSceneNode';
|
||||
export * from './transformImageNode';
|
||||
export * from './transformTextNode';
|
||||
export * from './transformVectorNode';
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
transformDimensionAndPosition,
|
||||
transformSceneNode
|
||||
} from '@plugin/transformers/partials';
|
||||
import { translateFills } from '@plugin/translators';
|
||||
import { translateFills, translateStrokes } from '@plugin/translators';
|
||||
|
||||
import { CircleShape } from '@ui/lib/types/circle/circleShape';
|
||||
|
||||
|
@ -16,6 +16,7 @@ export const transformEllipseNode = (
|
|||
type: 'circle',
|
||||
name: node.name,
|
||||
fills: translateFills(node.fills, node.width, node.height),
|
||||
strokes: translateStrokes(node),
|
||||
...transformDimensionAndPosition(node, baseX, baseY),
|
||||
...transformSceneNode(node),
|
||||
...transformBlend(node)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { transformDimensionAndPosition, transformSceneNode } from '@plugin/transformers/partials';
|
||||
import { transformChildren } from '@plugin/transformers/partials';
|
||||
import { translateFills } from '@plugin/translators';
|
||||
import { translateFills, translateStrokes } from '@plugin/translators';
|
||||
|
||||
import { FrameShape } from '@ui/lib/types/frame/frameShape';
|
||||
|
||||
|
@ -13,6 +13,7 @@ export const transformFrameNode = async (
|
|||
type: 'frame',
|
||||
name: node.name,
|
||||
fills: translateFills(node.fills, node.width, node.height),
|
||||
strokes: translateStrokes(node),
|
||||
...(await transformChildren(node, baseX, baseY)),
|
||||
...transformDimensionAndPosition(node, baseX, baseY),
|
||||
...transformSceneNode(node)
|
||||
|
|
25
plugin-src/transformers/transformPolygonNode.ts
Normal file
25
plugin-src/transformers/transformPolygonNode.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import {
|
||||
transformBlend,
|
||||
transformDimensionAndPosition,
|
||||
transformSceneNode
|
||||
} from '@plugin/transformers/partials';
|
||||
import { translateFills, translateStrokes, translateVectorPaths } from '@plugin/translators';
|
||||
|
||||
import { PathShape } from '@ui/lib/types/path/pathShape';
|
||||
|
||||
export const transformPolygonNode = (
|
||||
node: DefaultShapeMixin,
|
||||
baseX: number,
|
||||
baseY: number
|
||||
): PathShape => {
|
||||
return {
|
||||
type: 'path',
|
||||
name: node.name,
|
||||
content: translateVectorPaths(node.fillGeometry, baseX + node.x, baseY + node.y),
|
||||
strokes: translateStrokes(node),
|
||||
fills: translateFills(node.fills, node.width, node.height),
|
||||
...transformDimensionAndPosition(node, baseX, baseY),
|
||||
...transformSceneNode(node),
|
||||
...transformBlend(node)
|
||||
};
|
||||
};
|
|
@ -3,7 +3,7 @@ import {
|
|||
transformDimensionAndPosition,
|
||||
transformSceneNode
|
||||
} from '@plugin/transformers/partials';
|
||||
import { translateFills } from '@plugin/translators';
|
||||
import { translateFills, translateStrokes } from '@plugin/translators';
|
||||
|
||||
import { RectShape } from '@ui/lib/types/rect/rectShape';
|
||||
|
||||
|
@ -16,6 +16,7 @@ export const transformRectangleNode = (
|
|||
type: 'rect',
|
||||
name: node.name,
|
||||
fills: translateFills(node.fills, node.width, node.height),
|
||||
strokes: translateStrokes(node),
|
||||
...transformDimensionAndPosition(node, baseX, baseY),
|
||||
...transformSceneNode(node),
|
||||
...transformBlend(node)
|
||||
|
|
|
@ -7,8 +7,10 @@ import {
|
|||
transformFrameNode,
|
||||
transformGroupNode,
|
||||
transformImageNode,
|
||||
transformPolygonNode,
|
||||
transformRectangleNode,
|
||||
transformTextNode
|
||||
transformTextNode,
|
||||
transformVectorNode
|
||||
} from '.';
|
||||
|
||||
export const transformSceneNode = async (
|
||||
|
@ -40,6 +42,11 @@ export const transformSceneNode = async (
|
|||
return await transformGroupNode(node, baseX, baseY);
|
||||
case 'TEXT':
|
||||
return transformTextNode(node, baseX, baseY);
|
||||
case 'STAR':
|
||||
case 'POLYGON':
|
||||
return transformPolygonNode(node, baseX, baseY);
|
||||
case 'VECTOR':
|
||||
return transformVectorNode(node, baseX, baseY);
|
||||
}
|
||||
|
||||
throw new Error(`Unsupported node type: ${node.type}`);
|
||||
|
|
21
plugin-src/transformers/transformVectorNode.ts
Normal file
21
plugin-src/transformers/transformVectorNode.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import {
|
||||
transformBlend,
|
||||
transformDimensionAndPosition,
|
||||
transformSceneNode
|
||||
} from '@plugin/transformers/partials';
|
||||
import { translateFills, translateStrokes, translateVectorPaths } from '@plugin/translators';
|
||||
|
||||
import { PathShape } from '@ui/lib/types/path/pathShape';
|
||||
|
||||
export const transformVectorNode = (node: VectorNode, baseX: number, baseY: number): PathShape => {
|
||||
return {
|
||||
type: 'path',
|
||||
name: node.name,
|
||||
fills: node.fillGeometry.length ? translateFills(node.fills, node.width, node.height) : [],
|
||||
content: translateVectorPaths(node.vectorPaths, baseX + node.x, baseY + node.y),
|
||||
strokes: translateStrokes(node),
|
||||
...transformDimensionAndPosition(node, baseX, baseY),
|
||||
...transformSceneNode(node),
|
||||
...transformBlend(node)
|
||||
};
|
||||
};
|
|
@ -1,6 +1,8 @@
|
|||
export * from './translateBlendMode';
|
||||
export * from './translateFills';
|
||||
export * from './translateGradientLinearFill';
|
||||
export * from './translateSolidFill';
|
||||
export * from './translateStrokes';
|
||||
export * from './translateTextDecoration';
|
||||
export * from './translateTextTransform';
|
||||
export * from './translateBlendMode';
|
||||
export * from './translateVectorPaths';
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Fill } from '@ui/lib/types/utils/fill';
|
|||
import { translateGradientLinearFill } from './translateGradientLinearFill';
|
||||
import { translateSolidFill } from './translateSolidFill';
|
||||
|
||||
const translateFill = (fill: Paint, width: number, height: number): Fill | undefined => {
|
||||
export const translateFill = (fill: Paint, width: number, height: number): Fill | undefined => {
|
||||
switch (fill.type) {
|
||||
case 'SOLID':
|
||||
return translateSolidFill(fill);
|
||||
|
|
14
plugin-src/translators/translateStrokes.ts
Normal file
14
plugin-src/translators/translateStrokes.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { translateFill } from '@plugin/translators/translateFills';
|
||||
|
||||
import { Stroke } from '@ui/lib/types/utils/stroke';
|
||||
|
||||
export const translateStrokes = (node: MinimalStrokesMixin): Stroke[] => {
|
||||
return node.strokes.map(stroke => {
|
||||
const fill = translateFill(stroke, 0, 0);
|
||||
return {
|
||||
strokeColor: fill?.fillColor,
|
||||
strokeOpacity: fill?.fillOpacity,
|
||||
strokeWidth: node.strokeWeight === figma.mixed ? 1 : node.strokeWeight
|
||||
};
|
||||
});
|
||||
};
|
60
plugin-src/translators/translateVectorPaths.ts
Normal file
60
plugin-src/translators/translateVectorPaths.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import SVGPathCommander from 'svg-path-commander';
|
||||
|
||||
import { Segment } from '@ui/lib/types/path/PathContent';
|
||||
|
||||
export const translateVectorPaths = (
|
||||
paths: VectorPaths,
|
||||
baseX: number,
|
||||
baseY: number
|
||||
): Segment[] => {
|
||||
let segments: Segment[] = [];
|
||||
|
||||
for (const path of paths) {
|
||||
segments = [...segments, ...translateVectorPath(path, baseX, baseY)];
|
||||
}
|
||||
|
||||
return segments;
|
||||
};
|
||||
|
||||
const translateVectorPath = (path: VectorPath, baseX: number, baseY: number): Segment[] => {
|
||||
const segments: Segment[] = [];
|
||||
|
||||
const normalizedPath = SVGPathCommander.normalizePath(path.data);
|
||||
|
||||
for (const [command, ...rest] of normalizedPath) {
|
||||
switch (command) {
|
||||
case 'M':
|
||||
segments.push({
|
||||
command: 'move-to',
|
||||
params: { x: (rest[0] ?? 0) + baseX, y: (rest[1] ?? 0) + baseY }
|
||||
});
|
||||
break;
|
||||
case 'L':
|
||||
segments.push({
|
||||
command: 'line-to',
|
||||
params: { x: (rest[0] ?? 0) + baseX, y: (rest[1] ?? 0) + baseY }
|
||||
});
|
||||
break;
|
||||
case 'C':
|
||||
segments.push({
|
||||
command: 'curve-to',
|
||||
params: {
|
||||
c1x: (rest[0] ?? 0) + baseX,
|
||||
c1y: (rest[1] ?? 0) + baseY,
|
||||
c2x: (rest[2] ?? 0) + baseX,
|
||||
c2y: (rest[3] ?? 0) + baseY,
|
||||
x: (rest[4] ?? 0) + baseX,
|
||||
y: (rest[5] ?? 0) + baseY
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'Z':
|
||||
segments.push({
|
||||
command: 'close-path'
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return segments;
|
||||
};
|
|
@ -6,6 +6,7 @@ import {
|
|||
createPenpotCircle,
|
||||
createPenpotGroup,
|
||||
createPenpotImage,
|
||||
createPenpotPath,
|
||||
createPenpotRectangle,
|
||||
createPenpotText
|
||||
} from '.';
|
||||
|
@ -22,6 +23,8 @@ export const createPenpotItem = (file: PenpotFile, node: PenpotNode) => {
|
|||
return createPenpotGroup(file, node);
|
||||
case 'image':
|
||||
return createPenpotImage(file, node);
|
||||
case 'path':
|
||||
return createPenpotPath(file, node);
|
||||
case 'text':
|
||||
return createPenpotText(file, node);
|
||||
}
|
||||
|
|
21
ui-src/converters/createPenpotPath.ts
Normal file
21
ui-src/converters/createPenpotPath.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { PenpotFile } from '@ui/lib/penpot';
|
||||
import { PATH_TYPE } from '@ui/lib/types/path/pathAttributes';
|
||||
import { PathShape } from '@ui/lib/types/path/pathShape';
|
||||
import {
|
||||
translateFillGradients,
|
||||
translatePathContent,
|
||||
translateUiBlendMode
|
||||
} from '@ui/translators';
|
||||
|
||||
export const createPenpotPath = (
|
||||
file: PenpotFile,
|
||||
{ type, fills, blendMode, content, ...rest }: PathShape
|
||||
) => {
|
||||
file.createPath({
|
||||
type: PATH_TYPE,
|
||||
fills: translateFillGradients(fills),
|
||||
blendMode: translateUiBlendMode(blendMode),
|
||||
content: translatePathContent(content),
|
||||
...rest
|
||||
});
|
||||
};
|
|
@ -5,5 +5,6 @@ export * from './createPenpotGroup';
|
|||
export * from './createPenpotImage';
|
||||
export * from './createPenpotItem';
|
||||
export * from './createPenpotPage';
|
||||
export * from './createPenpotPath';
|
||||
export * from './createPenpotRectangle';
|
||||
export * from './createPenpotText';
|
||||
|
|
3
ui-src/lib/penpot.d.ts
vendored
3
ui-src/lib/penpot.d.ts
vendored
|
@ -3,6 +3,7 @@ import { CircleShape } from '@ui/lib/types/circle/circleShape';
|
|||
import { FrameShape } from '@ui/lib/types/frame/frameShape';
|
||||
import { GroupShape } from '@ui/lib/types/group/groupShape';
|
||||
import { ImageShape } from '@ui/lib/types/image/imageShape';
|
||||
import { PathShape } from '@ui/lib/types/path/pathShape';
|
||||
import { RectShape } from '@ui/lib/types/rect/rectShape';
|
||||
import { TextShape } from '@ui/lib/types/text/textShape';
|
||||
|
||||
|
@ -18,7 +19,7 @@ export interface PenpotFile {
|
|||
closeBool(): void;
|
||||
createRect(rect: RectShape): void;
|
||||
createCircle(circle: CircleShape): void;
|
||||
// createPath(path: any): void;
|
||||
createPath(path: PathShape): void;
|
||||
createText(options: TextShape): void;
|
||||
createImage(image: ImageShape): void;
|
||||
// createSVG(svg: any): void;
|
||||
|
|
48
ui-src/lib/types/path/PathContent.ts
Normal file
48
ui-src/lib/types/path/PathContent.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
export const VECTOR_LINE_TO: unique symbol = Symbol.for('line-to');
|
||||
export const VECTOR_CLOSE_PATH: unique symbol = Symbol.for('close-path');
|
||||
export const VECTOR_MOVE_TO: unique symbol = Symbol.for('move-to');
|
||||
export const VECTOR_CURVE_TO: unique symbol = Symbol.for('curve-to');
|
||||
|
||||
export type PathContent = Segment[];
|
||||
export type Segment = LineTo | ClosePath | MoveTo | CurveTo;
|
||||
export type Command =
|
||||
| 'line-to'
|
||||
| 'close-path'
|
||||
| 'move-to'
|
||||
| 'curve-to'
|
||||
| typeof VECTOR_LINE_TO
|
||||
| typeof VECTOR_CLOSE_PATH
|
||||
| typeof VECTOR_MOVE_TO
|
||||
| typeof VECTOR_CURVE_TO;
|
||||
|
||||
type LineTo = {
|
||||
command: 'line-to' | typeof VECTOR_LINE_TO;
|
||||
params: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
};
|
||||
|
||||
type ClosePath = {
|
||||
command: 'close-path' | typeof VECTOR_CLOSE_PATH;
|
||||
};
|
||||
|
||||
type MoveTo = {
|
||||
command: 'move-to' | typeof VECTOR_MOVE_TO;
|
||||
params: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
};
|
||||
|
||||
type CurveTo = {
|
||||
command: 'curve-to' | typeof VECTOR_CURVE_TO;
|
||||
params: {
|
||||
x: number;
|
||||
y: number;
|
||||
c1x: number;
|
||||
c1y: number;
|
||||
c2x: number;
|
||||
c2y: number;
|
||||
};
|
||||
};
|
8
ui-src/lib/types/path/pathAttributes.ts
Normal file
8
ui-src/lib/types/path/pathAttributes.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { PathContent } from '@ui/lib/types/path/PathContent';
|
||||
|
||||
export const PATH_TYPE: unique symbol = Symbol.for('path');
|
||||
|
||||
export type PathAttributes = {
|
||||
type: 'path' | typeof PATH_TYPE;
|
||||
content: PathContent;
|
||||
};
|
9
ui-src/lib/types/path/pathShape.d.ts
vendored
Normal file
9
ui-src/lib/types/path/pathShape.d.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { LayoutChildAttributes } from '@ui/lib/types/layout/layoutChildAttributes';
|
||||
import { PathAttributes } from '@ui/lib/types/path/pathAttributes';
|
||||
import { ShapeAttributes } from '@ui/lib/types/shape/shapeAttributes';
|
||||
import { ShapeBaseAttributes } from '@ui/lib/types/shape/shapeBaseAttributes';
|
||||
|
||||
export type PathShape = ShapeBaseAttributes &
|
||||
ShapeAttributes &
|
||||
PathAttributes &
|
||||
LayoutChildAttributes;
|
10
ui-src/lib/types/penpotNode.d.ts
vendored
10
ui-src/lib/types/penpotNode.d.ts
vendored
|
@ -2,7 +2,15 @@ import { CircleShape } from '@ui/lib/types/circle/circleShape';
|
|||
import { FrameShape } from '@ui/lib/types/frame/frameShape';
|
||||
import { GroupShape } from '@ui/lib/types/group/groupShape';
|
||||
import { ImageShape } from '@ui/lib/types/image/imageShape';
|
||||
import { PathShape } from '@ui/lib/types/path/pathShape';
|
||||
import { RectShape } from '@ui/lib/types/rect/rectShape';
|
||||
import { TextShape } from '@ui/lib/types/text/textShape';
|
||||
|
||||
export type PenpotNode = FrameShape | GroupShape | RectShape | CircleShape | TextShape | ImageShape;
|
||||
export type PenpotNode =
|
||||
| FrameShape
|
||||
| GroupShape
|
||||
| PathShape
|
||||
| RectShape
|
||||
| CircleShape
|
||||
| TextShape
|
||||
| ImageShape;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { PATH_TYPE } from '@ui/lib/types/path/pathAttributes';
|
||||
import { Matrix } from '@ui/lib/types/utils/matrix';
|
||||
import { Point } from '@ui/lib/types/utils/point';
|
||||
import { Selrect } from '@ui/lib/types/utils/selrect';
|
||||
|
@ -12,7 +13,6 @@ import { RECT_TYPE } from '../rect/rectAttributes';
|
|||
import { TEXT_TYPE } from '../text/textAttributes';
|
||||
|
||||
// @TODO: Move to its own file once we support all the shapes
|
||||
export const PATH_TYPE: unique symbol = Symbol.for('path');
|
||||
export const SVG_RAW_TYPE: unique symbol = Symbol.for('svg-raw');
|
||||
|
||||
export type ShapeBaseAttributes = {
|
||||
|
|
6
ui-src/lib/types/utils/stroke.d.ts
vendored
6
ui-src/lib/types/utils/stroke.d.ts
vendored
|
@ -8,12 +8,14 @@ export type Stroke = {
|
|||
strokeOpacity?: number;
|
||||
strokeStyle?: 'solid' | 'dotted' | 'dashed' | 'mixed' | 'none' | 'svg';
|
||||
strokeWidth?: number;
|
||||
strokeAlignment?: 'center' | 'inner' | 'outer';
|
||||
strokeAlignment?: StrokeAlignment;
|
||||
strokeCapStart?: StrokeCaps;
|
||||
strokeCapEnd?: StrokeCaps;
|
||||
strokeColorGradient: Gradient;
|
||||
strokeColorGradient?: Gradient;
|
||||
};
|
||||
|
||||
export type StrokeAlignment = 'center' | 'inner' | 'outer';
|
||||
|
||||
type StrokeCapLine = 'round' | 'square';
|
||||
type StrokeCapMarker =
|
||||
| 'line-arrow'
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export * from './translateFillGradients';
|
||||
export * from './translateFontStyle';
|
||||
export * from './translateHorizontalAlign';
|
||||
export * from './translateVerticalAlign';
|
||||
export * from './translateFillGradients';
|
||||
export * from './translatePathContent';
|
||||
export * from './translateUiBlendMode';
|
||||
export * from './translateVerticalAlign';
|
||||
|
|
32
ui-src/translators/translatePathContent.ts
Normal file
32
ui-src/translators/translatePathContent.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import {
|
||||
Command,
|
||||
PathContent,
|
||||
Segment,
|
||||
VECTOR_CLOSE_PATH,
|
||||
VECTOR_CURVE_TO,
|
||||
VECTOR_LINE_TO,
|
||||
VECTOR_MOVE_TO
|
||||
} from '@ui/lib/types/path/PathContent';
|
||||
|
||||
export const translatePathContent = (content: PathContent): PathContent =>
|
||||
content.map(({ command, ...rest }) => {
|
||||
return {
|
||||
command: translatePathCommand(command),
|
||||
...rest
|
||||
} as Segment;
|
||||
});
|
||||
|
||||
const translatePathCommand = (command: Command): Command => {
|
||||
switch (command) {
|
||||
case 'line-to':
|
||||
return VECTOR_LINE_TO;
|
||||
case 'close-path':
|
||||
return VECTOR_CLOSE_PATH;
|
||||
case 'move-to':
|
||||
return VECTOR_MOVE_TO;
|
||||
case 'curve-to':
|
||||
return VECTOR_CURVE_TO;
|
||||
}
|
||||
|
||||
throw new Error('Unknown path command');
|
||||
};
|
Loading…
Reference in a new issue