forked from svga/SVGAPlayer-iOS
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSVGABezierPath.m
More file actions
117 lines (106 loc) · 5.19 KB
/
SVGABezierPath.m
File metadata and controls
117 lines (106 loc) · 5.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//
// SVGABezierPath.m
// SVGAPlayer
//
// Created by 崔明辉 on 16/6/28.
// Copyright © 2016年 UED Center. All rights reserved.
//
#import "SVGABezierPath.h"
@interface SVGABezierPath ()
@property (nonatomic, assign) BOOL displaying;
@property (nonatomic, copy) NSString *backValues;
@end
@implementation SVGABezierPath
- (void)setValues:(nonnull NSString *)values {
if (!self.displaying) {
self.backValues = values;
return;
}
static NSSet *validMethods;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
validMethods = [NSSet setWithArray:@[@"M",@"L",@"H",@"V",@"C",@"S",@"Q",@"R",@"A",@"Z",@"m",@"l",@"h",@"v",@"c",@"s",@"q",@"r",@"a",@"z"]];
});
values = [values stringByReplacingOccurrencesOfString:@"([a-zA-Z])" withString:@"|||$1 " options:NSRegularExpressionSearch range:NSMakeRange(0, values.length)];
values = [values stringByReplacingOccurrencesOfString:@"," withString:@" "];
NSArray<NSString *> *segments = [values componentsSeparatedByString:@"|||"];
for (NSString *segment in segments) {
if (segment.length == 0) {
continue;
}
NSString *firstLetter = [segment substringToIndex:1];
if ([validMethods containsObject:firstLetter]) {
NSArray *args = [[[segment substringFromIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsSeparatedByString:@" "];
[self operate:firstLetter args:args];
}
}
}
- (nonnull CAShapeLayer *)createLayer {
if (!self.displaying) {
self.displaying = YES;
[self setValues:self.backValues];
}
CAShapeLayer *layer = [CAShapeLayer layer];
layer.path = self.CGPath;
layer.fillColor = [UIColor blackColor].CGColor;
return layer;
}
- (void)operate:(NSString *)method args:(NSArray<NSString *> *)args {
if (([method isEqualToString:@"M"] || [method isEqualToString:@"m"]) && args.count == 2) {
CGPoint iPoint = [self argPoint:CGPointMake([args[0] floatValue], [args[1] floatValue]) relative:[method isEqualToString:@"m"]];
if (!CGPointEqualToPoint(iPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN))) {
[self moveToPoint:iPoint];
}
}
else if (([method isEqualToString:@"L"] || [method isEqualToString:@"l"]) && args.count == 2) {
CGPoint iPoint = [self argPoint:CGPointMake([args[0] floatValue], [args[1] floatValue]) relative:[method isEqualToString:@"l"]];
if (!CGPointEqualToPoint(iPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN))) {
[self addLineToPoint:iPoint];
}
}
else if (([method isEqualToString:@"C"] || [method isEqualToString:@"c"]) && args.count == 6) {
CGPoint iPoint = [self argPoint:CGPointMake([args[0] floatValue], [args[1] floatValue]) relative:[method isEqualToString:@"c"]];
CGPoint iiPoint = [self argPoint:CGPointMake([args[2] floatValue], [args[3] floatValue]) relative:[method isEqualToString:@"c"]];
CGPoint iiiPoint = [self argPoint:CGPointMake([args[4] floatValue], [args[5] floatValue]) relative:[method isEqualToString:@"c"]];
if (!CGPointEqualToPoint(iPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN)) &&
!CGPointEqualToPoint(iiPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN)) &&
!CGPointEqualToPoint(iiiPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN))) {
[self addCurveToPoint:iiiPoint controlPoint1:iPoint controlPoint2:iiPoint];
}
}
else if (([method isEqualToString:@"Q"] || [method isEqualToString:@"q"]) && args.count == 4) {
CGPoint iPoint = [self argPoint:CGPointMake([args[0] floatValue], [args[1] floatValue]) relative:[method isEqualToString:@"q"]];
CGPoint iiPoint = [self argPoint:CGPointMake([args[2] floatValue], [args[3] floatValue]) relative:[method isEqualToString:@"q"]];
if (!CGPointEqualToPoint(iPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN)) &&
!CGPointEqualToPoint(iiPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN))) {
[self addQuadCurveToPoint:iiPoint controlPoint:iPoint];
}
}
else if (([method isEqualToString:@"H"] || [method isEqualToString:@"h"]) && args.count == 1) {
CGFloat iValue = [self argFloat:args[0].floatValue relativeValue:([method isEqualToString:@"h"] ? self.currentPoint.x : 0.0)];
if (iValue != CGFLOAT_MIN) {
[self addLineToPoint:CGPointMake(iValue, self.currentPoint.y)];
}
}
else if (([method isEqualToString:@"V"] || [method isEqualToString:@"v"]) && args.count == 1) {
CGFloat iValue = [self argFloat:args[0].floatValue relativeValue:([method isEqualToString:@"v"] ? self.currentPoint.y : 0.0)];
if (iValue != CGFLOAT_MIN) {
[self addLineToPoint:CGPointMake(self.currentPoint.x, iValue)];
}
}
else if (([method isEqualToString:@"Z"] || [method isEqualToString:@"z"])) {
[self closePath];
}
}
- (CGFloat)argFloat:(CGFloat)value relativeValue:(CGFloat)relativeValue {
return value + relativeValue;
}
- (CGPoint)argPoint:(CGPoint)point relative:(BOOL)relative {
if (relative) {
return CGPointMake(point.x + self.currentPoint.x, point.y + self.currentPoint.y);
}
else {
return point;
}
}
@end