10. Drawing Operations

10.1. Set Pixel

This operation is the lowest level operation you can do to a framebuffer. It sets a buffer at a particular XY location to a certain color.

10.1.1. Set Pixel in Scheme

This can be called using the function monolith:gfx-pixel-set.

<<gfx_scheme_entries>>=
{"monolith:gfx-pixel-set", pp_pixel_set, 6, 6, {INT,INT,INT}},
<<gfx_scheme_functions>>=
static cell pp_pixel_set(cell p)
{
    int x, y;
    int r, g, b, a;
    monolith_framebuffer *fb;
    monolith_d *m;
    char name[] = "monolith:gfx-pixel-set";

    x = integer_value(name, car(p));
    p = cdr(p);
    y = integer_value(name, car(p));
    p = cdr(p);
    r = integer_value(name, car(p));
    p = cdr(p);
    g = integer_value(name, car(p));
    p = cdr(p);
    b = integer_value(name, car(p));
    p = cdr(p);
    a = integer_value(name, car(p));
    p = cdr(p);
    m = monolith_data_get();
    fb = monolith_fb_get(m);
    if(fb != NULL) {
        monolith_gfx_pixel_set(fb, x, y, monolith_pixel_make(r, g, b, a));
    }
    return UNSPECIFIC;
}

10.1.2. Set Pixel in Janet

<<gfx_janet>>=
static Janet j_gfx_pixel_set(int32_t argc, Janet *argv)
{
    int x, y;
    int r, g, b, a;
    monolith_framebuffer *fb;
    monolith_d *m;

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

    x = janet_unwrap_integer(argv[0]);
    y = janet_unwrap_integer(argv[1]);
    r = janet_unwrap_integer(argv[2]);
    g = janet_unwrap_integer(argv[3]);
    b = janet_unwrap_integer(argv[4]);
    a = janet_unwrap_integer(argv[5]);

    if(fb != NULL) {
        monolith_gfx_pixel_set(fb,
                               x, y,
                               monolith_pixel_make(r, g, b, a));
    }

    return janet_wrap_nil();
}
<<gfx_janet_entries>>=
{
"monolith/gfx-pixel-set",
j_gfx_pixel_set,
"Draws a pixel to the framebuffer."
},

10.2. DONE Copy image

CLOSED: [2019-10-07 Mon 14:58] Copies an image img (or portion of image) to framebuffer fb. The top left position on the framebuffer is stored in the x and y variables, and the offx and offy are the offset coordinates inside the image. If w and h are less than zero, the images full width and height are used.

10.2.1. imgcopy in C

<<gfx_function_declarations>>=
int monolith_gfx_imgcopy(monolith_framebuffer *f,
                         monolith_gfx_img *img,
                         int x, int y,
                         int w, int h,
                         int off_x, int off_y);
<<gfx_functions>>=
int monolith_gfx_imgcopy(monolith_framebuffer *f,
                         monolith_gfx_img *img,
                         int x, int y,
                         int w, int h,
                         int off_x, int off_y)
{
    int ix, iy;
    unsigned int iw, ih;
    unsigned int pos;
    unsigned int maxpos;
    unsigned char *data;
    monolith_pixel p;

    if (img == NULL) return MONOLITH_NOTOK;

    monolith_gfx_img_data(img, &data, NULL);
    monolith_gfx_img_dim(img, &iw, &ih);

    if (w <= 0) w = iw;
    if (h <= 0) h = ih;

    maxpos = iw * ih * 4;

    for (iy = 0; iy < h; iy++) {
        for (ix = 0; ix < w; ix++) {
            pos = 4 * (((iy + off_y) * iw) + (off_x + ix));
            if (pos > maxpos) continue;
            p.r = data[pos];
            p.g = data[pos + 1];
            p.b = data[pos + 2];
            p.a = data[pos + 3];
            monolith_gfx_pixel_set(f, x + ix, y + iy, p);
        }
    }


    return MONOLITH_OK;
}

10.2.2. imgcopy in janet

<<gfx_janet>>=
static Janet j_gfx_imgcopy(int32_t argc, Janet *argv)
{
    monolith_d *m;
    monolith_framebuffer *fb;
    monolith_gfx_img *img;
    int x, y;
    int w, h;
    int off_x, off_y;

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

    img = janet_unwrap_abstract(argv[0]);
    x = janet_unwrap_integer(argv[1]);
    y = janet_unwrap_integer(argv[2]);
    w = janet_unwrap_integer(argv[3]);
    h = janet_unwrap_integer(argv[4]);
    off_x = janet_unwrap_integer(argv[5]);
    off_y = janet_unwrap_integer(argv[6]);

    monolith_gfx_imgcopy(fb, img, x, y, w, h, off_x, off_y);

    return janet_wrap_nil();
}
<<gfx_janet_entries>>=
{
"monolith/gfx-imgcopy",
j_gfx_imgcopy,
"(monolith/gfx-imgcopy img x y w h off_x off_y)\n"
"Copies a region of an image to framebuffer.\n"
},

10.3. DONE Draw Tile

