2024-05-21 07:36:30 -05:00
|
|
|
import { parseSVG } from 'svg-path-parser';
|
|
|
|
|
2024-05-13 06:21:46 -05:00
|
|
|
import {
|
|
|
|
transformBlend,
|
|
|
|
transformEffects,
|
2024-06-14 03:18:34 -05:00
|
|
|
transformLayoutAttributes,
|
2024-05-13 06:21:46 -05:00
|
|
|
transformProportion,
|
|
|
|
transformSceneNode,
|
2024-06-19 08:58:13 -05:00
|
|
|
transformStrokesFromVector,
|
|
|
|
transformVectorFills
|
2024-05-13 06:21:46 -05:00
|
|
|
} from '@plugin/transformers/partials';
|
2024-06-17 05:14:16 -05:00
|
|
|
import { translateCommands, translateWindingRule } from '@plugin/translators/vectors';
|
2024-04-17 03:53:38 -05:00
|
|
|
|
2024-06-14 03:33:23 -05:00
|
|
|
import { PathShape } from '@ui/lib/types/shapes/pathShape';
|
2024-05-13 06:21:46 -05:00
|
|
|
|
2024-06-19 01:10:20 -05:00
|
|
|
export const transformVectorPaths = (node: VectorNode): PathShape[] => {
|
2024-06-05 05:36:49 -05:00
|
|
|
const pathShapes = node.vectorPaths
|
|
|
|
.filter((vectorPath, index) => {
|
|
|
|
return (
|
|
|
|
nodeHasFills(node, vectorPath, (node.vectorNetwork.regions ?? [])[index]) ||
|
|
|
|
node.strokes.length > 0
|
|
|
|
);
|
|
|
|
})
|
|
|
|
.map((vectorPath, index) =>
|
2024-06-19 01:10:20 -05:00
|
|
|
transformVectorPath(node, vectorPath, (node.vectorNetwork.regions ?? [])[index])
|
2024-06-05 05:36:49 -05:00
|
|
|
);
|
2024-05-21 07:36:30 -05:00
|
|
|
|
2024-06-05 05:36:49 -05:00
|
|
|
const geometryShapes = node.fillGeometry
|
|
|
|
.filter(
|
|
|
|
geometry =>
|
|
|
|
!node.vectorPaths.find(
|
|
|
|
vectorPath => normalizePath(vectorPath.data) === normalizePath(geometry.data)
|
|
|
|
)
|
|
|
|
)
|
2024-06-19 01:10:20 -05:00
|
|
|
.map(geometry => transformVectorPath(node, geometry, undefined));
|
2024-05-21 07:36:30 -05:00
|
|
|
|
|
|
|
return [...geometryShapes, ...pathShapes];
|
|
|
|
};
|
|
|
|
|
|
|
|
const normalizePath = (path: string): string => {
|
|
|
|
// Round to 2 decimal places all numbers
|
|
|
|
const str = path.replace(/(\d+\.\d+|\d+)/g, (match: string) => {
|
|
|
|
return parseFloat(match).toFixed(2);
|
|
|
|
});
|
2024-06-14 03:33:23 -05:00
|
|
|
|
2024-05-21 07:36:30 -05:00
|
|
|
// remove spaces
|
|
|
|
return str.replace(/\s/g, '');
|
|
|
|
};
|
|
|
|
|
|
|
|
const nodeHasFills = (
|
|
|
|
node: VectorNode,
|
|
|
|
vectorPath: VectorPath,
|
|
|
|
vectorRegion: VectorRegion | undefined
|
|
|
|
): boolean => {
|
|
|
|
return !!(vectorPath.windingRule !== 'NONE' && (vectorRegion?.fills || node.fills));
|
2024-05-13 06:21:46 -05:00
|
|
|
};
|
|
|
|
|
2024-06-05 05:36:49 -05:00
|
|
|
const transformVectorPath = (
|
2024-05-13 06:21:46 -05:00
|
|
|
node: VectorNode,
|
|
|
|
vectorPath: VectorPath,
|
2024-06-19 01:10:20 -05:00
|
|
|
vectorRegion: VectorRegion | undefined
|
2024-06-05 05:36:49 -05:00
|
|
|
): PathShape => {
|
2024-05-21 07:36:30 -05:00
|
|
|
const normalizedPaths = parseSVG(vectorPath.data);
|
|
|
|
|
2024-05-13 06:21:46 -05:00
|
|
|
return {
|
|
|
|
type: 'path',
|
|
|
|
name: 'svg-path',
|
2024-06-19 01:10:20 -05:00
|
|
|
content: translateCommands(node, normalizedPaths),
|
2024-05-21 07:36:30 -05:00
|
|
|
svgAttrs: {
|
|
|
|
fillRule: translateWindingRule(vectorPath.windingRule)
|
|
|
|
},
|
2024-06-06 05:17:17 -05:00
|
|
|
constraintsH: 'scale',
|
|
|
|
constraintsV: 'scale',
|
2024-06-19 08:58:13 -05:00
|
|
|
...transformVectorFills(node, vectorPath, vectorRegion),
|
2024-06-05 05:36:49 -05:00
|
|
|
...transformStrokesFromVector(node, normalizedPaths, vectorRegion),
|
2024-05-13 06:21:46 -05:00
|
|
|
...transformEffects(node),
|
|
|
|
...transformSceneNode(node),
|
|
|
|
...transformBlend(node),
|
2024-06-14 03:18:34 -05:00
|
|
|
...transformProportion(node),
|
|
|
|
...transformLayoutAttributes(node)
|
2024-05-13 06:21:46 -05:00
|
|
|
};
|
|
|
|
};
|