From 282511b60efc52548b4406250a5c5ad2aee96285 Mon Sep 17 00:00:00 2001 From: Marcin Kulik Date: Fri, 16 Mar 2012 20:18:15 +0100 Subject: [PATCH] Move changed fragments detection to ScreenBuffer --- app/assets/javascripts/player/brush.js.coffee | 10 ++++ .../player/renderers/base.js.coffee | 4 +- .../player/renderers/canvas.js.coffee | 41 +++++--------- .../player/renderers/pre.js.coffee | 55 +++++++++---------- .../player/screen_buffer.js.coffee | 33 ++++++++++- 5 files changed, 81 insertions(+), 62 deletions(-) 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 = {}