11. Rounded Rectangle

This rounded rectangle is based off of the algorithm used in the Adafruit graphics library.

11.1. Stroked Rounded Rectangle

<<funcdefs>>=
void btprnt_draw_roundrect(btprnt_region *reg,
                           int x, int y,
                           int w, int h,
                           int r,
                           int clr);
<<funcs>>=
static void quadcirc(btprnt_region *reg,
                     int x0, int y0,
                     int r,
                     int corner,
                     int clr)
{
    int f;
    int ddf_x;
    int ddf_y;
    int x;
    int y;

    f = 1 - r;
    ddf_x = 1;
    ddf_y = -2 * r;
    x = 0;
    y = r;

    while (x < y) {
        if (f >= 0) {
            y--;
            ddf_y += 2;
            f += ddf_y;
        }

        x++;
        ddf_x += 2;
        f += ddf_x;

        if (corner & 0x4) {
            btprnt_region_draw(reg, x0 + x, y0 + y, clr);
            btprnt_region_draw(reg, x0 + y, y0 + x, clr);
        }

        if (corner & 0x2) {
            btprnt_region_draw(reg, x0 + x, y0 - y, clr);
            btprnt_region_draw(reg, x0 + y, y0 - x, clr);
        }

        if (corner & 0x8) {
            btprnt_region_draw(reg, x0 - y, y0 + x, clr);
            btprnt_region_draw(reg, x0 - x, y0 + y, clr);
        }

        if (corner & 0x1) {
            btprnt_region_draw(reg, x0 - y, y0 - x, clr);
            btprnt_region_draw(reg, x0 - x, y0 - y, clr);
        }
    }
}

void btprnt_draw_roundrect(btprnt_region *reg,
                           int x, int y,
                           int w, int h,
                           int r,
                           int clr)
{
    btprnt_draw_hline(reg, x + r, y, w - 2 * r, clr);
    btprnt_draw_hline(reg, x + r, y + h - 1, w - 2 * r, clr);
    btprnt_draw_vline(reg, x, y + r, h - 2 * r, clr);
    btprnt_draw_vline(reg, x + w - 1, y + r, h - 2 * r, clr);

    quadcirc(reg, x + r, y + r, r, 1, clr);
    quadcirc(reg, x + w - r - 1, y + r, r, 2, clr);
    quadcirc(reg, x + w - r - 1, y + h - r - 1, r, 4, clr);
    quadcirc(reg, x + r, y + h - r - 1, r, 8, clr);
}

11.2. Filled Rounded Rectangle

<<funcdefs>>=
void btprnt_draw_roundrect_filled(btprnt_region *r,
                                  int x, int y,
                                  int w, int h,
                                  int rad,
                                  int clr);
<<funcs>>=
static void quadcirc_filled(btprnt_region *reg,
                            int x0, int y0, int r,
                            int corner, int delta,
                            int clr)
{
    int f;
    int ddf_x;
    int ddf_y;
    int x;
    int y;
    int px;
    int py;

    f = 1 - r;
    ddf_x = 1;
    ddf_y = -2 * r;
    x = 0;
    y = r;
    px = x;
    py = y;

    delta++;

    while (x < y) {
        if (f >= 0) {
            y--;
            ddf_y += 2;
            f += ddf_y;
        }

        x++;
        ddf_x += 2;
        f += ddf_x;

        if (x < (y + 1)) {
            if (corner & 1) {
                btprnt_draw_vline(reg,
                                  x0 + x, y0 - y,
                                  2 * y + delta, clr);
            }

            if (corner & 2) {
                btprnt_draw_vline(reg,
                                  x0 - x, y0 - y,
                                  2 * y + delta, clr);
            }
        }
        if (y != py) {
            if (corner & 1) {
                btprnt_draw_vline(reg,
                                  x0 + py, y0 - px,
                                  2 * px + delta, clr);
            }

            if (corner & 2) {
                btprnt_draw_vline(reg,
                                  x0 - py, y0 - px,
                                  2 * px + delta, clr);
            }

            py = y;
        }
        px = x;
    }
}

void btprnt_draw_roundrect_filled(btprnt_region *reg,
                                  int x, int y,
                                  int w, int h,
                                  int r,
                                  int clr)
{
  int max_radius = ((w < h) ? w : h) / 2;
  if (r > max_radius)
    r = max_radius;
  btprnt_draw_rect_filled(reg, x + r, y, w - 2 * r, h, clr);
  quadcirc_filled(reg,
                  x + w - r - 1, y + r,
                  r, 1, h - 2 * r - 1, clr);
  quadcirc_filled(reg,
                  x + r, y + r,
                  r, 2, h - 2 * r - 1, clr);
}



prev | home | next