/** * 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 "RNSVGText.h" #import "RNSVGTextPath.h" #import #import #import "RNSVGGlyphContext.h" #import "RNSVGTextProperties.h" @implementation RNSVGText { RNSVGGlyphContext *_glyphContext; } - (void)invalidate { [super invalidate]; [self releaseCachedPath]; } - (void)renderLayerTo:(CGContextRef)context rect:(CGRect)rect { [self clip:context]; CGContextSaveGState(context); [self setupGlyphContext:context]; CGPathRef path = [self getGroupPath:context]; [self renderGroupTo:context rect:rect]; CGContextRestoreGState(context); CGPathRef transformedPath = CGPathCreateCopyByTransformingPath(path, &CGAffineTransformIdentity); [self setHitArea:transformedPath]; CGPathRelease(transformedPath); } - (void)setupGlyphContext:(CGContextRef)context { _glyphContext = [[RNSVGGlyphContext alloc] initWithScale:1 width:[self getContextWidth] height:[self getContextHeight]]; } // release the cached CGPathRef for RNSVGTSpan - (void)releaseCachedPath { [self traverseSubviews:^BOOL(__kindof RNSVGNode *node) { RNSVGText *text = node; [text releaseCachedPath]; return YES; }]; } - (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]; return (CGPathRef)CFAutorelease(CGPathCreateCopyByTransformingPath(groupPath, &CGAffineTransformIdentity)); } - (void)renderGroupTo:(CGContextRef)context rect:(CGRect)rect { [self pushGlyphContext]; [super renderGroupTo:context rect:rect]; [self popGlyphContext]; } // TODO: Optimisation required - (RNSVGText *)textRoot { RNSVGText *root = self; while (root && [root class] != [RNSVGText class]) { if (![root isKindOfClass:[RNSVGText class]]) { //todo: throw exception here break; } root = (RNSVGText*)[root superview]; } return root; } - (NSString *)alignmentBaseline { if (_alignmentBaseline != nil) { return _alignmentBaseline; } UIView* parent = self.superview; while (parent != nil) { if ([parent isKindOfClass:[RNSVGText class]]) { RNSVGText* node = (RNSVGText*)parent; NSString* baseline = node.alignmentBaseline; if (baseline != nil) { _alignmentBaseline = baseline; return baseline; } } parent = [parent superview]; } if (_alignmentBaseline == nil) { _alignmentBaseline = RNSVGAlignmentBaselineStrings[0]; } return _alignmentBaseline; } - (NSString *)baselineShift { if (_baselineShift != nil) { return _baselineShift; } UIView* parent = [self superview]; while (parent != nil) { if ([parent isKindOfClass:[RNSVGText class]]) { RNSVGText* node = (RNSVGText*)parent; NSString* baselineShift = node.baselineShift; if (baselineShift != nil) { _baselineShift = baselineShift; return baselineShift; } } parent = [parent superview]; } // set default value _baselineShift = @""; return _baselineShift; } - (RNSVGGlyphContext *)getGlyphContext { return _glyphContext; } - (void)pushGlyphContext { [[self.textRoot getGlyphContext] pushContext:self font:self.font x:self.positionX y:self.positionY deltaX:self.deltaX deltaY:self.deltaY rotate:self.rotate]; } - (void)popGlyphContext { [[self.textRoot getGlyphContext] popContext]; } - (CTFontRef)getFontFromContext { return [[self.textRoot getGlyphContext] getGlyphFont]; } @end