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

custom gradient

This commit is contained in:
Alex Sánchez 2024-04-15 09:48:03 +02:00
parent 5c58d53e60
commit f1e6f76c4f
No known key found for this signature in database
GPG key ID: 68A95170EEB87E16
8 changed files with 135 additions and 33 deletions

18
package-lock.json generated
View file

@ -9,7 +9,6 @@
"version": "0.0.1",
"license": "MPL2.0",
"dependencies": {
"@figma-plugin/helpers": "^0.15",
"react": "^18.2",
"react-dom": "^18.2",
"slugify": "^1.6"
@ -1164,15 +1163,6 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@figma-plugin/helpers": {
"version": "0.15.2",
"resolved": "https://registry.npmjs.org/@figma-plugin/helpers/-/helpers-0.15.2.tgz",
"integrity": "sha512-ggFxoefZKc0D/HJXFHqliLWCLQG3QTbByHqgiSpTK0D76qTDv2fpcF9bytjSMVnc4flD7Rq17tLNP/WmaJt3dA==",
"dependencies": {
"lodash": "^4.17.15",
"matrix-inverse": "^1.0.1"
}
},
"node_modules/@figma/eslint-plugin-figma-plugins": {
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/@figma/eslint-plugin-figma-plugins/-/eslint-plugin-figma-plugins-0.15.0.tgz",
@ -5098,7 +5088,8 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/lodash.merge": {
"version": "4.6.2",
@ -5154,11 +5145,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/matrix-inverse": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/matrix-inverse/-/matrix-inverse-1.0.1.tgz",
"integrity": "sha512-ubaJ6vEJfpsRpOLYLJN3bCW3VbO2t0OtZIfausKiizsPNCvCXsWsLMR8jm4zmi8bSnodp3ht25iqdpSe0wIbxg=="
},
"node_modules/mdn-data": {
"version": "2.0.30",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",

View file

@ -24,7 +24,6 @@
"author": "Kaleidos",
"license": "MPL2.0",
"dependencies": {
"@figma-plugin/helpers": "^0.15",
"react": "^18.2",
"react-dom": "^18.2",
"slugify": "^1.6"

View file

@ -1,5 +1,5 @@
export * from './translateFills';
// export * from './translateGradientLinearFill';
export * from './translateGradientLinearFill';
export * from './translateSolidFill';
export * from './translateTextDecoration';
export * from './translateTextTransform';

View file

@ -3,17 +3,10 @@ import { Fill } from '@ui/lib/types/utils/fill';
// import { translateGradientLinearFill } from './translateGradientLinearFill';
import { translateSolidFill } from './translateSolidFill';
const translateFill = (
fill: Paint,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
width: number,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
height: number
): Fill | undefined => {
const translateFill = (fill: Paint /*, width: number, height: number*/): Fill | undefined => {
switch (fill.type) {
case 'SOLID':
return translateSolidFill(fill);
// @TODO: fix this
// case 'GRADIENT_LINEAR':
// return translateGradientLinearFill(fill, width, height);
}
@ -22,9 +15,9 @@ const translateFill = (
};
export const translateFills = (
fills: readonly Paint[] | typeof figma.mixed,
width: number,
height: number
fills: readonly Paint[] | typeof figma.mixed
// width: number,
// height: number
): Fill[] => {
// @TODO: think better variable name
// @TODO: make it work with figma.mixed
@ -33,7 +26,7 @@ export const translateFills = (
const penpotFills = [];
for (const fill of fills2) {
const penpotFill = translateFill(fill, width, height);
const penpotFill = translateFill(fill /*, width, height*/);
if (penpotFill) {
penpotFills.unshift(penpotFill);

View file

@ -1,6 +1,5 @@
import { extractLinearGradientParamsFromTransform } from '@figma-plugin/helpers';
import { rgbToHex } from '@plugin/utils';
import { calculateLinearGradient } from '@plugin/utils/calculateLinearGradient';
import { Fill } from '@ui/lib/types/utils/fill';
@ -9,7 +8,7 @@ export const translateGradientLinearFill = (
width: number,
height: number
): Fill => {
const points = extractLinearGradientParamsFromTransform(width, height, fill.gradientTransform);
const points = calculateLinearGradient(width, height, fill.gradientTransform);
return {
fillColorGradient: {

View file

@ -0,0 +1,6 @@
export const applyMatrixToPoint = (matrix: number[][], point: number[]) => {
return [
point[0] * matrix[0][0] + point[1] * matrix[0][1] + matrix[0][2],
point[0] * matrix[1][0] + point[1] * matrix[1][1] + matrix[1][2]
];
};

View file

@ -0,0 +1,23 @@
import { applyMatrixToPoint } from '@plugin/utils/applyMatrixToPoint';
import { matrixInvert } from '@plugin/utils/matrixInvert';
export const calculateLinearGradient = (shapeWidth: number, shapeHeight: number, t: Transform) => {
const transform = t.length === 2 ? [...t, [0, 0, 1]] : [...t];
const mxInv = matrixInvert(transform);
if (!mxInv) {
return {
start: [0, 0],
end: [0, 0]
};
}
const startEnd = [
[0, 0.5],
[1, 0.5]
].map(p => applyMatrixToPoint(mxInv, p));
return {
start: [startEnd[0][0] * shapeWidth, startEnd[0][1] * shapeHeight],
end: [startEnd[1][0] * shapeWidth, startEnd[1][1] * shapeHeight]
};
};

View file

@ -0,0 +1,96 @@
export const matrixInvert = (M: number[][]): number[][] | undefined => {
// if the matrix isn't square: exit (error)
if (M.length !== M[0].length) {
return;
}
// create the identity matrix (I), and a copy (C) of the original
const dim = M.length;
let i = 0,
ii = 0,
j = 0,
e = 0;
const I: number[][] = [],
C: number[][] = [];
for (i = 0; i < dim; i += 1) {
// Create the row
I[i] = [];
C[i] = [];
for (j = 0; j < dim; j += 1) {
// if we're on the diagonal, put a 1 (for identity)
if (i === j) {
I[i][j] = 1;
} else {
I[i][j] = 0;
}
// Also, make the copy of the original
C[i][j] = M[i][j];
}
}
// Perform elementary row operations
for (i = 0; i < dim; i += 1) {
// get the element e on the diagonal
e = C[i][i];
// if we have a 0 on the diagonal (we'll need to swap with a lower row)
if (e === 0) {
// look through every row below the i'th row
for (ii = i + 1; ii < dim; ii += 1) {
// if the ii'th row has a non-0 in the i'th col
if (C[ii][i] !== 0) {
// it would make the diagonal have a non-0 so swap it
for (j = 0; j < dim; j++) {
e = C[i][j]; // temp store i'th row
C[i][j] = C[ii][j]; // replace i'th row by ii'th
C[ii][j] = e; // replace ii'th by temp
e = I[i][j]; // temp store i'th row
I[i][j] = I[ii][j]; // replace i'th row by ii'th
I[ii][j] = e; // replace ii'th by temp
}
// don't bother checking other rows since we've swapped
break;
}
}
// get the new diagonal
e = C[i][i];
// if it's still 0, not invertable (error)
if (e === 0) {
return;
}
}
// Scale this row down by e (so we have a 1 on the diagonal)
for (j = 0; j < dim; j++) {
C[i][j] = C[i][j] / e; // apply to original matrix
I[i][j] = I[i][j] / e; // apply to identity
}
// Subtract this row (scaled appropriately for each row) from ALL of
// the other rows so that there will be 0's in this column in the
// rows above and below this one
for (ii = 0; ii < dim; ii++) {
// Only apply to other rows (we want a 1 on the diagonal)
if (ii === i) {
continue;
}
// We want to change this element to 0
e = C[ii][i];
// Subtract (the row above(or below) scaled by e) from (the
// current row) but start at the i'th column and assume all the
// stuff left of diagonal is 0 (which it should be if we made this
// algorithm correctly)
for (j = 0; j < dim; j++) {
C[ii][j] -= e * C[i][j]; // apply to original matrix
I[ii][j] -= e * I[i][j]; // apply to identity
}
}
}
// we've done all operations, C should be the identity
// matrix I should be the inverse:
return I;
};