2024-05-13 10:04:13 -05:00
|
|
|
import { translateFill } from '@plugin/translators/fills';
|
2024-04-16 09:08:39 -05:00
|
|
|
|
2024-04-18 02:42:45 -05:00
|
|
|
import { Stroke, StrokeAlignment, StrokeCaps } from '@ui/lib/types/utils/stroke';
|
2024-04-16 09:08:39 -05:00
|
|
|
|
2024-05-09 09:59:27 -05:00
|
|
|
export const translateStrokes = async (
|
2024-05-21 07:36:30 -05:00
|
|
|
node: MinimalStrokesMixin | (MinimalStrokesMixin & IndividualStrokesMixin),
|
|
|
|
strokeCaps: (stroke: Stroke) => Stroke = stroke => stroke
|
2024-05-09 09:59:27 -05:00
|
|
|
): Promise<Stroke[]> => {
|
2024-05-21 07:36:30 -05:00
|
|
|
const sharedStrokeProperties: Partial<Stroke> = {
|
|
|
|
strokeWidth: translateStrokeWeight(node),
|
|
|
|
strokeAlignment: translateStrokeAlignment(node.strokeAlign),
|
|
|
|
strokeStyle: node.dashPattern.length ? 'dashed' : 'solid'
|
|
|
|
};
|
2024-04-17 03:53:38 -05:00
|
|
|
|
2024-05-21 07:36:30 -05:00
|
|
|
return await Promise.all(
|
|
|
|
node.strokes.map(
|
|
|
|
async (paint, index) =>
|
|
|
|
await translateStroke(paint, sharedStrokeProperties, strokeCaps, index === 0)
|
|
|
|
)
|
2024-05-09 09:59:27 -05:00
|
|
|
);
|
2024-04-16 09:08:39 -05:00
|
|
|
};
|
2024-04-17 03:53:38 -05:00
|
|
|
|
2024-05-21 07:36:30 -05:00
|
|
|
export const translateStroke = async (
|
|
|
|
paint: Paint,
|
|
|
|
sharedStrokeProperties: Partial<Stroke>,
|
|
|
|
strokeCaps: (stroke: Stroke) => Stroke,
|
|
|
|
firstStroke: boolean
|
|
|
|
): Promise<Stroke> => {
|
|
|
|
const fill = await translateFill(paint);
|
2024-04-18 02:42:45 -05:00
|
|
|
|
2024-05-21 07:36:30 -05:00
|
|
|
let stroke: Stroke = {
|
|
|
|
strokeColor: fill?.fillColor,
|
|
|
|
strokeOpacity: fill?.fillOpacity,
|
|
|
|
strokeImage: fill?.fillImage,
|
|
|
|
...sharedStrokeProperties
|
|
|
|
};
|
2024-04-18 02:42:45 -05:00
|
|
|
|
2024-05-21 07:36:30 -05:00
|
|
|
if (firstStroke) {
|
|
|
|
stroke = strokeCaps(stroke);
|
2024-04-18 02:42:45 -05:00
|
|
|
}
|
2024-05-21 07:36:30 -05:00
|
|
|
|
|
|
|
return stroke;
|
2024-04-18 02:42:45 -05:00
|
|
|
};
|
|
|
|
|
2024-05-21 07:36:30 -05:00
|
|
|
export const translateStrokeCap = (vertex: VectorVertex): StrokeCaps | undefined => {
|
2024-04-17 03:53:38 -05:00
|
|
|
switch (vertex.strokeCap as StrokeCap | ConnectorStrokeCap) {
|
|
|
|
case 'ROUND':
|
|
|
|
return 'round';
|
|
|
|
case 'ARROW_EQUILATERAL':
|
|
|
|
case 'TRIANGLE_FILLED':
|
|
|
|
return 'triangle-arrow';
|
|
|
|
case 'SQUARE':
|
|
|
|
return 'square';
|
|
|
|
case 'CIRCLE_FILLED':
|
|
|
|
return 'circle-marker';
|
|
|
|
case 'DIAMOND_FILLED':
|
|
|
|
return 'diamond-marker';
|
|
|
|
case 'ARROW_LINES':
|
|
|
|
return 'line-arrow';
|
2024-04-24 09:29:24 -05:00
|
|
|
case 'NONE':
|
|
|
|
default:
|
|
|
|
return;
|
2024-04-17 03:53:38 -05:00
|
|
|
}
|
|
|
|
};
|
2024-05-21 07:36:30 -05:00
|
|
|
|
|
|
|
const translateStrokeWeight = (
|
|
|
|
node: MinimalStrokesMixin | (MinimalStrokesMixin & IndividualStrokesMixin)
|
|
|
|
): number => {
|
|
|
|
if (node.strokeWeight !== figma.mixed) {
|
|
|
|
return node.strokeWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isIndividualStrokes(node)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Math.max(
|
|
|
|
node.strokeTopWeight,
|
|
|
|
node.strokeRightWeight,
|
|
|
|
node.strokeBottomWeight,
|
|
|
|
node.strokeLeftWeight
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const isIndividualStrokes = (
|
|
|
|
node: MinimalStrokesMixin | IndividualStrokesMixin
|
|
|
|
): node is IndividualStrokesMixin => {
|
|
|
|
return 'strokeTopWeight' in node;
|
|
|
|
};
|
|
|
|
|
|
|
|
const translateStrokeAlignment = (
|
|
|
|
strokeAlign: 'CENTER' | 'INSIDE' | 'OUTSIDE'
|
|
|
|
): StrokeAlignment => {
|
|
|
|
switch (strokeAlign) {
|
|
|
|
case 'CENTER':
|
|
|
|
return 'center';
|
|
|
|
case 'INSIDE':
|
|
|
|
return 'inner';
|
|
|
|
case 'OUTSIDE':
|
|
|
|
return 'outer';
|
|
|
|
}
|
|
|
|
};
|