0
Fork 0
mirror of https://github.com/penpot/penpot-exporter-figma-plugin.git synced 2024-12-22 05:33:02 -05:00

remove base rotation and calculate it instead (#178)

This commit is contained in:
Jordi Sala Morales 2024-06-19 08:10:20 +02:00 committed by GitHub
parent 8eb2b1a1be
commit 4e5d01adb3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 109 additions and 139 deletions

View file

@ -6,16 +6,13 @@ const nodeActsAsMask = (node: SceneNode): boolean => {
return 'isMask' in node && node.isMask; return 'isMask' in node && node.isMask;
}; };
export const transformChildren = async ( export const transformChildren = async (node: ChildrenMixin): Promise<Children> => {
node: ChildrenMixin,
baseRotation: number = 0
): Promise<Children> => {
const maskIndex = node.children.findIndex(nodeActsAsMask); const maskIndex = node.children.findIndex(nodeActsAsMask);
const containsMask = maskIndex !== -1; const containsMask = maskIndex !== -1;
return { return {
children: containsMask children: containsMask
? await translateMaskChildren(node.children, maskIndex, baseRotation) ? await translateMaskChildren(node.children, maskIndex)
: await translateChildren(node.children, baseRotation) : await translateChildren(node.children)
}; };
}; };

View file