CLOSED: [2019-10-07 Mon 15:07] Copies a tile from an image and places it to an arbitrary location on the framebuffer. It is assumed that the image is a spritesheet.

drawtile will place the image starting on the left corner at the position x and y. The w and h should be the image dimensions for the tile. off_x and off_y are in units relative to the tile size. So, the first tile on the second row would be (1, 0).

10.3.1. drawtile in C

<<gfx_function_declarations>>=
int monolith_gfx_drawtile(monolith_framebuffer *f,
                          monolith_gfx_img *img,
                          int x, int y,
                          int w, int h,
                          int off_x, int off_y);
<<gfx_functions>>=
int monolith_gfx_drawtile(monolith_framebuffer *f,
                          monolith_gfx_img *img,
                          int x, int y,
                          int w, int h,
                          int off_x, int off_y)
{
    return monolith_gfx_imgcopy(f, img,
                                x, y,
                                w, h,
                                off_x * w, off_y * h);
}

10.3.2. drawtile in Janet

<<gfx_janet>>=
static Janet j_gfx_drawtile(int32_t argc, Janet *argv)
{
    monolith_d *m;
    monolith_framebuffer *fb;
    monolith_gfx_img *img;
    int x, y;
    int w, h;
    int off_x, off_y;

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

    img = janet_unwrap_abstract(argv[0]);
    x = janet_unwrap_integer(argv[1]);
    y = janet_unwrap_integer(argv[2]);
    w = janet_unwrap_integer(argv[3]);
    h = janet_unwrap_integer(argv[4]);
    off_x = janet_unwrap_integer(argv[5]);
    off_y = janet_unwrap_integer(argv[6]);

    monolith_gfx_drawtile(fb, img,
                          x, y,
                          w, h,
                          off_x, off_y);

    return janet_wrap_nil();
}
<<gfx_janet_entries>>=
{
"monolith/gfx-drawtile",
j_gfx_drawtile,
"(monolith/gfx-drawtile img x y w h off_x off_y)\n"
"Copies a (w,h) tile from a tileset to framebuffer.\n"
},

10.4. Draw Filled Rectangle

10.4.1. Draw Filled Rectangle in C

<<gfx_function_declarations>>=
void monolith_gfx_rect_fill(monolith_framebuffer *f,
                            int xpos, int ypos,
                            int w, int h,
                            monolith_pixel p);
<<gfx_functions>>=
void monolith_gfx_rect_fill(monolith_framebuffer *f,
                            int xpos, int ypos,
                            int w, int h,
                            monolith_pixel p)
{
    int x, y;

    for (x = 0; x < w; x++) {
        for (y = 0; y < h; y++) {
            monolith_gfx_pixel_set(f,
                                   x + xpos, y + ypos,
                                   p);
        }
    }
}

10.4.2. Draw Filled Rectable in Janet

<<gfx_janet_entries>>=
{
"monolith/gfx-rect-fill",
j_gfx_rect_fill,
"Draws a filled rectangle."
},
<<gfx_janet>>=
static Janet j_gfx_rect_fill(int32_t argc, Janet *argv)
{
    int x, y;
    int w, h;
    int r, g, b;
    monolith_framebuffer *fb;
    monolith_d *m;

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

    x = janet_unwrap_integer(argv[0]);
    y = janet_unwrap_integer(argv[1]);
    w = janet_unwrap_integer(argv[2]);
    h = janet_unwrap_integer(argv[3]);
    r = janet_unwrap_integer(argv[4]);
    g = janet_unwrap_integer(argv[5]);
    b = janet_unwrap_integer(argv[6]);

    if(fb != NULL) {
        monolith_gfx_rect_fill(fb,
                               x, y,
                               w, h,
                               monolith_pixel_make(r, g, b, 255));
    }

    return janet_wrap_nil();
}

10.5. Draw a Line

10.5.1. Draw a Line in C

<<gfx_function_declarations>>=
void monolith_gfx_line(monolith_framebuffer *f,
                       int x1, int y1,
                       int x2, int y2,
                       monolith_pixel p);
<<gfx_functions>>=
static void swap(int *a, int *b)
{
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
}

void monolith_gfx_line(monolith_framebuffer *f,
                       int x0, int y0,
                       int x1, int y1,
                       monolith_pixel p)
{
    int x, y;
    int dx, dy;
    int derror2;
    int error2;
    char steep = 0;

    if(abs(x0 - x1) < abs(y0 - y1)) {
        swap(&x0, &y0);
        swap(&x1, &y1);
        steep = 1;
    }

    if(x0 > x1) {
        swap(&x0, &x1);
        swap(&y0, &y1);
    }

    dx = x1 - x0;
    dy = y1 - y0;
    derror2 = abs(dy) * 2;
    error2 = 0;
    y = y0;

    for(x = x0; x < x1; x++) {
        if(steep) {
            monolith_gfx_pixel_set(f, y, x, p);
        } else {
            monolith_gfx_pixel_set(f, x, y, p);
        }
        error2 += derror2;
        if(error2 > dx) {
            y += (y1 > y0 ? 1 : -1);
            error2 -= dx * 2;
        }
    }
}

