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
.
{"monolith:gfx-pixel-set", pp_pixel_set, 6, 6, {INT,INT,INT}},
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
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();
}
{
"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
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 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
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();
}
{
"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
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);
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
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();
}
{
"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
void monolith_gfx_rect_fill(monolith_framebuffer *f,
int xpos, int ypos,
int w, int h,
monolith_pixel p);
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
{
"monolith/gfx-rect-fill",
j_gfx_rect_fill,
"Draws a filled rectangle."
},
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
void monolith_gfx_line(monolith_framebuffer *f,
int x1, int y1,
int x2, int y2,
monolith_pixel p);
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
{
"monolith/gfx-line",
j_gfx_line,
"Draws a line."
},
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
void monolith_gfx_colorswap(monolith_framebuffer *f,
int xpos, int ypos,
int w, int h,
monolith_pixel c1,
monolith_pixel c2);
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
{
"monolith/gfx-colorswap",
j_gfx_colorswap,
"Swap two colors in a rectangular region."
},
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
void monolith_gfx_fill(monolith_framebuffer *f,
monolith_pixel c);
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
{
"monolith/gfx-fill",
j_gfx_fill,
"Fill entire framebuffer with color."
},
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