diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/include/kogata/draw.h | 22 | ||||
-rw-r--r-- | src/lib/libkogata/draw.c | 148 |
2 files changed, 158 insertions, 12 deletions
diff --git a/src/lib/include/kogata/draw.h b/src/lib/include/kogata/draw.h index d96f2ee..7eee2ba 100644 --- a/src/lib/include/kogata/draw.h +++ b/src/lib/include/kogata/draw.h @@ -45,8 +45,6 @@ void g_line(fb_t *fb, int x1, int y1, int x2, int y2, color_t c); void g_rect(fb_t *fb, int x, int y, int w, int h, color_t c); void g_fillrect(fb_t *fb, int x, int y, int w, int h, color_t c); -void g_rectregion(fb_t *fb, fb_region_t reg, color_t c); -void g_fillregion(fb_t *fb, fb_region_t reg, color_t c); void g_circle(fb_t *fb, int cx, int cy, int r, color_t c); void g_fillcircle(fb_t *fb, int cx, int cy, int r, color_t c); @@ -56,6 +54,25 @@ void g_blit_region(fb_t *dst, int x, int y, fb_t *src, fb_region_t reg); void g_scroll_up(fb_t *fb, int l); +// ---- Drawing primitives, in a subregion + +void g_region_plot(fb_t *fb, fb_region_t *reg, int x, int y, color_t c); + +void g_region_hline(fb_t *fb, fb_region_t *reg, int x, int y, int w, color_t c); // horizontal line +void g_region_vline(fb_t *fb, fb_region_t *reg, int x, int y, int h, color_t c); // vertical line +void g_region_line(fb_t *fb, fb_region_t *reg, int x1, int y1, int x2, int y2, color_t c); + +void g_region_rect(fb_t *fb, fb_region_t *reg, int x, int y, int w, int h, color_t c); +void g_region_fillrect(fb_t *fb, fb_region_t *reg, int x, int y, int w, int h, color_t c); + +void g_region_circle(fb_t *fb, fb_region_t *reg, int cx, int cy, int r, color_t c); +void g_region_fillcircle(fb_t *fb, fb_region_t *reg, int cx, int cy, int r, color_t c); + +void g_region_blit(fb_t *dst, fb_region_t *reg, int x, int y, fb_t *src); +void g_region_blit_region(fb_t *dst, fb_region_t *dstreg, int x, int y, fb_t *src, fb_region_t srcreg); + +void g_region_scroll_up(fb_t *fb, fb_region_t *reg, int l); + // ---- Text manipulation font_t *g_load_ascii_bitmap_font(const char* filename); @@ -67,6 +84,7 @@ int g_text_width(font_t *f, const char* text, int size); int g_text_height(font_t *f, const char* text, int size); void g_write(fb_t *fb, int x, int y, const char* text, font_t *font, int size, color_t c); +void g_region_write(fb_t *fb, fb_region_t *reg, int x, int y, const char* text, font_t *font, int size, color_t c); /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/lib/libkogata/draw.c b/src/lib/libkogata/draw.c index 14f1dcf..4e5dcf2 100644 --- a/src/lib/libkogata/draw.c +++ b/src/lib/libkogata/draw.c @@ -112,7 +112,7 @@ color_t g_color_rgb(fb_t *f, uint8_t r, uint8_t g, uint8_t b) { return 0; // unknown? } -// ---- Plot +// ---- Drawing functions static inline void g_plot24(uint8_t* p, color_t c) { p[0] = c & 0xFF; @@ -120,7 +120,11 @@ static inline void g_plot24(uint8_t* p, color_t c) { p[2] = (c >> 16) & 0xFF; } -void g_plot(fb_t *fb, int x, int y, color_t c) { +// # Plot # + +inline void g_plot(fb_t *fb, int x, int y, color_t c) { + if (x < 0 || y < 0 || x >= fb->geom.width || y >= fb->geom.height) return; + if (fb->geom.bpp == 8) { fb->data[y * fb->geom.pitch + x] = (c & 0xFF); } else if (fb->geom.bpp == 15 || fb->geom.bpp == 16) { @@ -134,7 +138,22 @@ void g_plot(fb_t *fb, int x, int y, color_t c) { } } -void g_hline(fb_t *fb, int x, int y, int w, color_t c) { +inline void g_region_plot(fb_t *fb, fb_region_t *reg, int x, int y, color_t c) { + if (x < 0 || y < 0 || x >= reg->w || y >= reg->h) return; + g_plot(fb, x + reg->x, y + reg->y, c); +} + + +// # Horizontal line # + +inline void g_hline(fb_t *fb, int x, int y, int w, color_t c) { + if (x < 0) w = w + x, x = 0; + if (x >= fb->geom.width) return; + if (x + w < 0) return; + if (x + w > fb->geom.width) w = fb->geom.width - x; + if (y < 0 || y >= fb->geom.height) return; + if (w <= 0) return; + if (fb->geom.bpp == 8) { for (int u = x; u < x + w; u++) { fb->data[y * fb->geom.pitch + u] = (c & 0xFF); @@ -151,12 +170,33 @@ void g_hline(fb_t *fb, int x, int y, int w, color_t c) { } else if (fb->geom.bpp == 32) { for (int u = x; u < x + w; u++) { uint32_t *p = (uint32_t*)(fb->data + y * fb->geom.pitch + 4 * u); - *p = c; + *p = c | 0xFF000000; // alpha = 0xFF } } } -void g_vline(fb_t *fb, int x, int y, int h, color_t c) { +inline void g_region_hline(fb_t *fb, fb_region_t *reg, int x, int y, int w, color_t c) { + if (x < 0) w = w + x, x = 0; + if (x >= reg->w) return; + if (x + w < 0) return; + if (x + w > reg->w) w = reg->w - x; + if (y < 0 || y >= reg->h) return; + if (w <= 0) return; + + g_hline(fb, reg->x + x, reg->y + y, w, c); +} + + +// # Vertical line # + +inline void g_vline(fb_t *fb, int x, int y, int h, color_t c) { + if (y < 0) h = h + y, y = 0; + if (y >= fb->geom.height) return; + if (y + h < 0) return; + if (y + h > fb->geom.width) h = fb->geom.height - y; + if (x < 0 || x >= fb->geom.width) return; + if (h <= 0) return; + if (fb->geom.bpp == 8) { for (int v = y; v < y + h; v++) { fb->data[v * fb->geom.pitch + x] = (c & 0xFF); @@ -178,10 +218,31 @@ void g_vline(fb_t *fb, int x, int y, int h, color_t c) { } } +inline void g_region_vline(fb_t *fb, fb_region_t *reg, int x, int y, int h, color_t c) { + if (y < 0) h = h + y, y = 0; + if (y >= reg->h) return; + if (y + h < 0) return; + if (y + h > reg->h) h = reg->h - y; + if (x < 0 || x >= reg->h) return; + if (h <= 0) return; + + g_vline(fb, reg->x + x, reg->y + y, h, c); +} + + +// # Line # + void g_line(fb_t *fb, int x1, int y1, int x2, int y2, color_t c) { // TODO } +void g_region_line(fb_t *fb, fb_region_t *reg, int x1, int y1, int x2, int y2, color_t c) { + // TODO +} + + +// # Rectangle # + void g_rect(fb_t *fb, int x, int y, int w, int h, color_t c) { g_hline(fb, x, y, w, c); g_hline(fb, x, y+h-1, w, c); @@ -189,7 +250,25 @@ void g_rect(fb_t *fb, int x, int y, int w, int h, color_t c) { g_vline(fb, x+w-1, y, h, c); } +void g_region_rect(fb_t *fb, fb_region_t *reg, int x, int y, int w, int h, color_t c) { + g_region_hline(fb, reg, x, y, w, c); + g_region_hline(fb, reg, x, y+h-1, w, c); + g_region_vline(fb, reg, x, y, h, c); + g_region_vline(fb, reg, x+w-1, y, h, c); +} + + +// # Filled rectangle # + void g_fillrect(fb_t *fb, int x, int y, int w, int h, color_t c) { + if (x < 0) w = w + x, x = 0; + if (y < 0) h = h + y, y = 0; + + if (x + w > fb->geom.width) w = fb->geom.width - x; + if (y + h > fb->geom.height) h = fb->geom.height - y; + + if (w <= 0 || h <= 0) return; + if (fb->geom.bpp == 8) { for (int v = y; v < y + h; v++) { for (int u = x; u < x + w; u++) { @@ -219,22 +298,43 @@ void g_fillrect(fb_t *fb, int x, int y, int w, int h, color_t c) { } } -void g_rectregion(fb_t *fb, fb_region_t reg, color_t c) { - g_rect(fb, reg.x, reg.y, reg.w, reg.h, c); -} +void g_region_fillrect(fb_t *fb, fb_region_t *reg, int x, int y, int w, int h, color_t c) { + if (x < 0) w = w + x, x = 0; + if (y < 0) h = h + y, y = 0; + + if (x + w > reg->w) w = reg->w - x; + if (y + h > reg->h) h = reg->h - y; -void g_fillregion(fb_t *fb, fb_region_t reg, color_t c) { - g_fillrect(fb, reg.x, reg.y, reg.w, reg.h, c); + if (w <= 0 || h <= 0) return; + + g_fillrect(fb, x + reg->x, y + reg->y, w, h, c); } + +// # Circle # + void g_circle(fb_t *fb, int cx, int cy, int r, color_t c) { // TODO } +void g_region_circle(fb_t *fb, fb_region_t *reg, int cx, int cy, int r, color_t c) { + // TODO +} + + +// # Filled circle # + void g_fillcircle(fb_t *fb, int cx, int cy, int r, color_t c) { // TODO } +void g_region_fillcircle(fb_t *fb, fb_region_t *reg, int cx, int cy, int r, color_t c) { + // TODO +} + + +// # Blit # + void g_blit(fb_t *dst, int x, int y, fb_t *src) { fb_region_t r; @@ -246,6 +346,17 @@ void g_blit(fb_t *dst, int x, int y, fb_t *src) { g_blit_region(dst, x, y, src, r); } +void g_region_blit(fb_t *dst, fb_region_t *reg, int x, int y, fb_t *src) { + fb_region_t r; + + r.x = 0; + r.y = 0; + r.w = src->geom.width; + r.h = src->geom.height; + + g_region_blit_region(dst, reg, x, y, src, r); +} + void g_blit_region(fb_t *dst, int x, int y, fb_t *src, fb_region_t reg) { if (x < 0 || y < 0 || reg.x < 0 || reg.y < 0 || reg.w < 0 || reg.h < 0) return; // invalid argument @@ -311,6 +422,15 @@ void g_blit_region(fb_t *dst, int x, int y, fb_t *src, fb_region_t reg) { } } +void g_region_blit_region(fb_t *dst, fb_region_t *reg, int x, int y, fb_t *src, fb_region_t r) { + if (x + r.w > reg->w) r.w = reg->w - x; + if (y + r.h > reg->h) r.h = reg->h - y; + + g_blit_region(dst, x + reg->x, y + reg->y, src, r); +} + +// # Scroll # + void g_scroll_up(fb_t *dst, int l) { for (int y = 0; y < dst->geom.height - l; y++) { memcpy(dst->data + y * dst->geom.pitch, @@ -319,6 +439,10 @@ void g_scroll_up(fb_t *dst, int l) { } } +void g_region_scroll_up(fb_t *fb, fb_region_t *reg, int l) { + // TODO +} + // ---- Text manipulation #define FONT_ASCII_BITMAP 1 @@ -562,5 +686,9 @@ void g_write(fb_t *fb, int x, int y, const char* text, font_t *font, int size, c } } +void g_region_write(fb_t *fb, fb_region_t *reg, int x, int y, const char* text, font_t *font, int size, color_t c) { + // TODO +} + /* vim: set ts=4 sw=4 tw=0 noet :*/ |