           x += w * charWidth
     context.fill()
 
+  copyBitmapPart: (context, bitmapCanvas, srcRow, destRow, rowCount) ->
+    lineHeight = @getLineHeight()
+    context.drawImage(bitmapCanvas,
+        0, srcRow * lineHeight,
+        bitmapCanvas.width, rowCount * lineHeight,
+        0, destRow * lineHeight,
+        bitmapCanvas.width, rowCount * lineHeight)
+
+  fillGapsBetweenIntactRanges: (context, intactRanges, firstRow, lastRow) ->
+    currentRow = firstRow
+    # intactRanges is sorted, we can safely fill between ranges
+    for intact in intactRanges
+      @drawLines(context, currentRow, intact.start-1, currentRow-firstRow)
+      currentRow = intact.end
+    if currentRow <= lastRow
+      @drawLines(context, currentRow, lastRow, currentRow-firstRow)
+
   update: =>
     return unless @editorView?
     return unless @displayBuffer.tokenizedBuffer.fullyTokenized

      @tokenColorCache[flatScopes] = color
    @tokenColorCache[flatScopes]

  drawLines: (firstRow, lastRow, offsetRow, context) ->
    lines = @editor.linesForScreenRows(firstRow, lastRow)
    lineHeight = @getLineHeight()
    charHeight = @getCharHeight()

    firstRow = @getFirstVisibleScreenRow()
    lastRow = @getLastVisibleScreenRow()

    intactRanges = @computeIntactRanges(firstRow, lastRow)
    if intactRanges.length is 0
      @drawLines(@context, firstRow, lastRow, 0)
    else
      for intact in intactRanges
        @copyBitmapPart(@context, @offscreenCanvas, intact.domStart, intact.start-firstRow, intact.end-intact.start)
      @fillGapsBetweenIntactRanges(@context, intactRanges, firstRow, lastRow)

    # copy displayed canvas to offscreen canvas
    @offscreenCanvas.width = @lineCanvas[0].width
