loadtiles
1. Gesture Notation is Made up Of Tiles
In order to notate gesture structures, the use of tiles
is required, or at the very least, highly encouraged.
The proposed system (which has not been established at
the time of writing) uses a system inspired by brutalist
aesthetics which will be referred to as
brutalist gesture notation
, meaning that notation is
specifically optimized for the medium it lives on: digital
pixels. The symbols, glyphs, and sigils used to describe
Gesture are made up of smaller components, which can be
efficiently maintained as rectangular chunks of pixels
known as tiles
. Tiles that are the same size can be
packed together in a grid in what is known as a tilemap
.
There is more than one way to make a tilemap. The author has opted to use a text editor. Text editors are a familiar keyboard-driven interface, and are suitable enough for making sets of small monochrome tiles. Text also happens to be a very convenient format.
2. The Loadtiles Function
loadtiles
is a function that reads a specially formatted
text file containing data a tilemap
, and assembles it
into a raw in-memory tilemap via a Janet Buffer.
The filename
argument points to the locatino of
the text file containing the tilemap. gwidth
and
gheight
refer to the pixel dimensions of an
individual glyph. cols
and rows
refer to the size
of the tilemap.
Most of this code has already been been implemented
in curated_lglyphs as loadbuf_v2
. This
version aims to clean things up a bit. The goal is to make
this a re-usable component.
(defn loadtiles [filename gwidth gheight cols rows]
(var xpos 0)
(var ypos 0)
(def onbit ((string/bytes "#") 0))
(def offbit ((string/bytes "-") 0))
# btprnt usually does this automatically
# handle non-multiples of 8
# (def stride
# (let (w (* gwidth cols))
# (if (= (% w 8) 0)
# (/ w 8)
# (+ (math/floor (/ w 8)) 1))))
(def total-size
(let (sz (* gwidth gheight cols rows))
(if (= (% sz 8) 0)
(/ sz 8)
(+ (math/floor (/ sz 8)) 1))))
(def stride (* cols gwidth))
(def height (* rows gheight))
#(var buf (buffer/new-filled (* stride height)))
(var buf (buffer/new-filled total-size))
(var f (file/open filename :r))
(var linepos 0)
# turns out janet bitmaps tightly pack bits without
# zero-padding rows up to the nearest byte
(defn pixel [x y s]
(def pos-in-bits (+ (* stride y) x))
(def pos (brshift pos-in-bits 3))
(def bitpos (- pos-in-bits (blshift pos 3)))
(if (= s 1)
(set (buf pos)
(bor (buf pos) (blshift 1 bitpos)))
(set (buf pos)
(band (buf pos) (bnot (blshift 1 bitpos))))))
(loop [line :iterate (:read f :line)]
(var a (string/bytes line))
(if (or (= (a 0) onbit) (= (a 0) offbit))
(do
(if (>= linepos gheight)
# end of glyph. get ready for next glyph.
(do
(set linepos 0)
(set xpos (+ xpos 1))
# possibly go to new road if at the end
(if (>= xpos cols)
(do
(set xpos 0)
(set ypos (+ ypos 1))))))
# add bits to row, then get ready for next row
(for i 0 (length a)
(cond
(>= i gwidth)
'()
(= (a i) offbit)
(pixel
(+ (* xpos gwidth) i)
(+ (* ypos gheight) linepos)
0)
(= (a i) onbit)
(pixel
(+ (* xpos gwidth) i)
(+ (* ypos gheight) linepos)
1))
)
(set linepos (+ linepos 1)))))
(file/close f)
buf)
<<gen-tilemap>>
3. Generating a Tilemap
Initially built while making protosigils, the
gen-tilemap
will load a text file into a btprnt buffer.
In addition to calling loadbits
to load the file into
a Janet buffer, it will also call on drawbits
to actually
place those into a newly allocated btprnt buffer.
(defn gen-tilemap [filename gw gh ncols nrows]
(def buf
(loadtiles filename gw gh ncols nrows))
(def w (* ncols gw))
(def h (* nrows gh))
(def bp (btprnt/new w h))
(btprnt/drawbits
bp buf
@[0 0 w h]
0 0 w h
0 0)
bp)