10.5.2. Draw a Line in Janet

<<gfx_janet_entries>>=
{
"monolith/gfx-line",
j_gfx_line,
"Draws a line."
},
<<gfx_janet>>=
static Janet j_gfx_line(int32_t argc, Janet *argv)
{
    int x0, y0;
    int x1, y1;
    int r, g, b;
    monolith_framebuffer *fb;
    monolith_d *m;

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

    x0 = janet_unwrap_integer(argv[0]);
    y0 = janet_unwrap_integer(argv[1]);
    x1 = janet_unwrap_integer(argv[2]);
    y1 = janet_unwrap_integer(argv[3]);
    r = janet_unwrap_integer(argv[4]);
    g = janet_unwrap_integer(argv[5]);
    b = janet_unwrap_integer(argv[6]);

    if(fb != NULL) {
        monolith_gfx_line(fb,
                          x0, y0,
                          x1, y1,
                          monolith_pixel_make(r, g, b, 255));
    }

    return janet_wrap_nil();
}

10.6. Color Swap

Takes a rectangular region in a buffer, and swaps two colors out.

10.6.1. Color Swap in C

<<gfx_function_declarations>>=
void monolith_gfx_colorswap(monolith_framebuffer *f,
                            int xpos, int ypos,
                            int w, int h,
                            monolith_pixel c1,
                            monolith_pixel c2);
<<gfx_functions>>=
static int colormatch(monolith_pixel *c1, monolith_pixel *c2)
{
    return
        (c1->r == c2->r) &&
        (c1->g == c2->g) &&
        (c1->b == c2->b);
}

void monolith_gfx_colorswap(monolith_framebuffer *f,
                            int xpos, int ypos,
                            int w, int h,
                            monolith_pixel c1,
                            monolith_pixel c2)
{
    int x, y;
    int rc;
    monolith_pixel p;

    p = c1;
    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            rc = monolith_gfx_pixel_get(f,
                                        xpos + x, ypos + y,
                                        &p);
            if (!rc) continue;

            if (colormatch(&p, &c1)) {
                monolith_gfx_pixel_set(f,
                                       xpos + x, ypos + y,
                                       c2);
            } else if (colormatch(&p, &c2)) {
                monolith_gfx_pixel_set(f,
                                       xpos + x, ypos + y,
                                       c1);
            }
        }
    }
}

10.6.2. Color Swap in Janet

<<gfx_janet_entries>>=
{
"monolith/gfx-colorswap",
j_gfx_colorswap,
"Swap two colors in a rectangular region."
},
<<gfx_janet>>=
static Janet j_gfx_colorswap(int32_t argc, Janet *argv)
{
    int x, y;
    int w, h;
    int rgb1[3];
    int rgb2[3];
    monolith_framebuffer *fb;
    monolith_d *m;

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

    x = janet_unwrap_integer(argv[0]);
    y = janet_unwrap_integer(argv[1]);
    w = janet_unwrap_integer(argv[2]);
    h = janet_unwrap_integer(argv[3]);
    rgb1[0] = janet_unwrap_integer(argv[4]);
    rgb1[1] = janet_unwrap_integer(argv[5]);
    rgb1[2] = janet_unwrap_integer(argv[6]);
    rgb2[0] = janet_unwrap_integer(argv[7]);
    rgb2[1] = janet_unwrap_integer(argv[8]);
    rgb2[2] = janet_unwrap_integer(argv[9]);

    if(fb != NULL) {
        monolith_gfx_colorswap(fb,
                               x, y,
                               w, h,
                               monolith_pixel_make(rgb1[0],
                                                   rgb1[1],
                                                   rgb1[2],
                                                   255),
                               monolith_pixel_make(rgb2[0],
                                                   rgb2[1],
                                                   rgb2[2],
                                                   255));
    }

    return janet_wrap_nil();
}

10.7. Fill

Fill whole buffer with one color.

10.7.1. Fill in C

<<gfx_function_declarations>>=
void monolith_gfx_fill(monolith_framebuffer *f,
                       monolith_pixel c);
<<gfx_functions>>=
void monolith_gfx_fill(monolith_framebuffer *f,
                       monolith_pixel c)
{
    int x, y;
    int w, h;

    w = monolith_gfx_width(f);
    h = monolith_gfx_height(f);

    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            monolith_gfx_pixel_set(f, x, y, c);
        }
    }
}

10.7.2. Fill in Janet

<<gfx_janet_entries>>=
{
"monolith/gfx-fill",
j_gfx_fill,
"Fill entire framebuffer with color."
},
<<gfx_janet>>=
static Janet j_gfx_fill(int32_t argc, Janet *argv)
{
    int r, g, b;
    monolith_framebuffer *fb;
    monolith_d *m;
    monolith_pixel p;

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

    r = janet_unwrap_integer(argv[0]);
    g = janet_unwrap_integer(argv[1]);
    b = janet_unwrap_integer(argv[2]);

    p = monolith_pixel_make(r, g, b, 255);

    if(fb != NULL) {
        monolith_gfx_fill(fb, p);
    }

    return janet_wrap_nil();
}



prev | home | next