First attempt at nested svg support.

This commit is contained in:
Mikael Sand
2018-02-06 11:18:18 +02:00
parent 824a181a3d
commit ee1d1f78cc
13 changed files with 208 additions and 92 deletions
+3 -1
View File
@@ -19,7 +19,9 @@
- (void)parseReference
{
[self traverseSubviews:^(RNSVGNode *node) {
[node parseReference];
if ([node isKindOfClass:[RNSVGNode class]]) {
[node parseReference];
}
return YES;
}];
}
+27 -13
View File
@@ -34,19 +34,29 @@
{
[self pushGlyphContext];
RNSVGSvgView* svg = [self getSvgView];
[self traverseSubviews:^(RNSVGNode *node) {
if (node.responsible && !svg.responsible) {
svg.responsible = YES;
}
[self traverseSubviews:^(UIView *node) {
if ([node isKindOfClass:[RNSVGNode class]]) {
RNSVGNode* svgNode = (RNSVGNode*)node;
if (svgNode.responsible && !svg.responsible) {
svg.responsible = YES;
}
if ([node isKindOfClass:[RNSVGRenderable class]]) {
[(RNSVGRenderable*)node mergeProperties:self];
}
if ([node isKindOfClass:[RNSVGRenderable class]]) {
[(RNSVGRenderable*)node mergeProperties:self];
}
[node renderTo:context];
[svgNode renderTo:context];
if ([node isKindOfClass:[RNSVGRenderable class]]) {
[(RNSVGRenderable*)node resetProperties];
if ([node isKindOfClass:[RNSVGRenderable class]]) {
[(RNSVGRenderable*)node resetProperties];
}
} else if ([node isKindOfClass:[RNSVGSvgView class]]) {
RNSVGSvgView* svgView = (RNSVGSvgView*)node;
CGRect rect = CGRectMake(0, 0, [svgView.bbWidth floatValue], [svgView.bbHeight floatValue]);
CGContextClipToRect(context, rect);
[svgView drawToContext:context withRect:(CGRect)rect];
} else {
RCTLogWarn(@"Not a RNSVGNode: %@", node.class);
}
return YES;
@@ -89,8 +99,10 @@
{
CGMutablePathRef __block path = CGPathCreateMutable();
[self traverseSubviews:^(RNSVGNode *node) {
CGAffineTransform transform = node.matrix;
CGPathAddPath(path, &transform, [node getPath:context]);
if ([node isKindOfClass:[RNSVGNode class]]) {
CGAffineTransform transform = node.matrix;
CGPathAddPath(path, &transform, [node getPath:context]);
}
return YES;
}];
@@ -147,7 +159,9 @@
}
[self traverseSubviews:^(__kindof RNSVGNode *node) {
[node parseReference];
if ([node isKindOfClass:[RNSVGNode class]]) {
[node parseReference];
}
return YES;
}];
}
+8
View File
@@ -15,6 +15,8 @@
@interface RNSVGSvgView : UIView <RNSVGContainer>
@property (nonatomic, strong) NSString *bbWidth;
@property (nonatomic, strong) NSString *bbHeight;
@property (nonatomic, assign) CGFloat minX;
@property (nonatomic, assign) CGFloat minY;
@property (nonatomic, assign) CGFloat vbWidth;
@@ -22,6 +24,8 @@
@property (nonatomic, strong) NSString *align;
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
@property (nonatomic, assign) BOOL responsible;
@property (nonatomic, assign) CGRect boundingBox;
/**
* define <ClipPath></ClipPath> content as clipPath template.
@@ -42,4 +46,8 @@
- (CGRect)getContextBounds;
- (void)drawRect:(CGRect)rect;
- (void)drawToContext:(CGContextRef)context withRect:(CGRect)rect;
@end
+57 -29
View File
@@ -16,7 +16,6 @@
NSMutableDictionary<NSString *, RNSVGNode *> *_clipPaths;
NSMutableDictionary<NSString *, RNSVGNode *> *_templates;
NSMutableDictionary<NSString *, RNSVGPainter *> *_painters;
CGRect _boundingBox;
CGAffineTransform _viewBoxTransform;
}
@@ -48,7 +47,7 @@
if (minX == _minX) {
return;
}
[self invalidate];
_minX = minX;
}
@@ -58,7 +57,7 @@
if (minY == _minY) {
return;
}
[self invalidate];
_minY = minY;
}
@@ -68,7 +67,7 @@
if (vbWidth == _vbWidth) {
return;
}
[self invalidate];
_vbWidth = vbWidth;
}
@@ -78,17 +77,37 @@
if (_vbHeight == vbHeight) {
return;
}
[self invalidate];
_vbHeight = vbHeight;
}
- (void)setBBWidth:(NSString *)bbWidth
{
if ([bbWidth isEqualToString:_bbWidth]) {
return;
}
[self invalidate];
_bbWidth = bbWidth;
}
- (void)setBBHeight:(NSString *)bbHeight
{
if ([bbHeight isEqualToString:_bbHeight]) {
return;
}
[self invalidate];
_bbHeight = bbHeight;
}
- (void)setAlign:(NSString *)align
{
if ([align isEqualToString:_align]) {
return;
}
[self invalidate];
_align = align;
}
@@ -98,11 +117,29 @@
if (meetOrSlice == _meetOrSlice) {
return;
}
[self invalidate];
_meetOrSlice = meetOrSlice;
}
- (void)drawToContext:(CGContextRef)context withRect:(CGRect)rect {
if (self.align) {
_viewBoxTransform = [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight)
eRect:rect
align:self.align
meetOrSlice:self.meetOrSlice];
CGContextConcatCTM(context, _viewBoxTransform);
}
for (UIView *node in self.subviews) {
if ([node isKindOfClass:[RNSVGNode class]]) {
RNSVGNode *svg = (RNSVGNode *)node;
[svg renderTo:context];
}
}
}
- (void)drawRect:(CGRect)rect
{
_clipPaths = nil;
@@ -110,30 +147,21 @@
_painters = nil;
_boundingBox = rect;
CGContextRef context = UIGraphicsGetCurrentContext();
if (self.align) {
_viewBoxTransform = [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight)
eRect:rect
align:self.align
meetOrSlice:self.meetOrSlice];
CGContextConcatCTM(context, _viewBoxTransform);
}
for (RNSVGNode *node in self.subviews) {
for (UIView *node in self.subviews) {
if ([node isKindOfClass:[RNSVGNode class]]) {
if (node.responsible && !self.responsible) {
RNSVGNode *svg = (RNSVGNode *)node;
if (svg.responsible && !self.responsible) {
self.responsible = YES;
}
[node parseReference];
}
}
for (RNSVGNode *node in self.subviews) {
if ([node isKindOfClass:[RNSVGNode class]]) {
[node renderTo:context];
[svg parseReference];
} else {
RCTLogWarn(@"Not a RNSVGNode: %@", node.class);
}
}
[self drawToContext:context withRect:rect];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
@@ -143,15 +171,15 @@
if (![node isKindOfClass:[RNSVGNode class]]) {
continue;
}
if (event) {
node.active = NO;
} else if (node.active) {
return node;
}
UIView *hitChild = [node hitTest: point withEvent:event withTransform:_viewBoxTransform];
if (hitChild) {
node.active = YES;
return (node.responsible || (node != hitChild)) ? hitChild : self;
+1 -1
View File
@@ -103,6 +103,6 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
- (void)endTransparencyLayer:(CGContextRef)context;
- (void)traverseSubviews:(BOOL (^)(__kindof RNSVGNode *node))block;
- (void)traverseSubviews:(BOOL (^)(__kindof UIView *node))block;
@end
+8 -2
View File
@@ -310,13 +310,19 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
}
}
- (void)traverseSubviews:(BOOL (^)(__kindof RNSVGNode *node))block
- (void)traverseSubviews:(BOOL (^)(__kindof UIView *node))block
{
for (RNSVGNode *node in self.subviews) {
for (UIView *node in self.subviews) {
if ([node isKindOfClass:[RNSVGNode class]]) {
if (!block(node)) {
break;
}
} else if ([node isKindOfClass:[RNSVGSvgView class]]) {
if (!block(node)) {
break;
}
} else {
RCTLogWarn(@"Not a RNSVGNode: %@", node.class);
}
}
}
+2
View File
@@ -20,6 +20,8 @@ RCT_EXPORT_MODULE()
return [RNSVGSvgView new];
}
RCT_EXPORT_VIEW_PROPERTY(bbWidth, NSString)
RCT_EXPORT_VIEW_PROPERTY(bbHeight, NSString)
RCT_EXPORT_VIEW_PROPERTY(minX, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(minY, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(vbWidth, CGFloat)