LOTPathInterpolator.m 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. //
  2. // LOTPathInterpolator.m
  3. // Lottie
  4. //
  5. // Created by brandon_withrow on 7/13/17.
  6. // Copyright © 2017 Airbnb. All rights reserved.
  7. //
  8. #import "LOTPathInterpolator.h"
  9. #import "CGGeometry+LOTAdditions.h"
  10. @implementation LOTPathInterpolator
  11. - (LOTBezierPath *)pathForFrame:(NSNumber *)frame cacheLengths:(BOOL)cacheLengths {
  12. CGFloat progress = [self progressForFrame:frame];
  13. if (self.hasDelegateOverride) {
  14. CGPathRef callBackPath = [self.delegate pathForFrame:frame.floatValue
  15. startKeyframe:self.leadingKeyframe.keyframeTime.floatValue
  16. endKeyframe:self.trailingKeyframe.keyframeTime.floatValue
  17. interpolatedProgress:progress];
  18. return [LOTBezierPath pathWithCGPath:callBackPath];
  19. }
  20. LOTBezierPath *returnPath = [[LOTBezierPath alloc] init];
  21. returnPath.cacheLengths = cacheLengths;
  22. LOTBezierData *leadingData = self.leadingKeyframe.pathData;
  23. LOTBezierData *trailingData = self.trailingKeyframe.pathData;
  24. NSInteger vertexCount = leadingData ? leadingData.count : trailingData.count;
  25. BOOL closePath = leadingData ? leadingData.closed : trailingData.closed;
  26. CGPoint cp1 = CGPointMake(0, 0);
  27. CGPoint cp2, p1, cp3 = CGPointZero;
  28. CGPoint startPoint = CGPointMake(0, 0);
  29. CGPoint startInTangent = CGPointMake(0, 0);
  30. for (int i = 0; i < vertexCount; i++) {
  31. if (progress == 0) {
  32. cp2 = [leadingData inTangentAtIndex:i];
  33. p1 = [leadingData vertexAtIndex:i];
  34. cp3 = [leadingData outTangentAtIndex:i];
  35. } else if (progress == 1) {
  36. cp2 = [trailingData inTangentAtIndex:i];
  37. p1 = [trailingData vertexAtIndex:i];
  38. cp3 = [trailingData outTangentAtIndex:i];
  39. } else {
  40. cp2 = LOT_PointInLine([leadingData inTangentAtIndex:i],
  41. [trailingData inTangentAtIndex:i],
  42. progress);
  43. p1 = LOT_PointInLine([leadingData vertexAtIndex:i],
  44. [trailingData vertexAtIndex:i],
  45. progress);
  46. cp3 = LOT_PointInLine([leadingData outTangentAtIndex:i],
  47. [trailingData outTangentAtIndex:i],
  48. progress);
  49. }
  50. if (i == 0) {
  51. startPoint = p1;
  52. startInTangent = cp2;
  53. [returnPath LOT_moveToPoint:p1];
  54. } else {
  55. [returnPath LOT_addCurveToPoint:p1 controlPoint1:cp1 controlPoint2:cp2];
  56. }
  57. cp1 = cp3;
  58. }
  59. if (closePath) {
  60. [returnPath LOT_addCurveToPoint:startPoint controlPoint1:cp3 controlPoint2:startInTangent];
  61. [returnPath LOT_closePath];
  62. }
  63. return returnPath;
  64. }
  65. - (void)setValueDelegate:(id<LOTValueDelegate>)delegate {
  66. NSAssert(([delegate conformsToProtocol:@protocol(LOTPathValueDelegate)]), @"Path Interpolator set with incorrect callback type. Expected LOTPathValueDelegate");
  67. self.delegate = (id<LOTPathValueDelegate>)delegate;
  68. }
  69. - (BOOL)hasDelegateOverride {
  70. return self.delegate != nil;
  71. }
  72. @end