Skip to content

Commit 84a78d3

Browse files
committed
Now support ClipPath for SVGA Ver 1.0.1
1 parent c583675 commit 84a78d3

6 files changed

Lines changed: 170 additions & 0 deletions

File tree

SVGAPlayer.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
904D41F81D223DD20085A21A /* SVGABezierPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 904D41F71D223DD20085A21A /* SVGABezierPath.m */; };
1011
90A676E21D13A6DF008A69F3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 90A676E11D13A6DF008A69F3 /* main.m */; };
1112
90A676E51D13A6DF008A69F3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 90A676E41D13A6DF008A69F3 /* AppDelegate.m */; };
1213
90A676E81D13A6DF008A69F3 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 90A676E71D13A6DF008A69F3 /* ViewController.m */; };
@@ -23,6 +24,8 @@
2324
/* Begin PBXFileReference section */
2425
0168C6C4E93DA9A773F96545 /* Pods-SVGAPlayer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SVGAPlayer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SVGAPlayer/Pods-SVGAPlayer.debug.xcconfig"; sourceTree = "<group>"; };
2526
47C1F5D8678008484F80AF1A /* Pods-SVGAPlayer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SVGAPlayer.release.xcconfig"; path = "Pods/Target Support Files/Pods-SVGAPlayer/Pods-SVGAPlayer.release.xcconfig"; sourceTree = "<group>"; };
27+
904D41F61D223DD20085A21A /* SVGABezierPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGABezierPath.h; sourceTree = "<group>"; };
28+
904D41F71D223DD20085A21A /* SVGABezierPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVGABezierPath.m; sourceTree = "<group>"; };
2629
90A676DD1D13A6DF008A69F3 /* SVGAPlayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SVGAPlayer.app; sourceTree = BUILT_PRODUCTS_DIR; };
2730
90A676E11D13A6DF008A69F3 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
2831
90A676E31D13A6DF008A69F3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
@@ -127,6 +130,8 @@
127130
90A677021D13AE19008A69F3 /* SVGAVideoEntity.m */,
128131
90A677041D13BF77008A69F3 /* SVGAPlayer.h */,
129132
90A677051D13BF77008A69F3 /* SVGAPlayer.m */,
133+
904D41F61D223DD20085A21A /* SVGABezierPath.h */,
134+
904D41F71D223DD20085A21A /* SVGABezierPath.m */,
130135
);
131136
path = Source;
132137
sourceTree = "<group>";
@@ -255,6 +260,7 @@
255260
files = (
256261
90A676E81D13A6DF008A69F3 /* ViewController.m in Sources */,
257262
90A677031D13AE19008A69F3 /* SVGAVideoEntity.m in Sources */,
263+
904D41F81D223DD20085A21A /* SVGABezierPath.m in Sources */,
258264
90A676E51D13A6DF008A69F3 /* AppDelegate.m in Sources */,
259265
90A676FA1D13A81F008A69F3 /* SVGA.m in Sources */,
260266
90A677061D13BF77008A69F3 /* SVGAPlayer.m in Sources */,

Source/SVGABezierPath.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// SVGABezierPath.h
3+
// SVGAPlayer
4+
//
5+
// Created by 崔明辉 on 16/6/28.
6+
// Copyright © 2016年 UED Center. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
#import <UIKit/UIKit.h>
11+
12+
@interface SVGABezierPath : UIBezierPath
13+
14+
- (void)setValues:(nonnull NSString *)values;
15+
16+
- (nonnull CALayer *)createLayer;
17+
18+
@end

Source/SVGABezierPath.m

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//
2+
// SVGABezierPath.m
3+
// SVGAPlayer
4+
//
5+
// Created by 崔明辉 on 16/6/28.
6+
// Copyright © 2016年 UED Center. All rights reserved.
7+
//
8+
9+
#import "SVGABezierPath.h"
10+
11+
@implementation SVGABezierPath
12+
13+
- (void)setValues:(nonnull NSString *)values {
14+
static NSArray *validMethods;
15+
static dispatch_once_t onceToken;
16+
dispatch_once(&onceToken, ^{
17+
validMethods = @[@"M",@"L",@"H",@"V",@"C",@"S",@"Q",@"R",@"A",@"Z",@"m",@"l",@"h",@"v",@"c",@"s",@"q",@"r",@"a",@"z"];
18+
});
19+
values = [values stringByReplacingOccurrencesOfString:@"," withString:@" "];
20+
NSArray<NSString *> *items = [values componentsSeparatedByString:@" "];
21+
NSString *currentMethod = @"";
22+
NSMutableArray<NSString *> *args = [NSMutableArray array];
23+
NSString *argLast = nil;
24+
for (NSString *item in items) {
25+
if (item.length < 1) {
26+
continue;
27+
}
28+
NSString *firstLetter = [item substringToIndex:1];
29+
if ([validMethods indexOfObject:firstLetter] != NSNotFound) {
30+
if (argLast != nil) {
31+
[args addObject:argLast];
32+
}
33+
[self operate:currentMethod args:[args copy]];
34+
currentMethod = @"";
35+
[args removeAllObjects];
36+
argLast = nil;
37+
currentMethod = firstLetter;
38+
argLast = [item substringFromIndex:1];
39+
}
40+
else {
41+
if (argLast != nil && [argLast stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length) {
42+
[args addObject:[NSString stringWithFormat:@"%@,%@", argLast, item]];
43+
argLast = nil;
44+
}
45+
else {
46+
argLast = item;
47+
}
48+
}
49+
}
50+
[self operate:currentMethod args:[args copy]];
51+
}
52+
53+
- (nonnull CALayer *)createLayer {
54+
CAShapeLayer *layer = [CAShapeLayer layer];
55+
layer.path = self.CGPath;
56+
layer.fillColor = [UIColor blackColor].CGColor;
57+
return layer;
58+
}
59+
60+
- (void)operate:(NSString *)method args:(NSArray<NSString *> *)args {
61+
if (([method isEqualToString:@"M"] || [method isEqualToString:@"m"]) && args.count == 1) {
62+
CGPoint iPoint = [self argPoint:args[0] relative:[method isEqualToString:@"m"]];
63+
if (!CGPointEqualToPoint(iPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN))) {
64+
[self moveToPoint:iPoint];
65+
}
66+
}
67+
else if (([method isEqualToString:@"L"] || [method isEqualToString:@"l"]) && args.count == 1) {
68+
CGPoint iPoint = [self argPoint:args[0] relative:[method isEqualToString:@"l"]];
69+
if (!CGPointEqualToPoint(iPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN))) {
70+
[self addLineToPoint:iPoint];
71+
}
72+
}
73+
else if (([method isEqualToString:@"C"] || [method isEqualToString:@"c"]) && args.count == 3) {
74+
CGPoint iPoint = [self argPoint:args[0] relative:[method isEqualToString:@"c"]];
75+
CGPoint iiPoint = [self argPoint:args[1] relative:[method isEqualToString:@"c"]];
76+
CGPoint iiiPoint = [self argPoint:args[2] relative:[method isEqualToString:@"c"]];
77+
if (!CGPointEqualToPoint(iPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN)) &&
78+
!CGPointEqualToPoint(iiPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN)) &&
79+
!CGPointEqualToPoint(iiiPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN))) {
80+
[self addCurveToPoint:iiiPoint controlPoint1:iPoint controlPoint2:iiPoint];
81+
}
82+
}
83+
else if (([method isEqualToString:@"Q"] || [method isEqualToString:@"q"]) && args.count == 2) {
84+
CGPoint iPoint = [self argPoint:args[0] relative:[method isEqualToString:@"q"]];
85+
CGPoint iiPoint = [self argPoint:args[1] relative:[method isEqualToString:@"q"]];
86+
if (!CGPointEqualToPoint(iPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN)) &&
87+
!CGPointEqualToPoint(iiPoint, CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN))) {
88+
[self addQuadCurveToPoint:iiPoint controlPoint:iPoint];
89+
}
90+
}
91+
else if (([method isEqualToString:@"H"] || [method isEqualToString:@"h"]) && args.count == 1) {
92+
CGFloat iValue = [self argFloat:args[0] relativeValue:([method isEqualToString:@"h"] ? self.currentPoint.x : 0.0)];
93+
if (iValue != CGFLOAT_MIN) {
94+
[self addLineToPoint:CGPointMake(iValue, self.currentPoint.y)];
95+
}
96+
}
97+
else if (([method isEqualToString:@"V"] || [method isEqualToString:@"v"]) && args.count == 1) {
98+
CGFloat iValue = [self argFloat:args[0] relativeValue:([method isEqualToString:@"v"] ? self.currentPoint.y : 0.0)];
99+
if (iValue != CGFLOAT_MIN) {
100+
[self addLineToPoint:CGPointMake(self.currentPoint.x, iValue)];
101+
}
102+
}
103+
else if (([method isEqualToString:@"Z"] || [method isEqualToString:@"z"]) && args.count == 1) {
104+
[self closePath];
105+
}
106+
}
107+
108+
- (CGFloat)argFloat:(NSString *)arg relativeValue:(CGFloat)relativeValue {
109+
NSNumberFormatter *numberFotmatter = [[NSNumberFormatter alloc] init];
110+
NSNumber *x = [numberFotmatter numberFromString:arg];
111+
if (x != nil) {
112+
return x.floatValue + relativeValue;
113+
}
114+
else {
115+
return CGFLOAT_MIN;
116+
}
117+
}
118+
119+
- (CGPoint)argPoint:(NSString *)arg relative:(BOOL)relative {
120+
if ([arg componentsSeparatedByString:@","].count == 2) {
121+
NSNumberFormatter *numberFotmatter = [[NSNumberFormatter alloc] init];
122+
NSNumber *x = [numberFotmatter numberFromString:[arg componentsSeparatedByString:@","][0]];
123+
NSNumber *y = [numberFotmatter numberFromString:[arg componentsSeparatedByString:@","][1]];
124+
if (x != nil && y != nil) {
125+
if (relative) {
126+
return CGPointMake(x.floatValue + self.currentPoint.x, y.floatValue + self.currentPoint.y);
127+
}
128+
else {
129+
return CGPointMake(x.floatValue, y.floatValue);
130+
}
131+
}
132+
}
133+
return CGPointMake(CGFLOAT_MIN, CGFLOAT_MIN);
134+
}
135+
136+
@end

