123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- //
- // LOTGradientFillRender.m
- // Lottie
- //
- // Created by brandon_withrow on 7/27/17.
- // Copyright © 2017 Airbnb. All rights reserved.
- //
- #import "LOTGradientFillRender.h"
- #import "LOTArrayInterpolator.h"
- #import "LOTPointInterpolator.h"
- #import "LOTNumberInterpolator.h"
- #import "CGGeometry+LOTAdditions.h"
- #import "LOTHelpers.h"
- #import "LOTRadialGradientLayer.h"
- @implementation LOTGradientFillRender {
- BOOL _evenOddFillRule;
- CALayer *centerPoint_DEBUG;
-
- CAShapeLayer *_maskShape;
- LOTRadialGradientLayer *_gradientOpacityLayer;
- LOTRadialGradientLayer *_gradientLayer;
- NSInteger _numberOfPositions;
-
- CGPoint _startPoint;
- CGPoint _endPoint;
-
- LOTArrayInterpolator *_gradientInterpolator;
- LOTPointInterpolator *_startPointInterpolator;
- LOTPointInterpolator *_endPointInterpolator;
- LOTNumberInterpolator *_opacityInterpolator;
- }
- - (instancetype)initWithInputNode:(LOTAnimatorNode *)inputNode
- shapeGradientFill:(LOTShapeGradientFill *)fill {
- self = [super initWithInputNode:inputNode keyName:fill.keyname];
- if (self) {
- _gradientInterpolator = [[LOTArrayInterpolator alloc] initWithKeyframes:fill.gradient.keyframes];
- _startPointInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:fill.startPoint.keyframes];
- _endPointInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:fill.endPoint.keyframes];
- _opacityInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:fill.opacity.keyframes];
- _numberOfPositions = fill.numberOfColors.integerValue;
-
- _evenOddFillRule = fill.evenOddFillRule;
- CALayer *wrapperLayer = [CALayer new];
- _maskShape = [CAShapeLayer new];
- _maskShape.fillRule = _evenOddFillRule ? @"even-odd" : @"non-zero";
- _maskShape.fillColor = [UIColor whiteColor].CGColor;
- _maskShape.actions = @{@"path": [NSNull null]};
-
- _gradientOpacityLayer = [LOTRadialGradientLayer new];
- _gradientOpacityLayer.isRadial = (fill.type == LOTGradientTypeRadial);
- _gradientOpacityLayer.actions = @{@"startPoint" : [NSNull null],
- @"endPoint" : [NSNull null],
- @"opacity" : [NSNull null],
- @"locations" : [NSNull null],
- @"colors" : [NSNull null],
- @"bounds" : [NSNull null],
- @"anchorPoint" : [NSNull null],
- @"isRadial" : [NSNull null]};
- _gradientOpacityLayer.mask = _maskShape;
- [wrapperLayer addSublayer:_gradientOpacityLayer];
-
- _gradientLayer = [LOTRadialGradientLayer new];
- _gradientLayer.isRadial = (fill.type == LOTGradientTypeRadial);
- _gradientLayer.mask = wrapperLayer;
- _gradientLayer.actions = [_gradientOpacityLayer.actions copy];
- [self.outputLayer addSublayer:_gradientLayer];
-
- centerPoint_DEBUG = [CALayer layer];
- centerPoint_DEBUG.bounds = CGRectMake(0, 0, 20, 20);
- if (ENABLE_DEBUG_SHAPES) {
- [self.outputLayer addSublayer:centerPoint_DEBUG];
- }
- }
- return self;
- }
- - (NSDictionary *)valueInterpolators {
- return @{@"Start Point" : _startPointInterpolator,
- @"End Point" : _endPointInterpolator,
- @"Opacity" : _opacityInterpolator};
- }
- - (BOOL)needsUpdateForFrame:(NSNumber *)frame {
- return ([_gradientInterpolator hasUpdateForFrame:frame] ||
- [_startPointInterpolator hasUpdateForFrame:frame] ||
- [_endPointInterpolator hasUpdateForFrame:frame] ||
- [_opacityInterpolator hasUpdateForFrame:frame]);
- }
- - (void)performLocalUpdate {
- centerPoint_DEBUG.backgroundColor = [UIColor magentaColor].CGColor;
- centerPoint_DEBUG.borderColor = [UIColor lightGrayColor].CGColor;
- centerPoint_DEBUG.borderWidth = 2.f;
- _startPoint = [_startPointInterpolator pointValueForFrame:self.currentFrame];
- _endPoint = [_endPointInterpolator pointValueForFrame:self.currentFrame];
- self.outputLayer.opacity = [_opacityInterpolator floatValueForFrame:self.currentFrame];
- NSArray *numberArray = [_gradientInterpolator numberArrayForFrame:self.currentFrame];
- NSMutableArray *colorArray = [NSMutableArray array];
- NSMutableArray *locationsArray = [NSMutableArray array];
-
- NSMutableArray *opacityArray = [NSMutableArray array];
- NSMutableArray *opacitylocationsArray = [NSMutableArray array];
- for (int i = 0; i < _numberOfPositions; i++) {
- int ix = i * 4;
- NSNumber *location = numberArray[ix];
- NSNumber *r = numberArray[(ix + 1)];
- NSNumber *g = numberArray[(ix + 2)];
- NSNumber *b = numberArray[(ix + 3)];
- [locationsArray addObject:location];
- UIColor *color = [UIColor colorWithRed:r.floatValue green:g.floatValue blue:b.floatValue alpha:1];
- [colorArray addObject:(id)(color.CGColor)];
- }
- for (NSInteger i = (_numberOfPositions * 4); i < numberArray.count; i = i + 2) {
- NSNumber *opacityLocation = numberArray[i];
- [opacitylocationsArray addObject:opacityLocation];
- NSNumber *opacity = numberArray[i + 1];
- UIColor *opacityColor = [UIColor colorWithWhite:1 alpha:opacity.floatValue];
- [opacityArray addObject:(id)(opacityColor.CGColor)];
- }
- if (opacityArray.count == 0) {
- _gradientOpacityLayer.backgroundColor = [UIColor whiteColor].CGColor;
- } else {
- _gradientOpacityLayer.startPoint = _startPoint;
- _gradientOpacityLayer.endPoint = _endPoint;
- _gradientOpacityLayer.locations = opacitylocationsArray;
- _gradientOpacityLayer.colors = opacityArray;
- }
- _gradientLayer.startPoint = _startPoint;
- _gradientLayer.endPoint = _endPoint;
- _gradientLayer.locations = locationsArray;
- _gradientLayer.colors = colorArray;
- }
- - (void)rebuildOutputs {
- CGRect frame = [self.inputNode.outputPath bounds];
- CGPoint modifiedAnchor = CGPointMake(-frame.origin.x / frame.size.width,
- -frame.origin.y / frame.size.height);
- _maskShape.path = self.inputNode.outputPath.CGPath;
- _gradientOpacityLayer.bounds = frame;
- _gradientOpacityLayer.anchorPoint = modifiedAnchor;
-
- _gradientLayer.bounds = frame;
- _gradientLayer.anchorPoint = modifiedAnchor;
-
- }
- - (NSDictionary *)actionsForRenderLayer {
- return @{@"backgroundColor": [NSNull null],
- @"fillColor": [NSNull null],
- @"opacity" : [NSNull null]};
- }
- @end
|