Refactor Symbol on iOS

This commit is contained in:
Horcrux
2017-01-22 17:51:47 +08:00
parent f529f93565
commit 1b04e11ca4
21 changed files with 385 additions and 311 deletions

View File

@@ -4,7 +4,7 @@ import {ImageAttributes} from '../lib/attributes';
import {numberProp, touchableProps, responderProps} from '../lib/props';
import Shape from './Shape';
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
import {meetOrSliceTypes, alignEnum} from './ViewBox';
import {meetOrSliceTypes, alignEnum} from '../lib/extract/extractViewBox';
const spacesRegExp = /\s+/;
class Image extends Shape {

View File

@@ -11,8 +11,10 @@ import {
NativeModules,
Platform
} from 'react-native';
import ViewBox from './ViewBox';
import extractViewBox from '../lib/extract/extractViewBox';
import {ViewBoxAttributes} from '../lib/attributes';
import _ from 'lodash';
const RNSVGSvgViewManager = NativeModules.RNSVGSvgViewManager;
// Svg - Root node of all Svg elements
@@ -36,6 +38,10 @@ class Svg extends Component{
preserveAspectRatio: PropTypes.string
};
static defaultProps = {
preserveAspectRatio: 'xMidYMid meet'
};
constructor() {
super(...arguments);
id++;
@@ -79,52 +85,39 @@ class Svg extends Component{
};
render() {
let {props} = this;
let opacity = +props.opacity;
let width = +props.width;
let height = +props.height;
let viewBox = props.viewBox;
const {opacity, width, height, viewBox, preserveAspectRatio, style, ...props} = this.props;
let dimensions;
if (width && height) {
dimensions = {
width,
height,
width: +width,
height: +height,
flex: 0
};
}
if (props.viewbox) {
viewBox = props.viewbox;
console.warn('Prop `viewbox` is deprecated. please use `viewBox` instead.');
}
let content = viewBox ? <ViewBox
viewBox={viewBox}
preserveAspectRatio={props.preserveAspectRatio}
>{props.children}</ViewBox> : props.children;
const nativeProps = _.omit(props, ['width', 'height', 'viewBox', 'preserveAspectRatio', 'opacity']);
return <NativeSvgView
{...nativeProps}
{...props}
{...extractViewBox({ viewBox, preserveAspectRatio })}
ref={ele => {this.root = ele;}}
style={[
styles.svg,
props.style,
!isNaN(opacity) && {
opacity
style,
!isNaN(+opacity) && {
opacity: +opacity
},
dimensions
]}
onDataURL={this._onDataURL}
>
{content}
</NativeSvgView>;
/>;
}
}
const NativeSvgView = requireNativeComponent('RNSVGSvgView', null);
const NativeSvgView = requireNativeComponent('RNSVGSvgView', null, {
nativeOnly: {
...ViewBoxAttributes
}
});
export default Svg;

View File

@@ -1,7 +1,7 @@
import React, {Component, PropTypes} from 'react';
import ViewBox from './ViewBox';
import G from './G';
import Defs from './Defs';
import extractViewBox from '../lib/extract/extractViewBox';
import createReactNativeComponentClass from 'react-native/Libraries/Renderer/src/renderers/native/createReactNativeComponentClass';
import {SymbolAttributes} from '../lib/attributes';
class SymbolElement extends Component{
static displayName = 'Symbol';
@@ -13,26 +13,18 @@ class SymbolElement extends Component{
render() {
let {props} = this;
let viewBox = props.viewBox;
if (props.viewbox) {
viewBox = props.viewbox;
console.warn('Prop `viewbox` is deprecated. please use `viewBox` instead.');
}
let content = viewBox ? <ViewBox
return <RNSVGSymbol
name={props.id}
viewBox={viewBox}
preserveAspectRatio={props.preserveAspectRatio}
{...extractViewBox(props)}
>
{props.children}
</ViewBox> : <G id={props.id}>
{props.children}
</G>;
return <Defs>
{content}
</Defs>;
</RNSVGSymbol>;
}
}
const RNSVGSymbol = createReactNativeComponentClass({
validAttributes: SymbolAttributes,
uiViewClassName: 'RNSVGSymbol'
});
export default SymbolElement;

View File

@@ -1,79 +0,0 @@
import React, {Component, PropTypes} from 'react';
import createReactNativeComponentClass from 'react-native/Libraries/Renderer/src/renderers/native/createReactNativeComponentClass';
import {ViewBoxAttributes} from '../lib/attributes';
import G from './G';
const meetOrSliceTypes = {
meet: 0,
slice: 1,
none: 2
};
const alignEnum = [
'xMinYMin', 'xMidYMin', 'xMaxYMin',
'xMinYMid', 'xMidYMid', 'xMaxYMid',
'xMinYMax', 'xMidYMax', 'xMaxYMax',
'none'
].reduce((prev, name) => {
prev[name] = name;
return prev;
}, {});
const numberRegExp = /^\d*\.?\d*%?$/;
const spacesRegExp = /\s+/;
class ViewBox extends Component{
static displayName = 'ViewBox';
static propTypes = {
viewBox: PropTypes.string.isRequired,
preserveAspectRatio: PropTypes.string
};
static defaultProps = {
preserveAspectRatio: 'xMidYMid meet'
};
render() {
const {viewBox, preserveAspectRatio, name} = this.props;
let params = viewBox.trim().split(spacesRegExp);
if (params.length !== 4 || !params.some(param => param && numberRegExp.test(param))) {
console.warn('`viewBox` expected a string like `minX minY width height`, but got:' + viewBox);
return <G>
{this.props.children}
</G>;
}
let modes = preserveAspectRatio.trim().split(spacesRegExp);
let meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
let align = alignEnum[modes[0]] || 'xMidYMid';
return <RNSVGViewBox
name={name}
minX={params[0]}
minY={params[1]}
vbWidth={params[2]}
vbHeight={params[3]}
align={align}
meetOrSlice={meetOrSlice}
>
{this.props.children}
</RNSVGViewBox>;
}
}
const RNSVGViewBox = createReactNativeComponentClass({
validAttributes: ViewBoxAttributes,
uiViewClassName: 'RNSVGViewBox'
});
export default ViewBox;
export {
meetOrSliceTypes,
alignEnum
};

View File

@@ -9,11 +9,18 @@
#import <UIKit/UIKit.h>
#import "RNSVGBrushCOnverter.h"
#import "RNSVGContainer.h"
#import "RNSVGVBMOS.h"
@class RNSVGNode;
@interface RNSVGSvgView : UIView <RNSVGContainer>
@property (nonatomic, assign) CGFloat minX;
@property (nonatomic, assign) CGFloat minY;
@property (nonatomic, assign) CGFloat vbWidth;
@property (nonatomic, assign) CGFloat vbHeight;
@property (nonatomic, strong) NSString *align;
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
@property (nonatomic, assign) BOOL responsible;
/**

View File

@@ -7,7 +7,7 @@
*/
#import "RNSVGSvgView.h"
#import "RNSVGViewBox.h"
#import "RNSVGNode.h"
#import <React/RCTLog.h>
@@ -42,6 +42,66 @@
[self setNeedsDisplay];
}
- (void)setMinX:(CGFloat)minX
{
if (minX == _minX) {
return;
}
[self invalidate];
_minX = minX;
}
- (void)setMinY:(CGFloat)minY
{
if (minY == _minY) {
return;
}
[self invalidate];
_minY = minY;
}
- (void)setVbWidth:(CGFloat)vbWidth
{
if (vbWidth == _vbWidth) {
return;
}
[self invalidate];
_vbWidth = vbWidth;
}
- (void)setVbHeight:(CGFloat)vbHeight
{
if (_vbHeight == vbHeight) {
return;
}
[self invalidate];
_vbHeight = vbHeight;
}
- (void)setAlign:(NSString *)align
{
if ([align isEqualToString:_align]) {
return;
}
[self invalidate];
_align = align;
}
- (void)setMeetOrSlice:(RNSVGVBMOS)meetOrSlice
{
if (meetOrSlice == _meetOrSlice) {
return;
}
[self invalidate];
_meetOrSlice = meetOrSlice;
}
- (void)drawRect:(CGRect)rect
{
clipPaths = nil;
@@ -50,6 +110,15 @@
_boundingBox = rect;
CGContextRef context = UIGraphicsGetCurrentContext();
if (self.align) {
CGAffineTransform viewBoxTransform = [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight)
eRect:rect
align:self.align
meetOrSlice:self.meetOrSlice
fromSymbol:NO];
CGContextConcatCTM(context, viewBoxTransform);
}
for (RNSVGNode *node in self.subviews) {
if ([node isKindOfClass:[RNSVGNode class]]) {
if (node.responsible && !self.responsible) {

View File

@@ -0,0 +1,26 @@
/**
* 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 "RNSVGGroup.h"
/**
* RNSVG defination are implemented as abstract UIViews for all elements inside Defs.
*/
@interface RNSVGSymbol : RNSVGGroup
@property (nonatomic, assign) CGFloat minX;
@property (nonatomic, assign) CGFloat minY;
@property (nonatomic, assign) CGFloat vbWidth;
@property (nonatomic, assign) CGFloat vbHeight;
@property (nonatomic, strong) NSString *align;
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
- (void)renderSymbolTo:(CGContextRef)context width:(CGFloat)width height:(CGFloat)height;
@end

View File

@@ -0,0 +1,96 @@
/**
* 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 "RNSVGSymbol.h"
#import "RNSVGViewBox.h"
@class RNSVGNode;
@implementation RNSVGSymbol
- (void)setMinX:(CGFloat)minX
{
if (minX == _minX) {
return;
}
[self invalidate];
_minX = minX;
}
- (void)setMinY:(CGFloat)minY
{
if (minY == _minY) {
return;
}
[self invalidate];
_minY = minY;
}
- (void)setVbWidth:(CGFloat)vbWidth
{
if (vbWidth == _vbWidth) {
return;
}
[self invalidate];
_vbWidth = vbWidth;
}
- (void)setVbHeight:(CGFloat)vbHeight
{
if (_vbHeight == vbHeight) {
return;
}
[self invalidate];
_vbHeight = vbHeight;
}
- (void)setAlign:(NSString *)align
{
if ([align isEqualToString:_align]) {
return;
}
[self invalidate];
_align = align;
}
- (void)setMeetOrSlice:(RNSVGVBMOS)meetOrSlice
{
if (meetOrSlice == _meetOrSlice) {
return;
}
[self invalidate];
_meetOrSlice = meetOrSlice;
}
- (void)renderTo:(CGContextRef)context
{
[self saveDefinition];
}
- (void)renderSymbolTo:(CGContextRef)context width:(CGFloat)width height:(CGFloat)height
{
if (self.align) {
CGRect eRect = CGRectMake([self getContextLeft], [self getContextTop], width, height);
CGAffineTransform viewBoxTransform = [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight)
eRect:eRect
align:self.align
meetOrSlice:self.meetOrSlice
fromSymbol:YES];
CGContextConcatCTM(context, viewBoxTransform);
}
[self renderGroupTo:context];
}
@end

View File

@@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree.
*/
#import "RNSVGUse.h"
#import "RNSVGSymbol.h"
#import <React/RCTLog.h>
@implementation RNSVGUse
@@ -27,8 +28,16 @@
if (template) {
[self beginTransparencyLayer:context];
[self clip:context];
[template mergeProperties:self];
[template renderTo:context];
if ([template class] == [RNSVGSymbol class]) {
[template mergeProperties:self];
RNSVGSymbol *symbol = template;
[symbol renderSymbolTo:context width:[self relativeOnWidth:self.width] height:[self relativeOnWidth:self.height]];
} else {
[template mergeProperties:self];
[template renderTo:context];
}
[self endTransparencyLayer:context];
} else if (self.href) {
// TODO: calling yellow box here

View File

@@ -23,8 +23,6 @@
1039D2951CE71EC2001E90A8 /* RNSVGText.m in Sources */ = {isa = PBXBuildFile; fileRef = 1039D2901CE71EC2001E90A8 /* RNSVGText.m */; };
1039D2A01CE72177001E90A8 /* RCTConvert+RNSVG.m in Sources */ = {isa = PBXBuildFile; fileRef = 1039D29C1CE72177001E90A8 /* RCTConvert+RNSVG.m */; };
1039D2B01CE72F27001E90A8 /* RNSVGPercentageConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */; };
10ABC7331D435915006CCF6E /* RNSVGViewBoxManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10ABC7321D435915006CCF6E /* RNSVGViewBoxManager.m */; };
10ABC7361D43595E006CCF6E /* RNSVGViewBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 10ABC7351D43595E006CCF6E /* RNSVGViewBox.m */; };
10BA0D341CE74E3100887C2B /* RNSVGCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10BA0D1D1CE74E3100887C2B /* RNSVGCircleManager.m */; };
10BA0D351CE74E3100887C2B /* RNSVGEllipseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10BA0D1F1CE74E3100887C2B /* RNSVGEllipseManager.m */; };
10BA0D361CE74E3100887C2B /* RNSVGGroupManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10BA0D211CE74E3100887C2B /* RNSVGGroupManager.m */; };
@@ -54,6 +52,9 @@
7F08CEA01E23479700650F83 /* RNSVGTextPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F08CE9D1E23479700650F83 /* RNSVGTextPath.m */; };
7F08CEA11E23479700650F83 /* RNSVGTSpan.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F08CE9F1E23479700650F83 /* RNSVGTSpan.m */; };
7F9CDAFA1E1F809C00E0C805 /* RNSVGPathParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F9CDAF91E1F809C00E0C805 /* RNSVGPathParser.m */; };
7FC260CE1E3499BC00A39833 /* RNSVGViewBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FC260CD1E3499BC00A39833 /* RNSVGViewBox.m */; };
7FC260D11E34A12000A39833 /* RNSVGSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FC260D01E34A12000A39833 /* RNSVGSymbol.m */; };
7FC260D41E34A12A00A39833 /* RNSVGSymbolManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FC260D31E34A12A00A39833 /* RNSVGSymbolManager.m */; };
7FFC4EA41E24E5AD00AD5BE5 /* RNSVGGlyphContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FFC4EA31E24E5AD00AD5BE5 /* RNSVGGlyphContext.m */; };
/* End PBXBuildFile section */
@@ -105,10 +106,6 @@
1039D2A11CE721A7001E90A8 /* RNSVGContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGContainer.h; sourceTree = "<group>"; };
1039D2AE1CE72F27001E90A8 /* RNSVGPercentageConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGPercentageConverter.h; path = Utils/RNSVGPercentageConverter.h; sourceTree = "<group>"; };
1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNSVGPercentageConverter.m; path = Utils/RNSVGPercentageConverter.m; sourceTree = "<group>"; };
10ABC7311D435915006CCF6E /* RNSVGViewBoxManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGViewBoxManager.h; sourceTree = "<group>"; };
10ABC7321D435915006CCF6E /* RNSVGViewBoxManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSVGViewBoxManager.m; sourceTree = "<group>"; };
10ABC7341D43595E006CCF6E /* RNSVGViewBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGViewBox.h; sourceTree = "<group>"; };
10ABC7351D43595E006CCF6E /* RNSVGViewBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSVGViewBox.m; sourceTree = "<group>"; };
10ABC7371D439779006CCF6E /* RNSVGCGFCRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGCGFCRule.h; path = Utils/RNSVGCGFCRule.h; sourceTree = "<group>"; };
10ABC7381D43982B006CCF6E /* RNSVGVBMOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGVBMOS.h; path = Utils/RNSVGVBMOS.h; sourceTree = "<group>"; };
10BA0D1C1CE74E3100887C2B /* RNSVGCircleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGCircleManager.h; sourceTree = "<group>"; };
@@ -171,6 +168,12 @@
7F08CEA31E23481F00650F83 /* RNSVGTextAnchor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGTextAnchor.h; path = Utils/RNSVGTextAnchor.h; sourceTree = "<group>"; };
7F9CDAF81E1F809C00E0C805 /* RNSVGPathParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGPathParser.h; path = Utils/RNSVGPathParser.h; sourceTree = "<group>"; };
7F9CDAF91E1F809C00E0C805 /* RNSVGPathParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNSVGPathParser.m; path = Utils/RNSVGPathParser.m; sourceTree = "<group>"; };
7FC260CC1E3499BC00A39833 /* RNSVGViewBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGViewBox.h; path = Utils/RNSVGViewBox.h; sourceTree = "<group>"; };
7FC260CD1E3499BC00A39833 /* RNSVGViewBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNSVGViewBox.m; path = Utils/RNSVGViewBox.m; sourceTree = "<group>"; };
7FC260CF1E34A12000A39833 /* RNSVGSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGSymbol.h; path = Elements/RNSVGSymbol.h; sourceTree = "<group>"; };
7FC260D01E34A12000A39833 /* RNSVGSymbol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNSVGSymbol.m; path = Elements/RNSVGSymbol.m; sourceTree = "<group>"; };
7FC260D21E34A12A00A39833 /* RNSVGSymbolManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSVGSymbolManager.h; sourceTree = "<group>"; };
7FC260D31E34A12A00A39833 /* RNSVGSymbolManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSVGSymbolManager.m; sourceTree = "<group>"; };
7FFC4EA21E24E52500AD5BE5 /* RNSVGGlyphContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSVGGlyphContext.h; path = Text/RNSVGGlyphContext.h; sourceTree = "<group>"; };
7FFC4EA31E24E5AD00AD5BE5 /* RNSVGGlyphContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNSVGGlyphContext.m; path = Text/RNSVGGlyphContext.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -200,8 +203,6 @@
10ED4AA11CF078830078BC02 /* RNSVGNode.m */,
0CF68AE11AF0549300FF9E5C /* RNSVGRenderable.h */,
0CF68AE21AF0549300FF9E5C /* RNSVGRenderable.m */,
10ABC7341D43595E006CCF6E /* RNSVGViewBox.h */,
10ABC7351D43595E006CCF6E /* RNSVGViewBox.m */,
0CF68AC21AF0540F00FF9E5C /* Products */,
);
sourceTree = "<group>";
@@ -235,12 +236,12 @@
0CF68AF81AF0549300FF9E5C /* ViewManagers */ = {
isa = PBXGroup;
children = (
7FC260D21E34A12A00A39833 /* RNSVGSymbolManager.h */,
7FC260D31E34A12A00A39833 /* RNSVGSymbolManager.m */,
7F08CE961E23476900650F83 /* RNSVGTextPathManager.h */,
7F08CE971E23476900650F83 /* RNSVGTextPathManager.m */,
7F08CE981E23476900650F83 /* RNSVGTSpanManager.h */,
7F08CE991E23476900650F83 /* RNSVGTSpanManager.m */,
10ABC7311D435915006CCF6E /* RNSVGViewBoxManager.h */,
10ABC7321D435915006CCF6E /* RNSVGViewBoxManager.m */,
10BEC1BE1D3F680F00FDCB19 /* RNSVGLinearGradientManager.h */,
10BEC1BF1D3F680F00FDCB19 /* RNSVGLinearGradientManager.m */,
10BEC1C01D3F680F00FDCB19 /* RNSVGRadialGradientManager.h */,
@@ -312,6 +313,8 @@
1039D2801CE71DCF001E90A8 /* Elements */ = {
isa = PBXGroup;
children = (
7FC260CF1E34A12000A39833 /* RNSVGSymbol.h */,
7FC260D01E34A12000A39833 /* RNSVGSymbol.m */,
10BEC1B81D3F66F500FDCB19 /* RNSVGLinearGradient.h */,
10BEC1B91D3F66F500FDCB19 /* RNSVGLinearGradient.m */,
10BEC1BA1D3F66F500FDCB19 /* RNSVGRadialGradient.h */,
@@ -337,6 +340,8 @@
1039D29A1CE7212C001E90A8 /* Utils */ = {
isa = PBXGroup;
children = (
7FC260CC1E3499BC00A39833 /* RNSVGViewBox.h */,
7FC260CD1E3499BC00A39833 /* RNSVGViewBox.m */,
7F08CEA31E23481F00650F83 /* RNSVGTextAnchor.h */,
1039D29E1CE72177001E90A8 /* RNSVGCGFloatArray.h */,
10ABC7381D43982B006CCF6E /* RNSVGVBMOS.h */,
@@ -407,7 +412,6 @@
buildActionMask = 2147483647;
files = (
10BA0D3F1CE74E3100887C2B /* RNSVGTextManager.m in Sources */,
10ABC7361D43595E006CCF6E /* RNSVGViewBox.m in Sources */,
1039D28A1CE71EB7001E90A8 /* RNSVGImage.m in Sources */,
10BA0D4B1CE74E3D00887C2B /* RNSVGRect.m in Sources */,
10BA0D341CE74E3100887C2B /* RNSVGCircleManager.m in Sources */,
@@ -415,7 +419,6 @@
1039D2B01CE72F27001E90A8 /* RNSVGPercentageConverter.m in Sources */,
7FFC4EA41E24E5AD00AD5BE5 /* RNSVGGlyphContext.m in Sources */,
10BA0D491CE74E3D00887C2B /* RNSVGEllipse.m in Sources */,
10ABC7331D435915006CCF6E /* RNSVGViewBoxManager.m in Sources */,
1039D28B1CE71EB7001E90A8 /* RNSVGPath.m in Sources */,
7F08CEA01E23479700650F83 /* RNSVGTextPath.m in Sources */,
0CF68B0D1AF0549300FF9E5C /* RNSVGPattern.m in Sources */,
@@ -438,16 +441,19 @@
10BEC1C31D3F680F00FDCB19 /* RNSVGRadialGradientManager.m in Sources */,
10BA0D371CE74E3100887C2B /* RNSVGImageManager.m in Sources */,
10BA0D391CE74E3100887C2B /* RNSVGNodeManager.m in Sources */,
7FC260D11E34A12000A39833 /* RNSVGSymbol.m in Sources */,
1023B4901D3DF4C40051496D /* RNSVGDefs.m in Sources */,
10BA0D381CE74E3100887C2B /* RNSVGLineManager.m in Sources */,
10BA0D481CE74E3D00887C2B /* RNSVGCircle.m in Sources */,
10BA0D351CE74E3100887C2B /* RNSVGEllipseManager.m in Sources */,
1039D2A01CE72177001E90A8 /* RCTConvert+RNSVG.m in Sources */,
0CF68B0B1AF0549300FF9E5C /* RNSVGBrush.m in Sources */,
7FC260D41E34A12A00A39833 /* RNSVGSymbolManager.m in Sources */,
7F9CDAFA1E1F809C00E0C805 /* RNSVGPathParser.m in Sources */,
10BA0D361CE74E3100887C2B /* RNSVGGroupManager.m in Sources */,
7F08CE9A1E23476900650F83 /* RNSVGTextPathManager.m in Sources */,
7F08CE9B1E23476900650F83 /* RNSVGTSpanManager.m in Sources */,
7FC260CE1E3499BC00A39833 /* RNSVGViewBox.m in Sources */,
7F08CEA11E23479700650F83 /* RNSVGTSpan.m in Sources */,
10BA0D4A1CE74E3D00887C2B /* RNSVGLine.m in Sources */,
10FDEEB21D3FB60500A5C46C /* RNSVGBaseBrush.m in Sources */,

View File

@@ -66,9 +66,9 @@
*/
- (RNSVGSvgView *)getSvgView;
- (CGFloat)relativeOnWidth:(NSString *)position;
- (CGFloat)relativeOnWidth:(NSString *)length;
- (CGFloat)relativeOnHeight:(NSString *)position;
- (CGFloat)relativeOnHeight:(NSString *)length;
- (CGFloat)getContextWidth;

View File

@@ -139,7 +139,7 @@
}
}
- (CGPathRef)getPath: (CGContextRef) context
- (CGPathRef)getPath: (CGContextRef)context
{
// abstract
return nil;
@@ -184,14 +184,14 @@
return _svgView;
}
- (CGFloat)relativeOnWidth:(NSString *)position
- (CGFloat)relativeOnWidth:(NSString *)length
{
return [RNSVGPercentageConverter stringToFloat:position relative:[self getContextWidth] offset:0];
return [RNSVGPercentageConverter stringToFloat:length relative:[self getContextWidth] offset:0];
}
- (CGFloat)relativeOnHeight:(NSString *)position
- (CGFloat)relativeOnHeight:(NSString *)length
{
return [RNSVGPercentageConverter stringToFloat:position relative:[self getContextHeight] offset:0];
return [RNSVGPercentageConverter stringToFloat:length relative:[self getContextHeight] offset:0];
}
- (CGFloat)getContextWidth

View File

@@ -1,25 +0,0 @@
/**
* 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 "RNSVGGroup.h"
#import "RNSVGVBMOS.h"
@interface RNSVGViewBox : RNSVGGroup
@property (nonatomic, strong) NSString *minX;
@property (nonatomic, strong) NSString *minY;
@property (nonatomic, strong) NSString *vbWidth;
@property (nonatomic, strong) NSString *vbHeight;
@property (nonatomic, strong) NSString *align;
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
@property (nonatomic, strong) NSString *width;
@property (nonatomic, strong) NSString *height;
+ (CGAffineTransform)getTransform:(CGRect)vbRect eRect:(CGRect)eRect align:(NSString *)align meetOrSlice:(RNSVGVBMOS)meetOrSlice fromSymbol:(BOOL)fromSymbol;
@end

16
ios/Utils/RNSVGViewBox.h Normal file
View File

@@ -0,0 +1,16 @@
/**
* 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 <UIKit/UIKit.h>
#import "RNSVGVBMOS.h"
@interface RNSVGViewBox : NSObject
+ (CGAffineTransform)getTransform:(CGRect)vbRect eRect:(CGRect)eRect align:(NSString *)align meetOrSlice:(RNSVGVBMOS)meetOrSlice fromSymbol:(BOOL)fromSymbol;
@end

View File

@@ -11,92 +11,6 @@
#import "RNSVGUse.h"
@implementation RNSVGViewBox
{
BOOL _fromSymbol;
}
- (void)setMinX:(NSString *)minX
{
if (minX == _minX) {
return;
}
[self invalidate];
_minX = minX;
}
- (void)setMinY:(NSString *)minY
{
if (minY == _minY) {
return;
}
[self invalidate];
_minY = minY;
}
- (void)setVbHeight:(NSString *)vbHeight
{
if (vbHeight == _vbHeight) {
return;
}
[self invalidate];
_vbHeight = vbHeight;
}
- (void)setVbWidth:(NSString *)vbWidth
{
if (vbWidth == _vbWidth) {
return;
}
[self invalidate];
_vbWidth = vbWidth;
}
- (void)setAlign:(NSString *)align
{
if (align == _align) {
return;
}
[self invalidate];
_align = align;
}
- (void)setMeetOrSlice:(RNSVGVBMOS)meetOrSlice
{
if (meetOrSlice == _meetOrSlice) {
return;
}
[self invalidate];
_meetOrSlice = meetOrSlice;
}
- (void)renderTo:(CGContextRef)context
{
self.matrix = [self getTransformFromProps];
[super renderTo:context];
}
- (CGAffineTransform)getTransformFromProps
{
CGFloat vbX = [self relativeOnWidth:_minX];
CGFloat vbY = [self relativeOnWidth:_minY];
CGFloat vbWidth = [self relativeOnWidth:_vbWidth];
CGFloat vbHeight = [self relativeOnWidth:_vbHeight];
CGFloat eX = [self getContextLeft];
CGFloat eY = [self getContextTop];
CGFloat eWidth = self.width ? [self relativeOnWidth:self.width] : [self getContextWidth];
CGFloat eHeight = self.height ? [self relativeOnWidth:self.height] : [self getContextHeight];
return [RNSVGViewBox getTransform:CGRectMake(vbX, vbY, vbWidth, vbHeight)
eRect:CGRectMake(eX, eY, eWidth, eHeight)
align:self.align
meetOrSlice:self.meetOrSlice
fromSymbol:_fromSymbol];
}
+ (CGAffineTransform)getTransform:(CGRect)vbRect eRect:(CGRect)eRect align:(NSString *)align meetOrSlice:(RNSVGVBMOS)meetOrSlice fromSymbol:(BOOL)fromSymbol
{
@@ -180,22 +94,4 @@
return CGAffineTransformTranslate(transform, -translateX * (fromSymbol ? scaleX : 1), -translateY * (fromSymbol ? scaleY : 1));
}
- (void)mergeProperties:(__kindof RNSVGNode *)target
{
if ([target isKindOfClass:[RNSVGUse class]]) {
RNSVGUse *use = target;
_fromSymbol = YES;
self.width = use.width;
self.height = use.height;
}
}
- (void)resetProperties
{
if (_fromSymbol) {
self.width = self.height = nil;
_fromSymbol = NO;
}
}
@end

View File

@@ -20,6 +20,12 @@ RCT_EXPORT_MODULE()
return [RNSVGSvgView new];
}
RCT_EXPORT_VIEW_PROPERTY(minX, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(minY, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(vbWidth, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(vbHeight, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(align, NSString)
RCT_EXPORT_VIEW_PROPERTY(meetOrSlice, RNSVGVBMOS)
RCT_EXPORT_METHOD(toDataURL:(nonnull NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback)
{

View File

@@ -6,8 +6,8 @@
* LICENSE file in the root directory of this source tree.
*/
#import "RNSVGGroupManager.h"
#import "RNSVGNodeManager.h"
@interface RNSVGViewBoxManager : RNSVGGroupManager
@interface RNSVGSymbolManager : RNSVGNodeManager
@end

View File

@@ -0,0 +1,31 @@
/**
* 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 "RNSVGSymbolManager.h"
#import "RNSVGRenderable.h"
#import "RNSVGSymbol.h"
#import "RCTConvert+RNSVG.h"
#import "RNSVGVBMOS.h"
@implementation RNSVGSymbolManager
RCT_EXPORT_MODULE()
- (RNSVGRenderable *)node
{
return [RNSVGSymbol new];
}
RCT_EXPORT_VIEW_PROPERTY(minX, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(minY, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(vbWidth, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(vbHeight, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(align, NSString)
RCT_EXPORT_VIEW_PROPERTY(meetOrSlice, RNSVGVBMOS)
@end

View File

@@ -1,29 +0,0 @@
/**
* 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 "RNSVGViewBoxManager.h"
#import "RNSVGViewBox.h"
#import "RNSVGVBMOS.h"
@implementation RNSVGViewBoxManager
RCT_EXPORT_MODULE()
- (RNSVGViewBox *)node
{
return [RNSVGViewBox new];
}
RCT_EXPORT_VIEW_PROPERTY(minX, NSString)
RCT_EXPORT_VIEW_PROPERTY(minY, NSString)
RCT_EXPORT_VIEW_PROPERTY(vbWidth, NSString)
RCT_EXPORT_VIEW_PROPERTY(vbHeight, NSString)
RCT_EXPORT_VIEW_PROPERTY(align, NSString)
RCT_EXPORT_VIEW_PROPERTY(meetOrSlice, RNSVGVBMOS)
@end

View File

@@ -33,8 +33,7 @@ const ViewBoxAttributes = {
vbWidth: true,
vbHeight: true,
align: true,
meetOrSlice: true,
name: true
meetOrSlice: true
};
const NodeAttributes = {
@@ -81,6 +80,10 @@ const UseAttributes = merge({
height: true
}, RenderableAttributes);
const SymbolAttributes = merge({
name: true
}, ViewBoxAttributes);
const PathAttributes = merge({
d: true
}, RenderableAttributes);
@@ -185,6 +188,7 @@ export {
LineAttributes,
RectAttributes,
UseAttributes,
SymbolAttributes,
LinearGradientAttributes,
RadialGradientAttributes,
ViewBoxAttributes

View File

@@ -0,0 +1,56 @@
import React, {Component, PropTypes} from 'react';
import createReactNativeComponentClass from 'react-native/Libraries/Renderer/src/renderers/native/createReactNativeComponentClass';
import {ViewBoxAttributes} from '../attributes';
const meetOrSliceTypes = {
meet: 0,
slice: 1,
none: 2
};
const alignEnum = [
'xMinYMin', 'xMidYMin', 'xMaxYMin',
'xMinYMid', 'xMidYMid', 'xMaxYMid',
'xMinYMax', 'xMidYMax', 'xMaxYMax',
'none'
].reduce((prev, name) => {
prev[name] = name;
return prev;
}, {});
const spacesRegExp = /\s+/;
export default function (props) {
const {viewBox, preserveAspectRatio} = props;
if (!viewBox) {
return null;
}
let params = viewBox.trim().split(spacesRegExp);
if (params.length === 4 && params.every(param => !isNaN(+params))) {
console.warn('Invalid `viewBox` prop:' + viewBox);
return null;
}
let modes = preserveAspectRatio ? preserveAspectRatio.trim().split(spacesRegExp) : [];
let meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
let align = alignEnum[modes[0]] || 'xMidYMid';
return {
minX: +params[0],
minY: +params[1],
vbWidth: +params[2],
vbHeight: +params[3],
align,
meetOrSlice
}
}
export {
meetOrSliceTypes,
alignEnum
};