Class: Charming::Image::Source

Inherits:
Object
  • Object
show all
Defined in:
lib/charming/image/source.rb

Overview

Source owns an image's bytes, its stable id, and its transmit state — the "engine" half of the image feature, analogous to Audio::Player. Keep it in session (built once) rather than rebuilt per render, so #transmitted? reliably gates the one-time transmission.

It dispatches to the active Protocol (chosen by its Terminal) to build the out-of-band Transmit and the in-frame placeholder block, and is a no-op on terminals without graphics support, letting Components::Image fall back gracefully.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path: nil, data: nil, id: nil, terminal: Terminal.new) ⇒ Source

path or data supplies the (PNG) bytes — exactly one is required. id overrides the derived image id. terminal is the protocol-detection seam (injectable for specs).

Raises:

  • (ArgumentError)


17
18
19
20
21
22
23
24
25
# File 'lib/charming/image/source.rb', line 17

def initialize(path: nil, data: nil, id: nil, terminal: Terminal.new)
  raise ArgumentError, "provide either path: or data:" unless path || data

  @path = path
  @data = data
  @id = id
  @terminal = terminal
  @transmitted = false
end

Instance Attribute Details

#terminalObject (readonly)

The protocol-detection seam, exposed so the component can ask #supports_graphics?.



28
29
30
# File 'lib/charming/image/source.rb', line 28

def terminal
  @terminal
end

Instance Method Details

#image_idObject

The stable 32-bit image id (kept within 24 bits so the placeholder foreground colour fully encodes it). Derived from a digest of the bytes unless an explicit id was given.



32
33
34
# File 'lib/charming/image/source.rb', line 32

def image_id
  @image_id ||= @id || derive_id
end

#mark_transmittedObject

Records that the image has been transmitted, so it is not re-sent on later renders.



72
73
74
# File 'lib/charming/image/source.rb', line 72

def mark_transmitted
  @transmitted = true
end

#placement(rows:, cols:) ⇒ Object

The in-frame placeholder block sized rows×cols, or "" when graphics are unsupported.



50
51
52
53
54
# File 'lib/charming/image/source.rb', line 50

def placement(rows:, cols:)
  return "" unless protocol

  protocol.placeholder_block(image_id: image_id, rows: rows, cols: cols)
end

#releaseObject

Builds the out-of-band Transmit that frees the image from terminal memory, or nil when graphics are unsupported. Re-arms #transmitted? so a later render retransmits. Callers evicting an image register this the same way as #transmit.



59
60
61
62
63
64
# File 'lib/charming/image/source.rb', line 59

def release
  return unless protocol

  @transmitted = false
  Transmit.new(image_id: image_id, payload: protocol.delete(image_id: image_id))
end

#supports_graphics?Boolean

True when the host terminal supports a graphics protocol.

Returns:

  • (Boolean)


37
38
39
# File 'lib/charming/image/source.rb', line 37

def supports_graphics?
  @terminal.supports_graphics?
end

#transmit(rows:, cols:) ⇒ Object

Builds the out-of-band Transmit for a rows×cols placement, or nil when graphics are unsupported. The Runtime flushes it to the backend; Escape.register collects it.



43
44
45
46
47
# File 'lib/charming/image/source.rb', line 43

def transmit(rows:, cols:)
  return unless protocol

  Transmit.new(image_id: image_id, payload: protocol.transmit(image_id: image_id, png_bytes: bytes, rows: rows, cols: cols))
end

#transmitted?Boolean

True once #mark_transmitted has recorded that the image was sent to the terminal.

Returns:

  • (Boolean)


67
68
69
# File 'lib/charming/image/source.rb', line 67

def transmitted?
  @transmitted
end