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

Fills Refactor (#109)

* refactor

* changeset

* fixes
This commit is contained in:
Alex Sánchez 2024-05-13 17:04:13 +02:00 committed by GitHub
parent 23e97fb3d7
commit 3118d36f0a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 153 additions and 133 deletions

View file

@ -1,4 +1,4 @@
import { translateFills } from '@plugin/translators';
import { translateFills } from '@plugin/translators/fills';
import { ShapeAttributes } from '@ui/lib/types/shapes/shape';

View file

@ -7,7 +7,7 @@ import {
transformStrokes
} from '@plugin/transformers/partials';
import { createLineGeometry, translateVectorPath, translateVectorPaths } from '@plugin/translators';
import { translateFills } from '@plugin/translators';
import { translateFills } from '@plugin/translators/fills';
import { PathAttributes } from '@ui/lib/types/shapes/pathShape';
import { PathShape } from '@ui/lib/types/shapes/pathShape';

View file

@ -1,5 +1,5 @@
import { transformChildren } from '@plugin/transformers/partials';
import { translatePageFill } from '@plugin/translators';
import { translatePageFill } from '@plugin/translators/fills';
import { PenpotPage } from '@ui/lib/types/penpotPage';

View file

@ -0,0 +1,2 @@
export * from './translateGradientLinearFill';
export * from './translateGradientRadialFill';

View file

@ -0,0 +1,24 @@
import { calculateLinearGradient, rgbToHex } from '@plugin/utils';
import { Fill } from '@ui/lib/types/utils/fill';
export const translateGradientLinearFill = (fill: GradientPaint): Fill => {
const points = calculateLinearGradient(fill.gradientTransform);
return {
fillColorGradient: {
type: 'linear',
startX: points.start[0],
startY: points.start[1],
endX: points.end[0],
endY: points.end[1],
width: 1,
stops: fill.gradientStops.map(stop => ({
color: rgbToHex(stop.color),
offset: stop.position,
opacity: stop.color.a * (fill.opacity ?? 1)
}))
},
fillOpacity: !fill.visible ? 0 : fill.opacity
};
};

View file

@ -0,0 +1,24 @@
import { calculateRadialGradient, rgbToHex } from '@plugin/utils';
import { Fill } from '@ui/lib/types/utils/fill';
export const translateGradientRadialFill = (fill: GradientPaint): Fill => {
const points = calculateRadialGradient(fill.gradientTransform);
return {
fillColorGradient: {
type: 'radial',
startX: points.start[0],
startY: points.start[1],
endX: points.end[0],
endY: points.end[1],
width: 1,
stops: fill.gradientStops.map(stop => ({
color: rgbToHex(stop.color),
offset: stop.position,
opacity: stop.color.a * (fill.opacity ?? 1)
}))
},
fillOpacity: !fill.visible ? 0 : fill.opacity
};
};

View file

@ -0,0 +1,3 @@
export * from './translateFills';
export * from './translateImageFill';
export * from './translateSolidFill';

View file

@ -0,0 +1,49 @@
import { translateImageFill, translateSolidFill } from '@plugin/translators/fills';
import {
translateGradientLinearFill,
translateGradientRadialFill
} from '@plugin/translators/fills/gradients';
import { rgbToHex } from '@plugin/utils';
import { Fill } from '@ui/lib/types/utils/fill';
export const translateFill = async (fill: Paint): Promise<Fill | undefined> => {
switch (fill.type) {
case 'SOLID':
return translateSolidFill(fill);
case 'GRADIENT_LINEAR':
return translateGradientLinearFill(fill);
case 'GRADIENT_RADIAL':
return translateGradientRadialFill(fill);
case 'IMAGE':
return await translateImageFill(fill);
}
console.error(`Unsupported fill type: ${fill.type}`);
};
export const translateFills = async (
fills: readonly Paint[] | typeof figma.mixed
): Promise<Fill[]> => {
const figmaFills = fills === figma.mixed ? [] : fills;
const penpotFills: Fill[] = [];
for (const fill of figmaFills) {
const penpotFill = await translateFill(fill);
if (penpotFill) {
// fills are applied in reverse order in Figma, that's why we unshift
penpotFills.unshift(penpotFill);
}
}
return penpotFills;
};
export const translatePageFill = (fill: Paint): string | undefined => {
switch (fill.type) {
case 'SOLID':
return rgbToHex(fill.color);
}
console.error(`Unsupported page fill type: ${fill.type}`);
};

View file

@ -0,0 +1,36 @@
import { detectMimeType } from '@plugin/utils';
import { Fill } from '@ui/lib/types/utils/fill';
import { ImageColor } from '@ui/lib/types/utils/imageColor';
export const translateImageFill = async (fill: ImagePaint): Promise<Fill | undefined> => {
const fillImage = await translateImage(fill.imageHash);
if (!fillImage) return;
return {
fillOpacity: !fill.visible ? 0 : fill.opacity,
fillImage: fillImage
};
};
const translateImage = async (imageHash: string | null): Promise<ImageColor | undefined> => {
if (!imageHash) return;
const image = figma.getImageByHash(imageHash);
if (!image) return;
const bytes = await image.getBytesAsync();
const size = await image.getSizeAsync();
const b64 = figma.base64Encode(bytes);
const mimeType = detectMimeType(b64);
const dataUri = `data:${mimeType};base64,${b64}`;
return {
width: size.width,
height: size.height,
mtype: mimeType,
keepAspectRatio: true,
dataUri: dataUri,
id: '00000000-0000-0000-0000-000000000000'
};
};

View file

@ -0,0 +1,10 @@
import { rgbToHex } from '@plugin/utils';
import { Fill } from '@ui/lib/types/utils/fill';
export const translateSolidFill = (fill: SolidPaint): Fill => {
return {
fillColor: rgbToHex(fill.color),
fillOpacity: !fill.visible ? 0 : fill.opacity
};
};

View file

@ -1,6 +1,5 @@
export * from './translateBlendMode';
export * from './translateBlurEffects';
export * from './translateFills';
export * from './translateShadowEffects';
export * from './translateStrokes';
export * from './translateVectorPaths';

View file

@ -1,4 +1,4 @@
import { translateFills } from '@plugin/translators';
import { translateFills } from '@plugin/translators/fills';
import { translateFontId } from '@plugin/translators/text/font';
import { StyleTextSegment, translateParagraphProperties } from '@plugin/translators/text/paragraph';
import {

View file

@ -1,127 +0,0 @@
import { calculateRadialGradient, detectMimeType, rgbToHex } from '@plugin/utils';
import { calculateLinearGradient } from '@plugin/utils/calculateLinearGradient';
import { Fill } from '@ui/lib/types/utils/fill';
import { ImageColor } from '@ui/lib/types/utils/imageColor';
export const translateFill = async (fill: Paint): Promise<Fill | undefined> => {
switch (fill.type) {
case 'SOLID':
return translateSolidFill(fill);
case 'GRADIENT_LINEAR':
return translateGradientLinearFill(fill);
case 'GRADIENT_RADIAL':
return translateGradientRadialFill(fill);
case 'IMAGE':
return await translateImageFill(fill);
}
console.error(`Unsupported fill type: ${fill.type}`);
};
export const translateFills = async (
fills: readonly Paint[] | typeof figma.mixed
): Promise<Fill[]> => {
const figmaFills = fills === figma.mixed ? [] : fills;
const penpotFills: Fill[] = [];
for (const fill of figmaFills) {
const penpotFill = await translateFill(fill);
if (penpotFill) {
// fills are applied in reverse order in Figma, that's why we unshift
penpotFills.unshift(penpotFill);
}
}
return penpotFills;
};
export const translatePageFill = (fill: Paint): string | undefined => {
switch (fill.type) {
case 'SOLID':
return rgbToHex(fill.color);
}
console.error(`Unsupported page fill type: ${fill.type}`);
};
const translateImage = async (imageHash: string | null): Promise<ImageColor | undefined> => {
if (!imageHash) return;
const image = figma.getImageByHash(imageHash);
if (!image) return;
const bytes = await image.getBytesAsync();
const size = await image.getSizeAsync();
const b64 = figma.base64Encode(bytes);
const mimeType = detectMimeType(b64);
const dataUri = `data:${mimeType};base64,${b64}`;
return {
width: size.width,
height: size.height,
mtype: mimeType,
keepAspectRatio: true,
dataUri: dataUri,
id: '00000000-0000-0000-0000-000000000000'
};
};
const translateImageFill = async (fill: ImagePaint): Promise<Fill | undefined> => {
const fillImage = await translateImage(fill.imageHash);
if (!fillImage) return;
return {
fillOpacity: !fill.visible ? 0 : fill.opacity,
fillImage: fillImage
};
};
const translateSolidFill = (fill: SolidPaint): Fill => {
return {
fillColor: rgbToHex(fill.color),
fillOpacity: !fill.visible ? 0 : fill.opacity
};
};
const translateGradientLinearFill = (fill: GradientPaint): Fill => {
const points = calculateLinearGradient(fill.gradientTransform);
return {
fillColorGradient: {
type: 'linear',
startX: points.start[0],
startY: points.start[1],
endX: points.end[0],
endY: points.end[1],
width: 1,
stops: fill.gradientStops.map(stop => ({
color: rgbToHex(stop.color),
offset: stop.position,
opacity: stop.color.a * (fill.opacity ?? 1)
}))
},
fillOpacity: !fill.visible ? 0 : fill.opacity
};
};
const translateGradientRadialFill = (fill: GradientPaint): Fill => {
const points = calculateRadialGradient(fill.gradientTransform);
return {
fillColorGradient: {
type: 'radial',
startX: points.start[0],
startY: points.start[1],
endX: points.end[0],
endY: points.end[1],
width: 1,
stops: fill.gradientStops.map(stop => ({
color: rgbToHex(stop.color),
offset: stop.position,
opacity: stop.color.a * (fill.opacity ?? 1)
}))
},
fillOpacity: !fill.visible ? 0 : fill.opacity
};
};

View file

@ -1,4 +1,4 @@
import { translateFill } from '@plugin/translators/translateFills';
import { translateFill } from '@plugin/translators/fills';
import { Stroke, StrokeAlignment, StrokeCaps } from '@ui/lib/types/utils/stroke';