mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-06 08:22:23 +00:00
141 lines
3.6 KiB
JavaScript
141 lines
3.6 KiB
JavaScript
import React, { Children } from "react";
|
|
import extractLengthList from "./extractLengthList";
|
|
import { pickNotNil } from "../util";
|
|
|
|
const fontRegExp = /^\s*((?:(?:normal|bold|italic)\s+)*)(?:(\d+(?:\.\d+)?[ptexm%])*(?:\s*\/.*?)?\s+)?\s*"?([^"]*)/i;
|
|
const fontFamilyPrefix = /^[\s"']*/;
|
|
const fontFamilySuffix = /[\s"']*$/;
|
|
const commaReg = /\s*,\s*/g;
|
|
|
|
const cachedFontObjectsFromString = {};
|
|
|
|
function extractSingleFontFamily(fontFamilyString) {
|
|
// SVG on the web allows for multiple font-families to be specified.
|
|
// For compatibility, we extract the first font-family, hoping
|
|
// we'll get a match.
|
|
return fontFamilyString
|
|
? fontFamilyString
|
|
.split(commaReg)[0]
|
|
.replace(fontFamilyPrefix, "")
|
|
.replace(fontFamilySuffix, "")
|
|
: null;
|
|
}
|
|
|
|
function parseFontString(font) {
|
|
if (cachedFontObjectsFromString.hasOwnProperty(font)) {
|
|
return cachedFontObjectsFromString[font];
|
|
}
|
|
const match = fontRegExp.exec(font);
|
|
if (!match) {
|
|
return null;
|
|
}
|
|
const fontFamily = extractSingleFontFamily(match[3]);
|
|
const fontSize = match[2] || "12";
|
|
const isBold = /bold/.exec(match[1]);
|
|
const isItalic = /italic/.exec(match[1]);
|
|
const fontWeight = isBold ? "bold" : "normal";
|
|
const fontStyle = isItalic ? "italic" : "normal";
|
|
cachedFontObjectsFromString[font] = {
|
|
fontSize,
|
|
fontFamily,
|
|
fontWeight,
|
|
fontStyle,
|
|
};
|
|
return cachedFontObjectsFromString[font];
|
|
}
|
|
|
|
export function extractFont(prop) {
|
|
const props = { ...prop.style, ...prop };
|
|
const {
|
|
fontData,
|
|
fontStyle,
|
|
fontVariant,
|
|
fontWeight,
|
|
fontStretch,
|
|
fontSize,
|
|
fontFamily,
|
|
textAnchor,
|
|
textDecoration,
|
|
letterSpacing,
|
|
wordSpacing,
|
|
kerning,
|
|
fontVariantLigatures,
|
|
fontFeatureSettings,
|
|
font,
|
|
} = props;
|
|
|
|
const ownedFont = pickNotNil({
|
|
fontData,
|
|
fontStyle,
|
|
fontVariant,
|
|
fontWeight,
|
|
fontStretch,
|
|
fontSize,
|
|
fontFamily: extractSingleFontFamily(fontFamily),
|
|
textAnchor,
|
|
textDecoration,
|
|
letterSpacing,
|
|
wordSpacing,
|
|
kerning,
|
|
fontVariantLigatures,
|
|
fontFeatureSettings,
|
|
});
|
|
|
|
const baseFont = typeof font === "string" ? parseFontString(font) : font;
|
|
|
|
return { ...baseFont, ...ownedFont };
|
|
}
|
|
|
|
let TSpan;
|
|
|
|
export function setTSpan(TSpanImplementation) {
|
|
TSpan = TSpanImplementation;
|
|
}
|
|
|
|
function getChild(child) {
|
|
if (typeof child === "string" || typeof child === "number") {
|
|
return <TSpan>{String(child)}</TSpan>;
|
|
} else {
|
|
return child;
|
|
}
|
|
}
|
|
|
|
export default function(props, container = false) {
|
|
const {
|
|
x,
|
|
y,
|
|
dx,
|
|
dy,
|
|
rotate,
|
|
children,
|
|
baselineShift,
|
|
verticalAlign,
|
|
alignmentBaseline,
|
|
} = props;
|
|
|
|
const textChildren =
|
|
typeof children === "string" || typeof children === "number" ? (
|
|
container ? (
|
|
<TSpan>{String(children)}</TSpan>
|
|
) : null
|
|
) : Children.count(children) > 1 || Array.isArray(children) ? (
|
|
Children.map(children, getChild)
|
|
) : (
|
|
children
|
|
);
|
|
|
|
return {
|
|
content: textChildren === null ? String(children) : null,
|
|
children: textChildren,
|
|
baselineShift,
|
|
verticalAlign,
|
|
alignmentBaseline,
|
|
font: extractFont(props),
|
|
x: extractLengthList(x),
|
|
y: extractLengthList(y),
|
|
dx: extractLengthList(dx),
|
|
dy: extractLengthList(dy),
|
|
rotate: extractLengthList(rotate),
|
|
};
|
|
}
|