         return true
     }
     
-    private func beginScroll() {
-        beginScroll(true)
-    }
-    
-    private func beginScroll(_ delay: Bool) {
-        switch self.type {
-        case .leftRight, .rightLeft:
-            scrollAway(animationDuration, delay: animationDelay)
-        default:
-            scrollContinuous(animationDuration, delay: animationDelay)
-        }
+    private func beginScroll(_ sequence: [MarqueeStep]) {
+        let scroller = generateScrollAnimation(sequence)
+        let fader = generateGradientAnimation(sequence, totalDuration: scroller.duration)
+        
+        scroll(scroller, fader: fader)
     }
     
     private func returnLabelToHome() {

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

        
        // Label DOES need to scroll
        
        // Recompute the animation duration
        animationDuration = {
            switch self.speed {
            case .rate(let rate):
                return CGFloat(fabs(self.awayOffset) / rate)
            case .duration(let duration):
                return duration
            }
        }()
        
        // Spacing between primary and second sublabel must be at least equal to leadingBuffer, and at least equal to the fadeLength
        let minTrailing = max(max(leadingBuffer, trailingBuffer), fadeLength)
        
        // Determine positions and generate scroll steps
        let sequence: [MarqueeStep]
        
        switch type {
        case .continuous, .continuousReverse:
