fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
77 lines (71 loc) • 2.29 kB
text/typescript
import { isPercent } from '../../parser/percent';
import type { TSize } from '../../typedefs';
import type { GradientCoords, GradientType, GradientUnits } from '../typedefs';
import { parseGradientUnits, parseType } from './misc';
function convertPercentUnitsToValues<
T extends GradientType,
K extends keyof GradientCoords<T>,
>(
valuesToConvert: Record<K, string | number>,
{ width, height, gradientUnits }: TSize & { gradientUnits: GradientUnits },
) {
let finalValue;
return (Object.keys(valuesToConvert) as K[]).reduce(
(acc, prop) => {
const propValue = valuesToConvert[prop];
if (propValue === 'Infinity') {
finalValue = 1;
} else if (propValue === '-Infinity') {
finalValue = 0;
} else {
finalValue =
typeof propValue === 'string' ? parseFloat(propValue) : propValue;
if (typeof propValue === 'string' && isPercent(propValue)) {
finalValue *= 0.01;
if (gradientUnits === 'pixels') {
// then we need to fix those percentages here in svg parsing
if (prop === 'x1' || prop === 'x2' || prop === 'r2') {
finalValue *= width;
}
if (prop === 'y1' || prop === 'y2') {
finalValue *= height;
}
}
}
}
acc[prop] = finalValue;
return acc;
},
{} as Record<K, number>,
);
}
function getValue(el: SVGGradientElement, key: string) {
return el.getAttribute(key);
}
export function parseLinearCoords(el: SVGGradientElement) {
return {
x1: getValue(el, 'x1') || 0,
y1: getValue(el, 'y1') || 0,
x2: getValue(el, 'x2') || '100%',
y2: getValue(el, 'y2') || 0,
};
}
export function parseRadialCoords(el: SVGGradientElement) {
return {
x1: getValue(el, 'fx') || getValue(el, 'cx') || '50%',
y1: getValue(el, 'fy') || getValue(el, 'cy') || '50%',
r1: 0,
x2: getValue(el, 'cx') || '50%',
y2: getValue(el, 'cy') || '50%',
r2: getValue(el, 'r') || '50%',
};
}
export function parseCoords(el: SVGGradientElement, size: TSize) {
return convertPercentUnitsToValues(
parseType(el) === 'linear' ? parseLinearCoords(el) : parseRadialCoords(el),
{
...size,
gradientUnits: parseGradientUnits(el),
},
);
}