Class: Rufio::Renderer

Inherits:
Object
  • Object
show all
Defined in:
lib/rufio/renderer.rb

Overview

Renderer class - Front buffer for double buffering

Manages the front buffer (what’s currently displayed on screen) and performs differential rendering by comparing with the back buffer (Screen).

Features:

  • Diff rendering: Only updates changed lines

  • Cursor positioning: Uses ANSI escape codes

  • Flush control: Ensures all output is displayed

Instance Method Summary collapse

Constructor Details

#initialize(width, height, output: STDOUT) ⇒ Renderer

Returns a new instance of Renderer.



15
16
17
18
19
20
# File 'lib/rufio/renderer.rb', line 15

def initialize(width, height, output: STDOUT)
  @width = width
  @height = height
  @front = Array.new(height) { " " * width }
  @output = output
end

Instance Method Details

#clearObject

Clear the front buffer and screen



76
77
78
79
80
81
82
# File 'lib/rufio/renderer.rb', line 76

def clear
  @front = Array.new(@height) { " " * @width }

  # Clear screen and move cursor to home
  @output.print "\e[2J\e[H"
  @output.flush
end

#render(screen) ⇒ Boolean

Render the screen with differential updates

Parameters:

  • screen (Screen)

    The back buffer to render

Returns:

  • (Boolean)

    true if rendering was performed, false if skipped



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rufio/renderer.rb', line 26

def render(screen)
  # CPU最適化: Dirty rowsが空の場合は完全にスキップ
  dirty = screen.dirty_rows
  if dirty.empty?
    return false
  end

  # Phase1: Only process dirty rows (rows that have changed)
  # 全dirty rowsの出力を1つのバッファに積んでから単一の write() で書き出す。
  # STDOUT sync=true 環境で print を行ごとに呼ぶと各行で即座にフラッシュされ
  # 中間状態が表示されてちらつきが発生するため、アトミックな更新を保証する。
  buf = String.new("")
  rendered_count = 0
  dirty.each do |y|
    line = screen.row(y)
    next if line == @front[y]  # Skip if content is actually the same

    # Move cursor to line y (1-indexed) and buffer the line
    buf << "\e[#{y + 1};1H#{line}"
    @front[y] = line
    rendered_count += 1
  end

  # Phase1: Clear dirty tracking after rendering
  screen.clear_dirty

  # 単一の write() でアトミックに出力し、その後 flush する
  if rendered_count > 0
    @output.write(buf)
    @output.flush
  end

  true
end

#resize(width, height) ⇒ Object

Resize the front buffer

Parameters:

  • width (Integer)

    New width

  • height (Integer)

    New height



65
66
67
68
69
70
71
72
73
# File 'lib/rufio/renderer.rb', line 65

def resize(width, height)
  @width = width
  @height = height
  @front = Array.new(height) { " " * width }

  # Clear entire screen
  @output.print "\e[2J\e[H"
  @output.flush
end