Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

doc.gno

2.59 Kb · 52 lines
 1// Package art is the primitive layer for ASCII, ANSI and pixel art in a realm.
 2//
 3// A realm's Render returns one string and nothing tells the caller what kind of
 4// string it is, so every realm picks markdown and every terminal reader eats the
 5// syntax as noise. This package owns the half of that problem that is about
 6// pictures: it holds art in a form that can be emitted as plain text, as ANSI
 7// truecolour, or as SVG, and lets the caller choose at render time.
 8//
 9// # Two types, seen twice
10//
11// [Pix] is an indexed bitmap: a width, a height, one palette index per pixel,
12// and a [Palette] of hex colours. It is what a pixel-art NFT actually is.
13//
14// [Canvas] is a grid of [Cell], each carrying a rune and a foreground and
15// background colour. It is what a terminal actually is.
16//
17// The conversion between them is the point of the package. [Pix.Canvas] takes a
18// [Mode] and produces a Canvas; [Canvas.Text], [Canvas.ANSI] and [Canvas.SVG]
19// take it the rest of the way out.
20//
21// # Use Glyphs for sprites, Ramp for photos
22//
23// The obvious conversion, a luminance ramp, produces mush for pixel art.
24//
25// Measured on Settler #25, a 32x32 sprite on mainnet with 20 palette colours: a
26// ten-step luminance ramp resolves those 20 to 9, so eleven of the artist's
27// colours stop existing. The collisions are not between near-identical shades
28// either. The orange hat (#f08a2a, luminance 152) and the sky-blue tunic
29// (#3f8fd1, luminance 130) land in the same bucket and come out as the same
30// character, because luminance cannot tell a hue from a hue.
31//
32// Indexed art already carries its own segmentation, in the palette. So the right
33// rule for a sprite is one glyph per palette index ([Glyphs]), not one glyph per
34// brightness ([Ramp]). Ramp is kept because it is right for a photograph, where
35// there is no meaningful palette to key on.
36//
37// # ANSI is a terminal-only target, by construction
38//
39// [Canvas.ANSI] emits SGR escape sequences. Those cannot reach gnoweb: raw ESC
40// in a code fence is garbage in HTML, and gno.land/p/nt/markdown/sanitize strips
41// control bytes anyway. That is not a gap to close later, it is the reason the
42// target is a parameter instead of a decision. When colour has to survive the
43// web, use [Canvas.SVG] or [Pix.SVG], which carry the same colours through a
44// medium gnoweb can actually show.
45//
46// # Colours are packed ints
47//
48// A colour is an int holding 0xRRGGBB, or [Default] (-1) meaning "whatever the
49// consumer's default is": the terminal's default foreground for an FG, and
50// transparent for a background in SVG. [ParseHex] turns "#rrggbb" or "#rgb"
51// into one.
52package art