mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 14:05:09 +00:00
174 lines
4.3 KiB
Objective-C
174 lines
4.3 KiB
Objective-C
/**
|
|
* 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 <React/RCTFont.h>
|
|
#import <CoreText/CoreText.h>
|
|
#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
|