Source/SVGAPlayer.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ - (void)update {
9797
CGFloat offsetX = layer.frame.origin.x - nx;
9898
CGFloat offsetY = layer.frame.origin.y - ny;
9999
layer.position = CGPointMake(layer.position.x - offsetX, layer.position.y - offsetY);
100+
layer.mask = frameItem.maskLayer;
100101
}
101102
else {
102103
layer.hidden = YES;

Source/SVGAVideoEntity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
@property (nonatomic, readonly) CGRect layout;
4242
@property (nonatomic, readonly) CGFloat nx;
4343
@property (nonatomic, readonly) CGFloat ny;
44+
@property (nonatomic, readonly) CALayer *maskLayer;
4445

4546
- (instancetype)initWithJSONObject:(NSDictionary *)JSONObject;
4647

Source/SVGAVideoEntity.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88

99
#import "SVGAVideoEntity.h"
10+
#import "SVGABezierPath.h"
1011

1112
@interface SVGAVideoEntity ()
1213

@@ -136,6 +137,7 @@ @interface SVGAVideoSpriteFrameEntity ()
136137
@property (nonatomic, assign) CGRect layout;
137138
@property (nonatomic, assign) CGFloat nx;
138139
@property (nonatomic, assign) CGFloat ny;
140+
@property (nonatomic, strong) CALayer *maskLayer;
139141

140142
@end
141143

@@ -174,6 +176,12 @@ - (instancetype)initWithJSONObject:(NSDictionary *)JSONObject {
174176
_transform = CGAffineTransformMake(a.floatValue, b.floatValue, c.floatValue, d.floatValue, tx.floatValue, ty.floatValue);
175177
}
176178
}
179+
NSString *clipPath = JSONObject[@"clipPath"];
180+
if ([clipPath isKindOfClass:[NSString class]]) {
181+
SVGABezierPath *bezierPath = [[SVGABezierPath alloc] init];
182+
[bezierPath setValues:clipPath];
183+
self.maskLayer = [bezierPath createLayer];
184+
}
177185
}
178186
CGFloat llx = _transform.a * _layout.origin.x + _transform.c * _layout.origin.y + _transform.tx;
179187
CGFloat lrx = _transform.a * (_layout.origin.x + _layout.size.width) + _transform.c * _layout.origin.y + _transform.tx;

0 commit comments

Comments
 (0)