4. The Region

4.1. Region Overview

Regions are rectangular spaces to draw stuff into.

<<typedefs>>=
typedef struct btprnt_region btprnt_region;

A region provides two main things: a local coordinate space, and rectangular clipping.

A region contains the top left coordinate position, the region width, and the region height.

Because of how important regions for user level operations, this struct is actually exposed in the public header, allowing for instances to be allocated on the stack instead of the heap.

<<btprnt_region_struct>>=
struct btprnt_region {
    btprnt_canvas *c;
    int w, h;
    int x, y;
};

4.2. Create a New Region

A new region is created with btprnt_region_new.

<<funcdefs>>=
btprnt_region * btprnt_region_new(btprnt_canvas *c,
                                  int x, int y,
                                  int w, int h);
<<funcs>>=
btprnt_region * btprnt_region_new(btprnt_canvas *c,
                                  int x, int y,
                                  int w, int h)
{
    btprnt_region *r;

    r = calloc(1, sizeof(btprnt_region));

    if (r == NULL) return NULL;

    btprnt_region_init(c, r, x, y, w, h);

    return r;
}

4.3. Freeing a region

It is freed with btprnt_region_del.

<<funcdefs>>=
void btprnt_region_del(btprnt_region **r);
<<funcs>>=
void btprnt_region_del(btprnt_region **r)
{
    if (*r == NULL) return;
    free(*r);
    *r = NULL;
}

4.4. Initializing a Region

If a region is to be allocated on the stack, it needs only to be initialized. This can be done with btprnt_region_init.

<<funcdefs>>=
void btprnt_region_init(btprnt_canvas *c,
                        btprnt_region *r,
                        int x, int y,
                        int w, int h);
<<funcs>>=
void btprnt_region_init(btprnt_canvas *c,
                        btprnt_region *r,
                        int x, int y,
                        int w, int h)
{
    btprnt_region_xpos_set(r, x);
    btprnt_region_ypos_set(r, y);
    btprnt_region_width_set(r, w);
    btprnt_region_height_set(r, h);
    r->c = c;
}

4.5. Setters

The dimensions and position can be changed after it is instantiated.

<<funcdefs>>=
void btprnt_region_xpos_set(btprnt_region *r, int x);
void btprnt_region_ypos_set(btprnt_region *r, int y);
void btprnt_region_width_set(btprnt_region *r, int w);
void btprnt_region_height_set(btprnt_region *r, int h);
<<funcs>>=
void btprnt_region_xpos_set(btprnt_region *r, int x)
{
    r->x = x;
}

void btprnt_region_ypos_set(btprnt_region *r, int y)
{
    r->y = y;
}

void btprnt_region_width_set(btprnt_region *r, int w)
{
    r->w = w;
}

void btprnt_region_height_set(btprnt_region *r, int h)
{
    r->h = h;
}

4.6. Writing a Pixel

4.6.1. Default Write

Drawing utilities write to a region. The region ensures that the pixel is not being written beyond the bounds of itself. The actual placement on the buffer is handled via a canvas.

<<funcdefs>>=
void btprnt_region_draw(btprnt_region *r,
                        int x, int y,
                        int c);

For now, this function will be a little bit overpowered. In the future, it might be better to break this up into different components and flesh out the canvas interface.

<<funcs>>=
void btprnt_region_draw(btprnt_region *r,
                        int x, int y,
                        int c)
{
    btprnt_canvas *cv;
    int gx, gy;

    cv = r->c;

    if (x < 0 || x >= r->w) return;
    if (y < 0 || y >= r->h) return;

    gx = cv->offx + r->x + x;
    if (gx < 0 || gx >= cv->buf->w) return;
    gy = cv->offy + r->y + y;
    if (gy < 0 || gy >= cv->buf->h) return;

    btprnt_buf_write(cv->buf, gx, gy, c);
}

4.6.2. Write with wraparound

This will write a pixel, but will wraparound the region instead of truncating.

<<funcdefs>>=
void btprnt_region_draw_wrap(btprnt_region *r,
                             int x, int y,
                             int c);

Wraparound works by ensuring that X does is within range (0, tw) and Y is in range (0, th), where tw and th are the target widths and heights.

After these local coordinates are found, the global coordinates are factored in by applying the canvas offsets. Hard bounds checking is done here. If they exceed, no drawing is done.

<<funcs>>=
void btprnt_region_draw_wrap(btprnt_region *r,
                             int x, int y,
                             int c)
{
    btprnt_canvas *cv;
    int gx, gy;

    cv = r->c;

    while (x < 0) x += r->w;
    while (x >= r->w) x -= r->w;

    while (y < 0) y += r->h;
    while (y >= r->h) y -= r->h;

    gx = cv->offx + r->x + x;
    if (gx < 0 || gx >= cv->buf->w) return;
    gy = cv->offy + r->y + y;
    if (gy < 0 || gy >= cv->buf->h) return;

    btprnt_buf_write(cv->buf, gx, gy, c);
}

4.7. Reading a Pixel

Get the pixel of the region with coordinates relative to the region with btprnt_region_read.

<<funcdefs>>=
int btprnt_region_read(btprnt_region *r, int x, int y);
<<funcs>>=
int btprnt_region_read(btprnt_region *r, int x, int y)
{
    btprnt_canvas *cv;
    int gx, gy;

    cv = r->c;

    if (x < 0 || x >= r->w) return 0;
    if (y < 0 || y >= r->h) return 0;

    gx = cv->offx + r->x + x;
    if (gx < 0 || gx >= cv->buf->w) return 0;
    gy = cv->offy + r->y + y;
    if (gy < 0 || gy >= cv->buf->h) return 0;

    return btprnt_buf_read(cv->buf, gx, gy);
}



prev | home | next