Class ui.CanvasViewport

A viewport that maps a virtual coordinate space onto a Canvas.

This viewport is useful if a canvas is displayed in a TUI panel for example and you want to draw using a fixed logical coordinate system that is independent of the actual canvas pixel dimensions. The viewport applies a linear transformation to map virtual coordinates to the underlying canvas pixel coordinates, optionally preserving aspect ratio with letterboxing/pillarboxing.

Responsibility: pure coordinate transformation. This class translates drawing calls expressed in a user-defined virtual pixel space into the underlying Canvas's physical pixel space. It owns no scene data and records no operations; the caller is responsible for re-issuing draw calls whenever the canvas dimensions change (e.g. on panel resize).

What it is NOT:

  • Not a scene graph or display list. It does not remember what was drawn.
  • Not responsible for creating or managing the Canvas lifetime.
  • Not responsible for rendering or writing to the terminal.

Virtual coordinate space: Coordinates are 0-based, with origin (0, 0) at the top-left, x increasing to the right and y increasing downward — matching the Canvas pixel convention. The virtual space has a fixed logical size (width × height) set at construction. Drawing calls use these logical coordinates regardless of the physical canvas dimensions.

Scale modes: When the virtual aspect ratio does not match the physical canvas pixel aspect ratio, the viewport applies one of the following scale modes:

  • scale_modes.stretch: x and y are scaled independently to fill the canvas exactly. The image may be distorted.
  • scale_modes.fit: uniform scale so the virtual space fits entirely within the canvas. Unused bands (letterbox / pillarbox) are left blank. No clipping.
  • scale_modes.fill: uniform scale so the virtual space fills the canvas completely. Content that falls outside the canvas bounds is clipped (silently ignored, matching Canvas out-of-bounds behaviour).

Resize handling: The viewport holds a reference to a Canvas. When the panel is resized, the caller should replace the canvas via set_canvas and then re-issue all drawing calls.

Example usage:

local Canvas = require "terminal.ui.canvas"
local CanvasViewport = require "terminal.ui.canvasviewport"

-- Inside a Panel content callback, called on every render (including resize):
local c = Canvas({ width = panel.inner_width, height = panel.inner_height })
local vp = CanvasViewport({
  canvas = c, width = 300, height = 300,
  scale_mode = CanvasViewport.scale_modes.fit,
  anchor = CanvasViewport.anchors.center,
})
vp:line({ x1 = 0, y1 = 0, x2 = 299, y2 = 299 })  -- diagonal in virtual space
-- position cursor and write c:render() as usual

Fields

ui.canvasviewport.anchors Anchor constants; center or top_left determine the alignment of the virtual space within the canvas when scale_mode is fit or fill.
ui.canvasviewport.scale_modes Scale mode constants; stretch, fit, or fill determine how the virtual coordinate space is mapped to the underlying canvas when their aspect ratios do not match.

Methods

ui.canvasviewport:arc (opts) Draw an arc using virtual-space coordinates.
ui.canvasviewport:circle (opts) Draw a circle using virtual-space coordinates.
ui.canvasviewport:ellipse (opts) Draw an ellipse using virtual-space coordinates.
ui.canvasviewport:get_scale () Return the current scale factors applied to virtual coordinates.
ui.canvasviewport:init (opts) Create a new CanvasViewport.
ui.canvasviewport:line (opts) Draw a line between two virtual-space pixels.
ui.canvasviewport:polygon (opts) Draw a polygon from an array of virtual-space {x, y} points.
ui.canvasviewport:set (x, y) Set (illuminate) a pixel at a virtual coordinate.
ui.canvasviewport:set_canvas (canvas) Replace the underlying canvas.
ui.canvasviewport:unset (x, y) Clear (extinguish) a pixel at a virtual coordinate.


Fields

ui.canvasviewport.anchors
Anchor constants; center or top_left determine the alignment of the virtual space within the canvas when scale_mode is fit or fill. With center the virtual space is centered in the canvas, and with top_left the virtual space is aligned to the top-left corner of the canvas. This has no effect when scale_mode is stretch since the virtual space always fills the canvas in that mode.
ui.canvasviewport.scale_modes
Scale mode constants; stretch, fit, or fill determine how the virtual coordinate space is mapped to the underlying canvas when their aspect ratios do not match.

Methods

ui.canvasviewport:arc (opts)
Draw an arc using virtual-space coordinates. Scales the centre and radii into physical canvas pixels, then delegates to Canvas:arc. Angles are passed through unchanged; they describe the same geometric direction regardless of scale.

