Mercurial > molko
changeset 94:ed72843a7194
core: simplify font/texture interfaces
Expose the structure to avoid calling functions and heap allocations. While
here remove some useless functions.
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 30 Mar 2020 13:34:42 +0200 |
parents | d4a72fa16225 |
children | e82eca4f8606 |
files | src/adventure/main.c src/adventure/mainmenu_state.c src/adventure/panic_state.c src/adventure/splashscreen_state.c src/adventure/splashscreen_state.h src/core/debug.c src/core/font.c src/core/font.h src/core/image.c src/core/image.h src/core/map.c src/core/map.h src/core/map_state.c src/core/message.c src/core/message.h src/core/painter.c src/core/sprite.c src/core/sprite.h src/core/texture.c src/core/texture.h src/core/texture_p.h |
diffstat | 21 files changed, 300 insertions(+), 328 deletions(-) [+] |
line wrap: on
line diff
--- a/src/adventure/main.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/adventure/main.c Mon Mar 30 13:34:42 2020 +0200 @@ -48,6 +48,7 @@ #define WINDOW_HEIGHT 720 static jmp_buf panic_buf; +static struct font debug_font; static noreturn void unrecoverable(void) @@ -76,17 +77,18 @@ { union event ev; struct clock clock; - struct font *font; - struct texture *frame; + struct font font; + struct texture frame; int panic_trigger = 0; - if (!(font = font_openf(sys_datapath("fonts/DejaVuSans.ttf"), 15))) + if (!(font_open(&font, sys_datapath("fonts/DejaVuSans.ttf"), 15))) error_fatal(); - if (!(debug_options.default_font = font_openf(sys_datapath("fonts/DejaVuSans.ttf"), 10))) + if (!(font_open(&debug_font, sys_datapath("fonts/DejaVuSans.ttf"), 10))) error_fatal(); - if (!(frame = image_openf(sys_datapath("images/message.png")))) + if (!(image_open(&frame, sys_datapath("images/message.png")))) error_fatal(); + debug_options.default_font = &debug_font; debug_options.enable = true; clock_start(&clock);
--- a/src/adventure/mainmenu_state.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/adventure/mainmenu_state.c Mon Mar 30 13:34:42 2020 +0200 @@ -48,10 +48,11 @@ static unsigned int selection; static int destination; static enum substate substate; +static struct texture image; /* Menu items. */ static struct { - struct texture *texture; + struct texture texture; int x; int y; } items[3]; @@ -59,9 +60,9 @@ static void enter(void) { - struct font *font = font_openf(sys_datapath("fonts/pirata-one.ttf"), 30); + struct font font = { 0 }; - if (!font) + if (!font_open(&font, sys_datapath("fonts/pirata-one.ttf"), 30)) error_fatal(); substate = SUBSTATE_MOVING; @@ -70,36 +71,33 @@ destination = window_height() / 4; /* TODO: change continue color if no game exists. */ - items[0].texture = font_render(font, "New game", 0x000000ff); - items[0].x = (window_width() / 2) - (texture_width(items[0].texture) / 2); + font_render(&font, &items[0].texture, "New game"); + items[0].x = (window_width() / 2) - (items[0].texture.w / 2); items[0].y = window_height() * 0.75; - items[1].texture = font_render(font, "Continue", 0x000000ff); + font_render(&font, &items[1].texture, "Continue"); items[1].x = items[0].x; - items[1].y = items[0].y + texture_height(items[0].texture); + items[1].y = items[0].y + items[0].texture.h; - items[2].texture = font_render(font, "Quit", 0x000000ff); + font_render(&font, &items[2].texture, "Quit"); items[2].x = items[0].x; - items[2].y = items[1].y + texture_height(items[1].texture); + items[2].y = items[1].y + items[1].texture.h; + + font_finish(&font); } static void new(void) { - struct map map; - struct texture *image; - /* Prepare map. */ - if (!map_open(&map, sys_datapath("maps/test.map"))) + if (!map_open(&map_state_data.map.map, sys_datapath("maps/test.map"))) error_fatal(); - memcpy(&map_state_data.map.map, &map, sizeof (map)); - /* Prepare image and sprite. */ - if (!(image = image_openf(sys_datapath("sprites/test-walk.png")))) + if (!(image_open(&image, sys_datapath("sprites/test-walk.png")))) error_fatal(); - sprite_init(&map_state_data.player.sprite, image, 48, 48); + sprite_init(&map_state_data.player.sprite, &image, 48, 48); game_switch(&map_state, false); } @@ -177,12 +175,12 @@ { painter_set_color(0xffffffff); painter_clear(); - texture_draw(splashscreen_state_data.text, x, y); + texture_draw(&splashscreen_state_data.text, x, y); if (substate == SUBSTATE_WAITING) { - texture_draw(items[0].texture, items[0].x, items[0].y); - texture_draw(items[1].texture, items[1].x, items[1].y); - texture_draw(items[2].texture, items[2].x, items[2].y); + texture_draw(&items[0].texture, items[0].x, items[0].y); + texture_draw(&items[1].texture, items[1].x, items[1].y); + texture_draw(&items[2].texture, items[2].x, items[2].y); /* Selection cursor. */ @@ -196,8 +194,8 @@ static void leave(void) { - texture_close(items[0].texture); - texture_close(items[1].texture); + texture_finish(&items[0].texture); + texture_finish(&items[1].texture); memset(items, 0, sizeof (items)); }
--- a/src/adventure/panic_state.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/adventure/panic_state.c Mon Mar 30 13:34:42 2020 +0200 @@ -45,21 +45,21 @@ struct label { const char *text; - struct texture *texture; + struct texture texture; }; static struct { - struct font *font; + struct font font; } data; static struct label headers[] = { - { "An unrecoverable error occured and the game cannot continue.", NULL }, - { "Please report the detailed error as provided below.", NULL }, + { "An unrecoverable error occured and the game cannot continue.", 0 }, + { "Please report the detailed error as provided below.", 0 }, }; static struct label bottom[] = { - { "Press <s> to save information and generate a core dump.", NULL }, - { "Press <q> to quit without saving information.", NULL } + { "Press <s> to save information and generate a core dump.", 0 }, + { "Press <q> to quit without saving information.", 0 } }; static struct label lerror; @@ -136,12 +136,13 @@ assert(labels); for (size_t i = 0; i < labelsz; ++i) { - if (labels[i].texture) + if (texture_ok(&labels[i].texture)) continue; - labels[i].texture = font_render(data.font, labels[i].text, FOREGROUND); + data.font.color = FOREGROUND; + font_render(&data.font, &labels[i].texture, labels[i].text); - if (!labels[i].texture) + if (!texture_ok(&labels[i].texture)) error_fatal(); } } @@ -169,20 +170,20 @@ /* Header. */ for (size_t i = 0; i < NELEM(headers); ++i) { - texture_draw(headers[i].texture, PADDING, y); - y += texture_height(headers[i].texture) + 2; + texture_draw(&headers[i].texture, PADDING, y); + y += headers[i].texture.h + 2; } /* Error message. */ - texture_draw(lerror.texture, PADDING, y + PADDING); + texture_draw(&lerror.texture, PADDING, y + PADDING); /* Bottom. */ y = window_height() - PADDING; - y -= texture_height(bottom[0].texture); + y -= bottom[0].texture.h; for (size_t i = 0; i < NELEM(bottom); ++i) { - texture_draw(bottom[i].texture, PADDING, y); - y -= texture_height(bottom[i].texture) + 2; + texture_draw(&bottom[i].texture, PADDING, y); + y -= bottom[i].texture.h + 2; } } @@ -207,6 +208,6 @@ * useful information to the screen so as last resort print them * on the console. */ - if (!(data.font = font_openf(sys_datapath(FONT), FONT_SZ))) + if (!(font_open(&data.font, sys_datapath(FONT), FONT_SZ))) error_fatal(); }
--- a/src/adventure/splashscreen_state.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/adventure/splashscreen_state.c Mon Mar 30 13:34:42 2020 +0200 @@ -38,21 +38,23 @@ static void enter(void) { - struct font *font; + struct font font = { + .color = 0x000000ff + }; - if (!(font = font_openf(sys_datapath("fonts/teutonic1.ttf"), 130))) + if (!(font_open(&font, sys_datapath("fonts/teutonic1.ttf"), 130))) error_fatal(); - if (!(splashscreen_state_data.text = font_render(font, "Molko's Adventure", 0x000000ff))) + if (!(font_render(&font, &splashscreen_state_data.text, "Molko's Adventure"))) error_fatal(); /* Compute position. */ - const unsigned int w = texture_width(splashscreen_state_data.text); - const unsigned int h = texture_height(splashscreen_state_data.text); + const unsigned int w = splashscreen_state_data.text.w; + const unsigned int h = splashscreen_state_data.text.h; splashscreen_state_data.x = (window_width() / 2) - (w / 2); splashscreen_state_data.y = (window_height() / 2) - (h / 2); - font_close(font); + font_finish(&font); } static void @@ -81,7 +83,7 @@ { painter_set_color(0xffffffff); painter_clear(); - texture_draw(splashscreen_state_data.text, + texture_draw(&splashscreen_state_data.text, splashscreen_state_data.x, splashscreen_state_data.y); }
--- a/src/adventure/splashscreen_state.h Thu Mar 26 10:28:11 2020 +0100 +++ b/src/adventure/splashscreen_state.h Mon Mar 30 13:34:42 2020 +0200 @@ -24,13 +24,13 @@ * \brief Splash screen state. */ -struct texture; +#include "texture.h" /** * \brief Data for splashscreen. */ extern struct splashscreen_state_data { - struct texture *text; /*!< (RW) Texture for the text. */ + struct texture text; /*!< (RW) Texture for the text. */ int x; /*!< (RW) Position in x. */ int y; /*!< (RW) Position in y. */ unsigned int elapsed; /*!< (RW) Time elapsed. */
--- a/src/core/debug.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/debug.c Mon Mar 30 13:34:42 2020 +0200 @@ -51,21 +51,23 @@ assert(fmt); char line[DEBUG_LINE_MAX]; - struct texture *tex; + struct texture tex; struct font *font; unsigned int gapy; vsnprintf(line, sizeof (line), fmt, ap); + font = report->font ? report->font : debug_options.default_font; - tex = font_render_ex(font, line, report->color, report->style); + font->color = report->color; + font->style = report->style; - if (!tex) + if (!font_render(font, &tex, line)) return; gapy = (PADDING_Y * (report->count)) + (font_height(font) * (report->count)); report->count++; - texture_draw(tex, PADDING_X, gapy); - texture_close(tex); + texture_draw(&tex, PADDING_X, gapy); + texture_finish(&tex); }
--- a/src/core/font.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/font.c Mon Mar 30 13:34:42 2020 +0200 @@ -29,73 +29,57 @@ #include "texture_p.h" #include "util.h" -struct font { - TTF_Font *handle; -}; - -struct font * -font_openf(const char *path, unsigned int size) +bool +font_open(struct font *font, const char *path, unsigned int size) { + assert(font); assert(path); - struct font *f; - - f = ecalloc(1, sizeof (struct font)); + if (!(font->handle = TTF_OpenFont(path, size))) + return error_sdl(); - if (!(f->handle = TTF_OpenFont(path, size))) { - error_sdl(); - free(f); - return NULL; - } - - return f; + return true; } -struct font * -font_openb(const void *buffer, size_t buflen, unsigned int size) +bool +font_openmem(struct font *font, const void *buffer, size_t buflen, unsigned int size) { + assert(font); assert(buffer); - struct font *f; SDL_RWops *ops; - f = ecalloc(1, sizeof (struct font)); - if (!(ops = SDL_RWFromConstMem(buffer, buflen)) || - (!(f->handle = TTF_OpenFontRW(ops, true, size)))) { - error_sdl(); - free(f); - return NULL; - } + (!(font->handle = TTF_OpenFontRW(ops, true, size)))) + return error_sdl(); - return f; + return true; } -struct texture * -font_render(struct font *font, const char *text, unsigned long color) +bool +font_ok(const struct font *font) { - return font_render_ex(font, text, color, FONT_STYLE_ANTIALIASED); + assert(font); + + return font->handle; } -struct texture * -font_render_ex(struct font *font, - const char *text, - unsigned long color, - enum font_style style) +bool +font_render(struct font *font, struct texture *tex, const char *text) { assert(font); assert(text); SDL_Color fg = { - .r = COLOR_R(color), - .g = COLOR_G(color), - .b = COLOR_B(color), - .a = COLOR_A(color) + .r = COLOR_R(font->color), + .g = COLOR_G(font->color), + .b = COLOR_B(font->color), + .a = COLOR_A(font->color) }; SDL_Surface *surface; SDL_Surface *(*func)(TTF_Font *, const char *, SDL_Color); - switch (style) { + switch (font->style) { case FONT_STYLE_ANTIALIASED: func = TTF_RenderUTF8_Blended; break; @@ -104,25 +88,25 @@ break; } - if (!(surface = func(font->handle, text, fg))) { - error_sdl(); - return NULL; - } + if (!(surface = func(font->handle, text, fg))) + return error_sdl(); - return texture_from_surface(surface); + return texture_from_surface(tex, surface); } unsigned int font_height(const struct font *font) { + assert(font); + return TTF_FontHeight(font->handle); } void -font_close(struct font *font) +font_finish(struct font *font) { assert(font); - TTF_CloseFont(font->handle); - free(font); + if (font->handle) + TTF_CloseFont(font->handle); }
--- a/src/core/font.h Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/font.h Mon Mar 30 13:34:42 2020 +0200 @@ -25,70 +25,81 @@ * \ingroup drawing */ +#include <stdbool.h> #include <stddef.h> -/** - * \brief Font object. - * - * This object is not publicly defined because it contains - * implementation-defined data. - */ -struct font; struct texture; /** * \brief Font style for rendering. */ enum font_style { - FONT_STYLE_NONE, /*!< No antialiasing. */ - FONT_STYLE_ANTIALIASED /*!< Pretty antialiasing looking. */ + FONT_STYLE_ANTIALIASED, /*!< Pretty antialiasing looking. */ + FONT_STYLE_NONE /*!< No antialiasing. */ +}; + +/** + * \brief Font object. + */ +struct font { + enum font_style style; /*!< (RW) Style for rendering. */ + unsigned long color; /*!< (RW) Color for rendering. */ + void *handle; /*!< (RO) Native handle. */ }; /** * Open font from path file. * + * \pre font != NULL * \pre path != NULL + * \param font the font to initialize * \param path the path to the font * \param size the desired size - * \return the font or NULL on error + * \return False on errors. */ -struct font * -font_openf(const char *path, unsigned int size); +bool +font_open(struct font *font, const char *path, unsigned int size); /** * Open font from memory buffer. * + * \pre font != NULL * \pre buffer != NULL + * \param font the font to initialize * \param buffer the memory buffer * \param buflen the memory buffer length * \param size the desired size * \warning The buffer must remain valid until font is closed - * \return the font or NULL on error + * \return False on errors. */ -struct font * -font_openb(const void *buffer, size_t buflen, unsigned int size); - -/** - * Similar to \ref font_render_ex with predefined convenient values. - */ -struct texture * -font_render(struct font *font, const char *text, unsigned long color); +bool +font_openmem(struct font *font, const void *buffer, size_t buflen, unsigned int size); /** - * Render a text. + * Tells if the font was properly opened. * * \pre font != NULL - * \pre text != NULL - * \param font the font handle - * \param text the text in UTF-8 - * \param color the color - * \param style the font style + * \param font the font to check + * \return True if the native handle was opened. */ -struct texture * -font_render_ex(struct font *font, - const char *text, - unsigned long color, - enum font_style style); +bool +font_ok(const struct font *font); + +/** + * Render some text into the texture. + * + * This function use the current color/style and other properties in the font + * to render the texture. + * + * \pre font != NULL + * \pre tex != NULL + * \param font the font to use + * \param tex the texture to generate + * \param text the UTF-8 text + * \return False on errors. + */ +bool +font_render(struct font *font, struct texture *tex, const char *text); /** * Get the maximum height for all glyphs. @@ -107,6 +118,6 @@ * \param font the font handle */ void -font_close(struct font *font); +font_finish(struct font *font); #endif /* !MOLKO_FONT_H */
--- a/src/core/image.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/image.c Mon Mar 30 13:34:42 2020 +0200 @@ -24,33 +24,30 @@ #include "error_p.h" #include "texture_p.h" -struct texture * -image_openf(const char *path) +bool +image_open(struct texture *tex, const char *path) { + assert(tex); assert(path); SDL_Surface *surface = IMG_Load(path); - if (!surface) { - error_sdl(); - return NULL; - } + if (!surface) + return error_sdl(); - return texture_from_surface(surface); + return texture_from_surface(tex, surface); } -struct texture * -image_openb(const void *buffer, size_t size) +bool +image_openmem(struct texture *tex, const void *buffer, size_t size) { assert(buffer); SDL_RWops *ops = SDL_RWFromConstMem(buffer, size); SDL_Surface *surface; - if (!ops || !(surface = IMG_Load_RW(ops, true))) { - error_sdl(); - return NULL; - } + if (!ops || !(surface = IMG_Load_RW(ops, true))) + return error_sdl(); - return texture_from_surface(surface); + return texture_from_surface(tex, surface); }
--- a/src/core/image.h Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/image.h Mon Mar 30 13:34:42 2020 +0200 @@ -32,22 +32,28 @@ /** * Open a file from a path. * + * \pre tex != NULL * \pre path != NULL + * \param tex the texture to initialize * \param path the path to the file - * \return the texture or NULL on error + * \return False on errors. */ -struct texture * -image_openf(const char *path); +bool +image_open(struct texture *tex, const char *path); /** * Open a file from a memory buffer. * + * The buffer must be valid until the image is no longer used. + * + * \pre tex != NULL * \pre buffer != NULL + * \param tex the texture to initialize * \param buffer the memory buffer * \param size the memory size - * \return the texture or NULL on error + * \return False on errors. */ -struct texture * -image_openb(const void *buffer, size_t size); +bool +image_openmem(struct texture *tex, const void *buffer, size_t size); #endif /* !MOLKO_IMAGE_H */
--- a/src/core/map.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/map.c Mon Mar 30 13:34:42 2020 +0200 @@ -77,10 +77,8 @@ if (map->tilewidth == 0 || map->tileheight == 0) return; - if (!(map->tileset = image_openf(sys_datapath("tilesets/%s", filename)))) + if (!(image_open(&map->tileset, sys_datapath("tilesets/%s", filename)))) return; - - sprite_init(&map->sprite, map->tileset, map->tilewidth, map->tileheight); } static void @@ -109,7 +107,7 @@ { if (strlen(map->title) == 0) return error_printf("map has no title"); - if (!map->tileset) + if (!map->tileset.w || !map->tileset.h) return error_printf("unable to open tileset"); if (map->width == 0 || map->height == 0) return error_printf("map has null sizes"); @@ -127,16 +125,19 @@ assert(map); assert(layer); + struct sprite sprite; int x = 0, y = 0; + sprite_init(&sprite, &map->tileset, map->tilewidth, map->tileheight); + for (unsigned int r = 0; r < map->width; ++r) { for (unsigned int c = 0; c < map->height; ++c) { unsigned int si = r * map->width + c; - unsigned int sr = (layer->tiles[si] - 1) / map->sprite.ncols; - unsigned int sc = (layer->tiles[si] - 1) % map->sprite.nrows; + unsigned int sr = (layer->tiles[si] - 1) / sprite.ncols; + unsigned int sc = (layer->tiles[si] - 1) % sprite.nrows; if (layer->tiles[si] != 0) - sprite_draw(&map->sprite, sr, sc, x, y); + sprite_draw(&sprite, sr, sc, x, y); x += map->tilewidth; } @@ -169,14 +170,14 @@ fclose(fp); if (!check(map)) { - map_close(map); + map_finish(map); return false; } size_t pw = map->width * map->tilewidth; size_t ph = map->height * map->tileheight; - if (!(map->picture = texture_new(pw, ph))) + if (!(texture_new(&map->picture, pw, ph))) return error_sdl(); return true; @@ -185,8 +186,8 @@ void map_draw(struct map *map, int srcx, int srcy) { - texture_draw_ex( - map->picture, + texture_scale( + &map->picture, srcx, srcy, window_width(), @@ -202,21 +203,19 @@ void map_repaint(struct map *map) { - PAINTER_BEGIN(map->picture); + PAINTER_BEGIN(&map->picture); draw_layer(map, &map->layers[0]); draw_layer(map, &map->layers[1]); PAINTER_END(); } void -map_close(struct map *map) +map_finish(struct map *map) { assert(map); - if (map->tileset) - texture_close(map->tileset); - if (map->picture) - texture_close(map->picture); + texture_finish(&map->tileset); + texture_finish(&map->picture); free(map->layers[0].tiles); free(map->layers[1].tiles);
--- a/src/core/map.h Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/map.h Mon Mar 30 13:34:42 2020 +0200 @@ -26,15 +26,13 @@ #include <stdbool.h> -#include "sprite.h" +#include "texture.h" /** * \brief Max title length for a map. */ #define MAP_TITLE_MAX 32 -struct texture; - /** * \brief Map layer. */ @@ -50,9 +48,8 @@ */ struct map { char title[MAP_TITLE_MAX]; /*!< (RW) The map title */ - struct texture *tileset; /*!< (RW) Tileset to use */ - struct texture *picture; /*!< (RO) Map drawn into a picture */ - struct sprite sprite; /*!< (RO) Sprite to render */ + struct texture tileset; /*!< (RW) Tileset to use */ + struct texture picture; /*!< (RO) Map drawn into a picture */ int origin_x; /*!< (RO) Where the player starts in X */ int origin_y; /*!< (RO) Where the player starts in Y */ unsigned int width; /*!< (RO) Map width in cells */ @@ -102,6 +99,6 @@ * \param map the map to render */ void -map_close(struct map *map); +map_finish(struct map *map); #endif /* !MOLKO_MAP_H */
--- a/src/core/map_state.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/map_state.c Mon Mar 30 13:34:42 2020 +0200 @@ -122,12 +122,9 @@ /* Adjust map properties. */ struct map *m = &map_state_data.map.map; - if (!m->picture) - map_repaint(m); - map_repaint(m); - map_state_data.map.w = texture_width(m->picture); - map_state_data.map.h = texture_height(m->picture); + map_state_data.map.w = m->picture.w; + map_state_data.map.h = m->picture.h; /* Adjust view. */ map_state_data.view.w = window_width();
--- a/src/core/message.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/message.c Mon Mar 30 13:34:42 2020 +0200 @@ -74,9 +74,9 @@ unsigned int total = 0; for (int i = 0; i < 6; ++i) { - if (msg->textures[i]) { + if (msg->textures[i].w) { n += 1; - total += texture_height(msg->textures[i]); + total += msg->textures[i].h; } } @@ -86,12 +86,8 @@ static void clear(struct message *msg) { - for (unsigned int i = 0; i < 12; ++i) { - if (msg->textures[i]) { - texture_close(msg->textures[i]); - msg->textures[i] = NULL; - } - } + for (unsigned int i = 0; i < 12; ++i) + texture_finish(&msg->textures[i]); } static void @@ -105,23 +101,26 @@ continue; /* Normal lines of text. */ - unsigned long color = msg->colors[0]; + msg->font->color = msg->colors[0]; if (msg->flags & MESSAGE_QUESTION && msg->index == i) - color = msg->colors[1]; + msg->font->color = msg->colors[1]; - if (!msg->textures[i]) - msg->textures[i] = font_render( + if (!texture_ok(&msg->textures[i])) + font_render( msg->font, - msg->text[i], - color + &msg->textures[i], + msg->text[i] ); - if (!msg->textures[i + 6]) - msg->textures[i + 6] = font_render( + if (!texture_ok(&msg->textures[i + 6])) { + msg->font->color = 0x000000ff; + + font_render( msg->font, - msg->text[i], - 0x000000ff + &msg->textures[i + 6], + msg->text[i] ); + } } } @@ -132,7 +131,7 @@ msg->elapsed = 0; msg->state = msg->flags & MESSAGE_QUICK ? MESSAGE_SHOWING : MESSAGE_OPENING; - msg->height[0] = texture_height(msg->frame); + msg->height[0] = msg->frame->h; msg->height[1] = 0; redraw(msg); @@ -176,7 +175,7 @@ switch (msg->state) { case MESSAGE_OPENING: - msg->height[1] += texture_height(msg->frame) * ticks / MESSAGE_SPEED; + msg->height[1] += msg->frame->h * ticks / MESSAGE_SPEED; if (msg->height[1] > msg->height[0]) msg->height[1] = msg->height[0]; @@ -195,7 +194,7 @@ break; case MESSAGE_HIDING: - msg->height[1] -= texture_height(msg->frame) * ticks / MESSAGE_SPEED; + msg->height[1] -= msg->frame->h * ticks / MESSAGE_SPEED; if (msg->elapsed >= MESSAGE_SPEED) { msg->state = MESSAGE_NONE; @@ -216,8 +215,8 @@ assert(msg); assert(msg->frame); - const unsigned int w = texture_width(msg->frame); - const unsigned int h = texture_height(msg->frame); + const unsigned int w = msg->frame->w; + const unsigned int h = msg->frame->h; const unsigned int x = (window_width() / 2) - (w / 2); const unsigned int y = 80; const unsigned int avgh = average(msg); @@ -226,7 +225,7 @@ switch (msg->state) { case MESSAGE_OPENING: case MESSAGE_HIDING: - texture_draw_ex(msg->frame, 0, 0, w, msg->height[1], x, y, w, msg->height[1], 0); + texture_scale(msg->frame, 0, 0, w, msg->height[1], x, y, w, msg->height[1], 0); break; case MESSAGE_SHOWING: texture_draw(msg->frame, x, y); @@ -236,11 +235,11 @@ const int real_x = x + 20; const int real_y = y + ((i + 1) * gapy) + (i * avgh); - if (!msg->textures[i]) + if (!texture_ok(&msg->textures[i])) continue; - texture_draw(msg->textures[i + 6], real_x + 2, real_y + 2); - texture_draw(msg->textures[i], real_x, real_y); + texture_draw(&msg->textures[i + 6], real_x + 2, real_y + 2); + texture_draw(&msg->textures[i], real_x, real_y); } break; default:
--- a/src/core/message.h Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/message.h Mon Mar 30 13:34:42 2020 +0200 @@ -65,9 +65,10 @@ #include <stdbool.h> +#include "texture.h" + struct action; struct font; -struct texture; union event; @@ -98,9 +99,9 @@ */ struct message { const char *text[6]; /*!< (RW) Lines of text to show */ - struct texture *frame; /*!< (RW) Frame to use */ - struct texture *avatar; /*!< (RW) Avatar face (optional) */ - struct font *font; /*!< (RW) Font to use */ + struct texture *frame; /*!< (RW, ref) Frame to use */ + struct texture *avatar; /*!< (RW, ref, optional) Avatar face (optional) */ + struct font *font; /*!< (RW, ref) Font to use */ unsigned long colors[2]; /*!< (RW) Normal/selected colors */ unsigned int index; /*!< (RW) Line selected */ enum message_flags flags; /*!< (RW) Message flags */ @@ -108,7 +109,7 @@ /*! \cond PRIVATE */ - struct texture *textures[12]; + struct texture textures[12]; unsigned int elapsed; int height[2];
--- a/src/core/painter.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/painter.c Mon Mar 30 13:34:42 2020 +0200 @@ -18,7 +18,7 @@ #include "color.h" #include "painter.h" -#include "texture_p.h" +#include "texture.h" #include "window_p.h" static struct texture *renderer;
--- a/src/core/sprite.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/sprite.c Mon Mar 30 13:34:42 2020 +0200 @@ -19,7 +19,6 @@ #include <assert.h> #include "sprite.h" -#include "texture_p.h" #include "texture.h" void @@ -28,20 +27,14 @@ unsigned int cellw, unsigned int cellh) { - int w = 0; - int h = 0; - assert(sprite); - assert(tex); - - /* TODO: use texture_get_size */ - SDL_QueryTexture(tex->handle, NULL, NULL, &w, &h); + assert(tex && texture_ok(tex)); sprite->texture = tex; sprite->cellw = cellw; sprite->cellh = cellh; - sprite->nrows = h / cellh; - sprite->ncols = w / cellw; + sprite->nrows = tex->h / cellh; + sprite->ncols = tex->w / cellw; } void @@ -49,7 +42,7 @@ { assert(sprite); - texture_draw_ex( + texture_scale( sprite->texture, c * sprite->cellw, /* src y */ r * sprite->cellh, /* src x */
--- a/src/core/sprite.h Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/sprite.h Mon Mar 30 13:34:42 2020 +0200 @@ -51,7 +51,7 @@ * texture size. * * \pre sprite != NULL - * \pre tex != NULL + * \pre tex != NULL && texture_ok(tex) * \param sprite the sprite to initialize * \param tex the texture * \param cellw the width per cell in pixels
--- a/src/core/texture.c Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/texture.c Mon Mar 30 13:34:42 2020 +0200 @@ -25,75 +25,59 @@ #include "util.h" #include "window_p.h" -struct texture * -texture_new(unsigned int w, unsigned int h) -{ - struct texture *tex = emalloc(sizeof (struct texture)); - - if (!(tex->handle = SDL_CreateTexture(win.renderer, - SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h))) { - error_sdl(); - free(tex); - return NULL; - } - - return tex; -} - -unsigned int -texture_width(struct texture *tex) +bool +texture_new(struct texture *tex, unsigned int w, unsigned int h) { assert(tex); - int width; + tex->handle = SDL_CreateTexture(win.renderer, + SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h); - if (SDL_QueryTexture(tex->handle, NULL, NULL, &width, NULL) < 0) - return 0; + if (!tex->handle) { + tex->w = tex->h = 0; + return error_sdl(); + } - return width; + tex->w = w; + tex->h = h; + + return true; } -unsigned int -texture_height(struct texture *tex) +bool +texture_ok(const struct texture *tex) { assert(tex); - int height; - - if (SDL_QueryTexture(tex->handle, NULL, NULL, NULL, &height) < 0) - return 0; - - return height; + return tex->handle && tex->w && tex->h; } void texture_draw(struct texture *tex, int x, int y) { + assert(tex); + SDL_Rect dst = { .x = x, .y = y, - .w = 0, - .h = 0 + .w = tex->w, + .h = tex->h }; - assert(tex); - - /* We need to determine size */ - SDL_QueryTexture(tex->handle, NULL, NULL, &dst.w, &dst.h); SDL_RenderCopy(win.renderer, tex->handle, NULL, &dst); } void -texture_draw_ex(struct texture *tex, - int src_x, - int src_y, - unsigned src_w, - unsigned src_h, - int dst_x, - int dst_y, - unsigned dst_w, - unsigned dst_h, - double angle) +texture_scale(struct texture *tex, + int src_x, + int src_y, + unsigned src_w, + unsigned src_h, + int dst_x, + int dst_y, + unsigned dst_w, + unsigned dst_h, + double angle) { const SDL_Rect src = { .x = src_x, @@ -112,28 +96,31 @@ } void -texture_close(struct texture *tex) +texture_finish(struct texture *tex) { assert(tex); - SDL_DestroyTexture(tex->handle); - free(tex); + if (tex->handle) + SDL_DestroyTexture(tex->handle); + + memset(tex, 0, sizeof (*tex)); } /* private */ -struct texture * -texture_from_surface(SDL_Surface *surface) +bool +texture_from_surface(struct texture *tex, SDL_Surface *surface) { + assert(tex); assert(surface); - struct texture *texture = ecalloc(1, sizeof (struct texture)); - - if (!(texture->handle = SDL_CreateTextureFromSurface(win.renderer, surface))) { - error_sdl(); - free(texture); - return NULL; + if (!(tex->handle = SDL_CreateTextureFromSurface(win.renderer, surface))) { + tex->w = tex->h = 0; + return error_sdl(); } - return texture; + tex->w = surface->w; + tex->h = surface->h; + + return true; }
--- a/src/core/texture.h Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/texture.h Mon Mar 30 13:34:42 2020 +0200 @@ -31,41 +31,37 @@ /** * \brief Texture object. - * - * This object is not publicly defined because it contains - * implementation-defined data. */ -struct texture; +struct texture { + unsigned int w; /*!< (RO) Texture width. */ + unsigned int h; /*!< (RO) Texture height. */ + void *handle; /*!< (RO) Native handle. */ +}; /** * Create a new texture. * + * \pre tex != NULL + * \param tex the texture to initialize * \param w the width * \param h the height - * \return the texture or NULL on error + * \return False on error. */ -struct texture * -texture_new(unsigned int w, unsigned int h); +bool +texture_new(struct texture *tex, unsigned int w, unsigned int h); /** - * Get texture width. + * Check if the texture is valid. + * + * This function simply checks if the texture is initialized and has non-null + * dimensions. * * \pre tex != NULL - * \param tex the texture - * \return the width + * \param tex the texture to check + * \return True if the texture is initialized */ -unsigned int -texture_width(struct texture *tex); - -/** - * Get texture height. - * - * \pre tex != NULL - * \param tex the texture - * \return the height - */ -unsigned int -texture_height(struct texture *tex); +bool +texture_ok(const struct texture *tex); /** * Simple texture drawing. @@ -94,16 +90,16 @@ * \param angle the angle */ void -texture_draw_ex(struct texture *tex, - int src_x, - int src_y, - unsigned src_w, - unsigned src_h, - int dst_x, - int dst_y, - unsigned dst_w, - unsigned dst_h, - double angle); +texture_scale(struct texture *tex, + int src_x, + int src_y, + unsigned src_w, + unsigned src_h, + int dst_x, + int dst_y, + unsigned dst_w, + unsigned dst_h, + double angle); /** * Close the texture, do not use afterwards. @@ -112,6 +108,6 @@ * \param tex the texture */ void -texture_close(struct texture *tex); +texture_finish(struct texture *tex); #endif /* !MOLKO_TEXTURE_H */
--- a/src/core/texture_p.h Thu Mar 26 10:28:11 2020 +0100 +++ b/src/core/texture_p.h Mon Mar 30 13:34:42 2020 +0200 @@ -19,13 +19,13 @@ #ifndef MOLKO_TEXTURE_P_H #define MOLKO_TEXTURE_P_H +#include <stdbool.h> + #include <SDL.h> -struct texture { - SDL_Texture *handle; -}; +struct texture; -struct texture * -texture_from_surface(SDL_Surface *surface); +bool +texture_from_surface(struct texture *tex, SDL_Surface *surface); #endif /* !MOLKO_TEXTURE_P_H */