123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- //
- // SVGAVectorLayer.m
- // SVGAPlayer
- //
- // Created by 崔明辉 on 2017/2/20.
- // Copyright © 2017年 UED Center. All rights reserved.
- //
- #import "SVGAVectorLayer.h"
- #import "SVGABezierPath.h"
- #import "SVGAVideoSpriteFrameEntity.h"
- #import "Svga.pbobjc.h"
- @interface SVGAVectorLayer ()
- @property (nonatomic, strong) NSArray<SVGAVideoSpriteFrameEntity *> *frames;
- @property (nonatomic, assign) NSInteger drawedFrame;
- @property (nonatomic, strong) NSDictionary *keepFrameCache;
- @end
- @implementation SVGAVectorLayer
- - (instancetype)initWithFrames:(NSArray *)frames {
- self = [super init];
- if (self) {
- self.backgroundColor = [UIColor clearColor].CGColor;
- self.masksToBounds = NO;
- _frames = frames;
- _keepFrameCache = [NSMutableDictionary dictionary];
- [self resetKeepFrameCache];
- [self stepToFrame:0];
- }
- return self;
- }
- - (void)resetKeepFrameCache {
- __block NSInteger lastKeep = 0;
- __block NSMutableDictionary *keepFrameCache = [NSMutableDictionary dictionary];
- [self.frames enumerateObjectsUsingBlock:^(SVGAVideoSpriteFrameEntity * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- if (![self isKeepFrame:obj]) {
- lastKeep = idx;
- }
- else {
- [keepFrameCache setObject:@(lastKeep) forKey:@(idx)];
- }
- }];
- self.keepFrameCache = [keepFrameCache copy];
- }
- - (void)stepToFrame:(NSInteger)frame {
- if (frame < self.frames.count) {
- [self drawFrame:frame];
- }
- }
- - (BOOL)isKeepFrame:(SVGAVideoSpriteFrameEntity *)frameItem {
- if (frameItem.shapes.count == 0) {
- return NO;
- }
- else if ([frameItem.shapes.firstObject isKindOfClass:[NSDictionary class]]) {
- return [frameItem.shapes.firstObject[@"type"] isKindOfClass:[NSString class]] &&
- [frameItem.shapes.firstObject[@"type"] isEqualToString:@"keep"];
- }
- else if ([frameItem.shapes.firstObject isKindOfClass:[SVGAProtoShapeEntity class]]) {
- return [(SVGAProtoShapeEntity *)frameItem.shapes.firstObject type] == SVGAProtoShapeEntity_ShapeType_Keep;
- }
- else {
- return NO;
- }
- }
- - (NSInteger)requestKeepFrame:(NSInteger)frame {
- if ([self.keepFrameCache objectForKey:@(frame)] != nil) {
- return [[self.keepFrameCache objectForKey:@(frame)] integerValue];
- }
- return NSNotFound;
- }
- - (void)drawFrame:(NSInteger)frame {
- if (frame < self.frames.count) {
- SVGAVideoSpriteFrameEntity *frameItem = self.frames[frame];
- if ([self isKeepFrame:frameItem]) {
- if (self.drawedFrame == [self requestKeepFrame:frame]) {
- return;
- }
- }
- while(self.sublayers.count) [self.sublayers.firstObject removeFromSuperlayer];
- for (NSDictionary *shape in frameItem.shapes) {
- if ([shape isKindOfClass:[NSDictionary class]]) {
- if ([shape[@"type"] isKindOfClass:[NSString class]]) {
- if ([shape[@"type"] isEqualToString:@"shape"]) {
- [self addSublayer:[self createCurveLayer:shape]];
- }
- else if ([shape[@"type"] isEqualToString:@"ellipse"]) {
- [self addSublayer:[self createEllipseLayer:shape]];
- }
- else if ([shape[@"type"] isEqualToString:@"rect"]) {
- [self addSublayer:[self createRectLayer:shape]];
- }
- }
- }
- else if ([shape isKindOfClass:[SVGAProtoShapeEntity class]]) {
- SVGAProtoShapeEntity *shapeItem = (id)shape;
- if (shapeItem.type == SVGAProtoShapeEntity_ShapeType_Shape) {
- [self addSublayer:[self createCurveLayerWithProto:shapeItem]];
- }
- else if (shapeItem.type == SVGAProtoShapeEntity_ShapeType_Ellipse) {
- [self addSublayer:[self createEllipseLayerWithProto:shapeItem]];
- }
- else if (shapeItem.type == SVGAProtoShapeEntity_ShapeType_Rect) {
- [self addSublayer:[self createRectLayerWithProto:shapeItem]];
- }
- }
- }
- self.drawedFrame = frame;
- }
- }
- - (CALayer *)createCurveLayer:(NSDictionary *)shape {
- SVGABezierPath *bezierPath = [SVGABezierPath new];
- if ([shape[@"args"] isKindOfClass:[NSDictionary class]]) {
- if ([shape[@"args"][@"d"] isKindOfClass:[NSString class]]) {
- [bezierPath setValues:shape[@"args"][@"d"]];
- }
- }
- CAShapeLayer *shapeLayer = [bezierPath createLayer];
- [self resetStyles:shapeLayer shape:shape];
- [self resetTransform:shapeLayer shape:shape];
- return shapeLayer;
- }
- - (CALayer *)createCurveLayerWithProto:(SVGAProtoShapeEntity *)shape {
- SVGABezierPath *bezierPath = [SVGABezierPath new];
- if (shape.argsOneOfCase == SVGAProtoShapeEntity_Args_OneOfCase_Shape) {
- if ([shape.shape.d isKindOfClass:[NSString class]] && shape.shape.d.length > 0) {
- [bezierPath setValues:shape.shape.d];
- }
- }
- CAShapeLayer *shapeLayer = [bezierPath createLayer];
- [self resetStyles:shapeLayer protoShape:shape];
- [self resetTransform:shapeLayer protoShape:shape];
- return shapeLayer;
- }
- - (CALayer *)createEllipseLayer:(NSDictionary *)shape {
- UIBezierPath *bezierPath;
- if ([shape[@"args"] isKindOfClass:[NSDictionary class]]) {
- if ([shape[@"args"][@"x"] isKindOfClass:[NSNumber class]] &&
- [shape[@"args"][@"y"] isKindOfClass:[NSNumber class]] &&
- [shape[@"args"][@"radiusX"] isKindOfClass:[NSNumber class]] &&
- [shape[@"args"][@"radiusY"] isKindOfClass:[NSNumber class]]) {
- CGFloat x = [shape[@"args"][@"x"] floatValue];
- CGFloat y = [shape[@"args"][@"y"] floatValue];
- CGFloat rx = [shape[@"args"][@"radiusX"] floatValue];
- CGFloat ry = [shape[@"args"][@"radiusY"] floatValue];
- bezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(x - rx, y - ry, rx * 2, ry * 2)];
- }
- }
- if (bezierPath != nil) {
- CAShapeLayer *shapeLayer = [CAShapeLayer layer];
- [shapeLayer setPath:[bezierPath CGPath]];
- [self resetStyles:shapeLayer shape:shape];
- [self resetTransform:shapeLayer shape:shape];
- return shapeLayer;
- }
- else {
- return [CALayer layer];
- }
- }
- - (CALayer *)createEllipseLayerWithProto:(SVGAProtoShapeEntity *)shape {
- UIBezierPath *bezierPath;
- if (shape.argsOneOfCase == SVGAProtoShapeEntity_Args_OneOfCase_Ellipse) {
- bezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(shape.ellipse.x - shape.ellipse.radiusX,
- shape.ellipse.y - shape.ellipse.radiusY,
- shape.ellipse.radiusX * 2,
- shape.ellipse.radiusY * 2)];
- }
- if (bezierPath != nil) {
- CAShapeLayer *shapeLayer = [CAShapeLayer layer];
- [shapeLayer setPath:[bezierPath CGPath]];
- [self resetStyles:shapeLayer protoShape:shape];
- [self resetTransform:shapeLayer protoShape:shape];
- return shapeLayer;
- }
- else {
- return [CALayer layer];
- }
- }
- - (CALayer *)createRectLayer:(NSDictionary *)shape {
- UIBezierPath *bezierPath;
- if ([shape[@"args"] isKindOfClass:[NSDictionary class]]) {
- if ([shape[@"args"][@"x"] isKindOfClass:[NSNumber class]] &&
- [shape[@"args"][@"y"] isKindOfClass:[NSNumber class]] &&
- [shape[@"args"][@"width"] isKindOfClass:[NSNumber class]] &&
- [shape[@"args"][@"height"] isKindOfClass:[NSNumber class]] &&
- [shape[@"args"][@"cornerRadius"] isKindOfClass:[NSNumber class]]) {
- CGFloat x = [shape[@"args"][@"x"] floatValue];
- CGFloat y = [shape[@"args"][@"y"] floatValue];
- CGFloat width = [shape[@"args"][@"width"] floatValue];
- CGFloat height = [shape[@"args"][@"height"] floatValue];
- CGFloat cornerRadius = [shape[@"args"][@"cornerRadius"] floatValue];
- bezierPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(x, y, width, height) cornerRadius:cornerRadius];
- }
- }
- if (bezierPath != nil) {
- CAShapeLayer *shapeLayer = [CAShapeLayer layer];
- [shapeLayer setPath:[bezierPath CGPath]];
- [self resetStyles:shapeLayer shape:shape];
- [self resetTransform:shapeLayer shape:shape];
- return shapeLayer;
- }
- else {
- return [CALayer layer];
- }
- }
- - (CALayer *)createRectLayerWithProto:(SVGAProtoShapeEntity *)shape {
- UIBezierPath *bezierPath;
- if (shape.argsOneOfCase == SVGAProtoShapeEntity_Args_OneOfCase_Rect) {
- bezierPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(shape.rect.x, shape.rect.y, shape.rect.width, shape.rect.height)
- cornerRadius:shape.rect.cornerRadius];
- }
- if (bezierPath != nil) {
- CAShapeLayer *shapeLayer = [CAShapeLayer layer];
- [shapeLayer setPath:[bezierPath CGPath]];
- [self resetStyles:shapeLayer protoShape:shape];
- [self resetTransform:shapeLayer protoShape:shape];
- return shapeLayer;
- }
- else {
- return [CALayer layer];
- }
- }
- - (void)resetStyles:(CAShapeLayer *)shapeLayer shape:(NSDictionary *)shape {
- shapeLayer.masksToBounds = NO;
- shapeLayer.backgroundColor = [UIColor clearColor].CGColor;
- if ([shape[@"styles"] isKindOfClass:[NSDictionary class]]) {
- if ([shape[@"styles"][@"fill"] isKindOfClass:[NSArray class]]) {
- NSArray *colorArray = shape[@"styles"][@"fill"];
- if ([colorArray count] == 4 &&
- [colorArray[0] isKindOfClass:[NSNumber class]] &&
- [colorArray[1] isKindOfClass:[NSNumber class]] &&
- [colorArray[2] isKindOfClass:[NSNumber class]] &&
- [colorArray[3] isKindOfClass:[NSNumber class]]) {
- shapeLayer.fillColor = [UIColor colorWithRed:[colorArray[0] floatValue]
- green:[colorArray[1] floatValue]
- blue:[colorArray[2] floatValue]
- alpha:[colorArray[3] floatValue]].CGColor;
- }
- }
- else {
- shapeLayer.fillColor = [UIColor clearColor].CGColor;
- }
- if ([shape[@"styles"][@"stroke"] isKindOfClass:[NSArray class]]) {
- NSArray *colorArray = shape[@"styles"][@"stroke"];
- if ([colorArray count] == 4 &&
- [colorArray[0] isKindOfClass:[NSNumber class]] &&
- [colorArray[1] isKindOfClass:[NSNumber class]] &&
- [colorArray[2] isKindOfClass:[NSNumber class]] &&
- [colorArray[3] isKindOfClass:[NSNumber class]]) {
- shapeLayer.strokeColor = [UIColor colorWithRed:[colorArray[0] floatValue]
- green:[colorArray[1] floatValue]
- blue:[colorArray[2] floatValue]
- alpha:[colorArray[3] floatValue]].CGColor;
- }
- }
- if ([shape[@"styles"][@"strokeWidth"] isKindOfClass:[NSNumber class]]) {
- shapeLayer.lineWidth = [shape[@"styles"][@"strokeWidth"] floatValue];
- }
- if ([shape[@"styles"][@"lineCap"] isKindOfClass:[NSString class]]) {
- shapeLayer.lineCap = shape[@"styles"][@"lineCap"];
- }
- if ([shape[@"styles"][@"lineJoin"] isKindOfClass:[NSString class]]) {
- shapeLayer.lineJoin = shape[@"styles"][@"lineJoin"];
- }
- if ([shape[@"styles"][@"lineDash"] isKindOfClass:[NSArray class]]) {
- BOOL accept = YES;
- for (id obj in shape[@"styles"][@"lineDash"]) {
- if (![obj isKindOfClass:[NSNumber class]]) {
- accept = NO;
- }
- }
- if (accept) {
- if ([shape[@"styles"][@"lineDash"] count] == 3) {
- shapeLayer.lineDashPhase = [shape[@"styles"][@"lineDash"][2] floatValue];
- shapeLayer.lineDashPattern = @[
- ([shape[@"styles"][@"lineDash"][0] floatValue] < 1.0 ? @(1.0) : shape[@"styles"][@"lineDash"][0]),
- ([shape[@"styles"][@"lineDash"][1] floatValue] < 0.1 ? @(0.1) : shape[@"styles"][@"lineDash"][1])
- ];
- }
- }
- }
- if ([shape[@"styles"][@"miterLimit"] isKindOfClass:[NSNumber class]]) {
- shapeLayer.miterLimit = [shape[@"styles"][@"miterLimit"] floatValue];
- }
- }
- }
- - (void)resetStyles:(CAShapeLayer *)shapeLayer protoShape:(SVGAProtoShapeEntity *)protoShape {
- shapeLayer.masksToBounds = NO;
- shapeLayer.backgroundColor = [UIColor clearColor].CGColor;
- if (protoShape.hasStyles) {
- if (protoShape.styles.hasFill) {
- shapeLayer.fillColor = [UIColor colorWithRed:protoShape.styles.fill.r
- green:protoShape.styles.fill.g
- blue:protoShape.styles.fill.b
- alpha:protoShape.styles.fill.a].CGColor;
- }
- else {
- shapeLayer.fillColor = [UIColor clearColor].CGColor;
- }
- if (protoShape.styles.hasStroke) {
- shapeLayer.strokeColor = [UIColor colorWithRed:protoShape.styles.stroke.r
- green:protoShape.styles.stroke.g
- blue:protoShape.styles.stroke.b
- alpha:protoShape.styles.stroke.a].CGColor;
- }
- shapeLayer.lineWidth = protoShape.styles.strokeWidth;
- switch (protoShape.styles.lineCap) {
- case SVGAProtoShapeEntity_ShapeStyle_LineCap_LineCapButt:
- shapeLayer.lineCap = @"butt";
- break;
- case SVGAProtoShapeEntity_ShapeStyle_LineCap_LineCapRound:
- shapeLayer.lineCap = @"round";
- break;
- case SVGAProtoShapeEntity_ShapeStyle_LineCap_LineCapSquare:
- shapeLayer.lineCap = @"square";
- break;
- default:
- break;
- }
- switch (protoShape.styles.lineJoin) {
- case SVGAProtoShapeEntity_ShapeStyle_LineJoin_LineJoinRound:
- shapeLayer.lineJoin = @"round";
- break;
- case SVGAProtoShapeEntity_ShapeStyle_LineJoin_LineJoinMiter:
- shapeLayer.lineJoin = @"miter";
- break;
- case SVGAProtoShapeEntity_ShapeStyle_LineJoin_LineJoinBevel:
- shapeLayer.lineJoin = @"bevel";
- break;
- default:
- break;
- }
- shapeLayer.lineDashPhase = protoShape.styles.lineDashIii;
- if (protoShape.styles.lineDashI > 0.0 || protoShape.styles.lineDashIi > 0.0) {
- shapeLayer.lineDashPattern = @[
- (protoShape.styles.lineDashI < 1.0 ? @(1.0) : @(protoShape.styles.lineDashI)),
- (protoShape.styles.lineDashIi < 0.1 ? @(0.1) : @(protoShape.styles.lineDashIi))
- ];
- }
- shapeLayer.miterLimit = protoShape.styles.miterLimit;
- }
- }
- - (void)resetTransform:(CAShapeLayer *)shapeLayer shape:(NSDictionary *)shape {
- if ([shape[@"transform"] isKindOfClass:[NSDictionary class]]) {
- if ([shape[@"transform"][@"a"] isKindOfClass:[NSNumber class]] &&
- [shape[@"transform"][@"b"] isKindOfClass:[NSNumber class]] &&
- [shape[@"transform"][@"c"] isKindOfClass:[NSNumber class]] &&
- [shape[@"transform"][@"d"] isKindOfClass:[NSNumber class]] &&
- [shape[@"transform"][@"tx"] isKindOfClass:[NSNumber class]] &&
- [shape[@"transform"][@"ty"] isKindOfClass:[NSNumber class]]) {
- shapeLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake([shape[@"transform"][@"a"] floatValue],
- [shape[@"transform"][@"b"] floatValue],
- [shape[@"transform"][@"c"] floatValue],
- [shape[@"transform"][@"d"] floatValue],
- [shape[@"transform"][@"tx"] floatValue],
- [shape[@"transform"][@"ty"] floatValue])
- );
- }
- }
- }
- - (void)resetTransform:(CAShapeLayer *)shapeLayer protoShape:(SVGAProtoShapeEntity *)protoShape {
- if (protoShape.hasTransform) {
- shapeLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransformMake((CGFloat)protoShape.transform.a,
- (CGFloat)protoShape.transform.b,
- (CGFloat)protoShape.transform.c,
- (CGFloat)protoShape.transform.d,
- (CGFloat)protoShape.transform.tx,
- (CGFloat)protoShape.transform.ty)
- );
- }
- }
- @end
|