|
- #include "sdl_overlay.h"
-
- #include "charbits.h"
-
-
- typedef struct {
- const uint8_t* bits;
- uint8_t shift;
- } bit_buffer;
-
- void make_bit_buffer(bit_buffer* buf, const uint8_t* bits) {
- buf->bits = bits;
- buf->shift = 0;
- }
-
- uint8_t get_bits(bit_buffer* buf) {
- uint8_t val = ((buf->bits[0] >> buf->shift) & 3);
- if (buf->shift == 6) {
- buf->shift = 0;
- buf->bits++;
- } else {
- buf->shift += 2;
- }
- return val;
- }
-
- static const SDL_Color pal[2] = {
- {0, 0, 0, 255}, {255, 255, 255, 255}
- };
-
- static SDL_Surface* create_char_surface(const uint8_t* bits) {
- int w = *bits++;
- bit_buffer buf = {0};
- make_bit_buffer(&buf, bits);
-
- SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(
- 0, w, char_h, 8, SDL_PIXELFORMAT_INDEX8
- );
- SDL_SetPaletteColors(surface->format->palette, pal, 1U, 2U);
- SDL_SetColorKey(surface, SDL_TRUE, 0);
-
- uint8_t* line = surface->pixels;
- for (int y = char_h; y > 0; --y) {
- uint8_t* dst = line;
- for (int x = w; x > 0; --x) {
- *dst++ = get_bits(&buf);
- }
- for (int x = (char_w - w); x > 0; --x) get_bits(&buf);
- line += surface->pitch;
- }
-
- return surface;
- }
-
- static SDL_Texture* create_char_texture(SDL_Renderer* rend,
- const uint8_t* bits) {
- SDL_Surface* surface = create_char_surface(bits);
- SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
- SDL_Texture* texture = SDL_CreateTextureFromSurface(
- rend, surface
- );
- SDL_FreeSurface(surface);
- return texture;
- }
-
- int sdl_overlay_font_init(SDL_Renderer* rend,
- sdl_overlay_font* font) {
- font->chars = chars;
- font->charbits = charbits;
- font->char_count = char_count;
- font->textures = calloc(char_count, sizeof(SDL_Texture*));
- for (int i = 0; i < font->char_count; ++i) {
- font->textures[i] = create_char_texture(
- rend, &font->charbits[i * charbit_size]
- );
- }
- return 0;
- }
-
- void sdl_overlay_font_done(sdl_overlay_font* font) {
- for (int i = 0; i < font->char_count; ++i) {
- SDL_DestroyTexture(font->textures[i]);
- }
- }
-
- #define overlay_start_x (char_w / 2)
- #define overlay_start_y (char_h / 2)
-
- static inline int char_index(char c) {
- if (c >= 'a' && c <= 'z') c += ('A' - 'a');
- if (c > ' ' && c < 'a') return (c - ' ');
- if (c >= '{' && c <= '~') return (65 + c - '{');
- return 0;
- }
-
- static void render_string(SDL_Renderer* rend, int ox, int oy,
- int sx, int sy,
- sdl_overlay_font* font,
- const char* string) {
- for (const char* c = string; *c; ++c) {
- if (*c == ' ') {
- ox += ((char_w / 2) - 1);
- } else {
- int index = char_index(*c);
- int cw = font->charbits[index * charbit_size];
- SDL_Texture* texture = font->textures[index];
-
- SDL_Rect rect = {
- .x = ox * sx,
- .y = oy * sy,
- .w = cw * sx,
- .h = char_h * sy,
- };
-
- SDL_RenderCopy(rend, texture, NULL, &rect);
-
- ox += (cw - 1);
- }
- }
- }
-
- int sdl_overlay_frame(Overlay* overlay, sdl_overlay_font* font,
- SDL_Renderer* rend,
- int sx, int sy) {
- int y = overlay_start_y;
- overlay_message* last = NULL, *next = NULL;
- for ( overlay_message* message = overlay->messages;
- NULL != message;
- last = message, message = next) {
- next = message->next;
-
- render_string(rend, overlay_start_x, y, sx, sy,
- font, message->string);
- y += (char_h + 1);
-
- if (message->expiry > 0 && --(message->expiry) == 0) {
- if (NULL == last) {
- overlay->messages = message->next;
- } else {
- last->next = message->next;
- }
- free(message->string);
- free(message);
- }
- }
-
- return 0;
- }
|