diff --git a/android/src/main/java/com/horcrux/svg/ImageShadowNode.java b/android/src/main/java/com/horcrux/svg/ImageShadowNode.java index 35b94f74..dd0a00a2 100644 --- a/android/src/main/java/com/horcrux/svg/ImageShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/ImageShadowNode.java @@ -159,9 +159,6 @@ public class ImageShadowNode extends RenderableShadowNode { } private void doRender(Canvas canvas, Paint paint, Bitmap bitmap, float opacity) { - Paint alphaPaint = new Paint(); - alphaPaint.setAlpha((int) (opacity * 255)); - // apply viewBox transform on Image render. Rect rect = getRect(); float rectWidth = (float)rect.width(); @@ -212,6 +209,8 @@ public class ImageShadowNode extends RenderableShadowNode { canvas.clipPath(path, Region.Op.REPLACE); } + Paint alphaPaint = new Paint(); + alphaPaint.setAlpha((int) (opacity * 255)); canvas.drawBitmap(bitmap, null, renderRect, alphaPaint); } diff --git a/ios/Brushes/RNSVGBrushConverter.m b/ios/Brushes/RNSVGBrushConverter.m index 5f349ce4..99af3103 100644 --- a/ios/Brushes/RNSVGBrushConverter.m +++ b/ios/Brushes/RNSVGBrushConverter.m @@ -25,11 +25,10 @@ float offsetX = (midX - width / 2); float offsetY = (midY - height / 2); - RNSVGPercentageConverter* convert = [[RNSVGPercentageConverter alloc] init]; - CGFloat x1 = [convert stringToFloat:(NSString *)[self.points objectAtIndex:0] relative:width offset:offsetX]; - CGFloat y1 = [convert stringToFloat:(NSString *)[self.points objectAtIndex:1] relative:height offset:offsetY]; - CGFloat x2 = [convert stringToFloat:(NSString *)[self.points objectAtIndex:2] relative:width offset:offsetX]; - CGFloat y2 = [convert stringToFloat:(NSString *)[self.points objectAtIndex:3] relative:height offset:offsetY]; + CGFloat x1 = [RNSVGPercentageConverter stringToFloat:(NSString *)[self.points objectAtIndex:0] relative:width offset:offsetX]; + CGFloat y1 = [RNSVGPercentageConverter stringToFloat:(NSString *)[self.points objectAtIndex:1] relative:height offset:offsetY]; + CGFloat x2 = [RNSVGPercentageConverter stringToFloat:(NSString *)[self.points objectAtIndex:2] relative:width offset:offsetX]; + CGFloat y2 = [RNSVGPercentageConverter stringToFloat:(NSString *)[self.points objectAtIndex:3] relative:height offset:offsetY]; CGContextDrawLinearGradient(context, gradient, CGPointMake(x1, y1), CGPointMake(x2, y2), extendOptions); CGGradientRelease(gradient); @@ -48,13 +47,12 @@ float offsetX = (midX - width / 2); float offsetY = (midY - height / 2); - RNSVGPercentageConverter* convert = [[RNSVGPercentageConverter alloc] init]; - CGFloat rx = [convert stringToFloat:(NSString *)[_points objectAtIndex:2] relative:width offset:0]; - CGFloat ry = [convert stringToFloat:(NSString *)[_points objectAtIndex:3] relative:height offset:0]; - CGFloat fx = [convert stringToFloat:(NSString *)[_points objectAtIndex:0] relative:width offset:offsetX]; - CGFloat fy = [convert stringToFloat:(NSString *)[_points objectAtIndex:1] relative:height offset:offsetY] / (ry / rx); - CGFloat cx = [convert stringToFloat:(NSString *)[_points objectAtIndex:4] relative:width offset:offsetX]; - CGFloat cy = [convert stringToFloat:(NSString *)[_points objectAtIndex:5] relative:height offset:offsetY] / (ry / rx); + CGFloat rx = [RNSVGPercentageConverter stringToFloat:(NSString *)[_points objectAtIndex:2] relative:width offset:0]; + CGFloat ry = [RNSVGPercentageConverter stringToFloat:(NSString *)[_points objectAtIndex:3] relative:height offset:0]; + CGFloat fx = [RNSVGPercentageConverter stringToFloat:(NSString *)[_points objectAtIndex:0] relative:width offset:offsetX]; + CGFloat fy = [RNSVGPercentageConverter stringToFloat:(NSString *)[_points objectAtIndex:1] relative:height offset:offsetY] / (ry / rx); + CGFloat cx = [RNSVGPercentageConverter stringToFloat:(NSString *)[_points objectAtIndex:4] relative:width offset:offsetX]; + CGFloat cy = [RNSVGPercentageConverter stringToFloat:(NSString *)[_points objectAtIndex:5] relative:height offset:offsetY] / (ry / rx); CGAffineTransform transform = CGAffineTransformMakeScale(1, ry / rx); CGContextConcatCTM(context, transform); diff --git a/ios/Elements/RNSVGGroup.m b/ios/Elements/RNSVGGroup.m index 13a0dca9..deac7514 100644 --- a/ios/Elements/RNSVGGroup.m +++ b/ios/Elements/RNSVGGroup.m @@ -29,7 +29,6 @@ if ([node isKindOfClass: [RNSVGRenderable class]]) { RNSVGRenderable *renderable = node; - [self concatLayoutBoundingBox:[renderable getLayoutBoundingBox]]; } return YES; @@ -41,11 +40,6 @@ [super renderLayerTo:context]; } -- (void)concatLayoutBoundingBox:(CGRect)boundingBox -{ - [self setLayoutBoundingBox:CGRectUnion(boundingBox, [self getLayoutBoundingBox])]; -} - - (CGPathRef)getPath:(CGContextRef)context { CGMutablePathRef __block path = CGPathCreateMutable(); diff --git a/ios/Elements/RNSVGImage.m b/ios/Elements/RNSVGImage.m index 30b6b06b..6a3a92a7 100644 --- a/ios/Elements/RNSVGImage.m +++ b/ios/Elements/RNSVGImage.m @@ -97,7 +97,6 @@ CGPathRef hitArea = CGPathCreateWithRect(rect, nil); [self setHitArea:hitArea]; CGPathRelease(hitArea); - [self clip:context]; CGContextSaveGState(context); CGContextTranslateCTM(context, 0, rect.size.height + 2 * rect.origin.y); @@ -105,10 +104,10 @@ // apply viewBox transform on Image render. CGFloat imageRatio = _imageRatio; - CGFloat rectWidth = rect.size.width; - CGFloat rectHeight = rect.size.height; - CGFloat rectX = rect.origin.x; - CGFloat rectY = rect.origin.y; + CGFloat rectWidth = CGRectGetWidth(rect); + CGFloat rectHeight = CGRectGetHeight(rect); + CGFloat rectX = CGRectGetMinX(rect); + CGFloat rectY = CGRectGetMinY(rect); CGFloat rectRatio = rectWidth / rectHeight; CGRect renderRect; @@ -119,24 +118,18 @@ } else { renderRect = CGRectMake(0, 0, rectWidth, rectWidth / imageRatio); } - - RNSVGViewBox *viewBox = [[RNSVGViewBox alloc] init]; - viewBox.minX = viewBox.minY = @"0"; - viewBox.vbWidth = [NSString stringWithFormat:@"%f", renderRect.size.width]; - viewBox.vbHeight = [NSString stringWithFormat:@"%f", renderRect.size.height]; - viewBox.width = [NSString stringWithFormat:@"%f", rectWidth]; - viewBox.height = [NSString stringWithFormat:@"%f", rectHeight]; - viewBox.align = self.align; - viewBox.meetOrSlice = self.meetOrSlice; - [viewBox setContextBoundingBox:CGRectMake(0, 0, rectWidth, rectHeight)]; + CGRect vbRect = CGRectMake(0, 0, CGRectGetWidth(renderRect), CGRectGetHeight(renderRect)); + CGRect eRect = CGRectMake([self getContextLeft], [self getContextTop], rectWidth, rectHeight); + + CGAffineTransform transform = [RNSVGViewBox getTransform:vbRect eRect:eRect align:self.align meetOrSlice:self.meetOrSlice fromSymbol:NO]; - CGAffineTransform transform = [viewBox getTransform]; renderRect = CGRectApplyAffineTransform(renderRect, transform); renderRect = CGRectApplyAffineTransform(renderRect, CGAffineTransformMakeTranslation(rectX, rectY)); + [self clip:context]; CGContextClipToRect(context, rect); - [self setLayoutBoundingBox:rect]; + CGContextDrawImage(context, renderRect, _image); CGContextRestoreGState(context); @@ -144,12 +137,10 @@ - (CGRect)getRect:(CGContextRef)context { - [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; - CGFloat x = [self getWidthRelatedValue:self.x]; - CGFloat y = [self getHeightRelatedValue:self.y]; - CGFloat width = [self getWidthRelatedValue:self.width]; - CGFloat height = [self getHeightRelatedValue:self.height]; - return CGRectMake(x, y, width, height); + return CGRectMake([self relativeOnWidth:self.x], + [self relativeOnHeight:self.y], + [self relativeOnWidth:self.width], + [self relativeOnHeight:self.height]); } - (CGPathRef)getPath:(CGContextRef)context diff --git a/ios/Elements/RNSVGSvgView.h b/ios/Elements/RNSVGSvgView.h index 79f89469..3b82a1eb 100644 --- a/ios/Elements/RNSVGSvgView.h +++ b/ios/Elements/RNSVGSvgView.h @@ -20,11 +20,19 @@ * define content as clipPath template. */ - (void)defineClipPath:(__kindof RNSVGNode *)clipPath clipPathName:(NSString *)clipPathName; + - (RNSVGNode *)getDefinedClipPath:(NSString *)clipPathName; + - (void)defineTemplate:(__kindof RNSVGNode *)template templateName:(NSString *)templateName; + - (RNSVGNode *)getDefinedTemplate:(NSString *)templateName; + - (void)defineBrushConverter:(RNSVGBrushConverter *)brushConverter brushConverterName:(NSString *)brushConverterName; + - (RNSVGBrushConverter *)getDefinedBrushConverter:(NSString *)brushConverterName; + - (NSString *)getDataURL; +- (CGRect)getContextBounds; + @end diff --git a/ios/Elements/RNSVGSvgView.m b/ios/Elements/RNSVGSvgView.m index 5cfba6dc..eca7f57d 100644 --- a/ios/Elements/RNSVGSvgView.m +++ b/ios/Elements/RNSVGSvgView.m @@ -54,13 +54,8 @@ if ([node isKindOfClass:[RNSVGNode class]]) { if (node.responsible && !self.responsible) { self.responsible = YES; - break; } - } - } - - for (RNSVGNode *node in self.subviews) { - if ([node isKindOfClass:[RNSVGNode class]]) { + [node saveDefinition]; [node renderTo:context]; } @@ -123,4 +118,9 @@ return brushConverters ? [brushConverters objectForKey:brushConverterName] : nil; } +- (CGRect)getContextBounds +{ + return CGContextGetClipBoundingBox(UIGraphicsGetCurrentContext()); +} + @end diff --git a/ios/RNSVGNode.h b/ios/RNSVGNode.h index e41e7eb9..88273dcf 100644 --- a/ios/RNSVGNode.h +++ b/ios/RNSVGNode.h @@ -61,8 +61,23 @@ */ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event withTransform:(CGAffineTransform)transfrom; +/** + * get RNSVGSvgView which ownes current RNSVGNode + */ - (RNSVGSvgView *)getSvgView; +- (CGFloat)relativeOnWidth:(NSString *)position; + +- (CGFloat)relativeOnHeight:(NSString *)position; + +- (CGFloat)getContextWidth; + +- (CGFloat)getContextHeight; + +- (CGFloat)getContextLeft; + +- (CGFloat)getContextTop; + /** * save element`s defination into svg element. */ @@ -74,6 +89,6 @@ - (void)endTransparencyLayer:(CGContextRef)context; -- (void)traverseSubviews:(BOOL (^)(RNSVGNode *node))block; +- (void)traverseSubviews:(BOOL (^)(__kindof RNSVGNode *node))block; @end diff --git a/ios/RNSVGNode.m b/ios/RNSVGNode.m index 733824ca..01371fa4 100644 --- a/ios/RNSVGNode.m +++ b/ios/RNSVGNode.m @@ -14,6 +14,7 @@ { BOOL _transparent; CGPathRef _cachedClipPath; + UIView *_svgView; } - (instancetype)init @@ -165,12 +166,52 @@ - (RNSVGSvgView *)getSvgView { - UIView *parent = self.superview; - while (parent && [parent class] != [RNSVGSvgView class]) { - parent = parent.superview; + if (_svgView) { + return _svgView; } - return (RNSVGSvgView *)parent; + __kindof UIView *parent = self.superview; + + if ([parent class] == [RNSVGSvgView class]) { + _svgView = parent; + } else if ([parent isKindOfClass:[RNSVGNode class]]) { + RNSVGNode *node = parent; + _svgView = [node getSvgView]; + } else { + RCTLogError(@"RNSVG: %@ should be descendant of a SvgViewShadow.", NSStringFromClass(self.class)); + } + + return _svgView; +} + +- (CGFloat)relativeOnWidth:(NSString *)position +{ + return [RNSVGPercentageConverter stringToFloat:position relative:[self getContextWidth] offset:0]; +} + +- (CGFloat)relativeOnHeight:(NSString *)position +{ + return [RNSVGPercentageConverter stringToFloat:position relative:[self getContextHeight] offset:0]; +} + +- (CGFloat)getContextWidth +{ + return CGRectGetWidth([[self getSvgView] getContextBounds]); +} + +- (CGFloat)getContextHeight +{ + return CGRectGetHeight([[self getSvgView] getContextBounds]); +} + +- (CGFloat)getContextLeft +{ + return CGRectGetMinX([[self getSvgView] getContextBounds]); +} + +- (CGFloat)getContextTop +{ + return CGRectGetMinY([[self getSvgView] getContextBounds]); } - (void)saveDefinition diff --git a/ios/RNSVGRenderable.h b/ios/RNSVGRenderable.h index 648ab6ae..1d7a8657 100644 --- a/ios/RNSVGRenderable.h +++ b/ios/RNSVGRenderable.h @@ -29,14 +29,6 @@ @property (nonatomic, assign) CGFloat strokeDashoffset; @property (nonatomic, copy) NSArray *propList; -- (void)setContextBoundingBox:(CGRect)contextBoundingBox; -- (CGRect)getContextBoundingBox; -- (void)setLayoutBoundingBox:(CGRect)layoutBoundingBox; -- (CGRect)getLayoutBoundingBox; -- (CGFloat)getWidthRelatedValue:(NSString *)string; -- (CGFloat)getHeightRelatedValue:(NSString *)string; -- (RNSVGPercentageConverter *)getWidthConverter; -- (RNSVGPercentageConverter *)getHeightConverter; - (void)setHitArea:(CGPathRef)path; - (NSArray *)getAttributeList; diff --git a/ios/RNSVGRenderable.m b/ios/RNSVGRenderable.m index 5be88467..85cd011d 100644 --- a/ios/RNSVGRenderable.m +++ b/ios/RNSVGRenderable.m @@ -13,10 +13,6 @@ NSMutableDictionary *_originProperties; NSArray *_lastMergedList; NSArray *_attributeList; - RNSVGPercentageConverter *_widthConverter; - RNSVGPercentageConverter *_heightConverter; - CGRect _contextBoundingBox; - CGRect _renderBoundingBox; BOOL _fillEvenodd; CGPathRef _hitArea; } @@ -289,7 +285,7 @@ CGPathRelease(hitArea); if (contains) { - CGPathRef clipPath = [self getClipPath]; + CGPathRef clipPath = nil; if (!clipPath) { return self; @@ -304,50 +300,6 @@ } } -- (void)setContextBoundingBox:(CGRect)contextBoundingBox -{ - _contextBoundingBox = contextBoundingBox; - _widthConverter = [[RNSVGPercentageConverter alloc] initWithRelativeAndOffset:contextBoundingBox.size.width - offset:0]; - _heightConverter = [[RNSVGPercentageConverter alloc] initWithRelativeAndOffset:contextBoundingBox.size.height - offset:0]; -} - -- (RNSVGPercentageConverter *)getWidthConverter -{ - return _widthConverter; -} - -- (RNSVGPercentageConverter *)getHeightConverter -{ - return _heightConverter; -} - -- (CGRect)getContextBoundingBox -{ - return _contextBoundingBox; -} - -- (void)setLayoutBoundingBox:(CGRect)layoutBoundingBox -{ - _renderBoundingBox = layoutBoundingBox; -} - -- (CGRect)getLayoutBoundingBox -{ - return _renderBoundingBox; -} - -- (CGFloat)getWidthRelatedValue:(NSString *)string -{ - return [_widthConverter stringToFloat:string]; -} - -- (CGFloat)getHeightRelatedValue:(NSString *)string -{ - return [_heightConverter stringToFloat:string]; -} - - (NSArray *)getAttributeList { return _attributeList; diff --git a/ios/RNSVGViewBox.h b/ios/RNSVGViewBox.h index 54e3257c..7143b3ec 100644 --- a/ios/RNSVGViewBox.h +++ b/ios/RNSVGViewBox.h @@ -20,6 +20,6 @@ @property (nonatomic, strong) NSString *width; @property (nonatomic, strong) NSString *height; -- (CGAffineTransform)getTransform; ++ (CGAffineTransform)getTransform:(CGRect)vbRect eRect:(CGRect)eRect align:(NSString *)align meetOrSlice:(RNSVGVBMOS)meetOrSlice fromSymbol:(BOOL)fromSymbol; @end diff --git a/ios/RNSVGViewBox.m b/ios/RNSVGViewBox.m index 95145e11..45ae35e1 100644 --- a/ios/RNSVGViewBox.m +++ b/ios/RNSVGViewBox.m @@ -71,32 +71,52 @@ - (void)renderTo:(CGContextRef)context { - [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; - self.matrix = [self getTransform]; + self.matrix = [self getTransformFromProps]; [super renderTo:context]; } -- (CGAffineTransform)getTransform +- (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 { // based on https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform // Let vb-x, vb-y, vb-width, vb-height be the min-x, min-y, width and height values of the viewBox attribute respectively. - CGFloat vbX = [self getWidthRelatedValue:self.minX]; - CGFloat vbY = [self getHeightRelatedValue:self.minY]; - CGFloat vbWidth = [self getWidthRelatedValue:self.vbWidth]; - CGFloat vbHeight = [self getHeightRelatedValue:self.vbHeight]; + CGFloat vbX = CGRectGetMinX(vbRect); + CGFloat vbY = CGRectGetMinY(vbRect); + CGFloat vbWidth = CGRectGetWidth(vbRect); + CGFloat vbHeight = CGRectGetHeight(vbRect); // Let e-x, e-y, e-width, e-height be the position and size of the element respectively. - CGFloat eX = [self getContextBoundingBox].origin.x; - CGFloat eY = [self getContextBoundingBox].origin.y; - CGFloat eWidth = self.width ? [self getWidthRelatedValue:self.width] : [self getContextBoundingBox].size.width; - CGFloat eHeight = self.height ? [self getHeightRelatedValue:self.height] : [self getContextBoundingBox].size.height; + CGFloat eX = CGRectGetMinX(eRect); + CGFloat eY = CGRectGetMinY(eRect); + CGFloat eWidth = CGRectGetWidth(eRect); + CGFloat eHeight = CGRectGetHeight(eRect); // Let align be the align value of preserveAspectRatio, or 'xMidyMid' if preserveAspectRatio is not defined. - NSString *align = self.align; // Let meetOrSlice be the meetOrSlice value of preserveAspectRatio, or 'meet' if preserveAspectRatio is not defined or if meetOrSlice is missing from this value. - RNSVGVBMOS meetOrSlice = self.meetOrSlice; // Initialize scale-x to e-width/vb-width. CGFloat scaleX = eWidth / vbWidth; @@ -157,7 +177,7 @@ } CGAffineTransform transform = CGAffineTransformMakeScale(scaleX, scaleY); - return CGAffineTransformTranslate(transform, -translateX * (_fromSymbol ? scaleX : 1), -translateY * (_fromSymbol ? scaleY : 1)); + return CGAffineTransformTranslate(transform, -translateX * (fromSymbol ? scaleX : 1), -translateY * (fromSymbol ? scaleY : 1)); } - (void)mergeProperties:(__kindof RNSVGNode *)target diff --git a/ios/Shapes/RNSVGCircle.m b/ios/Shapes/RNSVGCircle.m index b95f0fac..164f5bf8 100644 --- a/ios/Shapes/RNSVGCircle.m +++ b/ios/Shapes/RNSVGCircle.m @@ -40,21 +40,19 @@ - (CGPathRef)getPath:(CGContextRef)context { - [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; CGMutablePathRef path = CGPathCreateMutable(); - RNSVGPercentageConverter* convert = [[RNSVGPercentageConverter alloc] init]; - CGFloat cx = [self getWidthRelatedValue:self.cx]; - CGFloat cy = [self getHeightRelatedValue:self.cy]; + CGFloat cx = [self relativeOnWidth:self.cx]; + CGFloat cy = [self relativeOnHeight:self.cy]; CGFloat r; // radius percentage calculate formula: // radius = sqrt(pow((width*percent), 2) + pow((height*percent), 2)) / sqrt(2) - if ([convert isPercentage:self.r]) { - CGFloat radiusPercent = [convert percentageToFloat:self.r relative:1 offset:0]; + if ([RNSVGPercentageConverter isPercentage:self.r]) { + CGFloat radiusPercent = [RNSVGPercentageConverter percentageToFloat:self.r relative:1 offset:0]; r = sqrt( - pow((CGRectGetWidth([self getContextBoundingBox]) * radiusPercent), 2) + - pow((CGRectGetHeight([self getContextBoundingBox]) * radiusPercent), 2) + pow([self getContextWidth] * radiusPercent, 2) + + pow([self getContextHeight] * radiusPercent, 2) ) / sqrt(2); } else { r = [self.r floatValue]; diff --git a/ios/Shapes/RNSVGEllipse.m b/ios/Shapes/RNSVGEllipse.m index 36eb11c7..6a26176a 100644 --- a/ios/Shapes/RNSVGEllipse.m +++ b/ios/Shapes/RNSVGEllipse.m @@ -49,12 +49,11 @@ - (CGPathRef)getPath:(CGContextRef)context { - [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; CGMutablePathRef path = CGPathCreateMutable(); - CGFloat cx = [self getWidthRelatedValue:self.cx]; - CGFloat cy = [self getHeightRelatedValue:self.cy]; - CGFloat rx = [self getWidthRelatedValue:self.rx]; - CGFloat ry = [self getHeightRelatedValue:self.ry]; + CGFloat cx = [self relativeOnWidth:self.cx]; + CGFloat cy = [self relativeOnHeight:self.cy]; + CGFloat rx = [self relativeOnWidth:self.rx]; + CGFloat ry = [self relativeOnHeight:self.ry]; CGPathAddEllipseInRect(path, nil, CGRectMake(cx - rx, cy - ry, rx * 2, ry * 2)); return (CGPathRef)CFAutorelease(path); } diff --git a/ios/Shapes/RNSVGLine.m b/ios/Shapes/RNSVGLine.m index 4fe744b3..5e23d4d0 100644 --- a/ios/Shapes/RNSVGLine.m +++ b/ios/Shapes/RNSVGLine.m @@ -49,12 +49,11 @@ - (CGPathRef)getPath:(CGContextRef)context { - [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; CGMutablePathRef path = CGPathCreateMutable(); - CGFloat x1 = [self getWidthRelatedValue:self.x1]; - CGFloat y1 = [self getHeightRelatedValue:self.y1]; - CGFloat x2 = [self getWidthRelatedValue:self.x2]; - CGFloat y2 = [self getHeightRelatedValue:self.y2]; + CGFloat x1 = [self relativeOnWidth:self.x1]; + CGFloat y1 = [self relativeOnHeight:self.y1]; + CGFloat x2 = [self relativeOnWidth:self.x2]; + CGFloat y2 = [self relativeOnHeight:self.y2]; CGPathMoveToPoint(path, nil, x1, y1); CGPathAddLineToPoint(path, nil, x2, y2); diff --git a/ios/Shapes/RNSVGRect.m b/ios/Shapes/RNSVGRect.m index 8136bdce..ff5f587e 100644 --- a/ios/Shapes/RNSVGRect.m +++ b/ios/Shapes/RNSVGRect.m @@ -67,14 +67,13 @@ - (CGPathRef)getPath:(CGContextRef)context { - [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; CGMutablePathRef path = CGPathCreateMutable(); - CGFloat x = [self getWidthRelatedValue:self.x]; - CGFloat y = [self getHeightRelatedValue:self.y]; - CGFloat width = [self getWidthRelatedValue:self.width]; - CGFloat height = [self getHeightRelatedValue:self.height]; - CGFloat rx = [self getWidthRelatedValue:self.rx]; - CGFloat ry = [self getHeightRelatedValue:self.ry]; + CGFloat x = [self relativeOnWidth:self.x]; + CGFloat y = [self relativeOnHeight:self.y]; + CGFloat width = [self relativeOnWidth:self.width]; + CGFloat height = [self relativeOnHeight:self.height]; + CGFloat rx = [self relativeOnWidth:self.rx]; + CGFloat ry = [self relativeOnHeight:self.ry]; if (rx != 0 || ry != 0) { if (rx == 0) { diff --git a/ios/Text/RNSVGGlyphContext.h b/ios/Text/RNSVGGlyphContext.h index 9a5340dc..d796c843 100644 --- a/ios/Text/RNSVGGlyphContext.h +++ b/ios/Text/RNSVGGlyphContext.h @@ -12,7 +12,7 @@ @interface RNSVGGlyphContext : NSObject -- (instancetype)initWithConverters:(RNSVGPercentageConverter *)widthConverter heightConverter:(RNSVGPercentageConverter *)heightConverter; +- (instancetype)initWithDimensions:(CGFloat)width height:(CGFloat)height; - (void)pushContext:(NSDictionary *)font deltaX:(NSArray *)deltaX deltaY:(NSArray *)deltaY positionX:(NSString *)positionX positionY:(NSString *)positionY; - (void)popContext; - (CTFontRef)getGlyphFont; diff --git a/ios/Text/RNSVGGlyphContext.m b/ios/Text/RNSVGGlyphContext.m index cb698b90..0ced39c8 100644 --- a/ios/Text/RNSVGGlyphContext.m +++ b/ios/Text/RNSVGGlyphContext.m @@ -8,6 +8,7 @@ #import "RNSVGGlyphContext.h" +#import "RNSVGPercentageConverter.h" #import @implementation RNSVGGlyphContext @@ -18,15 +19,15 @@ NSMutableArray *_deltaYContext; NSMutableArray *_xContext; CGPoint _currentLocation; - RNSVGPercentageConverter *_widthConverter; - RNSVGPercentageConverter *_heightConverter; + CGFloat _width; + CGFloat _height; } -- (instancetype)initWithConverters:(RNSVGPercentageConverter *)widthConverter heightConverter:(RNSVGPercentageConverter *)heightConverter +- (instancetype)initWithDimensions:(CGFloat)width height:(CGFloat)height { if (self = [super init]) { - _widthConverter = widthConverter; - _heightConverter = heightConverter; + _width = width; + _height = height; _fontContext = [[NSMutableArray alloc] init]; _locationContext = [[NSMutableArray alloc] init]; _deltaXContext = [[NSMutableArray alloc] init]; @@ -42,11 +43,11 @@ CGPoint location = _currentLocation; if (positionX) { - location.x = [_widthConverter stringToFloat:positionX]; + location.x = [RNSVGPercentageConverter stringToFloat:positionX relative:_width offset:0]; } if (positionY) { - location.y = [_heightConverter stringToFloat:positionY]; + location.y = [RNSVGPercentageConverter stringToFloat:positionY relative:_height offset:0]; } [_locationContext addObject:[NSValue valueWithCGPoint:location]]; diff --git a/ios/Text/RNSVGTSpan.m b/ios/Text/RNSVGTSpan.m index f5470ec8..28c2286b 100644 --- a/ios/Text/RNSVGTSpan.m +++ b/ios/Text/RNSVGTSpan.m @@ -140,7 +140,6 @@ [self traverseTextSuperviews:^(__kindof RNSVGText *node) { if ([node class] == [RNSVGTextPath class]) { RNSVGTextPath *textPath = node; - [node setContextBoundingBox:CGContextGetClipBoundingBox(context)]; bezierTransformer = [node getBezierTransformer]; return NO; } diff --git a/ios/Text/RNSVGText.m b/ios/Text/RNSVGText.m index 2392017e..66b7f22f 100644 --- a/ios/Text/RNSVGText.m +++ b/ios/Text/RNSVGText.m @@ -45,9 +45,8 @@ - (void)setupGlyphContext:(CGContextRef)context { - [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; - _glyphContext = [[RNSVGGlyphContext alloc] initWithConverters:[self getWidthConverter] - heightConverter:[self getHeightConverter]]; + _glyphContext = [[RNSVGGlyphContext alloc] initWithDimensions:[self getContextWidth] + height:[self getContextHeight]]; } // release the cached CGPathRef for RNSVGTSpan diff --git a/ios/Text/RNSVGTextPath.m b/ios/Text/RNSVGTextPath.m index 9b9a1fd1..d3717812 100644 --- a/ios/Text/RNSVGTextPath.m +++ b/ios/Text/RNSVGTextPath.m @@ -14,7 +14,6 @@ - (void)renderLayerTo:(CGContextRef)context { - [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; [self renderGroupTo:context]; } @@ -29,7 +28,7 @@ } RNSVGPath *path = template; - CGFloat startOffset = [self getWidthRelatedValue:self.startOffset]; + CGFloat startOffset = [self relativeOnWidth:self.startOffset]; return [[RNSVGBezierTransformer alloc] initWithBezierCurvesAndStartOffset:[path getBezierCurves] startOffset:startOffset]; } diff --git a/ios/Utils/RNSVGPercentageConverter.h b/ios/Utils/RNSVGPercentageConverter.h index 4eb94878..24ab0556 100644 --- a/ios/Utils/RNSVGPercentageConverter.h +++ b/ios/Utils/RNSVGPercentageConverter.h @@ -11,18 +11,10 @@ @interface RNSVGPercentageConverter : NSObject -- (NSRegularExpression *) getPercentageRegularExpression; ++ (CGFloat) percentageToFloat:(NSString *)percentage relative:(CGFloat)relative offset:(CGFloat)offset; -- (instancetype) initWithRelativeAndOffset:(CGFloat)relative offset:(CGFloat)offset; ++ (CGFloat) stringToFloat:(NSString *)string relative:(CGFloat)relative offset:(CGFloat)offset; -- (CGFloat) percentageToFloat:(NSString *)percentage relative:(CGFloat)relative offset:(CGFloat)offset; ++ (BOOL) isPercentage:(NSString *) string; -- (CGFloat) percentageToFloat:(NSString *)percentage; - -- (CGFloat) stringToFloat:(NSString *)string relative:(CGFloat)relative offset:(CGFloat)offset; - -- (CGFloat) stringToFloat:(NSString *)string; - -- (BOOL) isPercentage:(NSString *) string; - -@end \ No newline at end of file +@end diff --git a/ios/Utils/RNSVGPercentageConverter.m b/ios/Utils/RNSVGPercentageConverter.m index 3ba5986f..73ad18f0 100644 --- a/ios/Utils/RNSVGPercentageConverter.m +++ b/ios/Utils/RNSVGPercentageConverter.m @@ -9,59 +9,28 @@ #import "RNSVGPercentageConverter.h" @implementation RNSVGPercentageConverter + +static NSRegularExpression* percentageRegExp; + ++(void)initialize { - CGFloat _relative; - CGFloat _offset; - NSRegularExpression *_percentageRegularExpression; + percentageRegExp = [[NSRegularExpression alloc] initWithPattern:@"^(\\-?\\d+(?:\\.\\d+)?)%$" options:0 error:nil]; } -- (instancetype) initWithRelativeAndOffset:(CGFloat)relative offset:(CGFloat)offset ++ (CGFloat)stringToFloat:(NSString *)string relative:(CGFloat)relative offset:(CGFloat)offset { - if (self = [super init]) { - _relative = relative; - _offset = offset; - _percentageRegularExpression = [[NSRegularExpression alloc] initWithPattern:@"^(\\-?\\d+(?:\\.\\d+)?)%$" options:0 error:nil]; - } - return self; -} - -- (id)init -{ - if (self = [super init]) { - _percentageRegularExpression = [[NSRegularExpression alloc] initWithPattern:@"^(\\-?\\d+(?:\\.\\d+)?)%$" options:0 error:nil]; - } - return self; -} - -- (NSRegularExpression *) getPercentageRegularExpression -{ - return _percentageRegularExpression; -} - -- (CGFloat) stringToFloat:(NSString *)string -{ - return [self stringToFloat:string relative:_relative offset:_offset]; -} - -- (CGFloat) stringToFloat:(NSString *)string relative:(CGFloat)relative offset:(CGFloat)offset -{ - if ([self isPercentage:string] == NO) { + if (![self isPercentage:string]) { return [string floatValue]; } else { return [self percentageToFloat:string relative:relative offset:offset]; } } -- (CGFloat) percentageToFloat:(NSString *)percentage -{ - return [self percentageToFloat:percentage relative:_relative offset:_offset]; -} - -- (CGFloat) percentageToFloat:(NSString *)percentage relative:(CGFloat)relative offset:(CGFloat)offset ++ (CGFloat)percentageToFloat:(NSString *)percentage relative:(CGFloat)relative offset:(CGFloat)offset { __block CGFloat matched; - [_percentageRegularExpression enumerateMatchesInString:percentage + [percentageRegExp enumerateMatchesInString:percentage options:0 range:NSMakeRange(0, percentage.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) @@ -74,9 +43,9 @@ return matched; } -- (BOOL) isPercentage:(NSString *) string ++ (BOOL)isPercentage:(NSString *) string { - return [_percentageRegularExpression firstMatchInString:string options:0 range:NSMakeRange(0, [string length])] != nil; + return [percentageRegExp firstMatchInString:string options:0 range:NSMakeRange(0, [string length])] != nil; } @end