fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
77 lines (74 loc) • 2.86 kB
text/typescript
import { multiplyTransformMatrices } from '../util/misc/matrix';
import { parseUnit } from '../util/misc/svgParsing';
import { parseTransformAttribute } from './parseTransformAttribute';
import { CENTER, LEFT, RIGHT, NONE, FILL, STROKE } from '../constants';
import { TEXT_DECORATION_THICKNESS } from '../shapes/Text/constants';
export function normalizeValue(
attr: string,
value: any,
parentAttributes: Record<string, any>,
fontSize: number,
): string | null | boolean | number[] | number {
const isArray = Array.isArray(value);
let parsed: number | number[];
let ouputValue: string | null | boolean | number[] | number = value;
if ((attr === FILL || attr === STROKE) && value === NONE) {
ouputValue = '';
} else if (attr === 'strokeUniform') {
return value === 'non-scaling-stroke';
} else if (attr === 'strokeDashArray') {
if (value === NONE) {
ouputValue = null;
} else {
ouputValue = value.replace(/,/g, ' ').split(/\s+/).map(parseFloat);
}
} else if (attr === 'transformMatrix') {
if (parentAttributes && parentAttributes.transformMatrix) {
ouputValue = multiplyTransformMatrices(
parentAttributes.transformMatrix,
parseTransformAttribute(value),
);
} else {
ouputValue = parseTransformAttribute(value);
}
} else if (attr === 'visible') {
ouputValue = value !== NONE && value !== 'hidden';
// display=none on parent element always takes precedence over child element
if (parentAttributes && parentAttributes.visible === false) {
ouputValue = false;
}
} else if (attr === 'opacity') {
ouputValue = parseFloat(value);
if (parentAttributes && typeof parentAttributes.opacity !== 'undefined') {
ouputValue *= parentAttributes.opacity as number;
}
} else if (attr === 'textAnchor' /* text-anchor */) {
ouputValue = value === 'start' ? LEFT : value === 'end' ? RIGHT : CENTER;
} else if (attr === 'charSpacing' || attr === TEXT_DECORATION_THICKNESS) {
// parseUnit returns px and we convert it to em
parsed = (parseUnit(value, fontSize) / fontSize) * 1000;
} else if (attr === 'paintFirst') {
const fillIndex = value.indexOf(FILL);
const strokeIndex = value.indexOf(STROKE);
ouputValue = FILL;
if (fillIndex > -1 && strokeIndex > -1 && strokeIndex < fillIndex) {
ouputValue = STROKE;
} else if (fillIndex === -1 && strokeIndex > -1) {
ouputValue = STROKE;
}
} else if (
attr === 'href' ||
attr === 'xlink:href' ||
attr === 'font' ||
attr === 'id'
) {
return value;
} else if (attr === 'imageSmoothing') {
return value === 'optimizeQuality';
} else {
parsed = isArray
? (value as string[]).map(parseUnit)
: parseUnit(value, fontSize);
}
return !isArray && isNaN(parsed! as number) ? ouputValue : parsed!;
}