9
9
#import " RNSVGText.h"
10
10
#import " RNSVGTextPath.h"
11
11
#import " RNSVGTextProperties.h"
12
+ #import " RNSVGPathMeasure.h"
12
13
#import " RNSVGFontData.h"
13
14
14
15
static NSCharacterSet *RNSVGTSpan_separators = nil ;
@@ -38,18 +39,14 @@ - (void)drawTextInRect:(CGRect) rect
38
39
@implementation RNSVGTSpan
39
40
{
40
41
CGFloat startOffset;
41
- CGFloat _pathLength;
42
42
RNSVGTextPath *textPath;
43
- NSArray *lengths;
44
- NSArray *lines;
45
- NSUInteger lineCount;
46
- BOOL isClosed;
47
43
NSMutableArray *emoji;
48
44
NSMutableArray *emojiTransform;
49
45
CGFloat cachedAdvance;
50
46
CTFontRef fontRef;
51
47
CGFloat firstX;
52
48
CGFloat firstY;
49
+ RNSVGPathMeasure *measure;
53
50
}
54
51
55
52
- (id )init
@@ -62,6 +59,7 @@ - (id)init
62
59
63
60
emoji = [NSMutableArray arrayWithCapacity: 0 ];
64
61
emojiTransform = [NSMutableArray arrayWithCapacity: 0 ];
62
+ measure = [[RNSVGPathMeasure alloc ]init];
65
63
66
64
return self;
67
65
}
@@ -476,7 +474,7 @@ vertical alternates (OpenType feature: vert) must be enabled.
476
474
477
475
int side = 1 ;
478
476
CGFloat startOfRendering = 0 ;
479
- CGFloat endOfRendering = _pathLength ;
477
+ CGFloat endOfRendering = measure. pathLength ;
480
478
CGFloat fontSize = [gc getFontSize ];
481
479
// bool sharpMidLine = false;
482
480
if (hasTextPath) {
@@ -541,13 +539,13 @@ For the start (end) value, the text is rendered from the start (end) of the line
541
539
the path is reached.
542
540
*/
543
541
CGFloat absoluteStartOffset = [RNSVGPropHelper fromRelative: textPath.startOffset
544
- relative: _pathLength
542
+ relative: measure.pathLength
545
543
fontSize: fontSize];
546
544
offset += absoluteStartOffset;
547
- if (isClosed) {
548
- CGFloat halfPathDistance = _pathLength / 2 ;
545
+ if (measure. isClosed ) {
546
+ CGFloat halfPathDistance = measure. pathLength / 2 ;
549
547
startOfRendering = absoluteStartOffset + (textAnchor == RNSVGTextAnchorMiddle ? -halfPathDistance : 0 );
550
- endOfRendering = startOfRendering + _pathLength ;
548
+ endOfRendering = startOfRendering + measure. pathLength ;
551
549
}
552
550
/*
553
551
RNSVGTextPathSpacing spacing = textPath.getSpacing();
@@ -958,39 +956,10 @@ A negative value is an error (see Error processing).
958
956
continue ;
959
957
}
960
958
961
- // Investigation suggests binary search is faster at lineCount >= 16
962
- // https://gist.github.com/msand/4c7993319425f9d7933be58ad9ada1a4
963
- NSUInteger i = lineCount < 16 ?
964
- [lengths
965
- indexOfObjectPassingTest: ^(NSNumber * length, NSUInteger index, BOOL * _Nonnull stop) {
966
- BOOL contains = midPoint <= [length doubleValue ];
967
- return contains;
968
- }]
969
- :
970
- [lengths
971
- indexOfObject: [NSNumber numberWithDouble: midPoint]
972
- inSortedRange: NSMakeRange (0 , lineCount)
973
- options: NSBinarySearchingInsertionIndex
974
- usingComparator: ^(NSNumber * obj1, NSNumber * obj2) {
975
- return [obj1 compare: obj2];
976
- }];
977
-
978
- CGFloat totalLength = (CGFloat)[lengths[i] doubleValue ];
979
- CGFloat prevLength = i == 0 ? 0 : (CGFloat)[lengths[i - 1 ] doubleValue ];
980
-
981
- CGFloat length = totalLength - prevLength;
982
- CGFloat percent = (midPoint - prevLength) / length;
983
-
984
- NSArray * points = [lines objectAtIndex: i];
985
- CGPoint p1 = [[points objectAtIndex: 0 ] CGPointValue ];
986
- CGPoint p2 = [[points objectAtIndex: 1 ] CGPointValue ];
987
-
988
- CGFloat ldx = p2.x - p1.x ;
989
- CGFloat ldy = p2.y - p1.y ;
990
- CGFloat angle = atan2 (ldy, ldx);
991
-
992
- CGFloat px = p1.x + ldx * percent;
993
- CGFloat py = p1.y + ldy * percent;
959
+ CGFloat angle;
960
+ CGFloat px;
961
+ CGFloat py;
962
+ [measure getPosAndTan: &angle midPoint: midPoint px: &px py: &py];
994
963
995
964
transform = CGAffineTransformConcat (CGAffineTransformMakeTranslation (px, py), transform);
996
965
transform = CGAffineTransformConcat (CGAffineTransformMakeRotation (angle + r), transform);
@@ -1061,24 +1030,18 @@ + (CGFloat)getTextAnchorOffset:(RNSVGTextAnchor)textAnchor width:(CGFloat) width
1061
1030
1062
1031
- (void )setupTextPath : (CGContextRef)context
1063
1032
{
1064
- lines = nil ;
1065
- lengths = nil ;
1066
1033
textPath = nil ;
1067
1034
RNSVGText *parent = (RNSVGText*)[self superview ];
1068
-
1069
1035
while (parent) {
1070
1036
if ([parent class ] == [RNSVGTextPath class ]) {
1071
1037
textPath = (RNSVGTextPath*) parent;
1072
- [textPath getPathLength: &_pathLength
1073
- lineCount: &lineCount
1074
- lengths: &lengths
1075
- lines: &lines
1076
- isClosed: &isClosed];
1038
+ RNSVGNode *template = [self .svgView getDefinedTemplate: textPath.href];
1039
+ CGPathRef path = [template getPath: nil ];
1040
+ [measure extractPathData: path];
1077
1041
break ;
1078
1042
} else if (![parent isKindOfClass: [RNSVGText class ]]) {
1079
1043
break ;
1080
1044
}
1081
-
1082
1045
parent = (RNSVGText*)[parent superview ];
1083
1046
}
1084
1047
}
0 commit comments