Skip to content

Commit

Permalink
Merge branch 'main' into update-sdk-to-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
roppazvan authored Dec 16, 2024
2 parents 5b45ab4 + 41f7e34 commit 5d5fab9
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 64 deletions.
5 changes: 5 additions & 0 deletions .changeset/clever-turtles-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tokens-studio/figma-plugin": patch
---

Fix for linear gradient start/end points being outside the node bounding box when using angles that aren't divisible by 45.
5 changes: 0 additions & 5 deletions .changeset/seven-keys-tease.md

This file was deleted.

6 changes: 6 additions & 0 deletions packages/tokens-studio-for-figma/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @tokens-studio/figma-plugin

## 2.2.3

### Patch Changes

- 01ccff2a: Fixes an issue when updating a token's value from a reference to a hard value, the check we introduced in the last release caused those to not be updated (and only worked when changing to another reference).

## 2.2.2

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/tokens-studio-for-figma/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tokens-studio/figma-plugin",
"version": "2.2.2",
"version": "2.2.3",
"description": "Tokens Studio plugin for Figma",
"license": "MIT",
"private": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ describe('convertStringtoFigmaGradient', () => {
},
],
gradientTransform: [
[0.5000000000000001, -0.5, 0.49999999999999994],
[0.5, 0.5000000000000001, -5.551115123125784e-17],
[0.5, -0.5, 0.5],
[0.5, 0.5, 0],
],
},
};
Expand Down Expand Up @@ -64,8 +64,8 @@ describe('convertStringtoFigmaGradient', () => {
},
],
gradientTransform: [
[0.5000000000000001, -0.5, 0.49999999999999994],
[0.5, 0.5000000000000001, -5.551115123125784e-17],
[0.5, -0.5, 0.5],
[0.5, 0.5, 0],
],
},
};
Expand Down Expand Up @@ -103,8 +103,8 @@ describe('convertStringtoFigmaGradient', () => {
},
],
gradientTransform: [
[0.5000000000000001, -0.5, 0.49999999999999994],
[0.5, 0.5000000000000001, -5.551115123125784e-17],
[0.5, -0.5, 0.5],
[0.5, 0.5, 0],
],
},
};
Expand All @@ -118,25 +118,25 @@ describe('convertStringtoFigmaGradient', () => {
r: 0,
g: 0,
b: 0,
a: 1,
a: 1
},
position: 0,
position: 0
},
{
color: {
r: 1,
g: 1,
b: 1,
a: 1,
a: 1
},
position: 1,
},
position: 1
}
],
gradientTransform: [
[6.123233995736766e-17, 1, -6.123233995736766e-17],
[-1, 6.123233995736766e-17, 1],
[0, 1, 0],
[-1, 0, 1],
],
},
}
};

const test5 = {
Expand All @@ -148,22 +148,22 @@ describe('convertStringtoFigmaGradient', () => {
r: 0.9019607843137255,
g: 0.39215686274509803,
b: 0.396078431372549,
a: 1,
a: 1
},
position: 0,
position: 0
},
{
color: {
r: 0.5686274509803921,
g: 0.596078431372549,
b: 0.8980392156862745,
a: 1,
a: 1
},
position: 1,
},
position: 1
}
],
gradientTransform: [[1, 0, 0], [0, 1, 0]],
},
gradientTransform: [[1, 0, 0], [0, 1, 0]]
}
};

const test6 = {
Expand All @@ -175,33 +175,64 @@ describe('convertStringtoFigmaGradient', () => {
r: 0.9019607843137255,
g: 0.39215686274509803,
b: 0.396078431372549,
a: 1,
a: 1
},
position: 0,
position: 0
},
{
color: {
r: 0.5686274509803921,
g: 0.596078431372549,
b: 0.8980392156862745,
a: 1,
a: 1
},
position: 1,
},
position: 1
}
],
gradientTransform: [
[6.123233995736766e-17, 1, -6.123233995736766e-17],
[-1, 6.123233995736766e-17, 1],
[0, 1, 0],
[-1, 0, 1],
],
},
};

const test7 = {
input: 'linear-gradient(106.84deg, #FF0000 5.61%, #cc00ff00 89.41%)',
output: {
gradientStops: [
{
color: {
r: 1,
g: 0,
b: 0,
a: 1,
},
position: 0.056100000000000004,
},
{
color: {
r: 0.8,
g: 0,
b: 1,
a: 0,
},
position: 0.8941,
},
],
gradientTransform: [
[0.9160738743, 0.2772769934, -0.0966754339],
[-0.2772769934, 0.9160738743, 0.1806015595],
],
}
}

