0
Fork 0
mirror of https://github.com/penpot/penpot-exporter-figma-plugin.git synced 2025-04-01 17:41:56 -05:00

Implement rotation for frames and sections (#163)

* Implement rotation for frames and sections

* wip

* finish implementation

* add changelog
This commit is contained in:
Jordi Sala Morales 2024-06-14 16:28:01 +02:00 committed by GitHub
parent af81fc7e92
commit e5f2943532
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 172 additions and 199 deletions

View file

@ -0,0 +1,5 @@
---
"penpot-exporter": minor
---
Implement rotation for the missing figures

View file

@ -8,15 +8,14 @@ const nodeActsAsMask = (node: SceneNode): boolean => {
export const transformChildren = async (
node: ChildrenMixin,
baseX: number = 0,
baseY: number = 0
baseRotation: number = 0
): Promise<Children> => {
const maskIndex = node.children.findIndex(nodeActsAsMask);
const containsMask = maskIndex !== -1;
return {
children: containsMask
? await translateMaskChildren(node.children, maskIndex, baseX, baseY)
: await translateChildren(node.children, baseX, baseY)
? await translateMaskChildren(node.children, maskIndex, baseRotation)
: await translateChildren(node.children, baseRotation)
};
};

View file

@ -1,5 +1,3 @@
import { getBoundingBox } from '@plugin/utils';
import { ShapeGeomAttributes } from '@ui/lib/types/shapes/shape';
export const transformDimension = (
@ -11,41 +9,13 @@ export const transformDimension = (
};
};
export const transformPosition = (
node: DimensionAndPositionMixin,
baseX: number,
baseY: number
): Pick<ShapeGeomAttributes, 'x' | 'y'> => {
return {
x: node.x + baseX,
y: node.y + baseY
};
};
export const transformDimensionAndPosition = (
node: DimensionAndPositionMixin,
baseX: number,
baseY: number
node: DimensionAndPositionMixin
): ShapeGeomAttributes => {
return {
x: node.x + baseX,
y: node.y + baseY,
x: node.absoluteTransform[0][2],
y: node.absoluteTransform[1][2],
width: node.width,
height: node.height
};
};
export const transformDimensionAndPositionFromVectorPath = (
vectorPath: VectorPath,
baseX: number,
baseY: number
): ShapeGeomAttributes => {
const boundingBox = getBoundingBox(vectorPath);
return {
x: boundingBox.x1 + baseX,
y: boundingBox.y1 + baseY,
width: boundingBox.x2 - boundingBox.x1,
height: boundingBox.y2 - boundingBox.y1
};
};

View file

@ -4,13 +4,12 @@ import { ShapeBaseAttributes, ShapeGeomAttributes } from '@ui/lib/types/shapes/s
export const transformRotationAndPosition = (
node: LayoutMixin,
baseX: number,
baseY: number
baseRotation: number
): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> &
Pick<ShapeGeomAttributes, 'x' | 'y'> => {
const rotation = node.rotation;
const x = node.x + baseX;
const y = node.y + baseY;
const rotation = node.rotation + baseRotation;
const x = node.absoluteTransform[0][2];
const y = node.absoluteTransform[1][2];
if (!hasRotation(rotation) || !node.absoluteBoundingBox) {
return {

View file

@ -2,7 +2,6 @@ import { parseSVG } from 'svg-path-parser';
import {
transformBlend,
transformDimensionAndPositionFromVectorPath,
transformEffects,
transformLayoutAttributes,
transformProportion,
@ -14,11 +13,7 @@ import { translateCommandsToSegments, translateWindingRule } from '@plugin/trans
import { PathShape } from '@ui/lib/types/shapes/pathShape';
export const transformVectorPaths = (
node: VectorNode,
baseX: number,
baseY: number
): PathShape[] => {
export const transformVectorPaths = (node: VectorNode): PathShape[] => {
const pathShapes = node.vectorPaths
.filter((vectorPath, index) => {
return (
@ -27,7 +22,7 @@ export const transformVectorPaths = (
);
})
.map((vectorPath, index) =>
transformVectorPath(node, vectorPath, (node.vectorNetwork.regions ?? [])[index], baseX, baseY)
transformVectorPath(node, vectorPath, (node.vectorNetwork.regions ?? [])[index])
);
const geometryShapes = node.fillGeometry
@ -37,7 +32,7 @@ export const transformVectorPaths = (
vectorPath => normalizePath(vectorPath.data) === normalizePath(geometry.data)
)
)
.map(geometry => transformVectorPath(node, geometry, undefined, baseX, baseY));
.map(geometry => transformVectorPath(node, geometry, undefined));
return [...geometryShapes, ...pathShapes];
};
@ -63,16 +58,18 @@ const nodeHasFills = (
const transformVectorPath = (
node: VectorNode,
vectorPath: VectorPath,
vectorRegion: VectorRegion | undefined,
baseX: number,
baseY: number
vectorRegion: VectorRegion | undefined
): PathShape => {
const normalizedPaths = parseSVG(vectorPath.data);
return {
type: 'path',
name: 'svg-path',
content: translateCommandsToSegments(normalizedPaths, baseX + node.x, baseY + node.y),
content: translateCommandsToSegments(
normalizedPaths,
node.absoluteTransform[0][2],
node.absoluteTransform[1][2]
),
fills:
vectorPath.windingRule === 'NONE' ? [] : translateFills(vectorRegion?.fills ?? node.fills),
svgAttrs: {
@ -82,7 +79,6 @@ const transformVectorPath = (
constraintsV: 'scale',
...transformStrokesFromVector(node, normalizedPaths, vectorRegion),
...transformEffects(node),
...transformDimensionAndPositionFromVectorPath(vectorPath, baseX, baseY),
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),

View file

@ -1,12 +1,13 @@
import {
transformBlend,
transformChildren,
transformDimensionAndPosition,
transformDimension,
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformRotationAndPosition,
transformSceneNode,
transformStrokes
} from '@plugin/transformers/partials';
@ -16,19 +17,19 @@ import { BoolShape } from '@ui/lib/types/shapes/boolShape';
export const transformBooleanNode = async (
node: BooleanOperationNode,
baseX: number,
baseY: number
baseRotation: number
): Promise<BoolShape> => {
return {
type: 'bool',
name: node.name,
boolType: translateBoolType(node.booleanOperation),
...transformFigmaIds(node),
...(await transformChildren(node, baseX, baseY)),
...(await transformChildren(node, baseRotation)),
...transformFills(node),
...transformEffects(node),
...transformStrokes(node),
...transformDimensionAndPosition(node, baseX, baseY),
...transformDimension(node),
...transformRotationAndPosition(node, baseRotation),
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),

View file

@ -5,12 +5,13 @@ import {
transformChildren,
transformConstraints,
transformCornerRadius,
transformDimensionAndPosition,
transformDimension,
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformRotationAndPosition,
transformSceneNode,
transformStrokes
} from '@plugin/transformers/partials';
@ -19,8 +20,7 @@ import { ComponentRoot } from '@ui/types';
export const transformComponentNode = async (
node: ComponentNode,
baseX: number,
baseY: number
baseRotation: number
): Promise<ComponentRoot> => {
componentsLibrary.register(node.id, {
type: 'component',
@ -36,8 +36,9 @@ export const transformComponentNode = async (
...transformProportion(node),
...transformLayoutAttributes(node),
...transformCornerRadius(node),
...(await transformChildren(node, baseX + node.x, baseY + node.y)),
...transformDimensionAndPosition(node, baseX, baseY),
...(await transformChildren(node, node.rotation + baseRotation)),
...transformDimension(node),
...transformRotationAndPosition(node, baseRotation),
...transformConstraints(node),
...transformAutoLayout(node)
});

View file

@ -14,11 +14,7 @@ import {
import { CircleShape } from '@ui/lib/types/shapes/circleShape';
export const transformEllipseNode = (
node: EllipseNode,
baseX: number,
baseY: number
): CircleShape => {
export const transformEllipseNode = (node: EllipseNode, baseRotation: number): CircleShape => {
return {
type: 'circle',
name: node.name,
@ -27,7 +23,7 @@ export const transformEllipseNode = (
...transformEffects(node),
...transformStrokes(node),
...transformDimension(node),
...transformRotationAndPosition(node, baseX, baseY),
...transformRotationAndPosition(node, baseRotation),
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),

View file

@ -4,17 +4,19 @@ import {
transformChildren,
transformConstraints,
transformCornerRadius,
transformDimensionAndPosition,
transformDimension,
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformRotationAndPosition,
transformSceneNode,
transformStrokes
} from '@plugin/transformers/partials';
import { FrameShape } from '@ui/lib/types/shapes/frameShape';
import { Point } from '@ui/lib/types/utils/point';
const isSectionNode = (node: FrameNode | SectionNode | ComponentSetNode): node is SectionNode => {
return node.type === 'SECTION';
@ -22,12 +24,18 @@ const isSectionNode = (node: FrameNode | SectionNode | ComponentSetNode): node i
export const transformFrameNode = async (
node: FrameNode | SectionNode | ComponentSetNode,
baseX: number,
baseY: number
baseRotation: number
): Promise<FrameShape> => {
let frameSpecificAttributes: Partial<FrameShape> = {};
let referencePoint: Point = { x: node.absoluteTransform[0][2], y: node.absoluteTransform[1][2] };
let rotation = baseRotation;
if (!isSectionNode(node)) {
const { x, y, ...transformAndRotation } = transformRotationAndPosition(node, baseRotation);
referencePoint = { x, y };
rotation += node.rotation;
// Figma API does not expose strokes, blend modes, corner radius, or constraint proportions for sections,
// they plan to add it in the future. Refactor this when available.
frameSpecificAttributes = {
@ -40,7 +48,8 @@ export const transformFrameNode = async (
...transformCornerRadius(node),
...transformEffects(node),
...transformConstraints(node),
...transformAutoLayout(node)
...transformAutoLayout(node),
...transformAndRotation
};
}
@ -50,9 +59,10 @@ export const transformFrameNode = async (
showContent: isSectionNode(node) ? true : !node.clipsContent,
...transformFigmaIds(node),
...transformFills(node),
...referencePoint,
...frameSpecificAttributes,
...(await transformChildren(node, baseX + node.x, baseY + node.y)),
...transformDimensionAndPosition(node, baseX, baseY),
...transformDimension(node),
...(await transformChildren(node, rotation)),
...transformSceneNode(node)
};
};

View file

@ -1,8 +1,9 @@
import {
transformBlend,
transformDimensionAndPosition,
transformDimension,
transformEffects,
transformFigmaIds,
transformRotationAndPosition,
transformSceneNode
} from '@plugin/transformers/partials';
import { transformChildren } from '@plugin/transformers/partials';
@ -11,27 +12,26 @@ import { GroupShape } from '@ui/lib/types/shapes/groupShape';
export const transformGroupNode = async (
node: GroupNode,
baseX: number,
baseY: number
baseRotation: number
): Promise<GroupShape> => {
return {
...transformFigmaIds(node),
...transformGroupNodeLike(node, baseX, baseY),
...transformGroupNodeLike(node, baseRotation),
...transformEffects(node),
...transformBlend(node),
...(await transformChildren(node, baseX, baseY))
...(await transformChildren(node, baseRotation))
};
};
export const transformGroupNodeLike = (
node: BaseNodeMixin & DimensionAndPositionMixin & SceneNodeMixin,
baseX: number,
baseY: number
node: BaseNodeMixin & LayoutMixin & SceneNodeMixin,
baseRotation: number
): GroupShape => {
return {
type: 'group',
name: node.name,
...transformDimensionAndPosition(node, baseX, baseY),
...transformDimension(node),
...transformRotationAndPosition(node, baseRotation),
...transformSceneNode(node)
};
};

View file

@ -5,12 +5,13 @@ import {
transformChildren,
transformConstraints,
transformCornerRadius,
transformDimensionAndPosition,
transformDimension,
transformEffects,
transformFigmaIds,
transformFills,
transformLayoutAttributes,
transformProportion,
transformRotationAndPosition,
transformSceneNode,
transformStrokes
} from '@plugin/transformers/partials';
@ -19,8 +20,7 @@ import { ComponentInstance } from '@ui/types';
export const transformInstanceNode = async (
node: InstanceNode,
baseX: number,
baseY: number
baseRotation: number
): Promise<ComponentInstance | undefined> => {
const mainComponent = await node.getMainComponentAsync();
@ -47,10 +47,11 @@ export const transformInstanceNode = async (
...transformProportion(node),
...transformLayoutAttributes(node),
...transformCornerRadius(node),
...transformDimensionAndPosition(node, baseX, baseY),
...transformDimension(node),
...transformRotationAndPosition(node, baseRotation),
...transformConstraints(node),
...transformAutoLayout(node),
...(await transformChildren(node, baseX + node.x, baseY + node.y))
...(await transformChildren(node, node.rotation + baseRotation))
};
};

View file

@ -4,7 +4,6 @@ import {
transformEffects,
transformFigmaIds,
transformLayoutAttributes,
transformPosition,
transformProportion,
transformSceneNode,
transformStrokes
@ -19,15 +18,14 @@ import { PathShape } from '@ui/lib/types/shapes/pathShape';
*
* To represent the line rotated we do take into account the rotation of the line, but only in its content.
*/
export const transformLineNode = (node: LineNode, baseX: number, baseY: number): PathShape => {
export const transformLineNode = (node: LineNode, baseRotation: number): PathShape => {
return {
type: 'path',
name: node.name,
content: translateLineNode(node, baseX, baseY),
content: translateLineNode(node, baseRotation),
...transformFigmaIds(node),
...transformStrokes(node),
...transformEffects(node),
...transformPosition(node, baseX, baseY),
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),

View file

@ -1,7 +1,6 @@
import {
transformBlend,
transformConstraints,
transformDimensionAndPosition,
transformEffects,
transformFigmaIds,
transformFills,
@ -10,24 +9,22 @@ import {
transformSceneNode,
transformStrokes
} from '@plugin/transformers/partials';
import { translateVectorPaths } from '@plugin/translators/vectors';
import { translatePathNode } from '@plugin/translators/vectors';
import { PathShape } from '@ui/lib/types/shapes/pathShape';
export const transformPathNode = (
node: StarNode | PolygonNode,
baseX: number,
baseY: number
baseRotation: number
): PathShape => {
return {
type: 'path',
name: node.name,
content: translateVectorPaths(node.fillGeometry, baseX + node.x, baseY + node.y),
content: translatePathNode(node, baseRotation),
...transformFigmaIds(node),
...transformFills(node),
...transformStrokes(node),
...transformEffects(node),
...transformDimensionAndPosition(node, baseX, baseY),
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),

View file

@ -15,11 +15,7 @@ import {
import { RectShape } from '@ui/lib/types/shapes/rectShape';
export const transformRectangleNode = (
node: RectangleNode,
baseX: number,
baseY: number
): RectShape => {
export const transformRectangleNode = (node: RectangleNode, baseRotation: number): RectShape => {
return {
type: 'rect',
name: node.name,
@ -28,7 +24,7 @@ export const transformRectangleNode = (
...transformEffects(node),
...transformStrokes(node),
...transformDimension(node),
...transformRotationAndPosition(node, baseX, baseY),
...transformRotationAndPosition(node, baseRotation),
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),

View file

@ -16,8 +16,7 @@ import {
export const transformSceneNode = async (
node: SceneNode,
baseX: number = 0,
baseY: number = 0
baseRotation: number = 0
): Promise<PenpotNode | undefined> => {
let penpotNode: PenpotNode | undefined;
@ -28,40 +27,40 @@ export const transformSceneNode = async (
switch (node.type) {
case 'RECTANGLE':
penpotNode = transformRectangleNode(node, baseX, baseY);
penpotNode = transformRectangleNode(node, baseRotation);
break;
case 'ELLIPSE':
penpotNode = transformEllipseNode(node, baseX, baseY);
penpotNode = transformEllipseNode(node, baseRotation);
break;
case 'SECTION':
case 'FRAME':
case 'COMPONENT_SET':
penpotNode = await transformFrameNode(node, baseX, baseY);
penpotNode = await transformFrameNode(node, baseRotation);
break;
case 'GROUP':
penpotNode = await transformGroupNode(node, baseX, baseY);
penpotNode = await transformGroupNode(node, baseRotation);
break;
case 'TEXT':
penpotNode = transformTextNode(node, baseX, baseY);
penpotNode = transformTextNode(node, baseRotation);
break;
case 'VECTOR':
penpotNode = transformVectorNode(node, baseX, baseY);
penpotNode = transformVectorNode(node, baseRotation);
break;
case 'LINE':
penpotNode = transformLineNode(node, baseX, baseY);
penpotNode = transformLineNode(node, baseRotation);
break;
case 'STAR':
case 'POLYGON':
penpotNode = transformPathNode(node, baseX, baseY);
penpotNode = transformPathNode(node, baseRotation);
break;
case 'BOOLEAN_OPERATION':
penpotNode = await transformBooleanNode(node, baseX, baseY);
penpotNode = await transformBooleanNode(node, baseRotation);
break;
case 'COMPONENT':
penpotNode = await transformComponentNode(node, baseX, baseY);
penpotNode = await transformComponentNode(node, baseRotation);
break;
case 'INSTANCE':
penpotNode = await transformInstanceNode(node, baseX, baseY);
penpotNode = await transformInstanceNode(node, baseRotation);
break;
}

View file

@ -1,11 +1,12 @@
import {
transformBlend,
transformConstraints,
transformDimensionAndPosition,
transformDimension,
transformEffects,
transformFigmaIds,
transformLayoutAttributes,
transformProportion,
transformRotationAndPosition,
transformSceneNode,
transformStrokes,
transformText
@ -13,13 +14,14 @@ import {
import { TextShape } from '@ui/lib/types/shapes/textShape';
export const transformTextNode = (node: TextNode, baseX: number, baseY: number): TextShape => {
export const transformTextNode = (node: TextNode, baseRotation: number): TextShape => {
return {
type: 'text',
name: node.name,
...transformFigmaIds(node),
...transformText(node),
...transformDimensionAndPosition(node, baseX, baseY),
...transformDimension(node),
...transformRotationAndPosition(node, baseRotation),
...transformEffects(node),
...transformSceneNode(node),
...transformBlend(node),

View file

@ -17,10 +17,9 @@ import { transformGroupNodeLike } from '.';
*/
export const transformVectorNode = (
node: VectorNode,
baseX: number,
baseY: number
baseRotation: number
): GroupShape | PathShape => {
const children = transformVectorPaths(node, baseX, baseY);
const children = transformVectorPaths(node);
if (children.length === 1) {
return {
@ -32,7 +31,7 @@ export const transformVectorNode = (
}
return {
...transformGroupNodeLike(node, baseX, baseY),
...transformGroupNodeLike(node, baseRotation),
...transformFigmaIds(node),
...transformConstraints(node),
children

View file

@ -17,16 +17,31 @@ import { PenpotNode } from '@ui/types';
export const translateMaskChildren = async (
children: readonly SceneNode[],
maskIndex: number,
baseX: number,
baseY: number
baseRotation: number
): Promise<PenpotNode[]> => {
const maskChild = children[maskIndex];
const unmaskedChildren = await translateChildren(children.slice(0, maskIndex), baseX, baseY);
const maskedChildren = await translateChildren(children.slice(maskIndex), baseX, baseY);
const unmaskedChildren = await translateChildren(children.slice(0, maskIndex), baseRotation);
const maskedChildren = await translateChildren(children.slice(maskIndex), baseRotation);
if (
maskChild.type === 'STICKY' ||
maskChild.type === 'CONNECTOR' ||
maskChild.type === 'CODE_BLOCK' ||
maskChild.type === 'WIDGET' ||
maskChild.type === 'EMBED' ||
maskChild.type === 'LINK_UNFURL' ||
maskChild.type === 'MEDIA' ||
maskChild.type === 'SECTION' ||
maskChild.type === 'TABLE' ||
maskChild.type === 'SHAPE_WITH_TEXT'
) {
return [...unmaskedChildren, ...maskedChildren];
}
const maskGroup = {
...transformMaskFigmaIds(maskChild),
...transformGroupNodeLike(maskChild, baseX, baseY),
...transformGroupNodeLike(maskChild, baseRotation),
children: maskedChildren,
maskedGroup: true
};
@ -36,13 +51,12 @@ export const translateMaskChildren = async (
export const translateChildren = async (
children: readonly SceneNode[],
baseX: number = 0,
baseY: number = 0
baseRotation: number = 0
): Promise<PenpotNode[]> => {
const transformedChildren: PenpotNode[] = [];
for (const child of children) {
const penpotNode = await transformSceneNode(child, baseX, baseY);
const penpotNode = await transformSceneNode(child, baseRotation);
if (penpotNode) transformedChildren.push(penpotNode);

View file

@ -1,4 +1,4 @@
export * from './translateCommandsToSegments';
export * from './translateLineNode';
export * from './translateVectorPaths';
export * from './translatePathNode';
export * from './translateWindingRule';

View file

@ -4,8 +4,8 @@ import { Segment } from '@ui/lib/types/shapes/pathShape';
export const translateCommandsToSegments = (
commands: Command[],
baseX: number,
baseY: number
baseX: number = 0,
baseY: number = 0
): Segment[] => {
return commands.map(command => {
switch (command.command) {

View file

@ -6,8 +6,12 @@ import { Segment } from '@ui/lib/types/shapes/pathShape';
import { translateCommandsToSegments } from '.';
export const translateLineNode = (node: LineNode, baseX: number, baseY: number): Segment[] => {
if (!hasRotation(node.rotation) || !node.absoluteBoundingBox) {
export const translateLineNode = (node: LineNode, baseRotation: number): Segment[] => {
const rotation = node.rotation + baseRotation;
const x = node.absoluteTransform[0][2];
const y = node.absoluteTransform[1][2];
if (!hasRotation(rotation) || !node.absoluteBoundingBox) {
return translateCommandsToSegments(
[
{
@ -23,27 +27,27 @@ export const translateLineNode = (node: LineNode, baseX: number, baseY: number):
code: 'L'
}
],
baseX + node.x,
baseY + node.y
x,
y
);
}
const startPoint = applyRotation(
{ x: 0, y: 0 },
const referencePoint = applyInverseRotation(
{ x, y },
node.absoluteTransform,
node.absoluteBoundingBox
);
const endPoint = applyRotation(
{ x: node.width, y: 0 },
{ x: referencePoint.x + node.width, y: referencePoint.y },
node.absoluteTransform,
node.absoluteBoundingBox
);
const commands: Command[] = [
{
x: startPoint.x,
y: startPoint.y,
x,
y,
command: 'moveto',
code: 'M'
},
@ -55,11 +59,5 @@ export const translateLineNode = (node: LineNode, baseX: number, baseY: number):
}
];
const referencePoint = applyInverseRotation(
{ x: node.x, y: node.y },
node.absoluteTransform,
node.absoluteBoundingBox
);
return translateCommandsToSegments(commands, baseX + referencePoint.x, baseY + referencePoint.y);
return translateCommandsToSegments(commands);
};

View file

@ -0,0 +1,37 @@
import { parseSVG } from 'svg-path-parser';
import { applyInverseRotation, hasRotation } from '@plugin/utils';
import { Segment } from '@ui/lib/types/shapes/pathShape';
import { Point } from '@ui/lib/types/utils/point';
import { translateCommandsToSegments } from '.';
export const translatePathNode = (
node: StarNode | PolygonNode,
baseRotation: number
): Segment[] => {
let referencePoint: Point = {
x: node.absoluteTransform[0][2],
y: node.absoluteTransform[1][2]
};
if (hasRotation(node.rotation + baseRotation) && node.absoluteBoundingBox) {
referencePoint = applyInverseRotation(
{ x: referencePoint.x, y: referencePoint.y },
node.absoluteTransform,
node.absoluteBoundingBox
);
}
const segments: Segment[] = [];
for (const path of node.fillGeometry) {
segments.push(...translateVectorPath(path, referencePoint.x, referencePoint.y));
}
return segments;
};
const translateVectorPath = (path: VectorPath, baseX: number, baseY: number): Segment[] =>
translateCommandsToSegments(parseSVG(path.data), baseX, baseY);

View file

@ -1,19 +0,0 @@
import { parseSVG } from 'svg-path-parser';
import { Segment } from '@ui/lib/types/shapes/pathShape';
import { translateCommandsToSegments } from '.';
export const translateVectorPaths = (
paths: VectorPaths,
baseX: number,
baseY: number
): Segment[] => {
const segments: Segment[] = [];
for (const path of paths) {
segments.push(...translateCommandsToSegments(parseSVG(path.data), baseX, baseY));
}
return segments;
};

View file

@ -1,25 +0,0 @@
import { parseSVG } from 'svg-path-parser';
type BoundingBox = { x1: number; y1: number; x2: number; y2: number };
export const getBoundingBox = (vectorPath: VectorPath): BoundingBox => {
const path = parseSVG(vectorPath.data);
if (!path.length) return { x1: 0, y1: 0, x2: 0, y2: 0 };
const bounds = { x1: Infinity, y1: Infinity, x2: -Infinity, y2: -Infinity };
for (const points of path) {
switch (points.code) {
case 'M':
case 'L':
case 'C':
bounds.x1 = Math.min(bounds.x1, points.x);
bounds.y1 = Math.min(bounds.y1, points.y);
bounds.x2 = Math.max(bounds.x2, points.x);
bounds.y2 = Math.max(bounds.y2, points.y);
}
}
return bounds;
};

View file

@ -3,7 +3,6 @@ export * from './applyRotation';
export * from './calculateAdjustment';
export * from './calculateLinearGradient';
export * from './calculateRadialGradient';
export * from './getBoundingBox';
export * from './matrixInvert';
export * from './rgbToHex';
export * from './sleep';