PNGGIF::Painter
A small QPainter-style 2D rasterizer that draws into a PNGGIF::Bitmap
(RGBA pixels). Backend-agnostic: knows nothing about terminals, cells,
braille or sixel. Extracted from Crysterm, where Graph::Canvas allocates
the bitmap at the native resolution of whatever Media backend the terminal
supports and hands it here; the same paint code renders identically to
braille, sixel, kitty, …
Coordinates are logical. #set_window (logical bounds) and
#set_viewport (device-pixel bounds) define an affine logical→device
map, like QPainter#setWindow/#setViewport: declare your data space
once and draw resolution-independently. With no window set, logical
units equal device pixels.
#pen is the stroke color (0xRRGGBB); #pen_alpha its opacity. X and Y
scale independently (so axis-aligned plots fill the viewport regardless of
the device's pixel aspect); #draw_ellipse additionally honors
#pixel_aspect so circles stay round on non-square backends.
Constants
Device-radius cap for #ellipse: keeps the midpoint algorithm's squared
terms within Int64 and its iteration count bounded on pathological radii.
Off-canvas magnitude for device coordinates. Non-finite or out-of-range
logical inputs map here — well outside any real bitmap, so #plot's
bounds check rejects them — while staying far enough from Int32's limits
that downstream pixel arithmetic (marker/ellipse offsets, Bresenham
deltas) can't itself overflow.
Constructors
Instance methods
Fills the whole bitmap with color (default fully transparent, since translucent pixels leave the terminal untouched).
Draws an axis-aligned ellipse outline centered at logical (cx, cy) with
logical radii (rx, ry). Radii map to device space; #pixel_aspect
corrects the vertical radius so an intended circle stays round on
non-square backends.
Draws a small filled square marker (radius in device pixels) centered on the logical point — a single pixel is too faint for scatter points.
Connects consecutive points with line segments.
Outlines a rectangle (logical x,y = top-left; w,h = size).
Fills an annular sector (ring arc) in device pixels, centered at device
(cx, cy), between r_inner..r_outer radii, over start_deg..
start_deg + sweep_deg. 0° is up (12 o'clock), angles increase
clockwise. Vertical radius is scaled by #pixel_aspect so the ring is
physically round on non-square backends. Works in device space, so the
geometry is independent of any window/viewport.
Sets the stroke color, and recomputes @pen_px so the RGB unpack happens
once per stroke instead of once per plotted pixel.
Sets the stroke opacity, and recomputes the blend-invariant
@pen_af/@pen_ia factors so #plot doesn't redo the /255.0
division per pixel.
Physical width:height of one device pixel (1.0 = square). Used by
#draw_ellipse so an intended circle isn't squashed on backends whose
device pixels aren't square (block/quadrant/sextant).
Physical width:height of one device pixel (1.0 = square). Used by
#draw_ellipse so an intended circle isn't squashed on backends whose
device pixels aren't square (block/quadrant/sextant).
Sets the device viewport in pixels (QPainter#setViewport). Defaults to
the whole bitmap.
Sets the logical coordinate window (QPainter#setWindow): subsequent
draw calls are in these units. A zero extent is clamped to 1 to stay
invertible.