mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
Update lottie-ios
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
//
|
||||
// CompoundBezierPath.swift
|
||||
// lottie-swift
|
||||
//
|
||||
// Created by Brandon Withrow on 1/14/19.
|
||||
//
|
||||
|
||||
import CoreGraphics
|
||||
import Foundation
|
||||
|
||||
/// A collection of BezierPath objects that can be trimmed and added.
|
||||
///
|
||||
struct CompoundBezierPath {
|
||||
|
||||
// MARK: Lifecycle
|
||||
|
||||
init() {
|
||||
paths = []
|
||||
length = 0
|
||||
}
|
||||
|
||||
init(path: BezierPath) {
|
||||
paths = [path]
|
||||
length = path.length
|
||||
}
|
||||
|
||||
init(paths: [BezierPath], length: CGFloat) {
|
||||
self.paths = paths
|
||||
self.length = length
|
||||
}
|
||||
|
||||
init(paths: [BezierPath]) {
|
||||
self.paths = paths
|
||||
var l: CGFloat = 0
|
||||
for path in paths {
|
||||
l = l + path.length
|
||||
}
|
||||
length = l
|
||||
}
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
let paths: [BezierPath]
|
||||
|
||||
let length: CGFloat
|
||||
|
||||
func addPath(path: BezierPath) -> CompoundBezierPath {
|
||||
var newPaths = paths
|
||||
newPaths.append(path)
|
||||
return CompoundBezierPath(paths: newPaths, length: length + path.length)
|
||||
}
|
||||
|
||||
func combine(_ compoundBezier: CompoundBezierPath) -> CompoundBezierPath {
|
||||
var newPaths = paths
|
||||
newPaths.append(contentsOf: compoundBezier.paths)
|
||||
return CompoundBezierPath(paths: newPaths, length: length + compoundBezier.length)
|
||||
}
|
||||
|
||||
func trim(fromPosition: CGFloat, toPosition: CGFloat, offset: CGFloat, trimSimultaneously: Bool) -> CompoundBezierPath {
|
||||
if fromPosition == toPosition {
|
||||
return CompoundBezierPath()
|
||||
}
|
||||
|
||||
if trimSimultaneously {
|
||||
/// Trim each path individually.
|
||||
var newPaths = [BezierPath]()
|
||||
for path in paths {
|
||||
newPaths.append(contentsOf: path.trim(
|
||||
fromLength: fromPosition * path.length,
|
||||
toLength: toPosition * path.length,
|
||||
offsetLength: offset * path.length))
|
||||
}
|
||||
return CompoundBezierPath(paths: newPaths)
|
||||
}
|
||||
|
||||
/// Normalize lengths to the curve length.
|
||||
var startPosition = (fromPosition + offset).truncatingRemainder(dividingBy: 1)
|
||||
var endPosition = (toPosition + offset).truncatingRemainder(dividingBy: 1)
|
||||
|
||||
if startPosition < 0 {
|
||||
startPosition = 1 + startPosition
|
||||
}
|
||||
|
||||
if endPosition < 0 {
|
||||
endPosition = 1 + endPosition
|
||||
}
|
||||
|
||||
if startPosition == 1 {
|
||||
startPosition = 0
|
||||
}
|
||||
if endPosition == 0 {
|
||||
endPosition = 1
|
||||
}
|
||||
|
||||
if
|
||||
startPosition == 0 && endPosition == 1 ||
|
||||
startPosition == endPosition ||
|
||||
startPosition == 1 && endPosition == 0
|
||||
{
|
||||
/// The trim encompasses the entire path. Return.
|
||||
return self
|
||||
}
|
||||
|
||||
var positions: [(start: CGFloat, end: CGFloat)]
|
||||
if endPosition < startPosition {
|
||||
positions = [
|
||||
(start: 0, end: endPosition * length),
|
||||
(start: startPosition * length, end: length),
|
||||
]
|
||||
} else {
|
||||
positions = [(start: startPosition * length, end: endPosition * length)]
|
||||
}
|
||||
|
||||
var compoundPath = CompoundBezierPath()
|
||||
var trim = positions.remove(at: 0)
|
||||
var pathStartPosition: CGFloat = 0
|
||||
|
||||
var finishedTrimming = false
|
||||
var i = 0
|
||||
|
||||
while !finishedTrimming {
|
||||
if paths.count <= i {
|
||||
/// Rounding errors
|
||||
finishedTrimming = true
|
||||
continue
|
||||
}
|
||||
let path = paths[i]
|
||||
|
||||
let pathEndPosition = pathStartPosition + path.length
|
||||
|
||||
if pathEndPosition < trim.start {
|
||||
/// Path is not included in the trim, continue.
|
||||
pathStartPosition = pathEndPosition
|
||||
i = i + 1
|
||||
continue
|
||||
|
||||
} else if trim.start <= pathStartPosition, pathEndPosition <= trim.end {
|
||||
/// Full Path is inside of trim. Add full path.
|
||||
compoundPath = compoundPath.addPath(path: path)
|
||||
} else {
|
||||
if
|
||||
let trimPath = path.trim(
|
||||
fromLength: trim.start > pathStartPosition ? (trim.start - pathStartPosition) : 0,
|
||||
toLength: trim.end < pathEndPosition ? (trim.end - pathStartPosition) : path.length,
|
||||
offsetLength: 0).first
|
||||
{
|
||||
compoundPath = compoundPath.addPath(path: trimPath)
|
||||
}
|
||||
}
|
||||
|
||||
if trim.end <= pathEndPosition {
|
||||
/// We are done with the current trim.
|
||||
/// Advance trim but remain on the same path in case the next trim overlaps it.
|
||||
if positions.count > 0 {
|
||||
trim = positions.remove(at: 0)
|
||||
} else {
|
||||
finishedTrimming = true
|
||||
}
|
||||
} else {
|
||||
pathStartPosition = pathEndPosition
|
||||
i = i + 1
|
||||
}
|
||||
}
|
||||
return compoundPath
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user