mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 14:05:09 +00:00
first step of TSpan
This commit is contained in:
@@ -8,7 +8,8 @@ import Svg, {
|
|||||||
Stop,
|
Stop,
|
||||||
Defs,
|
Defs,
|
||||||
Path,
|
Path,
|
||||||
G
|
G,
|
||||||
|
TSpan
|
||||||
} from 'react-native-svg';
|
} from 'react-native-svg';
|
||||||
|
|
||||||
class TextExample extends Component{
|
class TextExample extends Component{
|
||||||
@@ -148,6 +149,33 @@ class TextPath extends Component{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TSpanExample extends Component{
|
||||||
|
static title = 'TSpan nest';
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
return <Svg
|
||||||
|
height="150"
|
||||||
|
width="300"
|
||||||
|
>
|
||||||
|
<Text y="20" dx="5 5">
|
||||||
|
<TSpan x="10" textAnchor="middle">tspan line 1</TSpan>
|
||||||
|
<TSpan x="10" dy="15">tspan line 2</TSpan>
|
||||||
|
<TSpan x="10" dx="10" dy="15">tspan line 3</TSpan>
|
||||||
|
</Text>
|
||||||
|
<Text x="10" y="60" fill="red" fontSize="14">
|
||||||
|
<TSpan dy="5 10 20" >12345</TSpan>
|
||||||
|
<TSpan fill="blue" dy="15" dx="0 5 5">
|
||||||
|
<TSpan>6</TSpan>
|
||||||
|
<TSpan>7</TSpan>
|
||||||
|
</TSpan>
|
||||||
|
<TSpan dx="0 10 20" dy="0 20" fontWeight="bold" fontSize="12">89a</TSpan>
|
||||||
|
</Text>
|
||||||
|
<Text y="140" dx="0 5 5" dy="0 -5 -5">delta on text</Text>
|
||||||
|
</Svg>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const icon = <Svg
|
const icon = <Svg
|
||||||
height="20"
|
height="20"
|
||||||
width="20"
|
width="20"
|
||||||
@@ -168,7 +196,8 @@ const samples = [
|
|||||||
TextRotate,
|
TextRotate,
|
||||||
TextStroke,
|
TextStroke,
|
||||||
TextFill,
|
TextFill,
|
||||||
TextPath
|
TextPath,
|
||||||
|
TSpanExample
|
||||||
];
|
];
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
40
elements/TSpan.js
Normal file
40
elements/TSpan.js
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import React, {PropTypes} from 'react';
|
||||||
|
import createReactNativeComponentClass from 'react/lib/createReactNativeComponentClass';
|
||||||
|
import {numberProp, pathProps} from '../lib/props';
|
||||||
|
import {TSpanAttributes} from '../lib/attributes';
|
||||||
|
import extractFrame from '../lib/extract/extractFrame';
|
||||||
|
import Shape from './Shape';
|
||||||
|
|
||||||
|
class TSpan extends Shape {
|
||||||
|
static displayName = 'TSpan';
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
...pathProps,
|
||||||
|
dx: numberProp,
|
||||||
|
dy: numberProp,
|
||||||
|
textAnchor: PropTypes.oneOf(['start', 'middle', 'end']),
|
||||||
|
fontFamily: PropTypes.string,
|
||||||
|
fontSize: numberProp,
|
||||||
|
fontWeight: PropTypes.string,
|
||||||
|
fontStyle: PropTypes.string,
|
||||||
|
font: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
setNativeProps = (...args) => {
|
||||||
|
this.root.setNativeProps(...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <RNSVGTSpan
|
||||||
|
ref={ele => {this.root = ele;}}
|
||||||
|
{...extractFrame(this.props)}
|
||||||
|
/>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const RNSVGTSpan = createReactNativeComponentClass({
|
||||||
|
validAttributes: TSpanAttributes,
|
||||||
|
uiViewClassName: 'RNSVGTSpan'
|
||||||
|
});
|
||||||
|
|
||||||
|
export default TSpan;
|
||||||
@@ -13,18 +13,11 @@ class Text extends Shape {
|
|||||||
dx: numberProp,
|
dx: numberProp,
|
||||||
dy: numberProp,
|
dy: numberProp,
|
||||||
textAnchor: PropTypes.oneOf(['start', 'middle', 'end']),
|
textAnchor: PropTypes.oneOf(['start', 'middle', 'end']),
|
||||||
path: PropTypes.string,
|
|
||||||
fontFamily: PropTypes.string,
|
fontFamily: PropTypes.string,
|
||||||
fontSize: numberProp,
|
fontSize: numberProp,
|
||||||
fontWeight: PropTypes.string,
|
fontWeight: PropTypes.string,
|
||||||
fontStyle: PropTypes.string,
|
fontStyle: PropTypes.string,
|
||||||
font: PropTypes.object,
|
font: PropTypes.object
|
||||||
lines: numberProp
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
dx: 0,
|
|
||||||
dy: 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
setNativeProps = (...args) => {
|
setNativeProps = (...args) => {
|
||||||
@@ -33,19 +26,9 @@ class Text extends Shape {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
let props = this.props;
|
let props = this.props;
|
||||||
|
|
||||||
let x = 0;
|
|
||||||
if (props.x) {
|
|
||||||
x = props.dx ? +props.x + (+props.dx) : +props.x;
|
|
||||||
}
|
|
||||||
let y = 0;
|
|
||||||
if (props.y) {
|
|
||||||
y = props.dy ? +props.y + (+props.dy) : +props.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <RNSVGText
|
return <RNSVGText
|
||||||
ref={ele => {this.root = ele;}}
|
ref={ele => {this.root = ele;}}
|
||||||
{...this.extractProps({...props, x, y})}
|
{...this.extractProps({...props})}
|
||||||
{...extractText(props)}
|
{...extractText(props)}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|||||||
19
ios/Text/RNSVGTSpan.h
Normal file
19
ios/Text/RNSVGTSpan.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Horcrux.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "RNSVGPath.h"
|
||||||
|
#import "RNSVGTextFrame.h"
|
||||||
|
|
||||||
|
@interface RNSVGText : RNSVGPath
|
||||||
|
|
||||||
|
@property (nonatomic, assign) CTTextAlignment alignment;
|
||||||
|
@property (nonatomic, assign) RNSVGTextFrame textFrame;
|
||||||
|
@property (nonatomic, assign) NSString
|
||||||
|
|
||||||
|
@end
|
||||||
136
ios/Text/RNSVGTSpan.m
Normal file
136
ios/Text/RNSVGTSpan.m
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Horcrux.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "RNSVGText.h"
|
||||||
|
#import "RNSVGBezierPath.h"
|
||||||
|
#import <CoreText/CoreText.h>
|
||||||
|
|
||||||
|
@implementation RNSVGText
|
||||||
|
|
||||||
|
static void RNSVGFreeTextFrame(RNSVGTextFrame frame)
|
||||||
|
{
|
||||||
|
if (frame.count) {
|
||||||
|
// We must release each line before freeing up this struct
|
||||||
|
for (int i = 0; i < frame.count; i++) {
|
||||||
|
CFRelease(frame.lines[i]);
|
||||||
|
}
|
||||||
|
free(frame.lines);
|
||||||
|
free(frame.widths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setAlignment:(CTTextAlignment)alignment
|
||||||
|
{
|
||||||
|
[self invalidate];
|
||||||
|
_alignment = alignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setTextFrame:(RNSVGTextFrame)textFrame
|
||||||
|
{
|
||||||
|
RNSVGFreeTextFrame(_textFrame);
|
||||||
|
[self invalidate];
|
||||||
|
_textFrame = textFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setPath:(NSArray *)path
|
||||||
|
{
|
||||||
|
if (path == _path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[self invalidate];
|
||||||
|
_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
RNSVGFreeTextFrame(_textFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGPathRef)getPath:(CGContextRef)context
|
||||||
|
{
|
||||||
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
|
RNSVGTextFrame frame = self.textFrame;
|
||||||
|
for (int i = 0; i < frame.count; i++) {
|
||||||
|
CGFloat shift;
|
||||||
|
CGFloat width = frame.widths[i];
|
||||||
|
switch (self.alignment) {
|
||||||
|
case kCTTextAlignmentRight:
|
||||||
|
shift = width;
|
||||||
|
break;
|
||||||
|
case kCTTextAlignmentCenter:
|
||||||
|
shift = width / 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
shift = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// We should consider snapping this shift to device pixels to improve rendering quality
|
||||||
|
// when a line has subpixel width.
|
||||||
|
CGAffineTransform offset = CGAffineTransformMakeTranslation(-shift, frame.baseLine + frame.lineHeight * i + (self.path ? -frame.lineHeight : 0));
|
||||||
|
|
||||||
|
CGMutablePathRef line = [self setLinePath:frame.lines[i]];
|
||||||
|
CGPathAddPath(path, &offset, line);
|
||||||
|
CGPathRelease(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (CGPathRef)CFAutorelease(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGMutablePathRef)setLinePath:(CTLineRef)line
|
||||||
|
{
|
||||||
|
CGAffineTransform upsideDown = CGAffineTransformMakeScale(1.0, -1.0);
|
||||||
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
|
|
||||||
|
CFArrayRef glyphRuns = CTLineGetGlyphRuns(line);
|
||||||
|
CTRunRef run = CFArrayGetValueAtIndex(glyphRuns, 0);
|
||||||
|
|
||||||
|
CFIndex runGlyphCount = CTRunGetGlyphCount(run);
|
||||||
|
CGPoint positions[runGlyphCount];
|
||||||
|
CGGlyph glyphs[runGlyphCount];
|
||||||
|
|
||||||
|
// Grab the glyphs, positions, and font
|
||||||
|
CTRunGetPositions(run, CFRangeMake(0, 0), positions);
|
||||||
|
CTRunGetGlyphs(run, CFRangeMake(0, 0), glyphs);
|
||||||
|
CFDictionaryRef attributes = CTRunGetAttributes(run);
|
||||||
|
|
||||||
|
CTFontRef runFont = CFDictionaryGetValue(attributes, kCTFontAttributeName);
|
||||||
|
|
||||||
|
RNSVGBezierPath *bezierPath = [[RNSVGBezierPath alloc] initWithBezierCurves:self.path];
|
||||||
|
|
||||||
|
for(CFIndex i = 0; i < runGlyphCount; ++i) {
|
||||||
|
CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyphs[i], nil);
|
||||||
|
CGPoint point = positions[i];
|
||||||
|
|
||||||
|
if (letter) {
|
||||||
|
CGAffineTransform transform;
|
||||||
|
|
||||||
|
// draw glyphs along path
|
||||||
|
if (self.path) {
|
||||||
|
transform = [bezierPath transformAtDistance:point.x];
|
||||||
|
|
||||||
|
// break loop if line reaches the end of the Path.
|
||||||
|
if (!transform.a || !transform.d) {
|
||||||
|
CGPathRelease(letter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
transform = CGAffineTransformScale(transform, 1.0, -1.0);
|
||||||
|
} else {
|
||||||
|
transform = CGAffineTransformTranslate(upsideDown, point.x, point.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CGPathAddPath(path, &transform, letter);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGPathRelease(letter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -17,30 +17,6 @@ function arrayDiffer(a, b) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fontAndLinesDiffer(a, b) {
|
|
||||||
if (a === b) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (a.font !== b.font) {
|
|
||||||
if (a.font === null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (b.font === null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
a.font.fontFamily !== b.font.fontFamily ||
|
|
||||||
a.font.fontSize !== b.font.fontSize ||
|
|
||||||
a.font.fontWeight !== b.font.fontWeight ||
|
|
||||||
a.font.fontStyle !== b.font.fontStyle
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return arrayDiffer(a.lines, b.lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ViewBoxAttributes = {
|
const ViewBoxAttributes = {
|
||||||
minX: true,
|
minX: true,
|
||||||
minY: true,
|
minY: true,
|
||||||
@@ -104,16 +80,22 @@ const PathAttributes = merge({
|
|||||||
}
|
}
|
||||||
}, RenderableAttributes);
|
}, RenderableAttributes);
|
||||||
|
|
||||||
const TextAttributes = merge({
|
const FontAttributes = merge({
|
||||||
alignment: true,
|
fontFamily: true,
|
||||||
frame: {
|
fontSize: true,
|
||||||
diff: fontAndLinesDiffer
|
fontWeight: true,
|
||||||
},
|
fontStyle: true
|
||||||
path: {
|
|
||||||
diff: arrayDiffer
|
|
||||||
}
|
|
||||||
}, RenderableAttributes);
|
}, RenderableAttributes);
|
||||||
|
|
||||||
|
const TSpanAttributes = merge({
|
||||||
|
line: true
|
||||||
|
}, FontAttributes);
|
||||||
|
|
||||||
|
|
||||||
|
const TextAttributes = merge({
|
||||||
|
alignment: true
|
||||||
|
}, FontAttributes);
|
||||||
|
|
||||||
const ClipPathAttributes = {
|
const ClipPathAttributes = {
|
||||||
name: true
|
name: true
|
||||||
};
|
};
|
||||||
@@ -184,6 +166,7 @@ const RectAttributes = merge({
|
|||||||
export {
|
export {
|
||||||
PathAttributes,
|
PathAttributes,
|
||||||
TextAttributes,
|
TextAttributes,
|
||||||
|
TSpanAttributes,
|
||||||
GroupAttributes,
|
GroupAttributes,
|
||||||
ClipPathAttributes,
|
ClipPathAttributes,
|
||||||
CircleAttributes,
|
CircleAttributes,
|
||||||
|
|||||||
21
lib/extract/extractFrame.js
Normal file
21
lib/extract/extractFrame.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import extractSpan from './extractSpan';
|
||||||
|
import extractTextContent from './extractTextContent';
|
||||||
|
|
||||||
|
export default function (props) {
|
||||||
|
let {children, line} = props;
|
||||||
|
let extractedProps = extractSpan(props);
|
||||||
|
|
||||||
|
if (typeof children === 'string') {
|
||||||
|
line = children;
|
||||||
|
children = null;
|
||||||
|
} else {
|
||||||
|
children = extractTextContent(props.children);
|
||||||
|
line = null;
|
||||||
|
}
|
||||||
|
console.log(extractedProps);
|
||||||
|
return {
|
||||||
|
...extractedProps,
|
||||||
|
children,
|
||||||
|
line
|
||||||
|
};
|
||||||
|
};
|
||||||
76
lib/extract/extractSpan.js
Normal file
76
lib/extract/extractSpan.js
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import React, {
|
||||||
|
Children
|
||||||
|
} from 'react';
|
||||||
|
|
||||||
|
import TSpan from '../../elements/TSpan';
|
||||||
|
import extractTextContent from './extractTextContent';
|
||||||
|
import SerializablePath from '../SerializablePath';
|
||||||
|
import _ from 'lodash';
|
||||||
|
const fontRegExp = /^\s*((?:(?:normal|bold|italic)\s+)*)(?:(\d+(?:\.\d+)?)[ptexm%]*(?:\s*\/.*?)?\s+)?\s*"?([^"]*)/i;
|
||||||
|
const fontFamilyPrefix = /^[\s"']*/;
|
||||||
|
const fontFamilySuffix = /[\s"']*$/;
|
||||||
|
const spaceReg = /\s+/;
|
||||||
|
const commaReg = /,/;
|
||||||
|
|
||||||
|
let 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];
|
||||||
|
}
|
||||||
|
let match = fontRegExp.exec(font);
|
||||||
|
if (!match) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let fontFamily = extractSingleFontFamily(match[3]);
|
||||||
|
let fontSize = +match[2] || 12;
|
||||||
|
let isBold = /bold/.exec(match[1]);
|
||||||
|
let isItalic = /italic/.exec(match[1]);
|
||||||
|
cachedFontObjectsFromString[font] = {
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: fontSize,
|
||||||
|
fontWeight: isBold ? 'bold' : 'normal',
|
||||||
|
fontStyle: isItalic ? 'italic' : 'normal'
|
||||||
|
};
|
||||||
|
return cachedFontObjectsFromString[font];
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractFont(props) {
|
||||||
|
let font = props.font;
|
||||||
|
let fontSize = +props.fontSize;
|
||||||
|
|
||||||
|
let ownedFont = {
|
||||||
|
fontFamily: extractSingleFontFamily(props.fontFamily),
|
||||||
|
fontSize: isNaN(fontSize) ? null : fontSize,
|
||||||
|
fontWeight: props.fontWeight,
|
||||||
|
fontStyle: props.fontStyle
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof props.font === 'string') {
|
||||||
|
font = parseFontString(props.font);
|
||||||
|
}
|
||||||
|
ownedFont = _.pickBy(ownedFont, prop => !_.isNil(prop));
|
||||||
|
|
||||||
|
return _.defaults(ownedFont, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseDelta(delta) {
|
||||||
|
return delta.toString().split(spaceReg);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function(props) {
|
||||||
|
return {
|
||||||
|
dx: parseDelta(props.dx || ''),
|
||||||
|
dy: parseDelta(props.dy || ''),
|
||||||
|
...extractFont(props)
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,93 +1,43 @@
|
|||||||
import SerializablePath from '../SerializablePath';
|
import extractTextContent from './extractTextContent';
|
||||||
import _ from 'lodash';
|
import extractSpan from './extractSpan';
|
||||||
const newLine = /\n/g;
|
|
||||||
const defaultFontFamily = '"Helvetica Neue", "Helvetica", Arial';
|
|
||||||
const fontRegExp = /^\s*((?:(?:normal|bold|italic)\s+)*)(?:(\d+(?:\.\d+)?)[ptexm%]*(?:\s*\/.*?)?\s+)?\s*"?([^"]*)/i;
|
|
||||||
const fontFamilyPrefix = /^[\s"']*/;
|
|
||||||
const fontFamilySuffix = /[\s"']*$/;
|
|
||||||
let cachedFontObjectsFromString = {};
|
|
||||||
|
|
||||||
function childrenAsString(children) {
|
const anchors = {
|
||||||
if (!children) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
if (typeof children === 'string') {
|
|
||||||
return children;
|
|
||||||
}
|
|
||||||
if (children.length) {
|
|
||||||
return children.join('\n');
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractFontAndLines(font, text) {
|
|
||||||
return {
|
|
||||||
font: extractFont(font),
|
|
||||||
lines: text.split(newLine)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractSingleFontFamily(fontFamilyString = defaultFontFamily) {
|
|
||||||
// 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.split(',')[0]
|
|
||||||
.replace(fontFamilyPrefix, '')
|
|
||||||
.replace(fontFamilySuffix, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseFontString(font) {
|
|
||||||
if (cachedFontObjectsFromString.hasOwnProperty(font)) {
|
|
||||||
return cachedFontObjectsFromString[font];
|
|
||||||
}
|
|
||||||
let match = fontRegExp.exec(font);
|
|
||||||
if (!match) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let fontFamily = extractSingleFontFamily(match[3]);
|
|
||||||
let fontSize = +match[2] || 12;
|
|
||||||
let isBold = /bold/.exec(match[1]);
|
|
||||||
let isItalic = /italic/.exec(match[1]);
|
|
||||||
cachedFontObjectsFromString[font] = {
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: fontSize,
|
|
||||||
fontWeight: isBold ? 'bold' : 'normal',
|
|
||||||
fontStyle: isItalic ? 'italic' : 'normal'
|
|
||||||
};
|
|
||||||
return cachedFontObjectsFromString[font];
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractFont(font) {
|
|
||||||
if (_.isNil(font)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (typeof font === 'string') {
|
|
||||||
return parseFontString(font);
|
|
||||||
}
|
|
||||||
let fontFamily = extractSingleFontFamily(font.fontFamily);
|
|
||||||
let fontSize = +font.fontSize || 12;
|
|
||||||
|
|
||||||
return {
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: fontSize,
|
|
||||||
fontWeight: font.fontWeight,
|
|
||||||
fontStyle: font.fontStyle
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const anchord = {
|
|
||||||
end: 1,
|
end: 1,
|
||||||
middle: 2,
|
middle: 2,
|
||||||
start: 0
|
start: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function(props) {
|
export default function(props) {
|
||||||
|
let children = extractTextContent(props.children);
|
||||||
|
let extractedProps = extractSpan(props);
|
||||||
|
let firstSpan = children[0];
|
||||||
|
let alignment;
|
||||||
|
let {dx, dy} = extractedProps;
|
||||||
|
let maxDeltaLength = Math.max(dx.length, dy.length);
|
||||||
|
|
||||||
|
if (firstSpan && firstSpan.props.hasOwnProperty('textAnchor')) {
|
||||||
|
alignment = anchors[firstSpan.props.textAnchor];
|
||||||
|
} else if (anchors[props.textAnchor]) {
|
||||||
|
alignment = anchors[props.textAnchor];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!alignment) {
|
||||||
|
alignment = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < maxDeltaLength; i++) {
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(extractedProps);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
alignment: anchord[props.textAnchor] || 0,
|
alignment,
|
||||||
frame: extractFontAndLines(
|
children,
|
||||||
props,
|
fontFamily: 'Helvetica Neue',
|
||||||
childrenAsString(props.children)
|
fontSize: 12,
|
||||||
),
|
fontStyle: 'normal',
|
||||||
path: props.path ? new SerializablePath(props.path).toJSON() : undefined
|
fontWeight: 'normal',
|
||||||
};
|
...extractedProps
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
lib/extract/extractTextContent.js
Normal file
26
lib/extract/extractTextContent.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import React, {
|
||||||
|
Children
|
||||||
|
} from 'react';
|
||||||
|
|
||||||
|
import TSpan from '../../elements/TSpan';
|
||||||
|
const newLine = /\n/g;
|
||||||
|
|
||||||
|
export default function(children) {
|
||||||
|
let spans = [];
|
||||||
|
|
||||||
|
Children.forEach(children, function (child = '') {
|
||||||
|
let span;
|
||||||
|
if (typeof child === 'string') {
|
||||||
|
span = <TSpan>{child.replace(newLine, ' ')}</TSpan>;
|
||||||
|
} else if (child.type === TSpan) {
|
||||||
|
span = child;
|
||||||
|
} else {
|
||||||
|
// give warning about the illegal child type
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spans.push(span);
|
||||||
|
});
|
||||||
|
|
||||||
|
return spans;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user