Last active
December 24, 2018 19:14
-
-
Save matt-curtis/cf7f925d8f48fa73c7e29f3f4deb9096 to your computer and use it in GitHub Desktop.
Revisions
-
matt-curtis revised this gist
Dec 24, 2018 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,5 @@ // // UnitBezier.swift // // Created by Matt Curtis on 12/24/18. // Copyright © 2018 Matt Curtis. All rights reserved. -
matt-curtis revised this gist
Dec 24, 2018 . No changes.There are no files selected for viewing
-
matt-curtis revised this gist
Dec 24, 2018 . No changes.There are no files selected for viewing
-
matt-curtis created this gist
Dec 24, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,124 @@ // // UnitBezier.swift // EpubRenderKit // // Created by Matt Curtis on 12/24/18. // Copyright © 2018 Matt Curtis. All rights reserved. // import Foundation // Almost exact translation of WebKit's UnitBezier struct: // https://github.com/WebKit/webkit/blob/89c28d471fae35f1788a0f857067896a10af8974/Source/WebCore/platform/graphics/UnitBezier.h struct UnitBezier { // MARK: - Properties let ax: Double let bx: Double let cx: Double let ay: Double let by: Double let cy: Double // MARK: - Init init(_ p1x: Double, _ p1y: Double, _ p2x: Double, _ p2y: Double) { // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1). cx = 3.0 * p1x bx = 3.0 * (p2x - p1x) - cx ax = 1.0 - cx - bx cy = 3.0 * p1y by = 3.0 * (p2y - p1y) - cy ay = 1.0 - cy - by } func sampleCurveX(_ t: Double) -> Double { // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule. return ((ax * t + bx) * t + cx) * t; } func sampleCurveY(_ t: Double) -> Double { return ((ay * t + by) * t + cy) * t } func sampleCurveDerivativeX(_ t: Double) -> Double { return (3.0 * ax * t + 2.0 * bx) * t + cx } // Given an x value, find a parametric value it came from. func solveCurveX(_ x: Double, _ epsilon: Double) -> Double { var t0: Double = 0 var t1: Double = 0 var t2: Double = x var x2: Double = 0 var d2: Double = 0 // First try a few iterations of Newton's method -- normally very fast. for _ in 0..<8 { x2 = sampleCurveX(t2) - x if fabs(x2) < epsilon { return t2 } d2 = sampleCurveDerivativeX(t2) if fabs(d2) < 1e-6 { break } t2 = t2 - x2 / d2; } // Fall back to the bisection method for reliability. t0 = 0.0 t1 = 1.0 t2 = x if t2 < t0 { return t0 } if (t2 > t1) { return t1 } while t0 < t1 { x2 = sampleCurveX(t2) if fabs(x2 - x) < epsilon { return t2 } if x > x2 { t0 = t2 } else { t1 = t2 } t2 = (t1 - t0) * 0.5 + t0 } // Failure. return t2 } func progress(atPercent percent: Double, epsilon: Double) -> Double { return sampleCurveY(solveCurveX(percent, epsilon)) } func progress(atPercent percent: Double, ofDuration duration: Double) -> Double { // Approach borrowed from WebKit's epsilon calculation, which is based on duration: // https://github.com/WebKit/webkit/blob/82bae82cf0f329dbe21059ef0986c4e92fea4ba6/Source/WebCore/platform/animation/TimingFunction.cpp#L77 // The epsilon value we pass to UnitBezier::solve given that the animation is going to run over |dur| seconds. The longer the // animation, the more precision we need in the timing function result to avoid ugly discontinuities. let epsilon = 1.0 / (1000.0 * duration) return progress(atPercent: percent, epsilon: epsilon) } }