diff --git a/ios/RNSVGRenderable.h b/ios/RNSVGRenderable.h index 0d77e393..c4c9c094 100644 --- a/ios/RNSVGRenderable.h +++ b/ios/RNSVGRenderable.h @@ -27,7 +27,6 @@ @property (nonatomic, assign) CGFloat strokeMiterlimit; @property (nonatomic, assign) RNSVGCGFloatArray strokeDasharray; @property (nonatomic, assign) CGFloat strokeDashoffset; -@property (nonatomic, assign) CGPathRef hitArea; @property (nonatomic, copy) NSArray *propList; @property (nonatomic, strong) NSArray *attributeList; @@ -39,5 +38,6 @@ - (CGFloat)getHeightRelatedValue:(NSString *)string; - (RNSVGPercentageConverter *)getWidthConverter; - (RNSVGPercentageConverter *)getHeightConverter; +- (void)setHitArea:(CGPathRef)path; @end diff --git a/ios/RNSVGRenderable.m b/ios/RNSVGRenderable.m index 20f5fb67..b6a1216b 100644 --- a/ios/RNSVGRenderable.m +++ b/ios/RNSVGRenderable.m @@ -17,6 +17,7 @@ CGRect _contextBoundingBox; CGRect _renderBoundingBox; BOOL _fillEvenodd; + CGPathRef _hitArea; } - (id)init @@ -132,17 +133,6 @@ _strokeDashoffset = strokeDashoffset; } -- (void)setHitArea:(CGPathRef)hitArea -{ - if (hitArea == _hitArea) { - return; - } - - [self invalidate]; - CGPathRelease(_hitArea); - _hitArea = CGPathRetain(hitArea); -} - - (void)setPropList:(NSArray *)propList { if (propList == _propList) { @@ -175,6 +165,7 @@ CGContextRestoreGState(context); } + - (void)renderLayerTo:(CGContextRef)context { BOOL shouldStroke = self.stroke && self.strokeWidth; @@ -184,21 +175,7 @@ } CGPathRef path = [self getPath:context]; - - if ([self getSvgView].responsible) { - // Add path to hitArea - CGMutablePathRef hitArea = CGPathCreateMutableCopy(path); - - if (self.stroke && self.strokeWidth) { - // Add stroke to hitArea - CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitArea, nil, self.strokeWidth, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit); - CGPathAddPath(hitArea, nil, strokePath); - CGPathRelease(strokePath); - } - - self.hitArea = CFAutorelease(CGPathCreateCopy(hitArea)); - CGPathRelease(hitArea); - } + [self setHitArea:path]; if (self.opacity == 0) { return; @@ -261,6 +238,25 @@ CGContextDrawPath(context, mode); } +- (void)setHitArea:(CGPathRef)path +{ + CGPathRelease(_hitArea); + if ([self getSvgView].responsible) { + // Add path to hitArea + CGMutablePathRef hitArea = CGPathCreateMutableCopy(path); + + if (self.stroke && self.strokeWidth) { + // Add stroke to hitArea + CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitArea, nil, self.strokeWidth, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit); + CGPathAddPath(hitArea, nil, strokePath); + CGPathRelease(strokePath); + } + + _hitArea = CGPathRetain(CGPathCreateCopy(hitArea)); + CGPathRelease(hitArea); + } + +} // hitTest delagate - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event @@ -278,7 +274,7 @@ } CGAffineTransform matrix = CGAffineTransformConcat(self.matrix, transform); - CGPathRef hitArea = CGPathCreateCopyByTransformingPath(self.hitArea, &matrix); + CGPathRef hitArea = CGPathCreateCopyByTransformingPath(_hitArea, &matrix); BOOL contains = CGPathContainsPoint(hitArea, nil, point, NO); CGPathRelease(hitArea); diff --git a/ios/Text/RNSVGTSpan.m b/ios/Text/RNSVGTSpan.m index 471c22ac..1536d3dd 100644 --- a/ios/Text/RNSVGTSpan.m +++ b/ios/Text/RNSVGTSpan.m @@ -42,10 +42,10 @@ NSString *text = self.content; if (!text) { - return [super getPath:context]; + return [self getGroupPath:context]; } - [self initialTextPath]; + [self setupTextPath]; [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; CGMutablePathRef path = CGPathCreateMutable(); @@ -53,7 +53,9 @@ // append spacing text = [text stringByAppendingString:@" "]; + [self pushGlyphContext]; CTFontRef font = [self getFontFromContext]; + // Create a dictionary for this font CFDictionaryRef attributes = (__bridge CFDictionaryRef)@{ (NSString *)kCTFontAttributeName: (__bridge id)font, @@ -67,20 +69,20 @@ CGMutablePathRef linePath = [self getLinePath:line]; CGAffineTransform offset = CGAffineTransformMakeTranslation(0, _bezierTransformer ? 0 : CTFontGetSize(font) * 1.1); CGPathAddPath(path, &offset, linePath); - + + _cache = CGPathRetain(CGPathCreateCopy(path)); + [self popGlyphContext]; + // clean up CFRelease(attrString); CFRelease(line); CGPathRelease(linePath); - _cache = CGPathRetain(CGPathCreateCopy(path)); - return (CGPathRef)CFAutorelease(path); } - (CGMutablePathRef)getLinePath:(CTLineRef)line { - [self pushGlyphContext]; CTRunRef run = CFArrayGetValueAtIndex(CTLineGetGlyphRuns(line), 0); CFIndex runGlyphCount = CTRunGetGlyphCount(run); @@ -98,7 +100,7 @@ for(CFIndex i = 0; i < runGlyphCount; i++) { CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyphs[i], nil); - glyphPoint = [self getGlyphPointFromContext:positions[i] glyphWidth:CGPathGetBoundingBox(letter).size.width]; + glyphPoint = [self getGlyphPointFromContext:positions[i] glyphWidth:CGRectGetWidth(CGPathGetBoundingBox(letter))]; CGAffineTransform textPathTransform = [self getTextPathTransform:glyphPoint.x]; @@ -121,11 +123,10 @@ CGPathRelease(letter); } - [self popGlyphContext]; return path; } -- (void)initialTextPath +- (void)setupTextPath { __block RNSVGBezierTransformer *bezierTransformer; [self traverseTextSuperviews:^(__kindof RNSVGText *node) { @@ -136,7 +137,7 @@ } return YES; }]; - + _bezierTransformer = bezierTransformer; } diff --git a/ios/Text/RNSVGText.h b/ios/Text/RNSVGText.h index fe775915..45d3e0c9 100644 --- a/ios/Text/RNSVGText.h +++ b/ios/Text/RNSVGText.h @@ -26,6 +26,7 @@ - (RNSVGText *)getTextRoot; - (void)releaseCachedPath; +- (CGPathRef)getGroupPath:(CGContextRef)context; - (RNSVGGlyphContext *)getGlyphContext; - (void)pushGlyphContext; diff --git a/ios/Text/RNSVGText.m b/ios/Text/RNSVGText.m index 6e5bbddd..32338c40 100644 --- a/ios/Text/RNSVGText.m +++ b/ios/Text/RNSVGText.m @@ -26,12 +26,9 @@ - (void)renderLayerTo:(CGContextRef)context { - [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; - _glyphContext = [[RNSVGGlyphContext alloc] initWithConverters:[self getWidthConverter] - heightConverter:[self getHeightConverter]]; - [self clip:context]; CGContextSaveGState(context); + [self setupGlyphContext:context]; CGAffineTransform transform = [self getAlignTransform:context]; CGContextConcatCTM(context, transform); [self renderGroupTo:context]; @@ -39,6 +36,14 @@ CGContextRestoreGState(context); } +- (void)setupGlyphContext:(CGContextRef)context +{ + [self setContextBoundingBox:CGContextGetClipBoundingBox(context)]; + _glyphContext = [[RNSVGGlyphContext alloc] initWithConverters:[self getWidthConverter] + heightConverter:[self getHeightConverter]]; +} + +// release the cached CGPathRef for RNSVGTSpan - (void)releaseCachedPath { [self traverseSubviews:^BOOL(__kindof RNSVGNode *node) { @@ -48,14 +53,22 @@ }]; } -- (CGPathRef)getPath:(CGContextRef)context +- (CGPathRef)getGroupPath:(CGContextRef)context { [self pushGlyphContext]; CGPathRef groupPath = [super getPath:context]; [self popGlyphContext]; + return groupPath; +} + +- (CGPathRef)getPath:(CGContextRef)context +{ + [self setupGlyphContext:context]; + CGPathRef groupPath = [self getGroupPath:context]; CGAffineTransform transform = [self getAlignTransform:context path:groupPath]; CGPathRef transformedPath = CGPathCreateCopyByTransformingPath(groupPath, &transform); + [self releaseCachedPath]; return transformedPath; } @@ -69,7 +82,7 @@ - (CGAffineTransform)getAlignTransform:(CGContextRef)context { - return [self getAlignTransform:context path:[self getPath:context]]; + return [self getAlignTransform:context path:[self getGroupPath:context]]; } - (CGAffineTransform)getAlignTransform:(CGContextRef)context path:(CGPathRef)path diff --git a/ios/Text/RNSVGTextPath.m b/ios/Text/RNSVGTextPath.m index c97314db..9b9a1fd1 100644 --- a/ios/Text/RNSVGTextPath.m +++ b/ios/Text/RNSVGTextPath.m @@ -34,4 +34,19 @@ startOffset:startOffset]; } +- (CGPathRef)getPath:(CGContextRef)context +{ + return [self getGroupPath:context]; +} + +- (void)pushGlyphContext +{ + // TextPath do not affect the glyphContext +} + +- (void)popGlyphContext +{ + // TextPath do not affect the glyphContext +} + @end