complete ClipPath refactor

This commit is contained in:
Horcrux
2016-07-20 14:44:19 +08:00
parent dd6cb80e84
commit 18e1b60823
30 changed files with 254 additions and 251 deletions

View File

@@ -7,7 +7,9 @@ import Svg, {
G,
Path,
Use,
Rect
Rect,
Circle,
ClipPath
} from 'react-native-svg';
class DefsExample extends Component{
@@ -19,12 +21,16 @@ class DefsExample extends Component{
width="100"
>
<Defs>
<G id="path" x="5" y="2">
<G id="path" x="5" y="2" opacity="0.9">
<Path id="test" fill='red' d="M38.459,1.66A0.884,0.884,0,0,1,39,2.5a0.7,0.7,0,0,1-.3.575L23.235,16.092,27.58,26.1a1.4,1.4,0,0,1,.148.3,1.3,1.3,0,0,1,0,.377,1.266,1.266,0,0,1-2.078.991L15.526,20.6l-7.58,4.35a1.255,1.255,0,0,1-.485,0,1.267,1.267,0,0,1-1.277-1.258q0-.01,0-0.02a1.429,1.429,0,0,1,0-.446C7.243,20.253,8.6,16.369,8.6,16.29L3.433,13.545A0.743,0.743,0,0,1,2.9,12.822a0.822,0.822,0,0,1,.623-0.773l8.164-2.972,3.018-8.5A0.822,0.822,0,0,1,15.427,0a0.752,0.752,0,0,1,.752.555l2.563,6.936S37.65,1.727,37.792,1.685A1.15,1.15,0,0,1,38.459,1.66Z"/>
</G>
<ClipPath id="clip">
<Circle r="20%" cx="0" cy="0" />
</ClipPath>
</Defs>
<Use href="url(#path)" x="0" fill="blue" />
<Use href="url(#path)" x="10" fill="#3a8" />
<Use href="url(#path)" x="0" fill="blue" opacity="0.5" />
<Use href="url(#path)" x="20" y="5" fill="#8a3" />
<Use href="url(#path)" x="30" clipPath="url(#clip)" />
</Svg>;
}
}
@@ -34,11 +40,11 @@ const icon = <Svg
width="20"
>
<Defs>
<G id="path">
<G id="path" scale="0.5">
<Path fill='red' d="M38.459,1.66A0.884,0.884,0,0,1,39,2.5a0.7,0.7,0,0,1-.3.575L23.235,16.092,27.58,26.1a1.4,1.4,0,0,1,.148.3,1.3,1.3,0,0,1,0,.377,1.266,1.266,0,0,1-2.078.991L15.526,20.6l-7.58,4.35a1.255,1.255,0,0,1-.485,0,1.267,1.267,0,0,1-1.277-1.258q0-.01,0-0.02a1.429,1.429,0,0,1,0-.446C7.243,20.253,8.6,16.369,8.6,16.29L3.433,13.545A0.743,0.743,0,0,1,2.9,12.822a0.822,0.822,0,0,1,.623-0.773l8.164-2.972,3.018-8.5A0.822,0.822,0,0,1,15.427,0a0.752,0.752,0,0,1,.752.555l2.563,6.936S37.65,1.727,37.792,1.685A1.15,1.15,0,0,1,38.459,1.66Z"/>
</G>
</Defs>
<Use href="url(#path)" x="10" fill="#3a8" />
<Use href="url(#path)" fill="#3a8" />
</Svg>;

View File

