         self.layer.mask = nil
     }
     
-    private func keyFrameAnimationForGradient(_ fadeLength: CGFloat, interval: CGFloat, delay: CGFloat) -> CAKeyframeAnimation {
-        // Setup
-        let values: [[CGColor]]
-        let keyTimes: [CGFloat]
-        let transp = UIColor.clear.cgColor
-        let opaque = UIColor.black.cgColor
-        
-        // Create new animation
-        let animation = CAKeyframeAnimation(keyPath: "colors")
-        
-        // Get timing function
-        let timingFunction = timingFunctionForAnimationCurve(animationCurve)
-        
-        // Define keyTimes
-        switch (type) {
-        case .leftRight, .rightLeft:
-            // Calculate total animation duration
-            let totalDuration = 2.0 * (delay + interval)
-            keyTimes =
-            [
-                0.0,                                                // 1) Initial gradient
-                delay/totalDuration,                                // 2) Begin of LE fade-in, just as scroll away starts
-                (delay + 0.4)/totalDuration,                        // 3) End of LE fade in [LE fully faded]
-                (delay + interval - 0.4)/totalDuration,             // 4) Begin of TE fade out, just before scroll away finishes
-                (delay + interval)/totalDuration,                   // 5) End of TE fade out [TE fade removed]
-                (delay + interval + delay)/totalDuration,           // 6) Begin of TE fade back in, just as scroll home starts
-                (delay + interval + delay + 0.4)/totalDuration,     // 7) End of TE fade back in [TE fully faded]
-                (totalDuration - 0.4)/totalDuration,                // 8) Begin of LE fade out, just before scroll home finishes
-                1.0                                                 // 9) End of LE fade out, just as scroll home finishes
-            ]
-            
-        // .MLContinuous, .MLContinuousReverse
-        default:
-            // Calculate total animation duration
-            let totalDuration = delay + interval
-            
-            // Find when the lead label will be totally offscreen
-            let offsetDistance = awayOffset
-            let startFadeFraction = fabs((sublabel.bounds.size.width + leadingBuffer) / offsetDistance)
-            // Find when the animation will hit that point
-            let startFadeTimeFraction = timingFunction.durationPercentageForPositionPercentage(startFadeFraction, duration: totalDuration)
-            let startFadeTime = delay + CGFloat(startFadeTimeFraction) * interval
-            
-            keyTimes = [
-                0.0,                                        // Initial gradient
-                delay/totalDuration,                        // Begin of fade in
-                (delay + 0.2)/totalDuration,                // End of fade in, just as scroll away starts
-                startFadeTime/totalDuration,                // Begin of fade out, just before scroll home completes
-                (startFadeTime + 0.1)/totalDuration,        // End of fade out, as scroll home completes
-                1.0                                         // Buffer final value (used on continuous types)
-            ]
-            break
-        }
-        
-        // Define values
-        // Get current layer values
-        let mask = maskLayer?.presentation()
-        let currentValues = mask?.colors as? [CGColor]
-        
-        switch (type) {
-        case .continuousReverse:
-            values = [
-                currentValues ?? [transp, opaque, opaque, opaque],           // Initial gradient
-                [transp, opaque, opaque, opaque],           // Begin of fade in
-                [transp, opaque, opaque, transp],           // End of fade in, just as scroll away starts
-                [transp, opaque, opaque, transp],           // Begin of fade out, just before scroll home completes
-                [transp, opaque, opaque, opaque],           // End of fade out, as scroll home completes
-                [transp, opaque, opaque, opaque]            // Final "home" value
-            ]
-            break
-        
-        case .rightLeft:
-            values = [
-                currentValues ?? [transp, opaque, opaque, opaque],           // 1)
-                [transp, opaque, opaque, opaque],           // 2)
-                [transp, opaque, opaque, transp],           // 3)
-                [transp, opaque, opaque, transp],           // 4)
-                [opaque, opaque, opaque, transp],           // 5)
-                [opaque, opaque, opaque, transp],           // 6)
-                [transp, opaque, opaque, transp],           // 7)
-                [transp, opaque, opaque, transp],           // 8)
-                [transp, opaque, opaque, opaque]            // 9)
-            ]
-            break
-            
-        case .continuous:
-            values = [
-                currentValues ?? [opaque, opaque, opaque, transp],           // Initial gradient
-                [opaque, opaque, opaque, transp],           // Begin of fade in
-                [transp, opaque, opaque, transp],           // End of fade in, just as scroll away starts
-                [transp, opaque, opaque, transp],           // Begin of fade out, just before scroll home completes
-                [opaque, opaque, opaque, transp],           // End of fade out, as scroll home completes
-                [opaque, opaque, opaque, transp]            // Final "home" value
-            ]
-            break
-            
-        case .leftRight:
-            values = [
-                currentValues ?? [opaque, opaque, opaque, transp],           // 1)
-                [opaque, opaque, opaque, transp],           // 2)
-                [transp, opaque, opaque, transp],           // 3)
-                [transp, opaque, opaque, transp],           // 4)
-                [transp, opaque, opaque, opaque],           // 5)
-                [transp, opaque, opaque, opaque],           // 6)
-                [transp, opaque, opaque, transp],           // 7)
-                [transp, opaque, opaque, transp],           // 8)
-                [opaque, opaque, opaque, transp]            // 9)
-            ]
-            break
-        }
-        
-        animation.values = values
-        animation.keyTimes = keyTimes.mapToNumbers()
-        animation.timingFunctions = [timingFunction, timingFunction, timingFunction, timingFunction]
-        
-        return animation
-    }
-    
-    private func keyFrameAnimationForProperty(_ property: String, values: [NSValue], interval: CGFloat, delay: CGFloat) -> CAKeyframeAnimation {
-        // Create new animation
-        let animation = CAKeyframeAnimation(keyPath: property)
-        
-        // Get timing function
-        let timingFunction = timingFunctionForAnimationCurve(animationCurve)
-        
-        // Calculate times based on marquee type
-        let totalDuration: CGFloat
-        let keyTimes: [CGFloat]
-        
-        switch (type) {
-        case .leftRight, .rightLeft:
-            //NSAssert(values.count == 5, @"Incorrect number of values passed for MLLeftRight-type animation")
-            totalDuration = 2.0 * (delay + interval)
-            // Set up keyTimes
-            keyTimes = [
-                0.0,                                            // Initial location, home
-                delay/totalDuration,                            // Initial delay, at home
-                (delay + interval)/totalDuration,               // Animation to away
-                (delay + interval + delay)/totalDuration,       // Delay at away
-                1.0                                             // Animation to home
-            ]
-            
-            animation.timingFunctions = [
-                timingFunction,
-                timingFunction,
-                timingFunction,
-                timingFunction
-            ]
-            
-            // .Continuous
-            // .ContinuousReverse
-        default:
-            //NSAssert(values.count == 3, @"Incorrect number of values passed for MLContinous-type animation")
-            totalDuration = delay + interval
-            // Set up keyTimes
-            keyTimes = [
-                0.0,                        // Initial location, home
-                delay/totalDuration,        // Initial delay, at home
-                1.0                         // Animation to away
-            ]
-            
-            animation.timingFunctions = [
-                timingFunction,
-                timingFunction
-            ]
-        }
-        
-        // Set values
-        animation.keyTimes = keyTimes.mapToNumbers()
-        animation.values = values
-        
-        return animation
-    }
-    
     private func timingFunctionForAnimationCurve(_ curve: UIViewAnimationCurve) -> CAMediaTimingFunction {
         let timingFunction: String?
         

            // Adjust stops based on fade length
            let leftFadeStop = fadeLength/self.bounds.size.width
            let rightFadeStop = 1.0 - fadeLength/self.bounds.size.width
            gradientMask.locations = [0.0, leftFadeStop, rightFadeStop, 1.0].mapToNumbers()
        }
        
        gradientMask.bounds = self.layer.bounds

                maskLayer?.removeAnimation(forKey: "setupFade")
                
                // Generate animation if needed
                if let previousAnimation = fader?.anim {
                    gradientAnimation = previousAnimation
                } else {
                    gradientAnimation = nil
                }
                
                // Apply fade animation
                maskLayer?.add(gradientAnimation!, forKey: "gradient")
            } else {
                // No animation needed
                fader = nil
            }
        #else
            fader = nil;
        #endif
        
        scrollCompletionBlock = { [weak self] (finished: Bool) -> () in
