Class: BitmapWindow
- Inherits:
-
Object
- Object
- BitmapWindow
- Defined in:
- lib/bitmapwindow.rb
Overview
A third implementation of the drawing interface WindowAdapter targets (alongside the X11 Window and the harness’s VirtualWindow): it rasterises real glyphs with skrift and composites them into an in-memory RGB buffer. Wrapped by WindowAdapter it is a full “bitmap backend” - the same Term core, rendered to a pixel buffer with no X server - useful for headless visual testing and for embedding the terminal anywhere a bitmap can go.
win = BitmapWindow.new(80, 24)
adapter = WindowAdapter.new(win, host) # host: term_width/blink_state...
... feed the terminal ...
win.save_png("screen.png")
Constant Summary collapse
- DEFAULT_FONT =
"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf"
Instance Attribute Summary collapse
-
#height ⇒ Object
readonly
Returns the value of attribute height.
-
#pixels ⇒ Object
readonly
Returns the value of attribute pixels.
-
#width ⇒ Object
readonly
Returns the value of attribute width.
Instance Method Summary collapse
- #char_h ⇒ Object
- #char_w ⇒ Object
- #clear(x, y, w, h) ⇒ Object
- #copy_buffer ⇒ Object
-
#dirty! ⇒ Object
Live-loop hooks: a bitmap has no separate front buffer / event channel.
-
#draw(x, y, str, fg, bg, _lineattrs = nil) ⇒ Object
x,y are pixel coordinates (WindowAdapter has already multiplied by the cell size).
- #draw_line(x, y, w, col) ⇒ Object
- #fillrect(x, y, w, h, col) ⇒ Object
- #flush ⇒ Object
-
#initialize(cols, rows, font: DEFAULT_FONT, size: 16, fg: 0xcccccc, bg: 0x000000) ⇒ BitmapWindow
constructor
A new instance of BitmapWindow.
- #map_window ⇒ Object
- #resize(w, h) ⇒ Object
-
#save_png(path) ⇒ Object
# Output.
- #scroll_down(srcy, w, h, step) ⇒ Object
-
#scroll_up(srcy, w, h, step) ⇒ Object
Mirror Window#scroll_up / #scroll_down: move a block of pixel rows and clear the vacated strip (geometry comes from WindowAdapter).
- #scrollback_count ⇒ Object
- #scrollback_mode ⇒ Object
- #set_buffer(_) ⇒ Object
Constructor Details
#initialize(cols, rows, font: DEFAULT_FONT, size: 16, fg: 0xcccccc, bg: 0x000000) ⇒ BitmapWindow
Returns a new instance of BitmapWindow.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/bitmapwindow.rb', line 20 def initialize(cols, rows, font: DEFAULT_FONT, size: 16, fg: 0xcccccc, bg: 0x000000) @font = Font.load(font) @sft = SFT.new(@font) @sft.x_scale = size @sft.y_scale = size lm = @sft.lmetrics @char_h = (lm.ascender - lm.descender + lm.line_gap).ceil @baseline = lm.ascender.round @char_w = @sft.gmetrics(@sft.lookup("M".ord)).advance_width.round @cols, @rows = cols, rows @fg, @bg = fg, bg @glyphs = {} resize(cols * @char_w, rows * @char_h) end |
Instance Attribute Details
#height ⇒ Object (readonly)
Returns the value of attribute height.
16 17 18 |
# File 'lib/bitmapwindow.rb', line 16 def height @height end |
#pixels ⇒ Object (readonly)
Returns the value of attribute pixels.
16 17 18 |
# File 'lib/bitmapwindow.rb', line 16 def pixels @pixels end |
#width ⇒ Object (readonly)
Returns the value of attribute width.
16 17 18 |
# File 'lib/bitmapwindow.rb', line 16 def width @width end |
Instance Method Details
#char_h ⇒ Object
37 |
# File 'lib/bitmapwindow.rb', line 37 def char_h = @char_h |
#char_w ⇒ Object
36 |
# File 'lib/bitmapwindow.rb', line 36 def char_w = @char_w |
#clear(x, y, w, h) ⇒ Object
64 |
# File 'lib/bitmapwindow.rb', line 64 def clear(x, y, w, h) = fillrect(x, y, w, h, @bg) |
#copy_buffer ⇒ Object
49 |
# File 'lib/bitmapwindow.rb', line 49 def copy_buffer = nil |
#dirty! ⇒ Object
Live-loop hooks: a bitmap has no separate front buffer / event channel.
47 |
# File 'lib/bitmapwindow.rb', line 47 def dirty! = nil |
#draw(x, y, str, fg, bg, _lineattrs = nil) ⇒ Object
x,y are pixel coordinates (WindowAdapter has already multiplied by the cell size). lineattrs (double width/height) is rendered as normal width for now - it does not affect correctness of the text, only its scale.
70 71 72 73 74 75 76 |
# File 'lib/bitmapwindow.rb', line 70 def draw(x, y, str, fg, bg, _lineattrs = nil) fillrect(x, y, str.length * @char_w, @char_h, bg) str.each_char.with_index do |ch, i| next if ch == " " blit_glyph(ch.ord, x + i * @char_w, y, fg) end end |
#draw_line(x, y, w, col) ⇒ Object
65 |
# File 'lib/bitmapwindow.rb', line 65 def draw_line(x, y, w, col) = fillrect(x, y, w, 1, col) |
#fillrect(x, y, w, h, col) ⇒ Object
55 56 57 58 59 60 61 62 |
# File 'lib/bitmapwindow.rb', line 55 def fillrect(x, y, w, h, col) x0 = x.clamp(0, @width); x1 = (x + w).clamp(0, @width) y0 = y.clamp(0, @height); y1 = (y + h).clamp(0, @height) (y0...y1).each do |py| base = py * @width (x0...x1).each { |px| @pixels[base + px] = col } end end |
#flush ⇒ Object
48 |
# File 'lib/bitmapwindow.rb', line 48 def flush = nil |
#map_window ⇒ Object
50 |
# File 'lib/bitmapwindow.rb', line 50 def map_window = nil |
#resize(w, h) ⇒ Object
39 40 41 42 |
# File 'lib/bitmapwindow.rb', line 39 def resize(w, h) @width, @height = w, h @pixels = Array.new(@width * @height, @bg) end |
#save_png(path) ⇒ Object
# Output
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/bitmapwindow.rb', line 92 def save_png(path) raw = +"".b @height.times do |y| raw << "\0" # filter: none base = y * @width @width.times do |x| p = @pixels[base + x] raw << ((p >> 16) & 0xff).chr << ((p >> 8) & 0xff).chr << (p & 0xff).chr end end png = +"\x89PNG\r\n\x1a\n".b png << png_chunk("IHDR", [@width, @height, 8, 2, 0, 0, 0].pack("NNC5")) png << png_chunk("IDAT", Zlib::Deflate.deflate(raw)) png << png_chunk("IEND", "") File.binwrite(path, png) path end |
#scroll_down(srcy, w, h, step) ⇒ Object
85 86 87 88 |
# File 'lib/bitmapwindow.rb', line 85 def scroll_down(srcy, w, h, step) move_rows(srcy, srcy + step, h) clear(0, srcy, @width, step) end |
#scroll_up(srcy, w, h, step) ⇒ Object
Mirror Window#scroll_up / #scroll_down: move a block of pixel rows and clear the vacated strip (geometry comes from WindowAdapter).
80 81 82 83 |
# File 'lib/bitmapwindow.rb', line 80 def scroll_up(srcy, w, h, step) move_rows(srcy, srcy - step, h) clear(0, srcy + h - step, @width, step + 1) end |
#scrollback_count ⇒ Object
53 |
# File 'lib/bitmapwindow.rb', line 53 def scrollback_count = 0 |
#scrollback_mode ⇒ Object
52 |
# File 'lib/bitmapwindow.rb', line 52 def scrollback_mode = false |
#set_buffer(_) ⇒ Object
51 |
# File 'lib/bitmapwindow.rb', line 51 def set_buffer(_) = nil |