aboutsummaryrefslogtreecommitdiff
path: root/src/lib/libkogata/draw.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libkogata/draw.c')
-rw-r--r--src/lib/libkogata/draw.c104
1 files changed, 95 insertions, 9 deletions
diff --git a/src/lib/libkogata/draw.c b/src/lib/libkogata/draw.c
index 29cae31..2db0d1d 100644
--- a/src/lib/libkogata/draw.c
+++ b/src/lib/libkogata/draw.c
@@ -9,6 +9,14 @@
#include <kogata/syscall.h>
#include <kogata/draw.h>
+// ----
+
+#define STB_IMAGE_IMPLEMENTATION
+#define STBI_NO_HDR
+#include "stb/stb_image.h"
+
+// ----
+
fb_t *g_fb_from_file(fd_t file, fb_info_t *geom) {
fb_t *ret = (fb_t*)malloc(sizeof(fb_t));
if (ret == 0) return 0;
@@ -46,6 +54,32 @@ fb_t *g_fb_from_mem(uint8_t* data, fb_info_t *geom, bool own_data) {
return ret;
}
+fb_t *g_load_image(const char* filename) {
+ int w, h, n;
+ uint8_t *data = stbi_load(filename, &w, &h, &n, 0);
+ if (data == NULL) {
+ return NULL;
+ }
+
+ fb_info_t geom;
+ geom.width = w;
+ geom.height = h;
+ geom.pitch = w * n;
+ geom.bpp = n * 8;
+ if (n == 1) geom.memory_model = FB_MM_GREY8;
+ if (n == 2) geom.memory_model = FB_MM_GA16;
+ if (n == 3) geom.memory_model = FB_MM_RGB24;
+ if (n == 4) geom.memory_model = FB_MM_RGBA32;
+
+ fb_t *fb = g_fb_from_mem(data, &geom, true);
+ if (fb == NULL) {
+ free(data);
+ return NULL;
+ }
+
+ return fb;
+}
+
void g_incref_fb(fb_t *fb) {
fb->nrefs++;
}
@@ -210,20 +244,75 @@ void g_blit(fb_t *dst, int x, int y, fb_t *src) {
}
void g_blit_region(fb_t *dst, int x, int y, fb_t *src, fb_region_t reg) {
- if (src->geom.memory_model == dst->geom.memory_model) {
- for (uint32_t i = 0; i < reg.h; i++) {
+ if (x < 0 || y < 0 || reg.x < 0 || reg.y < 0 || reg.w < 0 || reg.h < 0) return; // invalid argument
+
+ if (reg.x + reg.w > src->geom.width) reg.w = src->geom.width - reg.x;
+ if (reg.y + reg.h > src->geom.height) reg.h = src->geom.height - reg.y;
+ if (reg.w <= 0 || reg.h <= 0) return;
+
+ if (x + reg.w > dst->geom.width) reg.w = dst->geom.width - x;
+ if (y + reg.h > dst->geom.height) reg.h = dst->geom.height - y;
+ if (reg.w <= 0 || reg.h <= 0) return;
+
+ dbg_printf("Src: 0x%p, dst: 0x%p, x: %d, y: %d, rx: %d, ry: %d, rw: %d, rh: %d\n",
+ src->data, dst->data, x, y, reg.x, reg.y, reg.w, reg.h);
+
+ if (src->geom.memory_model == dst->geom.memory_model
+ && src->geom.memory_model != FB_MM_RGBA32
+ && src->geom.memory_model != FB_MM_GA16) {
+ for (int i = 0; i < reg.h; i++) {
memcpy(
dst->data + (y + i) * dst->geom.pitch + x * (dst->geom.bpp / 8),
src->data + (reg.y + i) * src->geom.pitch + reg.x * (src->geom.bpp / 8),
reg.w * (src->geom.bpp / 8));
}
+ } else if (src->geom.memory_model == FB_MM_RGBA32 && dst->geom.memory_model == FB_MM_RGB32) {
+ for (int i = 0; i < reg.h; i++) {
+ uint8_t *dln = dst->data + (y + i) * dst->geom.pitch + x * 4;
+ uint8_t *sln = src->data + (reg.y + i) * src->geom.pitch + reg.x * 4;
+ uint32_t *dln32 = (uint32_t*) dln;
+ uint32_t *sln32 = (uint32_t*) sln;
+ for (int j = 0; j < reg.w; j++) {
+ uint8_t a = sln[4*j+3];
+ if (a == 0xFF) {
+ dln32[j] = sln32[j];
+ } else if (a > 0) {
+ uint16_t r = (0x100 - a) * (uint16_t)dln[4*j] + a * (uint16_t)sln[4*j];
+ uint16_t g = (0x100 - a) * (uint16_t)dln[4*j+1] + a * (uint16_t)sln[4*j+1];
+ uint16_t b = (0x100 - a) * (uint16_t)dln[4*j+2] + a * (uint16_t)sln[4*j+2];
+ dln[4*j] = r >> 8;
+ dln[4*j+1] = g >> 8;
+ dln[4*j+2] = b >> 8;
+ }
+ }
+ }
+ } else if (src->geom.memory_model == FB_MM_RGBA32 && dst->geom.memory_model == FB_MM_RGB24) {
+ for (int i = 0; i < reg.h; i++) {
+ uint8_t *dln = dst->data + (y + i) * dst->geom.pitch + x * 4;
+ uint8_t *sln = src->data + (reg.y + i) * src->geom.pitch + reg.x * 4;
+ for (int j = 0; j < reg.w; j++) {
+ uint8_t a = sln[4*j+3];
+ if (a == 0xFF) {
+ dln[3*j] = sln[4*j];
+ dln[3*j+1] = sln[4*j+1];
+ dln[3*j+2] = sln[4*j+2];
+ } else if (a > 0) {
+ uint16_t r = (0x100 - a) * (uint16_t)dln[3*j] + a * (uint16_t)sln[4*j];
+ uint16_t g = (0x100 - a) * (uint16_t)dln[3*j+1] + a * (uint16_t)sln[4*j+1];
+ uint16_t b = (0x100 - a) * (uint16_t)dln[3*j+2] + a * (uint16_t)sln[4*j+2];
+ dln[3*j] = r >> 8;
+ dln[3*j+1] = g >> 8;
+ dln[3*j+2] = b >> 8;
+ }
+ }
+ }
} else {
- dbg_printf("Unsupported blit between different memory models.\n");
+ dbg_printf("Unsupported blit between different memory models %d and %d.\n", src->geom.memory_model, dst->geom.memory_model);
}
}
void g_scroll_up(fb_t *dst, int l) {
- for (unsigned y = 0; y < dst->geom.height - l; y++) {
+ for (int y = 0; y < dst->geom.height - l; y++) {
memcpy(dst->data + y * dst->geom.pitch,
dst->data + (y + l) * dst->geom.pitch,
dst->geom.pitch);
@@ -284,11 +373,8 @@ error:
return 0;
}
-font_t *g_load_font(const char* fontname) {
- char buf[128];
-
- snprintf(buf, 128, "sys:/fonts/%s.bf", fontname);
- fd_t f = sc_open(buf, FM_READ);
+font_t *g_load_font(const char* filename) {
+ fd_t f = sc_open(filename, FM_READ);
if (f != 0) return g_load_ascii_bitmap_font(f);
return 0;