diff --git a/ios/Elements/RNSVGPath.h b/ios/Elements/RNSVGPath.h
index ea8e2431..2caf060e 100644
--- a/ios/Elements/RNSVGPath.h
+++ b/ios/Elements/RNSVGPath.h
@@ -14,6 +14,4 @@
@property (nonatomic, strong) RNSVGPathParser *d;
-- (void)getPathLength:(CGFloat*)length lineCount:(NSInteger*)lineCount lengths:(NSArray* __strong *)lengths lines:(NSArray* __strong *)lines isClosed:(BOOL*)isClosed;
-
@end
diff --git a/ios/Elements/RNSVGPath.m b/ios/Elements/RNSVGPath.m
index 95eeb199..fc77c23f 100644
--- a/ios/Elements/RNSVGPath.m
+++ b/ios/Elements/RNSVGPath.m
@@ -7,256 +7,10 @@
*/
#import "RNSVGPath.h"
-#import "BezierElement.h"
-
-/* Bezier logic from PerformanceBezier */
-/*
-
- ## License
-
- 
This work is licensed under a Creative Commons Attribution 3.0 United States License.
-
- For attribution, please include:
-
- 1. Mention original author "Adam Wulf for Loose Leaf app"
- 2. Link to https://getlooseleaf.com/opensource/
- 3. Link to https://github.com/adamwulf/PerformanceBezier
-
- */
-static CGFloat idealFlatness = .01;
-
-/**
- * returns the distance between two points
- */
-CGFloat distance(CGPoint p1, CGPoint p2)
-{
- CGFloat dx = p2.x - p1.x;
- CGFloat dy = p2.y - p1.y;
-
- return sqrt(dx*dx + dy*dy);
-}
-
-/**
- * returns the dot product of two coordinates
- */
-CGFloat dotProduct(const CGPoint p1, const CGPoint p2) {
- return p1.x * p2.x + p1.y * p2.y;
-}
-
-/**
- * returns the shortest distance from a point to a line
- */
-CGFloat distanceOfPointToLine(CGPoint point, CGPoint start, CGPoint end){
- CGPoint v = CGPointMake(end.x - start.x, end.y - start.y);
- CGPoint w = CGPointMake(point.x - start.x, point.y - start.y);
- CGFloat c1 = dotProduct(w, v);
- CGFloat c2 = dotProduct(v, v);
- CGFloat d;
- if (c1 <= 0) {
- d = distance(point, start);
- }
- else if (c2 <= c1) {
- d = distance(point, end);
- }
- else {
- CGFloat b = c1 / c2;
- CGPoint Pb = CGPointMake(start.x + b * v.x, start.y + b * v.y);
- d = distance(point, Pb);
- }
- return d;
-}
-
-/**
- * calculate the point on a bezier at time t
- * where 0 < t < 1
- */
-CGPoint bezierPointAtT(const CGPoint bez[4], CGFloat t)
-{
- CGPoint q;
- CGFloat mt = 1 - t;
-
- CGPoint bez1[4];
- CGPoint bez2[4];
-
- q.x = mt * bez[1].x + t * bez[2].x;
- q.y = mt * bez[1].y + t * bez[2].y;
- bez1[1].x = mt * bez[0].x + t * bez[1].x;
- bez1[1].y = mt * bez[0].y + t * bez[1].y;
- bez2[2].x = mt * bez[2].x + t * bez[3].x;
- bez2[2].y = mt * bez[2].y + t * bez[3].y;
-
- bez1[2].x = mt * bez1[1].x + t * q.x;
- bez1[2].y = mt * bez1[1].y + t * q.y;
- bez2[1].x = mt * q.x + t * bez2[2].x;
- bez2[1].y = mt * q.y + t * bez2[2].y;
-
- bez1[3].x = bez2[0].x = mt * bez1[2].x + t * bez2[1].x;
- bez1[3].y = bez2[0].y = mt * bez1[2].y + t * bez2[1].y;
-
- return CGPointMake(bez1[3].x, bez1[3].y);
-}
-
-// Subdivide a Bézier (specific division)
-/*
- * (c) 2004 Alastair J. Houghton
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. The name of the author of this software may not be used to endorse
- * or promote products derived from the software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY DIRECT, INDIRECT,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-void subdivideBezierAtT(const CGPoint bez[4], CGPoint bez1[4], CGPoint bez2[4], CGFloat t)
-{
- CGPoint q;
- CGFloat mt = 1 - t;
-
- bez1[0].x = bez[0].x;
- bez1[0].y = bez[0].y;
- bez2[3].x = bez[3].x;
- bez2[3].y = bez[3].y;
-
- q.x = mt * bez[1].x + t * bez[2].x;
- q.y = mt * bez[1].y + t * bez[2].y;
- bez1[1].x = mt * bez[0].x + t * bez[1].x;
- bez1[1].y = mt * bez[0].y + t * bez[1].y;
- bez2[2].x = mt * bez[2].x + t * bez[3].x;
- bez2[2].y = mt * bez[2].y + t * bez[3].y;
-
- bez1[2].x = mt * bez1[1].x + t * q.x;
- bez1[2].y = mt * bez1[1].y + t * q.y;
- bez2[1].x = mt * q.x + t * bez2[2].x;
- bez2[1].y = mt * q.y + t * bez2[2].y;
-
- bez1[3].x = bez2[0].x = mt * bez1[2].x + t * bez2[1].x;
- bez1[3].y = bez2[0].y = mt * bez1[2].y + t * bez2[1].y;
-}
-
-void addLine(CGPoint *last, const CGPoint *next, NSMutableArray *lines, CGFloat *length, NSMutableArray *lengths) {
- NSArray *line = @[[NSValue valueWithCGPoint:*last], [NSValue valueWithCGPoint:*next]];
- [lines addObject:line];
- *length += distance(*last, *next);
- [lengths addObject:[NSNumber numberWithDouble:*length]];
- *last = *next;
-}
@implementation RNSVGPath
{
CGPathRef _path;
- NSMutableArray *lengths;
- NSMutableArray *lines;
- NSInteger lineCount;
- CGFloat length;
- BOOL isClosed;
- BOOL cached;
-}
-
-- (void)getPathLength:(CGFloat*)lengthP lineCount:(NSInteger*)lineCountP lengths:(NSArray* __strong *)lengthsP lines:(NSArray* __strong *)linesP isClosed:(BOOL*)isClosedP
-{
- if (!cached) {
- CGPoint origin = CGPointMake (0.0, 0.0);
- CGPoint last = CGPointMake (0.0, 0.0);
- lengths = [NSMutableArray array];
- lines = [NSMutableArray array];
- isClosed = NO;
- lineCount = 0;
- length = 0;
-
- NSArray *elements = [_d getBezierCurves];
- for (BezierElement *element in elements) {
- switch (element.elementType)
- {
- case kCGPathElementMoveToPoint:
- origin = last = element.point;
- break;
-
- case kCGPathElementAddLineToPoint: {
- CGPoint next = element.point;
- addLine(&last, &next, lines, &length, lengths);
- lineCount++;
- break;
- }
- case kCGPathElementAddQuadCurveToPoint:
- case kCGPathElementAddCurveToPoint:
- {
- // handle both curve types gracefully
- CGPoint curveTo = element.point;
- CGPoint ctrl1 = element.controlPoint1;
- CGPoint ctrl2 = element.elementType == kCGPathElementAddQuadCurveToPoint ? ctrl1 : element.controlPoint2;
-
- // this is the bezier for our current element
- CGPoint bezier[4] = { last, ctrl1, ctrl2, curveTo };
- NSValue *arr = [NSValue valueWithBytes:&bezier objCType:@encode(CGPoint[4])];
- NSMutableArray *curves = [NSMutableArray arrayWithObjects:arr, nil];
-
- for (NSInteger curveIndex = 0; curveIndex >= 0; curveIndex--) {
- CGPoint bez[4];
- [curves[curveIndex] getValue:&bez];
- [curves removeLastObject];
-
- // calculate the error rate of the curve vs
- // a line segement between the start and end points
- CGPoint onCurve = bezierPointAtT(bez, .5);
- CGPoint next = bez[3];
- CGFloat error = distanceOfPointToLine(onCurve, last, next);
-
- // if the error is less than our accepted level of error
- // then add a line, else, split the curve in half
- if (error <= idealFlatness) {
- addLine(&last, &next, lines, &length, lengths);
- lineCount++;
- } else {
- CGPoint bez1[4], bez2[4];
- subdivideBezierAtT(bez, bez1, bez2, .5);
- [curves addObject:[NSValue valueWithBytes:&bez2 objCType:@encode(CGPoint[4])]];
- [curves addObject:[NSValue valueWithBytes:&bez1 objCType:@encode(CGPoint[4])]];
- curveIndex += 2;
- }
- }
- last = curveTo;
- break;
- }
-
- case kCGPathElementCloseSubpath: {
- CGPoint next = origin;
- addLine(&last, &next, lines, &length, lengths);
- lineCount++;
- isClosed = YES;
- break;
- }
-
- default:
- break;
- }
- }
- cached = YES;
- }
- *lineCountP = lineCount;
- *isClosedP = isClosed;
- *lengthsP = lengths;
- *lengthP = length;
- *linesP = lines;
}
- (void)setD:(RNSVGPathParser *)d
@@ -267,9 +21,6 @@ void addLine(CGPoint *last, const CGPoint *next, NSMutableArray *lines, CGFloat
[self invalidate];
_d = d;
- lines = nil;
- lengths = nil;
- cached = false;
CGPathRelease(_path);
_path = CGPathRetain([d getPath]);
}
@@ -281,8 +32,6 @@ void addLine(CGPoint *last, const CGPoint *next, NSMutableArray *lines, CGFloat
- (void)dealloc
{
- lines = nil;
- lengths = nil;
CGPathRelease(_path);
}
diff --git a/ios/RNSVG.xcodeproj/project.pbxproj b/ios/RNSVG.xcodeproj/project.pbxproj
index 88570bcd..6bfe28ac 100644
--- a/ios/RNSVG.xcodeproj/project.pbxproj
+++ b/ios/RNSVG.xcodeproj/project.pbxproj
@@ -248,7 +248,6 @@
7F08CE9D1E23479700650F83 /* RNSVGTextPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNSVGTextPath.m; path = Text/RNSVGTextPath.m; sourceTree = ""; };
7F08CE9E1E23479700650F83 /* RNSVGTSpan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGTSpan.h; path = Text/RNSVGTSpan.h; sourceTree = ""; };
7F08CE9F1E23479700650F83 /* RNSVGTSpan.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNSVGTSpan.m; path = Text/RNSVGTSpan.m; sourceTree = ""; };
- 7F08CEA31E23481F00650F83 /* RNSVGTextAnchor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGTextAnchor.h; path = Utils/RNSVGTextAnchor.h; sourceTree = ""; };
7F69160D1E3703D800DA6EDC /* RNSVGUnits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGUnits.h; path = Utils/RNSVGUnits.h; sourceTree = ""; };
7F9CDAF81E1F809C00E0C805 /* RNSVGPathParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSVGPathParser.h; path = Utils/RNSVGPathParser.h; sourceTree = ""; };
7F9CDAF91E1F809C00E0C805 /* RNSVGPathParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNSVGPathParser.m; path = Utils/RNSVGPathParser.m; sourceTree = ""; };
@@ -501,7 +500,6 @@
7F69160D1E3703D800DA6EDC /* RNSVGUnits.h */,
10ABC7381D43982B006CCF6E /* RNSVGVBMOS.h */,
10ABC7371D439779006CCF6E /* RNSVGCGFCRule.h */,
- 7F08CEA31E23481F00650F83 /* RNSVGTextAnchor.h */,
7FC260CC1E3499BC00A39833 /* RNSVGViewBox.h */,
7FC260CD1E3499BC00A39833 /* RNSVGViewBox.m */,
1039D29E1CE72177001E90A8 /* RNSVGCGFloatArray.h */,
diff --git a/ios/Text/RNSVGTSpan.m b/ios/Text/RNSVGTSpan.m
index 1d549ccc..486699dd 100644
--- a/ios/Text/RNSVGTSpan.m
+++ b/ios/Text/RNSVGTSpan.m
@@ -870,7 +870,7 @@ CGFloat getTextAnchorOffset(enum TextAnchor textAnchor, CGFloat width)
[self traverseTextSuperviews:^(__kindof RNSVGText *node) {
if ([node class] == [RNSVGTextPath class]) {
textPath = (RNSVGTextPath*) node;
- [[textPath getPath] getPathLength:&_pathLength lineCount:&lineCount lengths:&lengths lines:&lines isClosed:&isClosed];
+ [textPath getPathLength:&_pathLength lineCount:&lineCount lengths:&lengths lines:&lines isClosed:&isClosed];
return NO;
}
return YES;
diff --git a/ios/Text/RNSVGText.h b/ios/Text/RNSVGText.h
index 42f66e40..47dddf2e 100644
--- a/ios/Text/RNSVGText.h
+++ b/ios/Text/RNSVGText.h
@@ -8,7 +8,6 @@
#import
#import "RNSVGGroup.h"
-#import "RNSVGTextAnchor.h"
#import "AlignmentBaseline.h"
@interface RNSVGText : RNSVGGroup
diff --git a/ios/Text/RNSVGTextPath.h b/ios/Text/RNSVGTextPath.h
index ec08b7ad..4105dc6f 100644
--- a/ios/Text/RNSVGTextPath.h
+++ b/ios/Text/RNSVGTextPath.h
@@ -19,6 +19,7 @@
@property (nonatomic, strong) NSString *spacing;
@property (nonatomic, strong) NSString *startOffset;
-- (RNSVGPath *)getPath;
+- (void)getPathLength:(CGFloat*)length lineCount:(NSInteger*)lineCount lengths:(NSArray* __strong *)lengths lines:(NSArray* __strong *)lines isClosed:(BOOL*)isClosed;
+
@end
diff --git a/ios/Text/RNSVGTextPath.m b/ios/Text/RNSVGTextPath.m
index 310a6b0e..db633b60 100644
--- a/ios/Text/RNSVGTextPath.m
+++ b/ios/Text/RNSVGTextPath.m
@@ -8,28 +8,267 @@
#import "RNSVGTextPath.h"
+#import "BezierElement.h"
+
+/* Bezier logic from PerformanceBezier */
+/*
+
+ ## License
+
+ 
This work is licensed under a Creative Commons Attribution 3.0 United States License.
+
+ For attribution, please include:
+
+ 1. Mention original author "Adam Wulf for Loose Leaf app"
+ 2. Link to https://getlooseleaf.com/opensource/
+ 3. Link to https://github.com/adamwulf/PerformanceBezier
+
+ */
+static CGFloat idealFlatness = .01;
+
+/**
+ * returns the distance between two points
+ */
+CGFloat distance(CGPoint p1, CGPoint p2)
+{
+ CGFloat dx = p2.x - p1.x;
+ CGFloat dy = p2.y - p1.y;
+
+ return sqrt(dx*dx + dy*dy);
+}
+
+/**
+ * returns the dot product of two coordinates
+ */
+CGFloat dotProduct(const CGPoint p1, const CGPoint p2) {
+ return p1.x * p2.x + p1.y * p2.y;
+}
+
+/**
+ * returns the shortest distance from a point to a line
+ */
+CGFloat distanceOfPointToLine(CGPoint point, CGPoint start, CGPoint end){
+ CGPoint v = CGPointMake(end.x - start.x, end.y - start.y);
+ CGPoint w = CGPointMake(point.x - start.x, point.y - start.y);
+ CGFloat c1 = dotProduct(w, v);
+ CGFloat c2 = dotProduct(v, v);
+ CGFloat d;
+ if (c1 <= 0) {
+ d = distance(point, start);
+ }
+ else if (c2 <= c1) {
+ d = distance(point, end);
+ }
+ else {
+ CGFloat b = c1 / c2;
+ CGPoint Pb = CGPointMake(start.x + b * v.x, start.y + b * v.y);
+ d = distance(point, Pb);
+ }
+ return d;
+}
+
+/**
+ * calculate the point on a bezier at time t
+ * where 0 < t < 1
+ */
+CGPoint bezierPointAtT(const CGPoint bez[4], CGFloat t)
+{
+ CGPoint q;
+ CGFloat mt = 1 - t;
+
+ CGPoint bez1[4];
+ CGPoint bez2[4];
+
+ q.x = mt * bez[1].x + t * bez[2].x;
+ q.y = mt * bez[1].y + t * bez[2].y;
+ bez1[1].x = mt * bez[0].x + t * bez[1].x;
+ bez1[1].y = mt * bez[0].y + t * bez[1].y;
+ bez2[2].x = mt * bez[2].x + t * bez[3].x;
+ bez2[2].y = mt * bez[2].y + t * bez[3].y;
+
+ bez1[2].x = mt * bez1[1].x + t * q.x;
+ bez1[2].y = mt * bez1[1].y + t * q.y;
+ bez2[1].x = mt * q.x + t * bez2[2].x;
+ bez2[1].y = mt * q.y + t * bez2[2].y;
+
+ bez1[3].x = bez2[0].x = mt * bez1[2].x + t * bez2[1].x;
+ bez1[3].y = bez2[0].y = mt * bez1[2].y + t * bez2[1].y;
+
+ return CGPointMake(bez1[3].x, bez1[3].y);
+}
+
+// Subdivide a Bézier (specific division)
+/*
+ * (c) 2004 Alastair J. Houghton
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author of this software may not be used to endorse
+ * or promote products derived from the software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+void subdivideBezierAtT(const CGPoint bez[4], CGPoint bez1[4], CGPoint bez2[4], CGFloat t)
+{
+ CGPoint q;
+ CGFloat mt = 1 - t;
+
+ bez1[0].x = bez[0].x;
+ bez1[0].y = bez[0].y;
+ bez2[3].x = bez[3].x;
+ bez2[3].y = bez[3].y;
+
+ q.x = mt * bez[1].x + t * bez[2].x;
+ q.y = mt * bez[1].y + t * bez[2].y;
+ bez1[1].x = mt * bez[0].x + t * bez[1].x;
+ bez1[1].y = mt * bez[0].y + t * bez[1].y;
+ bez2[2].x = mt * bez[2].x + t * bez[3].x;
+ bez2[2].y = mt * bez[2].y + t * bez[3].y;
+
+ bez1[2].x = mt * bez1[1].x + t * q.x;
+ bez1[2].y = mt * bez1[1].y + t * q.y;
+ bez2[1].x = mt * q.x + t * bez2[2].x;
+ bez2[1].y = mt * q.y + t * bez2[2].y;
+
+ bez1[3].x = bez2[0].x = mt * bez1[2].x + t * bez2[1].x;
+ bez1[3].y = bez2[0].y = mt * bez1[2].y + t * bez2[1].y;
+}
+
+void addLine(CGPoint *last, const CGPoint *next, NSMutableArray *lines, CGFloat *length, NSMutableArray *lengths) {
+ NSArray *line = @[[NSValue valueWithCGPoint:*last], [NSValue valueWithCGPoint:*next]];
+ [lines addObject:line];
+ *length += distance(*last, *next);
+ [lengths addObject:[NSNumber numberWithDouble:*length]];
+ *last = *next;
+}
@implementation RNSVGTextPath
+{
+ CGPathRef _path;
+ NSMutableArray *lengths;
+ NSMutableArray *lines;
+ NSInteger lineCount;
+ CGFloat length;
+ BOOL isClosed;
+}
+
+- (void)getPathLength:(CGFloat*)lengthP lineCount:(NSInteger*)lineCountP lengths:(NSArray* __strong *)lengthsP lines:(NSArray* __strong *)linesP isClosed:(BOOL*)isClosedP
+{
+ RNSVGSvgView *svg = [self getSvgView];
+ RNSVGNode *template = [svg getDefinedTemplate:self.href];
+ CGPathRef path = [template getPath:nil];
+
+ if (_path != path) {
+ _path = path;
+ CGPoint origin = CGPointMake (0.0, 0.0);
+ CGPoint last = CGPointMake (0.0, 0.0);
+ lengths = [NSMutableArray array];
+ lines = [NSMutableArray array];
+ isClosed = NO;
+ lineCount = 0;
+ length = 0;
+
+ NSArray *elements = [BezierElement elementsFromCGPath:path];
+ for (BezierElement *element in elements) {
+ switch (element.elementType)
+ {
+ case kCGPathElementMoveToPoint:
+ origin = last = element.point;
+ break;
+
+ case kCGPathElementAddLineToPoint: {
+ CGPoint next = element.point;
+ addLine(&last, &next, lines, &length, lengths);
+ lineCount++;
+ break;
+ }
+ case kCGPathElementAddQuadCurveToPoint:
+ case kCGPathElementAddCurveToPoint:
+ {
+ // handle both curve types gracefully
+ CGPoint curveTo = element.point;
+ CGPoint ctrl1 = element.controlPoint1;
+ CGPoint ctrl2 = element.elementType == kCGPathElementAddQuadCurveToPoint ? ctrl1 : element.controlPoint2;
+
+ // this is the bezier for our current element
+ CGPoint bezier[4] = { last, ctrl1, ctrl2, curveTo };
+ NSValue *arr = [NSValue valueWithBytes:&bezier objCType:@encode(CGPoint[4])];
+ NSMutableArray *curves = [NSMutableArray arrayWithObjects:arr, nil];
+
+ for (NSInteger curveIndex = 0; curveIndex >= 0; curveIndex--) {
+ CGPoint bez[4];
+ [curves[curveIndex] getValue:&bez];
+ [curves removeLastObject];
+
+ // calculate the error rate of the curve vs
+ // a line segement between the start and end points
+ CGPoint onCurve = bezierPointAtT(bez, .5);
+ CGPoint next = bez[3];
+ CGFloat error = distanceOfPointToLine(onCurve, last, next);
+
+ // if the error is less than our accepted level of error
+ // then add a line, else, split the curve in half
+ if (error <= idealFlatness) {
+ addLine(&last, &next, lines, &length, lengths);
+ lineCount++;
+ } else {
+ CGPoint bez1[4], bez2[4];
+ subdivideBezierAtT(bez, bez1, bez2, .5);
+ [curves addObject:[NSValue valueWithBytes:&bez2 objCType:@encode(CGPoint[4])]];
+ [curves addObject:[NSValue valueWithBytes:&bez1 objCType:@encode(CGPoint[4])]];
+ curveIndex += 2;
+ }
+ }
+ last = curveTo;
+ break;
+ }
+
+ case kCGPathElementCloseSubpath: {
+ CGPoint next = origin;
+ addLine(&last, &next, lines, &length, lengths);
+ lineCount++;
+ isClosed = YES;
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ }
+
+ *lineCountP = lineCount;
+ *isClosedP = isClosed;
+ *lengthsP = lengths;
+ *lengthP = length;
+ *linesP = lines;
+}
- (void)renderLayerTo:(CGContextRef)context
{
[self renderGroupTo:context];
}
-- (RNSVGPath *)getPath
-{
- RNSVGSvgView *svg = [self getSvgView];
- RNSVGNode *template = [svg getDefinedTemplate:self.href];
-
- if ([template class] != [RNSVGPath class]) {
- // warning about this.
- return nil;
- }
-
- RNSVGPath *path = (RNSVGPath *)template;
- return path;
-}
-
- (CGPathRef)getPath:(CGContextRef)context
{
return [self getGroupPath:context];
diff --git a/ios/Utils/BezierElement.h b/ios/Utils/BezierElement.h
index a78c8721..5d59efc0 100644
--- a/ios/Utils/BezierElement.h
+++ b/ios/Utils/BezierElement.h
@@ -17,5 +17,9 @@
@property (nonatomic, assign) CGPoint controlPoint1;
@property (nonatomic, assign) CGPoint controlPoint2;
+// Instance creation
++ (instancetype) elementWithPathElement: (CGPathElement) element;
++ (NSArray *) elementsFromCGPath:(CGPathRef)path;
+
@end;
diff --git a/ios/Utils/BezierElement.m b/ios/Utils/BezierElement.m
index 73a8eb50..98bc65d1 100644
--- a/ios/Utils/BezierElement.m
+++ b/ios/Utils/BezierElement.m
@@ -21,5 +21,57 @@
}
return self;
}
+
++ (instancetype) elementWithPathElement: (CGPathElement) element
+{
+ BezierElement *newElement = [[self alloc] init];
+ newElement.elementType = element.type;
+
+ switch (newElement.elementType)
+ {
+ case kCGPathElementCloseSubpath:
+ break;
+ case kCGPathElementMoveToPoint:
+ case kCGPathElementAddLineToPoint:
+ {
+ newElement.point = element.points[0];
+ break;
+ }
+ case kCGPathElementAddQuadCurveToPoint:
+ {
+ newElement.point = element.points[1];
+ newElement.controlPoint1 = element.points[0];
+ break;
+ }
+ case kCGPathElementAddCurveToPoint:
+ {
+ newElement.point = element.points[2];
+ newElement.controlPoint1 = element.points[0];
+ newElement.controlPoint2 = element.points[1];
+ break;
+ }
+ default:
+ break;
+ }
+
+ return newElement;
+}
+
+// Convert one element to BezierElement and save to array
+void GetBezierElements(void *info, const CGPathElement *element)
+{
+ NSMutableArray *bezierElements = (__bridge NSMutableArray *)info;
+ if (element)
+ [bezierElements addObject:[BezierElement elementWithPathElement:*element]];
+}
+
+// Retrieve array of component elements
++ (NSArray *) elementsFromCGPath:(CGPathRef)path
+{
+ NSMutableArray *elements = [NSMutableArray array];
+ CGPathApply(path, (__bridge void *)elements, GetBezierElements);
+ return elements;
+}
+
@end
diff --git a/ios/Utils/RCTConvert+RNSVG.h b/ios/Utils/RCTConvert+RNSVG.h
index 0b266d45..49500fd6 100644
--- a/ios/Utils/RCTConvert+RNSVG.h
+++ b/ios/Utils/RCTConvert+RNSVG.h
@@ -13,7 +13,6 @@
#import
#import "RNSVGCGFCRule.h"
#import "RNSVGVBMOS.h"
-#import "RNSVGTextAnchor.h"
#import "RNSVGUnits.h"
#import "RNSVGPathParser.h"
@@ -21,7 +20,6 @@
@interface RCTConvert (RNSVG)
-+ (RNSVGTextAnchor)RNSVGTextAnchor:(id)json;
+ (RNSVGCGFCRule)RNSVGCGFCRule:(id)json;
+ (RNSVGVBMOS)RNSVGVBMOS:(id)json;
+ (RNSVGUnits)RNSVGUnits:(id)json;
diff --git a/ios/Utils/RCTConvert+RNSVG.m b/ios/Utils/RCTConvert+RNSVG.m
index d3554ed0..53655148 100644
--- a/ios/Utils/RCTConvert+RNSVG.m
+++ b/ios/Utils/RCTConvert+RNSVG.m
@@ -26,13 +26,6 @@ RCT_ENUM_CONVERTER(RNSVGVBMOS, (@{
@"none": @(kRNSVGVBMOSNone)
}), kRNSVGVBMOSMeet, intValue)
-RCT_ENUM_CONVERTER(RNSVGTextAnchor, (@{
- @"auto": @(kRNSVGTextAnchorAuto),
- @"start": @(kRNSVGTextAnchorStart),
- @"middle": @(kRNSVGTextAnchorMiddle),
- @"end": @(kRNSVGTextAnchorEnd)
- }), kRNSVGTextAnchorAuto, intValue)
-
RCT_ENUM_CONVERTER(RNSVGUnits, (@{
@"objectBoundingBox": @(kRNSVGUnitsObjectBoundingBox),
@"userSpaceOnUse": @(kRNSVGUnitsUserSpaceOnUse),
diff --git a/ios/Utils/RNSVGPathParser.h b/ios/Utils/RNSVGPathParser.h
index da53782b..5ea68b82 100644
--- a/ios/Utils/RNSVGPathParser.h
+++ b/ios/Utils/RNSVGPathParser.h
@@ -13,6 +13,5 @@
- (instancetype) initWithPathString:(NSString *)d;
- (CGPathRef)getPath;
-- (NSArray *)getBezierCurves;
@end
diff --git a/ios/Utils/RNSVGPathParser.m b/ios/Utils/RNSVGPathParser.m
index 76d78c71..1c434cde 100644
--- a/ios/Utils/RNSVGPathParser.m
+++ b/ios/Utils/RNSVGPathParser.m
@@ -16,7 +16,6 @@
NSString* _d;
NSString* _originD;
NSRegularExpression* _pathRegularExpression;
- NSMutableArray* _bezierCurves;
float _penX;
float _penY;
float _penDownX;
@@ -42,7 +41,6 @@
{
CGMutablePathRef path = CGPathCreateMutable();
NSArray* results = [_pathRegularExpression matchesInString:_d options:0 range:NSMakeRange(0, [_d length])];
- _bezierCurves = [[NSMutableArray alloc] init];
unsigned long count = [results count];
if (count) {
@@ -121,15 +119,6 @@
return (CGPathRef)CFAutorelease(path);
}
-- (NSArray *)getBezierCurves
-{
- if (!_bezierCurves) {
- CGPathRelease([self getPath]);
- }
-
- return [_bezierCurves copy];
-}
-
- (NSString *)getNextValue:(NSTextCheckingResult *)result
{
if (!result) {
@@ -158,11 +147,6 @@
_pivotX = _penX = x;
_pivotY = _penY = y;
CGPathMoveToPoint(path, nil, x, y);
-
- BezierElement *newElement = [[BezierElement alloc] init];
- newElement.elementType = kCGPathElementMoveToPoint;
- newElement.point = CGPointMake(x, y);
- [_bezierCurves addObject:newElement];
}
- (void)line:(CGMutablePathRef)path x:(float)x y:(float)y
@@ -175,11 +159,6 @@
_pivotX = _penX = x;
_pivotY = _penY = y;
CGPathAddLineToPoint(path, nil, x, y);
-
- BezierElement *newElement = [[BezierElement alloc] init];
- newElement.elementType = kCGPathElementAddLineToPoint;
- newElement.point = CGPointMake(x, y);
- [_bezierCurves addObject:newElement];
}
- (void)curve:(CGMutablePathRef)path c1x:(float)c1x c1y:(float)c1y c2x:(float)c2x c2y:(float)c2y ex:(float)ex ey:(float)ey
@@ -205,13 +184,6 @@
_penX = ex;
_penY = ey;
CGPathAddCurveToPoint(path, nil, c1x, c1y, c2x, c2y, ex, ey);
-
- BezierElement *newElement = [[BezierElement alloc] init];
- newElement.elementType = kCGPathElementAddCurveToPoint;
- newElement.controlPoint1 = CGPointMake(c1x, c1y);
- newElement.controlPoint2 = CGPointMake(c2x, c2y);
- newElement.point = CGPointMake(ex, ey);
- [_bezierCurves addObject:newElement];
}
- (void)smoothCurve:(CGMutablePathRef)path c1x:(float)c1x c1y:(float)c1y ex:(float)ex ey:(float)ey
@@ -379,13 +351,6 @@
float ex = cx + xx * x + yx * y;
float ey = cy + xy * x + yy * y;
CGPathAddCurveToPoint(path, nil, c1x, c1y, c2x, c2y, ex, ey);
-
- BezierElement *newElement = [[BezierElement alloc] init];
- newElement.elementType = kCGPathElementAddCurveToPoint;
- newElement.controlPoint1 = CGPointMake(c1x, c1y);
- newElement.controlPoint2 = CGPointMake(c2x, c2y);
- newElement.point = CGPointMake(ex, ey);
- [_bezierCurves addObject:newElement];
}
}
@@ -396,9 +361,6 @@
_penY = _penDownY;
_penDownSet = NO;
CGPathCloseSubpath(path);
- BezierElement *newElement = [[BezierElement alloc] init];
- newElement.elementType = kCGPathElementCloseSubpath;
- [_bezierCurves addObject:newElement];
}
}
diff --git a/ios/Utils/RNSVGTextAnchor.h b/ios/Utils/RNSVGTextAnchor.h
deleted file mode 100644
index 06eded9d..00000000
--- a/ios/Utils/RNSVGTextAnchor.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * 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.
- */
-
-typedef CF_ENUM(int32_t, RNSVGTextAnchor) {
- kRNSVGTextAnchorAuto,
- kRNSVGTextAnchorStart,
- kRNSVGTextAnchorMiddle,
- kRNSVGTextAnchorEnd
-};
diff --git a/ios/ViewManagers/RNSVGTSpanManager.m b/ios/ViewManagers/RNSVGTSpanManager.m
index d9ddc646..fc5ca79d 100644
--- a/ios/ViewManagers/RNSVGTSpanManager.m
+++ b/ios/ViewManagers/RNSVGTSpanManager.m
@@ -9,7 +9,6 @@
#import "RNSVGTSpanManager.h"
#import "RNSVGTSpan.h"
-#import "RNSVGTextAnchor.h"
#import "RCTConvert+RNSVG.h"
@implementation RNSVGTSpanManager