     let strokeColor = rootNode?.textOutputNode.strokeColor ?? text.strokeColorData?.cgColorValue
     let strokeWidth = rootNode?.textOutputNode.strokeWidth ?? CGFloat(text.strokeWidth ?? 0)
     let tracking = (CGFloat(text.fontSize) * (rootNode?.textOutputNode.tracking ?? CGFloat(text.tracking))) / 1000.0
-    // TODO LINE HEIGHT
     
     let matrix = rootNode?.textOutputNode.xform ?? CATransform3DIdentity
     let ctFont = CTFontCreateWithName(text.fontFamily as CFString, CGFloat(text.fontSize), nil)
+    
+    let textString = textProvider.textFor(keypathName: self.keypathName, sourceText: text.text)
     
     var attributes: [NSAttributedString.Key : Any] = [
       NSAttributedString.Key.font: ctFont,
       NSAttributedString.Key.foregroundColor: fillColor,
       NSAttributedString.Key.kern: tracking,
-      ]
-    
-    if let strokeColor = strokeColor {
-      attributes[NSAttributedString.Key.strokeColor] = strokeColor
-      attributes[NSAttributedString.Key.strokeWidth] = strokeWidth
-    }
-    
-
-    let textString = textProvider.textFor(keypathName: self.keypathName, sourceText: text.text)
+    ]
     
     let paragraphStyle = NSMutableParagraphStyle()
     paragraphStyle.lineSpacing = CGFloat(text.lineHeight)
     paragraphStyle.alignment = text.justification.textAlignment
     attributes[NSAttributedString.Key.paragraphStyle] = paragraphStyle
     
-    let attributedString = NSAttributedString(string: textString, attributes: attributes )
+    let baseAttributedString = NSAttributedString(string: textString, attributes: attributes )
+    
+    if let strokeColor = strokeColor {
+      textStrokeLayer.isHidden = false
+      attributes[NSAttributedString.Key.strokeColor] = strokeColor
+      attributes[NSAttributedString.Key.strokeWidth] = strokeWidth
+    } else {
+      textStrokeLayer.isHidden = true
+    }
+    
+    let attributedString: NSAttributedString = NSAttributedString(string: textString, attributes: attributes )
     
     let framesetter = CTFramesetterCreateWithAttributedString(attributedString)
     

    }
    self.rootNode = rootNode
    self.textDocument = KeyframeInterpolator(keyframes: textLayer.text.keyframes)

    self.textProvider = textProvider

    // TODO: this has to be somewhere that can be interpolated
    // TODO: look for inspiration from other composite layer
    self.interpolatableAnchorPoint = KeyframeInterpolator(keyframes: textLayer.transform.anchorPoint.keyframes)

    }
    self.rootNode = nil
    self.textDocument = nil
    
    self.textProvider = DefaultTextProvider()
    
    self.interpolatableAnchorPoint = nil
    self.interpolatableScale = nil
    
    super.init(layer: layer)
  }
  
  override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) {
    guard let textDocument = textDocument else { return }
    
    textLayer.contentsScale = self.renderScale
    textStrokeLayer.contentsScale = self.renderScale
    
    let documentUpdate = textDocument.hasUpdate(frame: frame)
    let animatorUpdate = rootNode?.updateContents(frame, forceLocalUpdate: forceUpdates) ?? false
    guard documentUpdate == true || animatorUpdate == true else { return }
