A grid is a two-dimensional framebuffer where each cell stores a character (Glyph.t), foreground and background colors (RGBA), text attributes, and a hyperlink. Backed by bigarrays for cache-friendly access.
Single codepoints are stored directly as packed integers. Multi-codepoint grapheme clusters (ZWJ emoji, combining characters) are interned in a reference-counted Glyph.Pool.t. Wide characters span multiple cells: a start cell followed by continuation markers.
When respect_alpha is enabled, colors with alpha < 1.0 are blended with existing cell colors using a perceptual curve. A stack of scissor clipping regions constrains drawing; cells outside the active clip are silently skipped.
The type for rectangular areas in cell coordinates. Covers cells satisfying x <= col < x + width and y <= row < y + height. Non-positive width or height yields an empty region.
active_height g is the number of rows from the top containing non-blank content (character code other than 0 or space). Returns 0 for an empty or cleared grid.
Cell access
Linear index idx is row-major: idx = y * width + x.
is_empty g idx is true iff the cell is the null/empty glyph sentinel. Different from a blank space cell (Glyph.space), which is the default content after create and clear.
hyperlink_url_direct g id is like hyperlink_url but returns "" instead of None.
Manipulation
Sourceval resize : t->width:int ->height:int -> unit
resize g ~width ~height resizes the grid, preserving existing contents where possible. Cells outside the new bounds are released. No-op if dimensions are unchanged.
Raises Invalid_argument if width <= 0 or height <= 0.
clear ~color g resets all cells to spaces with white foreground and color background. color defaults to transparent. Releases all glyph pool references. The scissor stack is preserved.
blit ~src ~dst copies all cell data from src to dst, resizing dst to match. When pools are shared, codes are copied verbatim. When pools differ, each distinct grapheme is re-interned once. No alpha blending.
blit_region ~src ~dst ~src_x ~src_y ~width ~height ~dst_x ~dst_y copies a rectangular region from src to dst.
The region is clamped to valid bounds in both grids. Negative coordinates shift the region inward. Respects the scissor on dst. Alpha blending occurs when dst's respect_alpha is true or source alpha < 1.0. Same-grid overlapping regions are handled correctly. Never resizes dst.
Sourceval fill_rect :
t->x:int ->y:int ->width:int ->height:int ->color:Ansi.Color.t->
unit
fill_rect g ~x ~y ~width ~height ~color fills a rectangle:
Semi-transparent: blends over existing background.
Opaque: overwrites entirely (space glyph, white foreground, color background).
Clipped to grid bounds and scissor.
Drawing
Sourceval draw_text :
?style:Ansi.Style.t->?tab_width:int ->t->x:int ->y:int ->text:string ->
unit
draw_text ~style ~tab_width g ~x ~y ~text draws single-line text. Text is segmented into grapheme clusters using the current width_method. Wide characters occupy multiple cells with continuation markers. Newlines are skipped; tabs expand to tab_width spaces (default 2).
When the resolved background has alpha < 1.0, colors are blended with existing cells. A space on a translucent background preserves the existing glyph and tints its colors.
set_cell g ~x ~y ~glyph ~fg ~bg ~attrs () writes a single cell. blend defaults to the grid's respect_alpha setting; pass ~blend:true to force blending.
Cells outside the grid or scissor are skipped. Existing wide graphemes spanning this cell are cleaned up. The caller is responsible for writing continuation cells for multi-column graphemes.
current_opacity g is the product of all stacked opacities, or 1.0 if the stack is empty.
Scrolling
Sourceval scroll : t->top:int ->bottom:int ->int -> unit
scroll g ~top ~bottom n scrolls rows [top..bottom] by n lines. Positive n scrolls content up (new blank lines at bottom). Negative n scrolls down. Zero is a no-op.
diff_cells prev curr is the (x, y) coordinates of cells that differ. Iterates over the union of both grids' dimensions. Uses epsilon comparison for RGBA. Sorted by row then column.