@@ -7,15 +7,16 @@ import {circleProps, pathProps, fillProps, strokeProps, numberProp} from '../lib
class Circle extends Shape {
static displayName = 'Circle';
static propTypes = {
...pathProps,
...circleProps
};
static contextTypes = {
...fillProps,
...strokeProps,
...circleProps
static defaultProps = {
cx: 0,
cy: 0,
r: 0
};
setNativeProps = (...args) => {

View File

@@ -1,5 +1,4 @@
import React, {Component, PropTypes} from 'react';
import {set, remove} from '../lib/extract/extractClipping';
import createReactNativeComponentClass from 'react/lib/createReactNativeComponentClass';
import {ClipPathAttributes} from '../lib/attributes';
@@ -9,26 +8,9 @@ class ClipPath extends Component{
id: PropTypes.string.isRequired
};
constructor() {
super(...arguments);
this.id = this.props.id + ':' + this.props.svgId;
}
componentWillReceiveProps = nextProps => {
let id = nextProps.id + ':' + nextProps.svgId;
if (id !== this.id) {
remove(this.id);
}
};
componentWillUnmount = () => {
remove(this.id);
};
render() {
set(this.id, this.id);
return <RNSVGClipPath
name={this.id}
name={this.props.id}
>{this.props.children}</RNSVGClipPath>;
}
}

View File

@@ -7,15 +7,17 @@ import {EllipseAttributes} from '../lib/attributes';
class Ellipse extends Shape{
static displayName = 'Ellipse';
static propTypes = {
...pathProps,
...ellipseProps
};
static contextTypes = {
...fillProps,
...strokeProps,
...ellipseProps
static defaultProps = {
cx: 0,
cy: 0,
rx: 0,
ry: 0
};
setNativeProps = (...args) => {

View File

@@ -1,31 +1,14 @@
import React, {Component, PropTypes} from 'react';
import _ from 'lodash';
import createReactNativeComponentClass from 'react/lib/createReactNativeComponentClass';
import {numberProp, contextProps} from '../lib/props';
import {transformProps} from '../lib/props';
import {GroupAttributes} from '../lib/attributes';
import extractProps from '../lib/extract/extractProps';
class G extends Component{
static displayName = 'G';
static contextTypes = {
...contextProps
};
static childContextTypes = {
...contextProps
};
getChildContext = () => {
let context = _.reduce(contextProps, (props, value, key) => {
if (!_.isNil(this.props[key])) {
props[key] = this.props[key];
}
return props;
}, {});
return _.defaults({}, this.context, context);
};
static propTypes = transformProps;
setNativeProps = (...args) => {
this.root.setNativeProps(...args);

View File

@@ -11,14 +11,21 @@ class Image extends Shape {
static propTypes = {
x: numberProp,
y: numberProp,
width: numberProp,
height: numberProp,
width: numberProp.isRequired,
height: numberProp.isRequired,
href: PropTypes.number.isRequired,
...responderProps,
...touchableProps
//preserveAspectRatio: PropTypes.string
};
static defaultProps = {
x: 0,
y: 0,
width: 0,
height: 0
};
setNativeProps = (...args) => {
this.root.setNativeProps(...args);
};

View File

@@ -7,15 +7,17 @@ import {lineProps, pathProps, fillProps, strokeProps, numberProp} from '../lib/p
class Line extends Shape {
static displayName = 'Line';
static propTypes = {
...pathProps,
...lineProps
};
static contextTypes = {
...fillProps,
...strokeProps,
...lineProps
static defaultProps = {
x1: 0,
y1: 0,
x2: 0,
y2: 0
};
setNativeProps = (...args) => {

View File

@@ -10,23 +10,10 @@ class Path extends Shape {
static displayName = 'Path';
static propTypes = {
d: PropTypes.string,
d: PropTypes.string.isRequired,
...pathProps
};
static contextTypes = {
...pathProps
};
_dimensions = null;
componentWillReceiveProps = nextProps => {
if (nextProps.d !== this.props.d) {
this._dimensions = null;
}
};
setNativeProps = (...args) => {
this.root.setNativeProps(...args);
};

View File

@@ -1,12 +1,17 @@
import React, {Component, PropTypes} from 'react';
import Path from './Path';
import {pathProps} from '../lib/props';
import _ from 'lodash';
class Polygon extends Component{
static displayName = 'Polygon';
static propTypes = {
...pathProps,
points: PropTypes.oneOfType([PropTypes.string, PropTypes.array])
points: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired
};
static defaultProps = {
points: ''
};
setNativeProps = (...args) => {
@@ -14,10 +19,15 @@ class Polygon extends Component{
};
render() {
let points = this.props.points;
if (_.isArray(points)) {
points = points.join(',');
}
return <Path
ref={ele => this.root = ele}
{...this.props}
d={`M${this.props.points.trim().replace(/\s+/g, 'L')}z`}
d={`M${points.trim().replace(/\s+/g, 'L')}z`}
/>;
}
}

View File

@@ -1,12 +1,17 @@
import React, {Component, PropTypes} from 'react';
import Path from './Path';
import {pathProps} from '../lib/props';
import _ from 'lodash';
class Polyline extends Component{
static displayName = 'Polyline';
static propTypes = {
...pathProps,
points: PropTypes.oneOfType([PropTypes.string, PropTypes.array])
points: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired
};
static defaultProps = {
points: ''
};
setNativeProps = (...args) => {
@@ -14,10 +19,15 @@ class Polyline extends Component{
};
render() {
let points = this.props.points;
if (_.isArray(points)) {
points = points.join(',');
}
return <Path
ref={ele => this.root = ele}
{...this.props}
d={`M${this.props.points.trim().replace(/\s+/g, 'L')}`}
d={`M${points.trim().replace(/\s+/g, 'L')}`}
/>;
}
}

View File

@@ -8,15 +8,19 @@ import Shape from './Shape';
class Rect extends Shape {
static displayName = 'Rect';
static propTypes = {
...pathProps,
...rectProps
};
static contextTypes = {
...fillProps,
...strokeProps,
...rectProps
static defaultProps = {
x: 0,
y: 0,
width: 0,
height: 0,
rx: 0,
ry: 0
};
setNativeProps = (...args) => {
@@ -37,8 +41,8 @@ class Rect extends Shape {
y={props.y.toString()}
width={props.width.toString()}
height={props.height.toString()}
rx={props.rx ? props.rx.toString() : '0'}
ry={props.ry ? props.ry.toString() : '0'}
rx={props.rx.toString()}
ry={props.ry.toString()}
/>;
}
}

View File

@@ -30,15 +30,6 @@ class Svg extends Component{
id++;
this.id = id;
}
getChildren = () => {
return Children.map(this.props.children, child => {
return cloneElement(child, {
svgId: this.id
});
});
};
measureInWindow = (...args) => {
this.root.measureInWindow(...args);
};
@@ -67,9 +58,7 @@ class Svg extends Component{
preserveAspectRatio={props.preserveAspectRatio}
width={props.width}
height={props.height}
>
{this.getChildren()}
</ViewBox> : this.getChildren();
>{props.children}</ViewBox> : props.children;
return (
<NativeSvgView

View File

@@ -10,6 +10,7 @@ import Shape from './Shape';
class Text extends Shape {
static displayName = 'Text';
static propTypes = {
dx: numberProp,
dy: numberProp,
@@ -17,10 +18,9 @@ class Text extends Shape {
...pathProps
};
static contextTypes = {
...textProps,
...fillProps,
...strokeProps
static defaultProps = {
dx: 0,
dy: 0
};
setNativeProps = (...args) => {

View File

@@ -1,10 +1,11 @@
import {PropTypes} from 'react';
import {pathProps} from '../lib/props';
import {UseAttributes} from '../lib/attributes';
import {UseAttributes, RenderableOnlyAttributes} from '../lib/attributes';
import Shape from './Shape';
import React from 'react';
import patternReg from '../lib/extract/patternReg';
import createReactNativeComponentClass from 'react/lib/createReactNativeComponentClass';
import _ from 'lodash';
class Defs extends Shape {
static displayName = 'Use';
@@ -32,14 +33,35 @@ class Defs extends Shape {
console.warn('Invalid `href` prop for `Use` element, expected a href like `"url(#id)"`, but got: "' + props.href + '"');
}
return <RNSVGUse
ref={ele => this.root = ele}
{...this.extractProps(props, {
let mergeList = [];
let extractedProps = this.extractProps(props, {
stroke: true,
fill: true,
responder: true,
transform: true
})}
});
Object.keys(RenderableOnlyAttributes).forEach(name => {
if (!_.isNil(props[name])) {
// clipPath prop may provide `clipPathRef` as native prop
if (name === 'clipPath') {
if (extractedProps[name]) {
mergeList.push(name);
} else if (extractedProps.clipPathRef) {
mergeList.push('clipPathRef');
}
} else {
mergeList.push(name);
}
}
});
return <RNSVGUse
ref={ele => this.root = ele}
{...extractedProps}
mergeList={mergeList}
href={href}
>{props.children}</RNSVGUse>;
}

View File

@@ -14,6 +14,4 @@
@interface RNSVGClipPath : RNSVGGroup
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
@end

View File

@@ -10,16 +10,16 @@
@implementation RNSVGClipPath
- (void)saveDefination:(CGContextRef)context
{
[[self getSvgView] defineClipPath:[self getPath:context] clipPathRef:self.name];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
return nil;
}
- (void)saveDefination:(CGContextRef)context
{
[[self getSvgView] defineClipPath:self clipPathRef:self.name];
}
- (void)removeDefination
{
if (self.name) {

View File

@@ -64,10 +64,17 @@
[super willRemoveSubview:subview];
}
- (void)mergeProperties:(__kindof RNSVGNode *)target
- (void)mergeProperties:(__kindof RNSVGNode *)target mergeList:(NSArray<NSString *> *)mergeList
{
for (RNSVGNode *node in self.subviews) {
[node mergeProperties:target];
[node mergeProperties:target mergeList:mergeList];
}
}
- (void)resetProperties
{
for (RNSVGNode *node in self.subviews) {
[node resetProperties];
}
}

View File

@@ -19,13 +19,13 @@
/**
* define <ClipPath></ClipPath> content as clipPath template.
*/
- (void)defineClipPath:(CGPathRef)clipPath clipPathRef:(NSString *)clipPathRef;
- (void)defineClipPath:(__kindof RNSVGNode *)clipPath clipPathRef:(NSString *)clipPathRef;
- (void)removeClipPath:(NSString *)clipPathRef;
- (CGPathRef)getDefinedClipPath:(NSString *)clipPathRef;
- (RNSVGNode *)getDefinedClipPath:(NSString *)clipPathRef;
- (void)defineTemplate:(RNSVGNode *)template templateRef:(NSString *)templateRef;
- (void)defineTemplate:(__kindof RNSVGNode *)template templateRef:(NSString *)templateRef;
- (void)removeTemplate:(NSString *)tempalteRef;

View File

@@ -13,7 +13,7 @@
@implementation RNSVGSvgView
{
NSMutableDictionary<NSString *, NSValue *> *clipPaths;
NSMutableDictionary<NSString *, RNSVGNode *> *clipPaths;
NSMutableDictionary<NSString *, RNSVGNode *> *templates;
}
@@ -64,12 +64,12 @@
return self.responsible ? [super hitTest:point withEvent:event] : nil;
}
- (void)defineClipPath:(CGPathRef)clipPath clipPathRef:(NSString *)clipPathRef
- (void)defineClipPath:(__kindof RNSVGNode *)clipPath clipPathRef:(NSString *)clipPathRef
{
if (!clipPaths) {
clipPaths = [[NSMutableDictionary alloc] init];
}
[clipPaths setValue:[NSValue valueWithPointer:clipPath] forKey:clipPathRef];
[clipPaths setObject:clipPath forKey:clipPathRef];
}
- (void)removeClipPath:(NSString *)clipPathRef
@@ -79,9 +79,9 @@
}
}
- (CGPathRef)getDefinedClipPath:(NSString *)clipPathRef
- (RNSVGNode *)getDefinedClipPath:(NSString *)clipPathRef
{
return clipPaths ? [[clipPaths valueForKey:clipPathRef] pointerValue] : nil;
return clipPaths ? [clipPaths objectForKey:clipPathRef] : nil;
}
- (void)defineTemplate:(RNSVGNode *)template templateRef:(NSString *)templateRef

View File

@@ -15,5 +15,7 @@
@interface RNSVGUse : RNSVGRenderable
@property (nonatomic, strong) NSString *href;
@property (nonatomic, copy) NSArray<NSString *> *mergeList;
@end

View File

@@ -10,12 +10,22 @@
@implementation RNSVGUse
- (void)setMergeList:(NSArray<NSString *> *)mergeList
{
if (mergeList == _mergeList) {
return;
}
_mergeList = mergeList;
[self invalidate];
}
- (void)renderLayerTo:(CGContextRef)context
{
RNSVGNode* template = [[self getSvgView] getDefinedTemplate:self.href];
if (template) {
[template mergeProperties:self];
[template mergeProperties:self mergeList:self.mergeList];
[template renderTo:context];
[template resetProperties];
} else if (self.href) {
// TODO: calling yellow box here
RCTLogWarn(@"`Use` element expected a pre-defined svg template as `href` prop, template named: %@ is not defined.", self.href);

View File

@@ -36,16 +36,13 @@
*/
- (void)renderLayerTo:(CGContextRef)context;
- (void)renderClip:(CGContextRef)context;
/**
* clip node by clipPath or clipPathRef.
*/
- (void)clip:(CGContextRef)context;
/**
* get clip path for current node.
*/
- (CGPathRef)getClipPath;
/**
* getPath will return the path inside node as a ClipPath.
*/
@@ -70,8 +67,13 @@
- (void)removeDefination;
/**
* merge owned properties into target element`s properties
* Just for template node to merge target node`s properties into owned properties
*/
- (void)mergeProperties:(__kindof RNSVGNode *)target;
- (void)mergeProperties:(__kindof RNSVGNode *)target mergeList:(NSArray<NSString *> *)mergeList;
/**
* Just for template node to reset all owned properties once after rendered.
*/
- (void)resetProperties;
@end

View File

@@ -11,6 +11,9 @@
#import "RNSVGClipPath.h"
@implementation RNSVGNode
{
CGFloat originOpacity;
}
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
{
@@ -76,13 +79,22 @@
if (transparent) {
CGContextBeginTransparencyLayer(context, NULL);
}
[self renderClip:context];
[self renderLayerTo:context];
if (transparent) {
CGContextEndTransparencyLayer(context);
}
CGContextRestoreGState(context);
}
- (void)renderClip:(CGContextRef)context
{
if (self.clipPathRef) {
self.clipPath = [[[self getSvgView] getDefinedClipPath:self.clipPathRef] getPath:context];
}
}
- (void)setClipPath:(CGPathRef)clipPath
{
if (_clipPath == clipPath) {
@@ -99,25 +111,12 @@
return CGPathCreateMutable();
}
- (CGPathRef)getClipPath
{
CGPathRef clipPath = nil;
if (self.clipPath) {
clipPath = self.clipPath;
} else if (self.clipPathRef) {
clipPath = [[self getSvgView] getDefinedClipPath:self.clipPathRef];
}
return clipPath;
}
- (void)clip:(CGContextRef)context
{
CGPathRef clipPath = [self getClipPath];
CGPathRef clipPath = self.clipPath;
if (clipPath) {
CGContextAddPath(context, [self getClipPath]);
CGContextAddPath(context, clipPath);
if (self.clipRule == kRNSVGCGFCRuleEvenodd) {
CGContextEOClip(context);
} else {
@@ -182,12 +181,17 @@
}
}
- (void)mergeProperties:(__kindof RNSVGNode *)target
- (void)mergeProperties:(__kindof RNSVGNode *)target mergeList:(NSArray<NSString *> *)mergeList
{
originOpacity = self.opacity;
self.opacity = target.opacity * self.opacity;
}
- (void)resetProperties
{
self.opacity = originOpacity;
}
- (void)dealloc
{
CGPathRelease(_clipPath);

View File

@@ -9,6 +9,10 @@
#import "RNSVGRenderable.h"
@implementation RNSVGRenderable
{
NSMutableDictionary *originProperties;
NSArray *changedList;
}
- (id)init
{
@@ -93,6 +97,7 @@
CGContextSaveGState(context);
CGContextConcatCTM(context, self.transform);
CGContextSetAlpha(context, self.opacity);
[self renderClip:context];
[self renderLayerTo:context];
CGContextRestoreGState(context);
}
@@ -100,7 +105,7 @@
// hitTest delagate
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGPathRef clipPath = [self getClipPath];
CGPathRef clipPath = self.clipPath;
if (self.nodeArea && CGPathContainsPoint(self.nodeArea, nil, point, NO)) {
if (!clipPath) {
return self;
@@ -112,38 +117,33 @@
}
}
- (void)mergeProperties:(__kindof RNSVGNode *)target
- (void)mergeProperties:(__kindof RNSVGNode *)target mergeList:(NSArray<NSString *> *)mergeList
{
RNSVGRenderable* renderableTarget = target;
if (renderableTarget.fill) {
self.fill = renderableTarget.fill;
if (mergeList.count == 0) {
return;
}
if (renderableTarget.fillRule) {
self.fillRule = renderableTarget.fillRule;
originProperties = [[NSMutableDictionary alloc] init];
changedList = mergeList;
for (NSString *key in mergeList) {
[originProperties setValue:[self valueForKey:key] forKey:key];
[self setValue:[target valueForKey:key] forKey:key];
}
if (renderableTarget.stroke) {
self.stroke = renderableTarget.stroke;
[super mergeProperties:target mergeList:mergeList];
}
- (void)resetProperties
{
if (changedList) {
for (NSString *key in changedList) {
[self setValue:[originProperties valueForKey:key] forKey:key];
}
if (renderableTarget.strokeWidth) {
self.strokeWidth = renderableTarget.strokeWidth;
}
if (renderableTarget.strokeLinecap) {
self.strokeLinecap = renderableTarget.strokeLinecap;
}
if (renderableTarget.strokeLinejoin) {
self.strokeLinejoin = renderableTarget.strokeLinejoin;
}
if (renderableTarget.strokeMiterlimit) {
self.strokeMiterlimit = renderableTarget.strokeMiterlimit;
}
if (renderableTarget.strokeDasharray.count != 0) {
self.strokeDasharray = renderableTarget.strokeDasharray;
}
if (renderableTarget.strokeDashoffset) {
self.strokeDashoffset = renderableTarget.strokeDashoffset;
}
[super mergeProperties:target];
[super resetProperties];
changedList = nil;
}
- (void)renderLayerTo:(CGContextRef)context

View File

@@ -20,5 +20,5 @@ RCT_EXPORT_MODULE()
RCT_EXPORT_VIEW_PROPERTY(href, NSString)
RCT_EXPORT_VIEW_PROPERTY(mergeList, NSArray<NSString *>)
@end

View File

@@ -42,6 +42,7 @@ function fontAndLinesDiffer(a, b) {
}
const NodeAttributes = {
name: true,
transform: {
diff: arrayDiffer
},
@@ -50,7 +51,7 @@ const NodeAttributes = {
responsible: true
};
const RenderableAttributes = merge(NodeAttributes, {
const RenderableOnlyAttributes = {
fill: {
diff: arrayDiffer
},
@@ -70,26 +71,31 @@ const RenderableAttributes = merge(NodeAttributes, {
},
strokeDashoffset: true,
strokeMiterlimit: true
});
};
const GroupAttributes = merge(NodeAttributes, {
const RenderableAttributes = merge({}, NodeAttributes, RenderableOnlyAttributes);
const GroupAttributes = merge({
clipPath: {
diff: arrayDiffer
},
clipRule: true
});
}, NodeAttributes);
const UseAttributes = merge(RenderableAttributes, {
const UseAttributes = merge({
mergeList: {
diff: arrayDiffer
},
href: true
});
}, RenderableAttributes);
const PathAttributes = merge(RenderableAttributes, {
const PathAttributes = merge({
d: {
diff: arrayDiffer
}
});
}, RenderableAttributes);
const TextAttributes = merge(RenderableAttributes, {
const TextAttributes = merge({
alignment: true,
frame: {
diff: fontAndLinesDiffer
@@ -97,48 +103,48 @@ const TextAttributes = merge(RenderableAttributes, {
path: {
diff: arrayDiffer
}
});
}, RenderableAttributes);
const ClipPathAttributes = merge(RenderableAttributes, {
const ClipPathAttributes = {
name: true
});
};
const CircleAttributes = merge(RenderableAttributes, {
const CircleAttributes = merge({
cx: true,
cy: true,
r: true
});
}, RenderableAttributes);
const EllipseAttributes = merge(RenderableAttributes, {
const EllipseAttributes = merge({
cx: true,
cy: true,
rx: true,
ry: true
});
}, RenderableAttributes);
const ImageAttributes = merge(RenderableAttributes, {
const ImageAttributes = merge({
x: true,
y: true,
width: true,
height: true,
src: true
});
}, RenderableAttributes);
const LineAttributes = merge(RenderableAttributes, {
const LineAttributes = merge({
x1: true,
y1: true,
x2: true,
y2: true
});
}, RenderableAttributes);
const RectAttributes = merge(RenderableAttributes, {
const RectAttributes = merge({
x: true,
y: true,
width: true,
height: true,
rx: true,
ry: true
});
}, RenderableAttributes);
export {
@@ -151,5 +157,6 @@ export {
ImageAttributes,
LineAttributes,
RectAttributes,
UseAttributes
UseAttributes,
RenderableOnlyAttributes
};

View File

@@ -1,21 +1,11 @@
import SerializablePath from 'react-native/Libraries/ART/ARTSerializablePath';
import clipReg from './patternReg';
let clipPatterns = {};
const clipRules = {
evenodd: 0,
nonzero: 1
};
function set(id, pattern) {
clipPatterns[id] = pattern;
}
function remove(id) {
delete clipPatterns[id];
}
export default function (props) {
let {clipPath, clipRule} = props;
let clippingProps = {};
@@ -26,22 +16,11 @@ export default function (props) {
let matched = clipPath.match(clipReg);
if (matched) {
let patternName = `${matched[1]}:${props.svgId}`;
let pattern = clipPatterns[patternName];
if (pattern) {
clippingProps.clipPathRef = pattern;
} else {
clippingProps = null;
// TODO: warn
}
clippingProps.clipPathRef = matched[1];
} else {
clippingProps.clipPath = new SerializablePath(clipPath).toJSON();
}
}
return clippingProps;
}
export {
set,
remove
};

View File

@@ -14,7 +14,7 @@ function fillFilter(props) {
if (fill === 'none') {
return null;
} else if (fill) {
return patterns(fill, fillOpacity, props.svgId);
return patterns(fill, fillOpacity);
} else if (props.fill === undefined) {
return rgba('#000', isNaN(fillOpacity) ? 1 : fillOpacity).rgbaString();
} else {

View File

@@ -39,7 +39,7 @@ function strokeFilter(props) {
// TODO: propTypes check
return {
stroke: patterns(stroke, +props.strokeOpacity, props.svgId),
stroke: patterns(stroke, +props.strokeOpacity),
strokeLinecap: caps[props.strokeLinecap] || 0,
strokeLinejoin: joins[props.strokeLinejoin] || 0,
strokeDasharray: strokeDasharray || null,

View File

@@ -86,44 +86,34 @@ const pathProps = {
};
const circleProps = {
cx: numberProp,
cy: numberProp,
r: numberProp
cx: numberProp.isRequired,
cy: numberProp.isRequired,
r: numberProp.isRequired
};
const ellipseProps = {
cx: numberProp,
cy: numberProp,
rx: numberProp,
ry: numberProp
cx: numberProp.isRequired,
cy: numberProp.isRequired,
rx: numberProp.isRequired,
ry: numberProp.isRequired
};
const lineProps = {
x1: numberProp,
x2: numberProp,
y1: numberProp,
y2: numberProp
x1: numberProp.isRequired,
x2: numberProp.isRequired,
y1: numberProp.isRequired,
y2: numberProp.isRequired
};
const rectProps = {
x: numberProp,
y: numberProp,
width: numberProp,
height: numberProp,
x: numberProp.isRequired,
y: numberProp.isRequired,
width: numberProp.isRequired,
height: numberProp.isRequired,
rx: numberProp,
ry: numberProp
};
const contextProps = {
...circleProps,
...ellipseProps,
...lineProps,
...rectProps,
...fillProps,
...strokeProps,
...textProps
};
export {
numberProp,
fillProps,
@@ -135,7 +125,6 @@ export {
ellipseProps,
lineProps,
rectProps,
contextProps,
pathProps,
responderProps,
responderPropsKeys,