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, >( valuesToConvert: Record, { width, height, gradientUnits }: TSize & { gradientUnits: GradientUnits }, ) { let finalValue; return (Object.entries(valuesToConvert) as [K, string | number][]).reduce( (acc, [prop, propValue]) => { if (propValue === 'Infinity') { finalValue = 1; } else if (propValue === '-Infinity') { finalValue = 0; } else { const isString = typeof propValue === 'string'; finalValue = isString ? parseFloat(propValue) : propValue; if (isString && 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, ); } 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), }, ); }