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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

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