13. btprnt + gfx framebuffer

btprnt is a 1-bit grahics library being worked on. A version of it has been absorbed into the monolith.

#include "btprnt/btprnt.h"

13.1. C implementatation

At the moment, most btprnt functionality is managed separately as a janet plugin (sure, Monolith is a monolith, but I'm pacing myself in order to manage scale). Despite it currently being an external janet plugin, it would be ideal to btprnt buffer as a kind of stencil, painting a specific color onto the framebuffer. A value of 1 would draw the color, a value of 0 would not draw anything.

Because of the real world analagy, this function is aptly named gfx_btprnt_stencil.

13.2. Stencil in C

This takes in the following arguments:

x,y: the top left starting point to draw the btprnt stencil.

w,h: the width and height of the space to draw. If these exceed the bounds of the btprnt buffer, these will be ignored.

offx, offy: the starting offset values.

c: the color to use, stored as a monolith_pixel.

void monolith_gfx_btprnt_stencil(monolith_framebuffer *f,
                                 btprnt *b,
                                 int xpos, int ypos,
                                 int w, int h,
                                 int offx, int offy,
                                 monolith_pixel p);

The stencil reads directly from the raw buffer, which can be retrieved with btprnt_buf_get. Data can be retrieved from the buffer using btprnt_buf_read.

Bounds checking will need to be put into place, as the raw reads do not do this.

void monolith_gfx_btprnt_stencil(monolith_framebuffer *f,
                                 btprnt *b,
                                 int xpos, int ypos,
                                 int w, int h,
                                 int offx, int offy,
                                 monolith_pixel p)
    int x, y;
    int bpw, bph;
    btprnt_buf *buf;

    buf = btprnt_buf_get(b);

    bpw = btprnt_buf_width(buf);
    bph = btprnt_buf_height(buf);

    if ((w + offx) > bpw) {
        w -= (w + offx) - bpw;

    if ((h + offy) > bph) {
        h -= (h + offy) - bph;

    if (w <= 0 || h <= 0) return;

    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            if (btprnt_buf_read(buf, x + offx, y + offy)) {
                                       xpos + x,
                                       ypos + y,


13.3. Stencil in Janet

Stencil in janet takes similar arguments to the one in C. RGB values are taken in as individual values.

The btprnt data that comes in is a little bit weird. btprnt is wrapped inside of struct called btprnt_janet. The btprnt can only be accessed using btprnt_janet_btprnt. It's all a little silly because as it turns out, the btprnt data is the only thing in that struct. I think this makes it easier to work with the GC in janet?

"Draws a line."

The way to get the btprnt data is through a function called janet2btprnt_unsafe, which returns the raw C pointer without doing any kind of type checking normally provided. Type checking does not seem to be possible when this function is baked into Monolith, and btprnt is an external Janet plugin.

btprnt * janet2btprnt_unsafe(Janet *argv, int argc);
static Janet j_gfx_btprnt_stencil(int32_t argc, Janet *argv)
    int xpos, ypos;
    int w, h;
    int offx, offy;
    int r, g, b;
    btprnt *bp;
    monolith_framebuffer *fb;
    monolith_d *m;

    janet_fixarity(argc, 10);
    m = monolith_data_get();
    fb = monolith_fb_get(m);

    bp = janet2btprnt_unsafe(argv, 0);
    xpos = janet_unwrap_integer(argv[1]);
    ypos = janet_unwrap_integer(argv[2]);
    w = janet_unwrap_integer(argv[3]);
    h = janet_unwrap_integer(argv[4]);

    offx = janet_unwrap_integer(argv[5]);
    offy = janet_unwrap_integer(argv[6]);

    r = janet_unwrap_integer(argv[7]);
    g = janet_unwrap_integer(argv[8]);
    b = janet_unwrap_integer(argv[9]);

    if(fb != NULL) {
        monolith_gfx_btprnt_stencil(fb, bp,
                          xpos, ypos,
                          w, h,
                          offx, offy,
                          monolith_pixel_make(r, g, b, 255));

    return janet_wrap_nil();

prev | home | next