Files
react-native-svg/lib/extract/extractText.js
Mikael Sand fe7e8b2b65 Implement baselineShift and verticalAlign (preferred).
Transverse Box Alignment, specifies how an inline-level box is aligned within the line, and by how much the box is shifted up from its alignment point.
 https://drafts.csswg.org/css-inline/#propdef-vertical-align
 https://www.w3.org/TR/css-inline-3/#propdef-baseline-shift
 https://www.w3.org/TR/css-inline-3/#transverse-alignment
2017-08-04 16:29:06 +03:00

146 lines
3.7 KiB
JavaScript

import _ from 'lodash';
//noinspection JSUnresolvedVariable
import React, {Children} from 'react';
import TSpan from '../../elements/TSpan';
import extractLengthList from './extractLengthList';
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(props) {
const {
fontStyle,
fontVariant,
fontWeight,
fontStretch,
textAnchor,
textDecoration,
letterSpacing,
wordSpacing,
kerning,
fontVariantLigatures,
} = props;
let {
fontSize,
fontFamily,
font,
} = props;
fontFamily = extractSingleFontFamily(fontFamily);
fontSize = fontSize ? '' + fontSize : null;
const ownedFont = _.pickBy({
fontStyle,
fontVariant,
fontWeight,
fontStretch,
fontSize,
fontFamily,
textAnchor,
textDecoration,
letterSpacing,
wordSpacing,
kerning,
fontVariantLigatures,
}, prop => !_.isNil(prop));
if (typeof font === 'string') {
font = parseFontString(font);
}
return _.defaults(ownedFont, font);
}
export default function(props, container) {
const {
x,
y,
dx,
dy,
alignmentBaseline,
baselineShift,
verticalAlign,
} = props;
let {
rotate,
children
} = props;
const positionX = extractLengthList(x);
const positionY = extractLengthList(y);
const deltaX = extractLengthList(dx);
const deltaY = extractLengthList(dy);
rotate = extractLengthList(rotate);
let content = null;
if (typeof children === 'string' || typeof children === 'number') {
const childrenString = children.toString();
if (container) {
children = <TSpan>{childrenString}</TSpan>;
} else {
content = childrenString;
children = null;
}
} else if (Children.count(children) > 1 || Array.isArray(children)) {
children = Children.map(children, child => {
if (typeof child === 'string' || typeof child === 'number') {
return <TSpan>{child.toString()}</TSpan>;
} else {
return child;
}
});
}
const font = extractFont(props);
return {
font,
children,
content,
positionX,
positionY,
rotate,
deltaX,
deltaY,
alignmentBaseline,
baselineShift,
verticalAlign,
};
}