Repository: airbnb/lottie-ios
File: Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift (Swift)

Code before:
    if minimumStrokeMultiplier < 0 {
      // Core Animation doesn't support negative stroke offsets, so we have to
      // shift all of the offset values up by the minimum
      adjustedStrokeStart = adjustedStrokeStart.map { LottieVector1D($0.value + (abs(minimumStrokeMultiplier) * 100.0)) }
      adjustedStrokeEnd = adjustedStrokeEnd.map { LottieVector1D($0.value + (abs(minimumStrokeMultiplier) * 100.0)) }
    }

    return (
      strokeStart: adjustedStrokeStart,
      strokeEnd: adjustedStrokeEnd,
      pathMultiplier: Int(abs(maximumStrokeMultiplier) + abs(minimumStrokeMultiplier)))
  }

  // MARK: Private

  /// Checks whether or not the value for `trim.start` is greater
  /// than the value for every `trim.end` at every keyframe.
  private func startValueIsAlwaysGreaterThanEndValue() -> Bool {
    startAndEndValuesAllSatisfy { startValue, endValue in
      endValue < startValue
    }
  }

  /// Checks whether or not the value for `trim.start` is less than
  /// or equal to the value for every `trim.end` at every keyframe.
  private func startValueIsLessThanEndValue() -> Bool {
    startAndEndValuesAllSatisfy { startValue, endValue in
      startValue <= endValue
    }
  }

  private func startAndEndValuesAllSatisfy(_ condition: (_ start: CGFloat, _ end: CGFloat) -> Bool) -> Bool {
    let keyframeTimes = Set(start.keyframes.map { $0.time } + end.keyframes.map { $0.time })

    let startInterpolator = KeyframeInterpolator(keyframes: start.keyframes)
    let endInterpolator = KeyframeInterpolator(keyframes: end.keyframes)

    for keyframeTime in keyframeTimes {
      guard
        let startAtTime = startInterpolator.value(frame: keyframeTime) as? LottieVector1D,
        let endAtTime = endInterpolator.value(frame: keyframeTime) as? LottieVector1D
      else { continue }

      if !condition(startAtTime.cgFloatValue, endAtTime.cgFloatValue) {
        return false
      }
    }

    return true
  }


Review comment (suggestion):
nit: to match other method?
```suggestion
  private func startValueIsAlwaysLessThanEndValue() -> Bool {
```

Code after:
    let maximumStrokeMultiplier = Double(ceil((endStrokes.max() ?? 100) / 100.0))

    if minimumStrokeMultiplier < 0 {
      // Core Animation doesn't support negative stroke offsets, so we have to
      // shift all of the offset values up by the minimum
      adjustedStrokeStart = adjustedStrokeStart.map { LottieVector1D($0.value + (abs(minimumStrokeMultiplier) * 100.0)) }
      adjustedStrokeEnd = adjustedStrokeEnd.map { LottieVector1D($0.value + (abs(minimumStrokeMultiplier) * 100.0)) }
    }

    return (
      strokeStart: adjustedStrokeStart,
      strokeEnd: adjustedStrokeEnd,
      pathMultiplier: Int(abs(maximumStrokeMultiplier) + abs(minimumStrokeMultiplier)))
  }

  // MARK: Private

  /// Checks whether or not the value for `trim.start` is less than
  /// or equal to the value for every `trim.end` at every frame.
  private func startValueIsAlwaysLessOrEqualToThanEndValue() -> Bool {
    startAndEndValuesAllSatisfy { startValue, endValue in
      startValue <= endValue
    }
  }

  /// Checks whether or not the value for `trim.start` is greater than
  /// or equal to the value for every `trim.end` at every frame.
  private func startValueIsAlwaysGreaterThanOrEqualToEndValue() -> Bool {
    startAndEndValuesAllSatisfy { startValue, endValue in
      startValue >= endValue
    }
  }

  private func startAndEndValuesAllSatisfy(_ condition: (_ start: CGFloat, _ end: CGFloat) -> Bool) -> Bool {
    let keyframeTimes = Set(start.keyframes.map { $0.time } + end.keyframes.map { $0.time })

    let startInterpolator = KeyframeInterpolator(keyframes: start.keyframes)
    let endInterpolator = KeyframeInterpolator(keyframes: end.keyframes)

    for keyframeTime in keyframeTimes {
      guard
        let startAtTime = startInterpolator.value(frame: keyframeTime) as? LottieVector1D,
        let endAtTime = endInterpolator.value(frame: keyframeTime) as? LottieVector1D
      else { continue }

      if !condition(startAtTime.cgFloatValue, endAtTime.cgFloatValue) {
        return false
      }
    }

    return true