expect(convertStringToFigmaGradient(test1.input)).toEqual(test1.output);
expect(convertStringToFigmaGradient(test2.input)).toEqual(test2.output);
expect(convertStringToFigmaGradient(test3.input)).toEqual(test3.output);
expect(convertStringToFigmaGradient(test4.input)).toEqual(test4.output);
expect(convertStringToFigmaGradient(test5.input)).toEqual(test5.output);
expect(convertStringToFigmaGradient(test6.input)).toEqual(test6.output);
expect(convertStringToFigmaGradient(test7.input)).toEqual(test7.output);
});

describe('convertFigmaGradientToString', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { figmaRGBToHex, extractLinearGradientParamsFromTransform } from '@figma-plugin/helpers';
import { Matrix, inverse } from 'ml-matrix';
import { Matrix } from 'ml-matrix';
import { convertToFigmaColor } from './colors';

export function convertDegreeToNumber(degreeString: string): number {
Expand All @@ -17,6 +17,12 @@ export function convertFigmaGradientToString(paint: GradientPaint) {
return `linear-gradient(${angleInDeg + 90}deg, ${gradientStopsString})`;
}

const roundToPrecision = (value, precision = 10) => {
const roundToPrecisionVal = 10 ** precision;
return Math.round((value + Number.EPSILON) * roundToPrecisionVal) / roundToPrecisionVal;
};

// if node type check is needed due to bugs caused by obscure node types, use (value: string/*, node?: BaseNode | PaintStyle) and convertStringToFigmaGradient(value, target)
export function convertStringToFigmaGradient(value: string) {
const parts = value.substring(value.indexOf('(') + 1, value.lastIndexOf(')')).split(', ').map((s) => s.trim());

Expand Down Expand Up @@ -63,39 +69,41 @@ export function convertStringToFigmaGradient(value: string) {

const degrees = -(angle - 90);
const rad = degrees * (Math.PI / 180);
const scale = angle % 90 === 0 ? 1 : Math.sqrt(1 + Math.tan(angle * (Math.PI / 180)) ** 2);

// start by transforming to the gradient center
let normalizedAngleRad = Math.abs(rad) % (Math.PI / 2);
if (normalizedAngleRad > Math.PI / 4) {
// adjust angle after 45 degrees to scale down correctly towards 90 degrees
normalizedAngleRad = Math.PI / 2 - normalizedAngleRad;
}

const sin = Math.sin(rad);
const cos = Math.cos(rad);

let scale = 1;

const normalisedCos = Math.cos(normalizedAngleRad);
scale = normalisedCos;
// Implement fallback if bugs are caused by obscure node types. This appears to be unnecessary
// if (!['RECTANGLE', 'FRAME', 'VECTOR'].includes(node?.type || '')) {
// // Old scale computation:
// scale = angle % 90 === 0 ? 1 : Math.sqrt(1 + Math.tan(angle * (Math.PI / 180)) ** 2);
// }

const scaledCos = cos * scale;
const scaledSin = sin * scale;

// start by transforming to the gradient center, to keep the gradient centered after scaling
// which for figma is .5 .5 as it is a relative transform
const tx = 0.5 - 0.5 * scaledCos + 0.5 * scaledSin;
const ty = 0.5 - 0.5 * scaledSin - 0.5 * scaledCos;

const transformationMatrix = new Matrix([
[1, 0, 0.5],
[0, 1, 0.5],
[roundToPrecision(scaledCos), roundToPrecision(-scaledSin), roundToPrecision(tx)],
[roundToPrecision(scaledSin), roundToPrecision(scaledCos), roundToPrecision(ty)],
[0, 0, 1],
]).mmul(
// we can then multiply this with the rotation matrix
new Matrix([
[Math.cos(rad), Math.sin(rad), 0],
[-Math.sin(rad), Math.cos(rad), 0],
[0, 0, 1],
]),
).mmul(
// next we need to multiply it with a scale matrix to fill the entire shape
new Matrix([
[scale, 0, 0],
[0, scale, 0],
[0, 0, 1],
]),
).mmul(
// lastly we need to translate it back to the 0,0 origin
// by negating the center transform
new Matrix([
[1, 0, -0.5],
[0, 1, -0.5],
[0, 0, 1],
]),
);

const gradientTransformMatrix = inverse(transformationMatrix).to2DArray();
]);

const gradientTransformMatrix = transformationMatrix.to2DArray();

const gradientStops = parts.map((stop, i, arr) => {
const seperatedStop = stop.split(' ');
Expand Down

0 comments on commit 5d5fab9

Please sign in to comment.