@ -1,13 +1,12 @@
import { translateRotation, translateZeroRotation } from '@plugin/translators'; import { translateRotation, translateZeroRotation } from '@plugin/translators';
import { applyInverseRotation, hasRotation } from '@plugin/utils'; import { applyInverseRotation, getRotation, hasRotation } from '@plugin/utils';
import { ShapeBaseAttributes, ShapeGeomAttributes } from '@ui/lib/types/shapes/shape'; import { ShapeBaseAttributes, ShapeGeomAttributes } from '@ui/lib/types/shapes/shape';
export const transformRotation = ( export const transformRotation = (
node: LayoutMixin, node: LayoutMixin
baseRotation: number
): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> => { ): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> => {
const rotation = node.rotation + baseRotation; const rotation = getRotation(node.absoluteTransform);
if (!hasRotation(rotation)) { if (!hasRotation(rotation)) {
return translateZeroRotation(); return translateZeroRotation();
@ -17,13 +16,12 @@ export const transformRotation = (
}; };
export const transformRotationAndPosition = ( export const transformRotationAndPosition = (
node: LayoutMixin, node: LayoutMixin
baseRotation: number
): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> & ): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> &
Pick<ShapeGeomAttributes, 'x' | 'y'> => { Pick<ShapeGeomAttributes, 'x' | 'y'> => {
const rotation = node.rotation + baseRotation;
const x = node.absoluteTransform[0][2]; const x = node.absoluteTransform[0][2];
const y = node.absoluteTransform[1][2]; const y = node.absoluteTransform[1][2];
const rotation = getRotation(node.absoluteTransform);
if (!hasRotation(rotation) || !node.absoluteBoundingBox) { if (!hasRotation(rotation) || !node.absoluteBoundingBox) {
return { return {

View file

@ -13,7 +13,7 @@ import { translateCommands, translateWindingRule } from '@plugin/translators/vec
import { PathShape } from '@ui/lib/types/shapes/pathShape'; import { PathShape } from '@ui/lib/types/shapes/pathShape';
export const transformVectorPaths = (node: VectorNode, baseRotation: number): PathShape[] => { export const transformVectorPaths = (node: VectorNode): PathShape[] => {
const pathShapes = node.vectorPaths const pathShapes = node.vectorPaths
.filter((vectorPath, index) => { .filter((vectorPath, index) => {
return ( return (
@ -22,7 +22,7 @@ export const transformVectorPaths = (node: VectorNode, baseRotation: number): Pa
); );
}) })
.map((vectorPath, index) => .map((vectorPath, index) =>
transformVectorPath(node, vectorPath, (node.vectorNetwork.regions ?? [])[index], baseRotation) transformVectorPath(node, vectorPath, (node.vectorNetwork.regions ?? [])[index])
); );
const geometryShapes = node.fillGeometry const geometryShapes = node.fillGeometry
@ -32,7 +32,7 @@ export const transformVectorPaths = (node: VectorNode, baseRotation: number): Pa
vectorPath => normalizePath(vectorPath.data) === normalizePath(geometry.data) vectorPath => normalizePath(vectorPath.data) === normalizePath(geometry.data)
) )
) )
.map(geometry => transformVectorPath(node, geometry, undefined, baseRotation)); .map(geometry => transformVectorPath(node, geometry, undefined));
return [...geometryShapes, ...pathShapes]; return [...geometryShapes, ...pathShapes];
}; };
@ -58,15 +58,14 @@ const nodeHasFills = (
const transformVectorPath = ( const transformVectorPath = (
node: VectorNode, node: VectorNode,
vectorPath: VectorPath, vectorPath: VectorPath,
vectorRegion: VectorRegion | undefined, vectorRegion: VectorRegion | undefined
baseRotation: number
): PathShape => { ): PathShape => {
const normalizedPaths = parseSVG(vectorPath.data); const normalizedPaths = parseSVG(vectorPath.data);
return { return {
type: 'path', type: 'path',
name: 'svg-path', name: 'svg-path',
content: translateCommands(node, normalizedPaths, baseRotation), content: translateCommands(node, normalizedPaths),
fills: fills:
vectorPath.windingRule === 'NONE' ? [] : translateFills(vectorRegion?.fills ?? node.fills), vectorPath.windingRule === 'NONE' ? [] : translateFills(vectorRegion?.fills ?? node.fills),
svgAttrs: { svgAttrs: {

View file

@ -16,21 +16,18 @@ import { translateBoolType } from '@plugin/translators';
import { BoolShape } from '@ui/lib/types/shapes/boolShape'; import { BoolShape } from '@ui/lib/types/shapes/boolShape';
export const transformBooleanNode = async ( export const transformBooleanNode = async (node: BooleanOperationNode): Promise<BoolShape> => {
node: BooleanOperationNode,
baseRotation: number
): Promise<BoolShape> => {
return { return {
type: 'bool', type: 'bool',
name: node.name, name: node.name,
boolType: translateBoolType(node.booleanOperation), boolType: translateBoolType(node.booleanOperation),
...transformFigmaIds(node), ...transformFigmaIds(node),
...(await transformChildren(node, baseRotation)), ...(await transformChildren(node)),
...transformFills(node), ...transformFills(node),
...transformEffects(node), ...transformEffects(node),
...transformStrokes(node), ...transformStrokes(node),
...transformDimension(node), ...transformDimension(node),
...transformRotationAndPosition(node, baseRotation), ...transformRotationAndPosition(node),
...transformSceneNode(node), ...transformSceneNode(node),
...transformBlend(node), ...transformBlend(node),
...transformProportion(node), ...transformProportion(node),

View file

@ -18,10 +18,7 @@ import {
import { ComponentRoot } from '@ui/types'; import { ComponentRoot } from '@ui/types';
export const transformComponentNode = async ( export const transformComponentNode = async (node: ComponentNode): Promise<ComponentRoot> => {
node: ComponentNode,
baseRotation: number
): Promise<ComponentRoot> => {
componentsLibrary.register(node.id, { componentsLibrary.register(node.id, {
type: 'component', type: 'component',
name: node.name, name: node.name,
@ -36,9 +33,9 @@ export const transformComponentNode = async (
...transformProportion(node), ...transformProportion(node),
...transformLayoutAttributes(node, true), ...transformLayoutAttributes(node, true),
...transformCornerRadius(node), ...transformCornerRadius(node),
...(await transformChildren(node, node.rotation + baseRotation)), ...(await transformChildren(node)),
...transformDimension(node), ...transformDimension(node),
...transformRotationAndPosition(node, baseRotation), ...transformRotationAndPosition(node),
...transformConstraints(node), ...transformConstraints(node),
...transformAutoLayout(node) ...transformAutoLayout(node)
}); });

View file

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

View file

@ -24,18 +24,15 @@ const isSectionNode = (node: FrameNode | SectionNode | ComponentSetNode): node i
}; };
export const transformFrameNode = async ( export const transformFrameNode = async (
node: FrameNode | SectionNode | ComponentSetNode, node: FrameNode | SectionNode | ComponentSetNode
baseRotation: number
): Promise<FrameShape> => { ): Promise<FrameShape> => {
let frameSpecificAttributes: Partial<FrameShape> = {}; let frameSpecificAttributes: Partial<FrameShape> = {};
let referencePoint: Point = { x: node.absoluteTransform[0][2], y: node.absoluteTransform[1][2] }; let referencePoint: Point = { x: node.absoluteTransform[0][2], y: node.absoluteTransform[1][2] };
let rotation = baseRotation;
if (!isSectionNode(node)) { if (!isSectionNode(node)) {
const { x, y, ...transformAndRotation } = transformRotationAndPosition(node, baseRotation); const { x, y, ...transformAndRotation } = transformRotationAndPosition(node);
referencePoint = { x, y }; referencePoint = { x, y };
rotation += node.rotation;
// Figma API does not expose strokes, blend modes, corner radius, or constraint proportions for sections, // 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. // they plan to add it in the future. Refactor this when available.
@ -63,7 +60,7 @@ export const transformFrameNode = async (
...referencePoint, ...referencePoint,
...frameSpecificAttributes, ...frameSpecificAttributes,
...transformDimension(node), ...transformDimension(node),
...(await transformChildren(node, rotation)), ...(await transformChildren(node)),
...transformSceneNode(node), ...transformSceneNode(node),
...transformOverrides(node) ...transformOverrides(node)
}; };

View file

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

View file

@ -21,8 +21,7 @@ import {
import { ComponentInstance, ComponentTextPropertyOverride } from '@ui/types'; import { ComponentInstance, ComponentTextPropertyOverride } from '@ui/types';
export const transformInstanceNode = async ( export const transformInstanceNode = async (
node: InstanceNode, node: InstanceNode
baseRotation: number
): Promise<ComponentInstance | undefined> => { ): Promise<ComponentInstance | undefined> => {
const mainComponent = await node.getMainComponentAsync(); const mainComponent = await node.getMainComponentAsync();
if (mainComponent === null) { if (mainComponent === null) {
@ -62,10 +61,10 @@ export const transformInstanceNode = async (
...transformLayoutAttributes(node, true), ...transformLayoutAttributes(node, true),
...transformCornerRadius(node), ...transformCornerRadius(node),
...transformDimension(node), ...transformDimension(node),
...transformRotationAndPosition(node, baseRotation), ...transformRotationAndPosition(node),
...transformConstraints(node), ...transformConstraints(node),
...transformAutoLayout(node), ...transformAutoLayout(node),
...(await transformChildren(node, node.rotation + baseRotation)), ...(await transformChildren(node)),
...transformOverrides(node) ...transformOverrides(node)
}; };
}; };

View file

@ -20,11 +20,11 @@ import { Segment } 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. * 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, baseRotation: number): PathShape => { export const transformLineNode = (node: LineNode): PathShape => {
return { return {
type: 'path', type: 'path',
name: node.name, name: node.name,
content: translateLineNode(node, baseRotation), content: translateLineNode(node),
...transformFigmaIds(node), ...transformFigmaIds(node),
...transformStrokes(node), ...transformStrokes(node),
...transformEffects(node), ...transformEffects(node),
@ -37,23 +37,19 @@ export const transformLineNode = (node: LineNode, baseRotation: number): PathSha
}; };
}; };
const translateLineNode = (node: LineNode, baseRotation: number): Segment[] => { const translateLineNode = (node: LineNode): Segment[] => {
return translateCommands( return translateCommands(node, [
node, {
[ x: 0,
{ y: 0,
x: 0, command: 'moveto',
y: 0, code: 'M'
command: 'moveto', },
code: 'M' {
}, x: node.width,
{ y: 0,
x: node.width, command: 'lineto',
y: 0, code: 'L'
command: 'lineto', }
code: 'L' ]);
}
],
baseRotation
);
}; };

View file

@ -17,14 +17,11 @@ import { translateCommands } from '@plugin/translators/vectors';
import { PathShape, Segment } from '@ui/lib/types/shapes/pathShape'; import { PathShape, Segment } from '@ui/lib/types/shapes/pathShape';
export const transformPathNode = ( export const transformPathNode = (node: StarNode | PolygonNode): PathShape => {
node: StarNode | PolygonNode,
baseRotation: number
): PathShape => {
return { return {
type: 'path', type: 'path',
name: node.name, name: node.name,
content: translatePathNode(node, baseRotation), content: translatePathNode(node),
...transformFigmaIds(node), ...transformFigmaIds(node),
...transformFills(node), ...transformFills(node),
...transformStrokes(node), ...transformStrokes(node),
@ -32,12 +29,12 @@ export const transformPathNode = (
...transformSceneNode(node), ...transformSceneNode(node),
...transformBlend(node), ...transformBlend(node),
...transformProportion(node), ...transformProportion(node),
...transformRotation(node, baseRotation), ...transformRotation(node),
...transformLayoutAttributes(node), ...transformLayoutAttributes(node),
...transformConstraints(node), ...transformConstraints(node),
...transformOverrides(node) ...transformOverrides(node)
}; };
}; };
const translatePathNode = (node: StarNode | PolygonNode, baseRotation: number): Segment[] => const translatePathNode = (node: StarNode | PolygonNode): Segment[] =>
translateCommands(node, parseSVG(node.fillGeometry[0].data), baseRotation); translateCommands(node, parseSVG(node.fillGeometry[0].data));

View file

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

View file

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

View file

@ -15,14 +15,14 @@ import {
import { TextShape } from '@ui/lib/types/shapes/textShape'; import { TextShape } from '@ui/lib/types/shapes/textShape';
export const transformTextNode = (node: TextNode, baseRotation: number): TextShape => { export const transformTextNode = (node: TextNode): TextShape => {
return { return {
type: 'text', type: 'text',
name: node.name, name: node.name,
...transformFigmaIds(node), ...transformFigmaIds(node),
...transformText(node), ...transformText(node),
...transformDimension(node), ...transformDimension(node),
...transformRotationAndPosition(node, baseRotation), ...transformRotationAndPosition(node),
...transformEffects(node), ...transformEffects(node),
...transformSceneNode(node), ...transformSceneNode(node),
...transformBlend(node), ...transformBlend(node),

View file

@ -16,11 +16,8 @@ import { transformGroupNodeLike } from '.';
* If there are no regions on the vector network, we treat it like a normal `PathShape`. * If there are no regions on the vector network, we treat it like a normal `PathShape`.
* If there are regions, we treat the vector node as a `GroupShape` with multiple `PathShape` children. * If there are regions, we treat the vector node as a `GroupShape` with multiple `PathShape` children.
*/ */
export const transformVectorNode = ( export const transformVectorNode = (node: VectorNode): GroupShape | PathShape => {
node: VectorNode, const children = transformVectorPaths(node);
baseRotation: number
): GroupShape | PathShape => {
const children = transformVectorPaths(node, baseRotation);
if (children.length === 1) { if (children.length === 1) {
return { return {
@ -33,7 +30,7 @@ export const transformVectorNode = (
} }
return { return {
...transformGroupNodeLike(node, baseRotation), ...transformGroupNodeLike(node),
...transformFigmaIds(node), ...transformFigmaIds(node),
...transformConstraints(node), ...transformConstraints(node),
...transformOverrides(node), ...transformOverrides(node),

View file

@ -16,13 +16,12 @@ import { PenpotNode } from '@ui/types';
*/ */
export const translateMaskChildren = async ( export const translateMaskChildren = async (
children: readonly SceneNode[], children: readonly SceneNode[],
maskIndex: number, maskIndex: number
baseRotation: number
): Promise<PenpotNode[]> => { ): Promise<PenpotNode[]> => {
const maskChild = children[maskIndex]; const maskChild = children[maskIndex];
const unmaskedChildren = await translateChildren(children.slice(0, maskIndex), baseRotation); const unmaskedChildren = await translateChildren(children.slice(0, maskIndex));
const maskedChildren = await translateChildren(children.slice(maskIndex), baseRotation); const maskedChildren = await translateChildren(children.slice(maskIndex));
if ( if (
maskChild.type === 'STICKY' || maskChild.type === 'STICKY' ||
@ -41,7 +40,7 @@ export const translateMaskChildren = async (
const maskGroup = { const maskGroup = {
...transformMaskFigmaIds(maskChild), ...transformMaskFigmaIds(maskChild),
...transformGroupNodeLike(maskChild, baseRotation), ...transformGroupNodeLike(maskChild),
children: maskedChildren, children: maskedChildren,
maskedGroup: true maskedGroup: true
}; };
@ -49,14 +48,11 @@ export const translateMaskChildren = async (
return [...unmaskedChildren, maskGroup]; return [...unmaskedChildren, maskGroup];
}; };
export const translateChildren = async ( export const translateChildren = async (children: readonly SceneNode[]): Promise<PenpotNode[]> => {
children: readonly SceneNode[],
baseRotation: number = 0
): Promise<PenpotNode[]> => {
const transformedChildren: PenpotNode[] = []; const transformedChildren: PenpotNode[] = [];
for (const child of children) { for (const child of children) {
const penpotNode = await transformSceneNode(child, baseRotation); const penpotNode = await transformSceneNode(child);
if (penpotNode) transformedChildren.push(penpotNode); if (penpotNode) transformedChildren.push(penpotNode);

View file

@ -3,25 +3,27 @@ import { ShapeBaseAttributes } from '@ui/lib/types/shapes/shape';
export const translateRotation = ( export const translateRotation = (
transform: Transform, transform: Transform,
rotation: number rotation: number
): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> => ({ ): Pick<ShapeBaseAttributes, 'transform' | 'transformInverse' | 'rotation'> => {
rotation: -rotation < 0 ? -rotation + 360 : -rotation, return {
transform: { rotation,
a: transform[0][0], transform: {
b: transform[1][0], a: transform[0][0],
c: transform[0][1], b: transform[1][0],
d: transform[1][1], c: transform[0][1],
e: 0, d: transform[1][1],
f: 0 e: 0,
}, f: 0
transformInverse: { },
a: transform[0][0], transformInverse: {
b: transform[0][1], a: transform[0][0],
c: transform[1][0], b: transform[0][1],
d: transform[1][1], c: transform[1][0],
e: 0, d: transform[1][1],
f: 0 e: 0,
} f: 0
}); }
};
};
export const translateZeroRotation = (): Pick< export const translateZeroRotation = (): Pick<
ShapeBaseAttributes, ShapeBaseAttributes,

View file

@ -1,12 +1,14 @@
import { Command } from 'svg-path-parser'; import { Command } from 'svg-path-parser';
import { hasRotation } from '@plugin/utils'; import { getRotation, hasRotation } from '@plugin/utils';
import { translateNonRotatedCommands } from '.'; import { translateNonRotatedCommands } from '.';
import { translateRotatedCommands } from './translateRotatedCommands'; import { translateRotatedCommands } from './translateRotatedCommands';
export const translateCommands = (node: LayoutMixin, commands: Command[], baseRotation: number) => { export const translateCommands = (node: LayoutMixin, commands: Command[]) => {
if (hasRotation(node.rotation + baseRotation) && node.absoluteBoundingBox) { const rotation = getRotation(node.absoluteTransform);
if (hasRotation(rotation) && node.absoluteBoundingBox) {
return translateRotatedCommands(commands, node.absoluteTransform, node.absoluteBoundingBox); return translateRotatedCommands(commands, node.absoluteTransform, node.absoluteBoundingBox);
} }

View file

@ -58,7 +58,10 @@ export const applyInverseRotation = (
boundingBox: Rect boundingBox: Rect
): Point => applyRotation(point, inverseMatrix(transform), boundingBox); ): Point => applyRotation(point, inverseMatrix(transform), boundingBox);
export const hasRotation = (rotation: number): boolean => Math.abs(rotation) > ROTATION_TOLERANCE; export const getRotation = (transform: Transform): number =>
Math.acos(transform[0][0]) * (180 / Math.PI);
export const hasRotation = (rotation: number): boolean => rotation > ROTATION_TOLERANCE;
const inverseMatrix = (matrix: Transform): Transform => [ const inverseMatrix = (matrix: Transform): Transform => [
[matrix[0][0], matrix[1][0], matrix[0][2]], [matrix[0][0], matrix[1][0], matrix[0][2]],