FrenchCurve.Geometry (FrenchCurve v0.1.3)

Copy Markdown View Source

Converts between terminal cells and pixels.

Sizing a raster to a region of the screen needs the terminal's cell size in pixels, which only the terminal knows. cell_size_query/0 returns the escape sequence that asks for it and parse_cell_size/1 reads the answer; detect_cell_size/1 does both through a callback you supply. When the terminal will not say, default_cell_px/0 stands in.

Sizes are {width, height} in pixels throughout, and regions are {cols, rows} in cells.

cell_px =
  case FrenchCurve.Geometry.detect_cell_size(&query_terminal/1) do
    {:ok, size} -> size
    :error -> FrenchCurve.Geometry.default_cell_px()
  end

{width, height} = FrenchCurve.Geometry.pixels_for_cells({40, 12}, cell_px)

Summary

Functions

Returns the pixels one braille cell covers, {2, 4}.

Returns the escape sequence that asks the terminal for its cell size in pixels.

Returns the assumed cell size, {10, 20} pixels, for terminals that do not report one.

Asks the terminal for its cell size through query_io and parses the reply.

Parses a terminal's reply to cell_size_query/0.

Returns the pixel size {width, height} of a {cols, rows} region of cells.

Types

cell_px()

@type cell_px() :: {pos_integer(), pos_integer()}

region()

@type region() :: {pos_integer(), pos_integer()}

Functions

braille_cell_px()

@spec braille_cell_px() :: cell_px()

Returns the pixels one braille cell covers, {2, 4}.

Fixed by the braille dot layout, not by the terminal: FrenchCurve.Backend.Braille maps a 2-by-4 block of raster pixels onto the eight dots of one character.

cell_size_query()

@spec cell_size_query() :: binary()

Returns the escape sequence that asks the terminal for its cell size in pixels.

Write it to the terminal and read the reply back with parse_cell_size/1.

default_cell_px()

@spec default_cell_px() :: cell_px()

Returns the assumed cell size, {10, 20} pixels, for terminals that do not report one.

detect_cell_size(query_io)

@spec detect_cell_size((binary() -> binary() | nil)) :: {:ok, cell_px()} | :error

Asks the terminal for its cell size through query_io and parses the reply.

query_io is a one-argument function; it is called with cell_size_query/0 and must write that to the terminal and return the terminal's raw reply as a binary, or any non-binary if there was none. Returns {:ok, {width, height}} in pixels, or :error when no reply came back or it could not be parsed.

parse_cell_size(reply)

@spec parse_cell_size(binary()) :: {:ok, cell_px()} | :error

Parses a terminal's reply to cell_size_query/0.

Expects a binary containing \e[6;<height>;<width>t; surrounding bytes are ignored. Returns {:ok, {width, height}} in pixels, or :error if the reply does not match. Note that the terminal reports height before width and this returns width first.

pixels_for_cells(region, arg2)

@spec pixels_for_cells(region(), cell_px() | :unknown) ::
  {pos_integer(), pos_integer()}

Returns the pixel size {width, height} of a {cols, rows} region of cells.

Multiplies each dimension by the corresponding cell dimension. Pass :unknown as the cell size to use default_cell_px/0.