aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2025-04-29 19:23:04 -0400
committerSam Anthony <sam@samanthony.xyz>2025-04-29 19:23:04 -0400
commit0e48f9ed9065ecf58944caa770f72d72f8a6dbe6 (patch)
treedd83286b4eeef3219882504186b1f6b15b399fa0
parentbbae94cdb3e6ab5eab6e57dacc26495184a47eee (diff)
downloadvolute-0e48f9ed9065ecf58944caa770f72d72f8a6dbe6.zip
canvas
-rw-r--r--renderer.c126
-rw-r--r--renderer.h2
2 files changed, 124 insertions, 4 deletions
diff --git a/renderer.c b/renderer.c
index 6c5782f..e832c81 100644
--- a/renderer.c
+++ b/renderer.c
@@ -25,7 +25,22 @@ enum window {
RENDERFLAGS = SDL_RENDERER_PRESENTVSYNC,
};
-enum { ICONLIST_SIZE = 32 };
+enum {
+ ICONLIST_SIZE = 32,
+ CANVASLIST_SIZE = 4,
+};
+
+enum { CIRCLE_RADIUS = 16 };
+
+enum rgb {
+ RGBA_DEPTH = 4*4,
+
+ RGB_RED = 0xFu << 3,
+ RGB_GREEN = 0xFu << 2,
+ RGB_BLUE = 0xFu << 1,
+
+ RGBA_BYTES_PER_PIXEL = RGBA_DEPTH / 8,
+};
static const char FONT[] = "font/P052-Roman.ttf";
enum font { FONTSIZE = 14, };
@@ -49,10 +64,15 @@ static const char key_map[256] = {
[SDLK_BACKSPACE & 0xff] = MU_KEY_BACKSPACE,
};
-mu_stack(SDL_Texture *, ICONLIST_SIZE) icon_list;
+
+typedef struct {
+ SDL_Surface *bg, *fg, *dst;
+ int icon_id;
+} Canvas;
static void print_info(void);
+static int draw_circle(void);
static int text_width(mu_Font mufont, const char *str, int len);
static int text_height(mu_Font mufont);
static void handle_event(SDL_Event e, mu_Context *ctx);
@@ -62,10 +82,18 @@ static void clip(mu_Rect rect);
static void draw_rect(mu_Rect rect, mu_Color color);
static void draw_text(mu_Font font, mu_Vec2 pos, mu_Color color, const char *str);
static void draw_icon(int id, mu_Rect r);
+static void free_canvas(Canvas c);
+
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
+mu_stack(SDL_Texture *, ICONLIST_SIZE) icon_list;
+mu_stack(Canvas, CANVASLIST_SIZE) canvas_list;
+
+SDL_Surface *circle;
+
+
/* Initialize the window and renderer. Returns non-zero on error. */
int
r_init(mu_Context *ctx, const char *title) {
@@ -105,14 +133,22 @@ r_init(mu_Context *ctx, const char *title) {
ctx->text_width = text_width;
ctx->text_height = text_height;
+ if (draw_circle() != 0) {
+ return 1;
+ }
+
return 0;
}
void
r_free(void) {
- while (icon_list.idx-- > 0) {
- SDL_DestroyTexture(icon_list.items[icon_list.idx]);
+ while (icon_list.idx > 0) {
+ r_remove_icon(icon_list.idx-1);
+ }
+ while (canvas_list.idx > 0) {
+ r_remove_canvas(canvas_list.idx-1);
}
+ SDL_FreeSurface(circle);
}
static void
@@ -127,6 +163,30 @@ print_info(void) {
}
static int
+draw_circle(void) {
+ int x, y;
+ uint8_t *p;
+
+ circle = SDL_CreateRGBSurface(0, 2*CIRCLE_RADIUS, 2*CIRCLE_RADIUS, RGBA_DEPTH, 0, 0, 0, 0);
+ if (!circle) {
+ fprintf(stderr, "%s\n", SDL_GetError());
+ return 1;
+ }
+
+ for (y = 0; y < circle->h; y++) {
+ for (x = 0; x < circle->w; x++) {
+ p = (uint8_t *) circle->pixels + y*circle->pitch + x*RGBA_BYTES_PER_PIXEL;
+ p[0] = RGB_RED;
+ }
+ }
+
+ return 0;
+
+ /* TODO */
+
+}
+
+static int
text_width(mu_Font font, const char *str, int len) {
if (!str || !*str) { return 0; }
@@ -347,3 +407,61 @@ r_get_icon_size(int id, int *w, int *h) {
fprintf(stderr, "%s\n", SDL_GetError());
}
}
+
+/* Create a canvas with the background loaded from an image file.
+ * Returns the id of the canvas, or -1 on error. */
+int
+r_add_canvas(const char *bg_img_path) {
+ Canvas *c;
+
+ expect(canvas_list.idx < CANVASLIST_SIZE);
+
+ c = &canvas_list.items[canvas_list.idx];
+
+ c->bg = IMG_Load(bg_img_path);
+ if (!c->bg) {
+ fprintf(stderr, "failed to load %s: %s\n", bg_img_path, SDL_GetError());
+ return -1;
+ }
+
+ c->fg = SDL_CreateRGBSurface(0, c->bg->w, c->bg->h, RGBA_DEPTH, 0, 0, 0, 0);
+ if (!c->fg) {
+ fprintf(stderr, "%s\n", SDL_GetError());
+ SDL_FreeSurface(c->bg);
+ return -1;
+ }
+
+ c->dst = SDL_CreateRGBSurface(0, c->bg->w, c->bg->h, RGBA_DEPTH, 0, 0, 0, 0);
+ if (!c->dst) {
+ fprintf(stderr, "%s\n", SDL_GetError());
+ SDL_FreeSurface(c->bg);
+ SDL_FreeSurface(c->fg);
+ return -1;
+ }
+
+ return canvas_list.idx++;
+}
+
+void
+r_remove_canvas(int id) {
+ Canvas *dst, *src;
+ size_t size;
+
+ expect(id >= 0 && id < canvas_list.idx);
+
+ free_canvas(canvas_list.items[id]);
+
+ dst = canvas_list.items + id;
+ src= canvas_list.items + id + 1;
+ size = (canvas_list.idx - id - 1) * sizeof(*canvas_list.items);
+ memmove(dst, src, size);
+
+ canvas_list.idx--;
+}
+
+static void
+free_canvas(Canvas c) {
+ SDL_FreeSurface(c.bg);
+ SDL_FreeSurface(c.fg);
+ SDL_FreeSurface(c.dst);
+}
diff --git a/renderer.h b/renderer.h
index 2a8d344..3608274 100644
--- a/renderer.h
+++ b/renderer.h
@@ -6,3 +6,5 @@ void r_get_window_size(int *w, int *h);
int r_add_icon(const char *path);
void r_remove_icon(int);
void r_get_icon_size(int id, int *w, int *h);
+int r_add_canvas(const char *bg_img_path);
+void r_remove_canvas(int id);