Note: angles are drawn clockwise, see Canvas:arc for details.

Parameters:

  • opts
    • x number Centre virtual pixel column, 0-based.
    • y number Centre virtual pixel row, 0-based.
    • rx number Horizontal radius in virtual pixels.
    • ry number Vertical radius in virtual pixels.
    • angle_start number Start angle in radians.
    • angle_end number End angle in radians (must be >= angle_start).
    • erase boolean If truthy, unset pixels instead of setting them. (default false)
ui.canvasviewport:circle (opts)
Draw a circle using virtual-space coordinates. Convenience wrapper around ellipse with equal horizontal and vertical radii. With scale_modes.fit or scale_modes.fill the uniform scale preserves the circular shape. With scale_modes.stretch the circle maps to an ellipse on the canvas.

Parameters:

  • opts
    • x number Centre virtual pixel column, 0-based.
    • y number Centre virtual pixel row, 0-based.
    • r number Radius in virtual pixels.
    • fill boolean If truthy, fill the interior. (default false)
    • erase boolean If truthy, unset pixels instead of setting them. (default false)
ui.canvasviewport:ellipse (opts)
Draw an ellipse using virtual-space coordinates. The virtual radii are scaled independently per axis, so a circle in virtual space becomes an ellipse on the canvas when scale_mode is scale_modes.stretch.

Parameters:

  • opts
    • x number Centre virtual pixel column, 0-based.
    • y number Centre virtual pixel row, 0-based.
    • rx number Horizontal radius in virtual pixels.
    • ry number Vertical radius in virtual pixels.
    • fill boolean If truthy, fill the interior. (default false)
    • erase boolean If truthy, unset pixels instead of setting them. (default false)
ui.canvasviewport:get_scale ()
Return the current scale factors applied to virtual coordinates. Useful for callers that need to reason about resolution (e.g. to decide whether to simplify a dense dataset before drawing).

Returns:

  1. number sx Scale factor applied to x (physicalpx / virtualpx).
  2. number sy Scale factor applied to y (physicalpx / virtualpx).
ui.canvasviewport:init (opts)
Create a new CanvasViewport. Do not call this method directly, call on the class instead.

Parameters:

  • opts
    • canvas Canvas The underlying Canvas to draw into.
    • width number Virtual space width in logical pixels.
    • height number Virtual space height in logical pixels.
    • scale_mode string One of CanvasViewport.scale_modes. (default scale_modes.stretch)
    • anchor string Alignment of the virtual space within the canvas when scale_mode is scale_modes.fit or scale_modes.fill. One of CanvasViewport.anchors. (default anchors.center)

Usage:

    local vp = CanvasViewport({
      canvas = c,
      width = 300,
      height = 300,
      scale_mode = CanvasViewport.scale_modes.fit,
      anchor = CanvasViewport.anchors.center,
    })
ui.canvasviewport:line (opts)
Draw a line between two virtual-space pixels.

Parameters:

  • opts
    • x1 number Start virtual pixel column, 0-based.
    • y1 number Start virtual pixel row, 0-based.
    • x2 number End virtual pixel column, 0-based.
    • y2 number End virtual pixel row, 0-based.
    • erase boolean If truthy, unset pixels instead of setting them. (default false)
ui.canvasviewport:polygon (opts)
Draw a polygon from an array of virtual-space {x, y} points. 1 point draws a dot, 2 points draw a line, 3+ points draw a closed polygon by default.

Parameters:

  • opts
    • points table Array of {x, y} virtual pixel coordinate pairs, 0-based.
    • open boolean If truthy, do not close the path back to the first point. (default false)
    • fill boolean If truthy, fill the interior of the polygon. (default false)
    • erase boolean If truthy, unset pixels instead of setting them. (default false)
ui.canvasviewport:set (x, y)
Set (illuminate) a pixel at a virtual coordinate. Out-of-bounds virtual coordinates (after mapping) are silently ignored.

Parameters:

  • x number Virtual pixel column, 0-based.
  • y number Virtual pixel row, 0-based.
ui.canvasviewport:set_canvas (canvas)
Replace the underlying canvas. Call this when the panel has been resized and a new Canvas has been created with updated dimensions. Scale factors are recomputed immediately.

Parameters:

  • canvas Canvas The new Canvas instance.
ui.canvasviewport:unset (x, y)
Clear (extinguish) a pixel at a virtual coordinate. Out-of-bounds virtual coordinates (after mapping) are silently ignored.

Parameters:

  • x number Virtual pixel column, 0-based.
  • y number Virtual pixel row, 0-based.
generated by LDoc 1.5.0