diff --git a/app/assets/javascripts/player/brush.js.coffee b/app/assets/javascripts/player/brush.js.coffee
index 47fcf77..8f3672e 100644
--- a/app/assets/javascripts/player/brush.js.coffee
+++ b/app/assets/javascripts/player/brush.js.coffee
@@ -30,3 +30,13 @@ class AsciiIo.Brush
hash: ->
AsciiIo.Brush.hash(this)
+
+ fgColor: ->
+ color = @fg || 7
+ color += 8 if color < 8 and @bright
+ color
+
+ bgColor: ->
+ color = @bg || 0
+ color += 8 if color < 8 and @blink
+ color
diff --git a/app/assets/javascripts/player/renderers/base.js.coffee b/app/assets/javascripts/player/renderers/base.js.coffee
index 8badf60..f91f8e7 100644
--- a/app/assets/javascripts/player/renderers/base.js.coffee
+++ b/app/assets/javascripts/player/renderers/base.js.coffee
@@ -13,9 +13,9 @@ class AsciiIo.Renderer.Base extends Backbone.View
@hideToggleOverlay()
render: (changes, cursorX, cursorY) ->
- for n, data of changes
+ for n, fragments of changes
c = if parseInt(n) is cursorY then cursorX else undefined
- @renderLine n, data || [], c
+ @renderLine n, fragments || [], c
renderLine: (n, data, cursorX) ->
throw '#renderLine not implemented'
diff --git a/app/assets/javascripts/player/renderers/canvas.js.coffee b/app/assets/javascripts/player/renderers/canvas.js.coffee
index 6cbabd2..a463538 100644
--- a/app/assets/javascripts/player/renderers/canvas.js.coffee
+++ b/app/assets/javascripts/player/renderers/canvas.js.coffee
@@ -17,54 +17,39 @@ class AsciiIo.Renderer.Canvas extends AsciiIo.Renderer.Base
@$el.attr('width', width)
@$el.attr('height', height)
@setFont()
- # @$el.css(width: width + 'px', height: height + 'px')
- # @ctx.scale(1, 1)
setFont: ->
size = @$el.css('font-size')
- console.log size
+ # console.log size
family = @$el.css('font-family')
- console.log family
+ # console.log family
@font = "#{size} #{family}"
@ctx.font = @font
@prevFont = @font
@ctx.textBaseline = 'bottom'
- renderLine: (n, data, cursorX) ->
+ renderLine: (n, fragments, cursorX) ->
left = 0
width = @cols * @cellWidth
top = n * @cellHeight
- for i in [0...@cols]
- d = data[i]
+ for fragment in fragments
+ [text, brush] = fragment
- if d
- [char, brush] = d
+ @setBackgroundAttributes(brush)
+ @ctx.fillRect left, top, text.length * @cellWidth, @cellHeight
- @setBackgroundAttributes(brush)
- @ctx.fillRect left + i * @cellWidth, top, @cellWidth, @cellHeight
+ # if char != ' '
+ @setTextAttributes(brush)
+ @ctx.fillText text, left, top + @cellHeight
- if char != ' '
- @setTextAttributes(brush)
- @ctx.fillText char, i * @cellWidth, top + @cellHeight
+ left += text.length * @cellWidth
setBackgroundAttributes: (brush) ->
- if brush.bg isnt undefined
- bg = brush.bg
- bg += 8 if bg < 8 and brush.blink
- else
- bg = 0
-
- @ctx.fillStyle = AsciiIo.colors[bg]
+ @ctx.fillStyle = AsciiIo.colors[brush.bgColor()]
setTextAttributes: (brush) ->
- if brush.fg isnt undefined
- fg = brush.fg
- fg += 8 if fg < 8 and brush.bright
- else
- fg = 7
-
- @ctx.fillStyle = AsciiIo.colors[fg]
+ @ctx.fillStyle = AsciiIo.colors[brush.fgColor()]
font = @font
diff --git a/app/assets/javascripts/player/renderers/pre.js.coffee b/app/assets/javascripts/player/renderers/pre.js.coffee
index e4d28a3..080a6ae 100644
--- a/app/assets/javascripts/player/renderers/pre.js.coffee
+++ b/app/assets/javascripts/player/renderers/pre.js.coffee
@@ -23,11 +23,12 @@ class AsciiIo.Renderer.Pre extends AsciiIo.Renderer.Base
@fixSize()
initialRender: ->
+ brush = AsciiIo.Brush.normal()
changes = {}
i = 0
while i < @lines
- changes[i] = undefined
+ changes[i] = [[' '.times(@cols), brush]]
i += 1
@render(changes, 0, 0)
@@ -41,53 +42,50 @@ class AsciiIo.Renderer.Pre extends AsciiIo.Renderer.Base
@$el.find('.cursor').removeClass('cursor')
super(changes, cursorX, cursorY)
- renderLine: (n, data, cursorX) ->
+ renderLine: (n, fragments, cursorX) ->
html = []
- prevBrush = undefined
- for i in [0...@cols]
- d = data[i]
+ rendered = 0
- if d
- [char, brush] = d
+ for fragment in fragments
+ [text, brush] = fragment
- char = char.replace('&', '&').replace('<', '<')
+ if cursorX isnt undefined and rendered < cursorX < rendered + text.length
+ left = text.slice(0, cursorX - rendered)
+ cursor =
+ '' + text[cursorX - rendered] + ''
+ right = text.slice(cursorX - rendered + 1)
- if brush != prevBrush or i is cursorX or i is (cursorX + 1)
- if prevBrush
- html.push ''
-
- html.push @spanFromBrush(brush, i is cursorX)
-
- prevBrush = brush
-
- html.push char
+ t = @escape(left) + cursor + @escape(right)
else
- html.push ' '
+ t = @escape(text)
- html.push '' if prevBrush
+ html.push @spanFromBrush(brush)
+ html.push t
+ html.push ''
+
+ rendered += text.length
@$el.find(".line:eq(" + n + ")")[0].innerHTML = '' + html.join('') + ''
- spanFromBrush: (brush, hasCursor) ->
- key = "#{brush.hash()}_#{hasCursor}"
+ escape: (text) ->
+ text.replace('&', '&').replace('<', '<')
+
+ spanFromBrush: (brush) ->
+ key = brush.hash()
span = @cachedSpans[key]
if not span
span = ""
- if hasCursor or brush != AsciiIo.Brush.normal()
+ if brush != AsciiIo.Brush.normal()
span = ""
@cachedSpans[key] = span
diff --git a/app/assets/javascripts/player/screen_buffer.js.coffee b/app/assets/javascripts/player/screen_buffer.js.coffee
index 3b8650f..efecc71 100644
--- a/app/assets/javascripts/player/screen_buffer.js.coffee
+++ b/app/assets/javascripts/player/screen_buffer.js.coffee
@@ -7,7 +7,7 @@ class AsciiIo.ScreenBuffer
@cursorX = 0
@cursorY = 0
- @setBrush AsciiIo.Brush.create({})
+ @setBrush AsciiIo.Brush.normal()
@setCharset 'us'
topMargin: ->
@@ -17,7 +17,7 @@ class AsciiIo.ScreenBuffer
@scrollRegion.getBottom()
updateLine: (n = @cursorY) ->
- @dirtyLines[n] = @lineData[n]
+ @dirtyLines[n] = true
updateLines: (a, b) ->
n = a
@@ -29,7 +29,34 @@ class AsciiIo.ScreenBuffer
@updateLine n for n in [0...@lines]
changes: ->
- @dirtyLines
+ changes = {}
+
+ for n, _ of @dirtyLines
+ data = @lineData[n] || []
+
+ fragments = []
+ currentBrush = AsciiIo.Brush.normal()
+ currentText = ''
+
+ for i in [0...@cols]
+ d = data[i]
+
+ if d
+ [char, brush] = d
+ else
+ [char, brush] = [' ', currentBrush]
+
+ if brush == currentBrush
+ currentText += char
+ else
+ fragments.push([currentText, currentBrush]) if currentText.length > 0
+ currentText = char
+ currentBrush = brush
+
+ fragments.push([currentText, currentBrush]) if currentText.length > 0
+ changes[n] = fragments
+
+ changes
clearChanges: ->
@dirtyLines = {}