diff --git a/src/api/renderer.c b/src/api/renderer.c index 6e4ebf40..c6883a95 100644 --- a/src/api/renderer.c +++ b/src/api/renderer.c @@ -72,9 +72,9 @@ static int f_draw_rect(lua_State *L) { } static int draw_text_subpixel_impl(lua_State *L, bool draw_subpixel) { - RenFont **font = luaL_checkudata(L, 1, API_TYPE_FONT); + FontDesc *font_desc = luaL_checkudata(L, 1, API_TYPE_FONT); const char *text = luaL_checkstring(L, 2); - /* The coordinate below will be in subpixels iff draw_subpixel is true. + /* The coordinate below will be in subpixel iff draw_subpixel is true. Otherwise it will be in pixels. */ int x_subpixel = luaL_checknumber(L, 3); int y = luaL_checknumber(L, 4); @@ -90,7 +90,7 @@ static int draw_text_subpixel_impl(lua_State *L, bool draw_subpixel) { replace_color = (RenColor) {0}; } - x_subpixel = rencache_draw_text(*font, text, x_subpixel, y, color, draw_subpixel, rep_table, replace_color); + x_subpixel = rencache_draw_text(font_desc, text, x_subpixel, y, color, draw_subpixel, rep_table, replace_color); lua_pushnumber(L, x_subpixel); return 1; } @@ -114,7 +114,7 @@ static const luaL_Reg lib[] = { { "draw_rect", f_draw_rect }, { "draw_text", f_draw_text }, { "draw_text_subpixel", f_draw_text_subpixel }, - { NULL, NULL } + { NULL, NULL } }; diff --git a/src/api/renderer_font.c b/src/api/renderer_font.c index dd5069bc..5cc8b400 100644 --- a/src/api/renderer_font.c +++ b/src/api/renderer_font.c @@ -1,8 +1,8 @@ #include "api.h" +#include "fontdesc.h" #include "renderer.h" #include "rencache.h" - static int f_load(lua_State *L) { const char *filename = luaL_checkstring(L, 1); float size = luaL_checknumber(L, 2); @@ -40,57 +40,72 @@ static int f_load(lua_State *L) { } lua_pop(L, 1); } - RenFont **self = lua_newuserdata(L, sizeof(*self)); + + if (ren_verify_font(filename)) { + luaL_error(L, "failed to load font"); + } + + FontDesc *font_desc = lua_newuserdata(L, sizeof(FontDesc)); + // FIXME: implement font_desc initialization in fontdesc.c + int filename_sz = strlen(filename) + 1; + font_desc->filename = malloc(filename_sz); + memcpy(font_desc->filename, filename, filename_sz); + font_desc->size = size; + font_desc->options = font_options; + font_desc->tab_size = 4; + font_desc->fonts_scale_length = 0; + font_desc->recent_font_scale_index = 0; /* No need to initialize. */ + luaL_setmetatable(L, API_TYPE_FONT); - *self = ren_load_font(filename, size, font_options); - if (!*self) { luaL_error(L, "failed to load font"); } return 1; } static int f_set_tab_size(lua_State *L) { - RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT); int n = luaL_checknumber(L, 2); - ren_set_font_tab_size(*self, n); + font_desc_set_tab_size(self, n); return 0; } static int f_gc(lua_State *L) { - RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); - if (*self) { rencache_free_font(*self); } + FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT); + rencache_free_font(self); return 0; } - static int f_get_width(lua_State *L) { - RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT); const char *text = luaL_checkstring(L, 2); - int subpixel_scale; - int w = ren_get_font_width(*self, text, &subpixel_scale); - lua_pushnumber(L, ren_font_subpixel_round(w, subpixel_scale, 0)); + /* By calling ren_get_font_width with NULL as third arguments + we will obtain the width in points. */ + int w = ren_get_font_width(self, text, NULL); + lua_pushnumber(L, w); return 1; } static int f_subpixel_scale(lua_State *L) { - RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); - lua_pushnumber(L, ren_get_font_subpixel_scale(*self)); + FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT); + lua_pushnumber(L, ren_get_font_subpixel_scale(self)); return 1; } - static int f_get_width_subpixel(lua_State *L) { - RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT); const char *text = luaL_checkstring(L, 2); - lua_pushnumber(L, ren_get_font_width(*self, text, NULL)); + int subpixel_scale; + /* We need to pass a non-null subpixel_scale pointer to force + subpixel width calculation. */ + lua_pushnumber(L, ren_get_font_width(self, text, &subpixel_scale)); return 1; } static int f_get_height(lua_State *L) { - RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); - lua_pushnumber(L, ren_get_font_height(*self) ); + FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT); + lua_pushnumber(L, ren_get_font_height(self) ); return 1; } diff --git a/src/api/system.c b/src/api/system.c index 826ad5c1..8fd00056 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -109,10 +109,9 @@ top: case SDL_WINDOWEVENT: if (e.window.event == SDL_WINDOWEVENT_RESIZED) { - ren_resize(); + ren_setup_renderer(); lua_pushstring(L, "resized"); - /* The size below can be wrong on Retina display by a multiplicative factor - but the size reported below is not currently used. */ + /* The size below will be in points. */ lua_pushnumber(L, e.window.data1); lua_pushnumber(L, e.window.data2); return 3; @@ -319,7 +318,7 @@ static int f_set_window_size(lua_State *L) { double y = luaL_checknumber(L, 4); SDL_SetWindowSize(window, w, h); SDL_SetWindowPosition(window, x, y); - ren_resize(); + ren_setup_renderer(); return 0; } diff --git a/src/fontdesc.c b/src/fontdesc.c new file mode 100644 index 00000000..8414a73d --- /dev/null +++ b/src/fontdesc.c @@ -0,0 +1,53 @@ +#include "fontdesc.h" +#include "renderer.h" + +void font_desc_set_tab_size(FontDesc *font_desc, int tab_size) { + font_desc->tab_size = tab_size; + for (int i = 0; i < font_desc->fonts_scale_length; i++) { + ren_set_font_tab_size(font_desc->fonts_scale[i].font, tab_size); + } +} + +int font_desc_get_tab_size(FontDesc *font_desc) { + return font_desc->tab_size; +} + +void font_desc_free(FontDesc *font_desc) { + for (int i = 0; i < font_desc->fonts_scale_length; i++) { + ren_free_font(font_desc->fonts_scale[i].font); + } + font_desc->fonts_scale_length = 0; + free(font_desc->filename); +} + +static void load_scaled_font(FontDesc *font_desc, int index, int scale) { + RenFont *font = ren_load_font(font_desc->filename, scale * font_desc->size, font_desc->options); + font_desc->fonts_scale[index].font = font; + font_desc->fonts_scale[index].scale = scale; +} + +RenFont *font_desc_get_font_at_scale(FontDesc *font_desc, int scale) { + int index = -1; + for (int i = 0; i < font_desc->fonts_scale_length; i++) { + if (font_desc->fonts_scale[i].scale == scale) { + index = i; + break; + } + } + if (index < 0) { + index = font_desc->fonts_scale_length; + if (index < FONT_SCALE_ARRAY_MAX) { + load_scaled_font(font_desc, index, scale); + font_desc->fonts_scale_length = index + 1; + } else { + // FIXME: should not print into the stderr or stdout. + fprintf(stderr, "Warning: max array of font scale reached.\n"); + index = (font_desc->recent_font_scale_index == 0 ? 1 : 0); + ren_free_font(font_desc->fonts_scale[index].font); + load_scaled_font(font_desc, index, scale); + } + } + font_desc->recent_font_scale_index = index; + return font_desc->fonts_scale[index].font; +} + diff --git a/src/fontdesc.h b/src/fontdesc.h new file mode 100644 index 00000000..d0326ca4 --- /dev/null +++ b/src/fontdesc.h @@ -0,0 +1,33 @@ +#ifndef FONT_DESC_H +#define FONT_DESC_H + +typedef struct RenFont RenFont; + +// FIXME: find a better name for the struct below +struct FontScaled { + RenFont *font; + short int scale; +}; +typedef struct FontScaled FontScaled; + +#define FONT_SCALE_ARRAY_MAX 2 + +struct FontDesc { + char *filename; + float size; + unsigned int options; + short int tab_size; +// FIXME: find a better name for the array below + FontScaled fonts_scale[FONT_SCALE_ARRAY_MAX]; + short int fonts_scale_length; + short int recent_font_scale_index; /* More recently scale used. */ +}; +typedef struct FontDesc FontDesc; + +int font_desc_get_tab_size(FontDesc *font_desc); +void font_desc_set_tab_size(FontDesc *font_desc, int tab_size); +void font_desc_free(FontDesc *font_desc); +RenFont *font_desc_get_font_at_scale(FontDesc *font_desc, int scale); + +#endif + diff --git a/src/meson.build b/src/meson.build index 2800d3d4..ed287bb8 100644 --- a/src/meson.build +++ b/src/meson.build @@ -5,6 +5,7 @@ lite_sources = [ 'api/renderer_font.c', 'api/system.c', 'renderer.c', + 'fontdesc.c', 'rencache.c', 'main.c', ] diff --git a/src/rencache.c b/src/rencache.c index 3d607094..36734b24 100644 --- a/src/rencache.c +++ b/src/rencache.c @@ -24,7 +24,7 @@ typedef struct { int32_t size; RenRect rect; RenColor color; - RenFont *font; + FontDesc *font_desc; CPReplaceTable *replacements; RenColor replace_color; char text[0]; @@ -115,9 +115,9 @@ void rencache_show_debug(bool enable) { } -void rencache_free_font(RenFont *font) { +void rencache_free_font(FontDesc *font_desc) { Command *cmd = push_command(FREE_FONT, COMMAND_BARE_SIZE); - if (cmd) { cmd->font = font; } + if (cmd) { cmd->font_desc = font_desc; } } @@ -136,17 +136,17 @@ void rencache_draw_rect(RenRect rect, RenColor color) { } } -int rencache_draw_text(RenFont *font, +int rencache_draw_text(FontDesc *font_desc, const char *text, int x, int y, RenColor color, bool draw_subpixel, CPReplaceTable *replacements, RenColor replace_color) { int subpixel_scale; - int w_subpixel = ren_get_font_width(font, text, &subpixel_scale); + int w_subpixel = ren_get_font_width(font_desc, text, &subpixel_scale); RenRect rect; rect.x = (draw_subpixel ? ren_font_subpixel_round(x, subpixel_scale, -1) : x); rect.y = y; rect.width = ren_font_subpixel_round(w_subpixel, subpixel_scale, 0); - rect.height = ren_get_font_height(font); + rect.height = ren_get_font_height(font_desc); if (rects_overlap(screen_rect, rect)) { int sz = strlen(text) + 1; @@ -154,11 +154,11 @@ int rencache_draw_text(RenFont *font, if (cmd) { memcpy(cmd->text, text, sz); cmd->color = color; - cmd->font = font; + cmd->font_desc = font_desc; cmd->rect = rect; cmd->subpixel_scale = (draw_subpixel ? subpixel_scale : 1); cmd->x_subpixel_offset = x - subpixel_scale * rect.x; - cmd->tab_size = ren_get_font_tab_size(font); + cmd->tab_size = font_desc_get_tab_size(font_desc); cmd->replacements = replacements; cmd->replace_color = replace_color; } @@ -272,13 +272,13 @@ void rencache_end_frame(void) { ren_draw_rect(cmd->rect, cmd->color); break; case DRAW_TEXT: - ren_set_font_tab_size(cmd->font, cmd->tab_size); - ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color, + font_desc_set_tab_size(cmd->font_desc, cmd->tab_size); + ren_draw_text(cmd->font_desc, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color, cmd->replacements, cmd->replace_color); break; case DRAW_TEXT_SUBPIXEL: - ren_set_font_tab_size(cmd->font, cmd->tab_size); - ren_draw_text_subpixel(cmd->font, cmd->text, + font_desc_set_tab_size(cmd->font_desc, cmd->tab_size); + ren_draw_text_subpixel(cmd->font_desc, cmd->text, cmd->subpixel_scale * cmd->rect.x + cmd->x_subpixel_offset, cmd->rect.y, cmd->color, cmd->replacements, cmd->replace_color); break; @@ -301,7 +301,7 @@ void rencache_end_frame(void) { cmd = NULL; while (next_command(&cmd)) { if (cmd->type == FREE_FONT) { - ren_free_font(cmd->font); + font_desc_free(cmd->font_desc); } } } diff --git a/src/rencache.h b/src/rencache.h index a532c9b5..b5c241ab 100644 --- a/src/rencache.h +++ b/src/rencache.h @@ -5,10 +5,11 @@ #include "renderer.h" void rencache_show_debug(bool enable); -void rencache_free_font(RenFont *font); +void rencache_free_font(FontDesc *font_desc); void rencache_set_clip_rect(RenRect rect); void rencache_draw_rect(RenRect rect, RenColor color); -int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color, bool draw_subpixel, CPReplaceTable *replacements, RenColor replace_color); +int rencache_draw_text(FontDesc *font_desc, const char *text, int x, int y, RenColor color, + bool draw_subpixel, CPReplaceTable *replacements, RenColor replace_color); void rencache_invalidate(void); void rencache_begin_frame(void); void rencache_end_frame(void); diff --git a/src/renderer.c b/src/renderer.c index b48bf3d2..e4e9dcbf 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -32,13 +32,16 @@ struct RenFont { }; -static SDL_Window *window; -static SDL_Renderer *window_renderer = NULL; -static SDL_Texture *window_texture = NULL; -static SDL_Surface *window_surface = NULL; -static int window_w = -1, window_h = -1; +struct Renderer { + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Texture *texture; + SDL_Surface *surface; + FR_Clip_Area clip; /* Clipping rect in pixel coordinates. */ + int surface_scale; +}; -static FR_Clip_Area clip; +static struct Renderer renderer = {0}; static void* check_alloc(void *ptr) { if (!ptr) { @@ -66,18 +69,30 @@ static const char* utf8_to_codepoint(const char *p, unsigned *dst) { } -static void init_window_surface() { - if (window_surface) { - SDL_FreeSurface(window_surface); - } - SDL_GL_GetDrawableSize(window, &window_w, &window_h); - window_surface = SDL_CreateRGBSurfaceWithFormat(0, window_w, window_h, 32, SDL_PIXELFORMAT_BGRA32); - ren_set_clip_rect( (RenRect) { 0, 0, window_w, window_h } ); +static int get_surface_scale() { + int w_pixels, h_pixels; + int w_points, h_points; + SDL_GL_GetDrawableSize(renderer.window, &w_pixels, &h_pixels); + SDL_GetWindowSize(renderer.window, &w_points, &h_points); + // FIXME: this assert is too harsh. + assert(w_pixels % w_points == 0 && h_pixels % h_points == 0 && w_pixels / w_points == h_pixels / h_points); + return w_pixels / w_points; } -static SDL_Surface *get_window_surface() { - return window_surface; +static FR_Clip_Area scaled_clip(const RenRect rect, const int scale) { + return (FR_Clip_Area) {rect.x * scale, rect.y * scale, (rect.x + rect.width) * scale, (rect.y + rect.height) * scale}; +} + + +static void init_window_surface() { + if (renderer.surface) { + SDL_FreeSurface(renderer.surface); + } + int w, h; + SDL_GL_GetDrawableSize(renderer.window, &w, &h); + renderer.surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_BGRA32); + renderer.clip = scaled_clip((RenRect) { 0, 0, w, h }, 1); } @@ -112,37 +127,39 @@ void ren_cp_replace_add(CPReplaceTable *rep_table, const char *src, const char * } void ren_free_window_resources() { - SDL_DestroyWindow(window); - SDL_DestroyRenderer(window_renderer); - SDL_DestroyTexture(window_texture); - window = NULL; - window_renderer = NULL; + SDL_DestroyWindow(renderer.window); + SDL_DestroyRenderer(renderer.renderer); + SDL_DestroyTexture(renderer.texture); + renderer.window = NULL; + renderer.renderer = NULL; } static void setup_renderer(int w, int h) { /* Note that w and h here should always be in pixels and obtained from a call to SDL_GL_GetDrawableSize(). */ - if (window_renderer) { - SDL_DestroyRenderer(window_renderer); - SDL_DestroyTexture(window_texture); + if (renderer.renderer) { + SDL_DestroyRenderer(renderer.renderer); + SDL_DestroyTexture(renderer.texture); } - window_renderer = SDL_CreateRenderer(window, -1, 0); + renderer.renderer = SDL_CreateRenderer(renderer.window, -1, 0); // May be we could use: SDL_CreateTextureFromSurface(sdlRenderer, mySurface); - window_texture = SDL_CreateTexture(window_renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_STREAMING, w, h); + renderer.texture = SDL_CreateTexture(renderer.renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_STREAMING, w, h); + renderer.surface_scale = get_surface_scale(); } void ren_init(SDL_Window *win) { assert(win); - window = win; + renderer.window = win; init_window_surface(); + renderer.surface_scale = get_surface_scale(); } -void ren_resize() { +void ren_setup_renderer() { int new_w, new_h; - SDL_GL_GetDrawableSize(window, &new_w, &new_h); + SDL_GL_GetDrawableSize(renderer.window, &new_w, &new_h); /* Note that (w, h) may differ from (new_w, new_h) on retina displays. */ - if (new_w != window_h || new_h != window_h) { + if (new_w != renderer.surface->w || new_h != renderer.surface->h) { init_window_surface(); setup_renderer(new_w, new_h); } @@ -153,31 +170,28 @@ void ren_update_rects(RenRect *rects, int count) { static bool initial_frame = true; if (initial_frame) { int w, h; - SDL_ShowWindow(window); - SDL_GL_GetDrawableSize(window, &w, &h); + SDL_ShowWindow(renderer.window); + SDL_GL_GetDrawableSize(renderer.window, &w, &h); setup_renderer(w, h); initial_frame = false; } // FIXME: we ignore the rects here. - SDL_UpdateTexture(window_texture, NULL, window_surface->pixels, window_w * 4); - SDL_RenderCopy(window_renderer, window_texture, NULL, NULL); - SDL_RenderPresent(window_renderer); + SDL_UpdateTexture(renderer.texture, NULL, renderer.surface->pixels, renderer.surface->w * 4); + SDL_RenderCopy(renderer.renderer, renderer.texture, NULL, NULL); + SDL_RenderPresent(renderer.renderer); } void ren_set_clip_rect(RenRect rect) { - clip.left = rect.x; - clip.top = rect.y; - clip.right = rect.x + rect.width; - clip.bottom = rect.y + rect.height; + renderer.clip = scaled_clip(rect, renderer.surface_scale); } void ren_get_size(int *x, int *y) { - SDL_Surface *surf = get_window_surface(); - *x = surf->w; - *y = surf->h; + const int scale = renderer.surface_scale; + *x = renderer.surface->w / scale; + *y = renderer.surface->h / scale; } @@ -214,6 +228,17 @@ static GlyphSet* get_glyphset(RenFont *font, int codepoint) { } +int ren_verify_font(const char *filename) { + RenFont font[1]; + font->renderer = FR_Renderer_New(0); + if (FR_Load_Font(font->renderer, filename)) { + return 1; + } + FR_Renderer_Free(font->renderer); + return 0; +} + + RenFont* ren_load_font(const char *filename, float size, unsigned int renderer_flags) { RenFont *font = NULL; @@ -274,25 +299,34 @@ int ren_get_font_tab_size(RenFont *font) { } -int ren_get_font_width(RenFont *font, const char *text, int *subpixel_scale) { +/* Important: if subpixel_scale is NULL we will return width in points. Otherwise we will + return width in subpixels. */ +int ren_get_font_width(FontDesc *font_desc, const char *text, int *subpixel_scale) { int x = 0; const char *p = text; unsigned codepoint; + const int surface_scale = renderer.surface_scale; + RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale); while (*p) { p = utf8_to_codepoint(p, &codepoint); GlyphSet *set = get_glyphset(font, codepoint); FR_Bitmap_Glyph_Metrics *g = &set->glyphs[codepoint & 0xff]; x += g->xadvance; } + /* At this point here x is in subpixel units */ + const int x_scale_to_points = FR_Subpixel_Scale(font->renderer) * surface_scale; if (subpixel_scale) { - *subpixel_scale = FR_Subpixel_Scale(font->renderer); + *subpixel_scale = x_scale_to_points; + return x; } - return x; + return (x + x_scale_to_points / 2) / x_scale_to_points; } -int ren_get_font_height(RenFont *font) { - return font->height; +int ren_get_font_height(FontDesc *font_desc) { + const int surface_scale = renderer.surface_scale; + RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale); + return (font->height + surface_scale / 2) / surface_scale; } @@ -305,16 +339,6 @@ static inline RenColor blend_pixel(RenColor dst, RenColor src) { } -static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color) { - src.a = (src.a * color.a) >> 8; - int ia = 0xff - src.a; - dst.r = ((src.r * color.r * src.a) >> 16) + ((dst.r * ia) >> 8); - dst.g = ((src.g * color.g * src.a) >> 16) + ((dst.g * ia) >> 8); - dst.b = ((src.b * color.b * src.a) >> 16) + ((dst.b * ia) >> 8); - return dst; -} - - #define rect_draw_loop(expr) \ for (int j = y1; j < y2; j++) { \ for (int i = x1; i < x2; i++) { \ @@ -327,17 +351,24 @@ static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color) void ren_draw_rect(RenRect rect, RenColor color) { if (color.a == 0) { return; } - int x1 = rect.x < clip.left ? clip.left : rect.x; - int y1 = rect.y < clip.top ? clip.top : rect.y; + const int surface_scale = renderer.surface_scale; + + /* transforms coordinates in pixels. */ + rect.x *= surface_scale; + rect.y *= surface_scale; + rect.width *= surface_scale; + rect.height *= surface_scale; + + int x1 = rect.x < renderer.clip.left ? renderer.clip.left : rect.x; + int y1 = rect.y < renderer.clip.top ? renderer.clip.top : rect.y; int x2 = rect.x + rect.width; int y2 = rect.y + rect.height; - x2 = x2 > clip.right ? clip.right : x2; - y2 = y2 > clip.bottom ? clip.bottom : y2; + x2 = x2 > renderer.clip.right ? renderer.clip.right : x2; + y2 = y2 > renderer.clip.bottom ? renderer.clip.bottom : y2; - SDL_Surface *surf = get_window_surface(); - RenColor *d = (RenColor*) surf->pixels; - d += x1 + y1 * surf->w; - int dr = surf->w - (x2 - x1); + RenColor *d = (RenColor*) renderer.surface->pixels; + d += x1 + y1 * renderer.surface->w; + int dr = renderer.surface->w - (x2 - x1); if (color.a == 0xff) { rect_draw_loop(color); @@ -358,13 +389,12 @@ static int codepoint_replace(CPReplaceTable *rep_table, unsigned *codepoint) { return 0; } - -void ren_draw_text_subpixel(RenFont *font, const char *text, int x_subpixel, int y, RenColor color, +static void draw_text_impl(RenFont *font, const char *text, int x_subpixel, int y_pixel, RenColor color, CPReplaceTable *replacements, RenColor replace_color) { + SDL_Surface *surf = renderer.surface; const char *p = text; unsigned codepoint; - SDL_Surface *surf = get_window_surface(); const FR_Color color_fr = { .r = color.r, .g = color.g, .b = color.b }; while (*p) { FR_Color color_rep; @@ -381,18 +411,29 @@ void ren_draw_text_subpixel(RenFont *font, const char *text, int x_subpixel, int color_rep = color_fr; } if (color.a != 0) { - FR_Blend_Glyph(font->renderer, &clip, - x_subpixel, y, (uint8_t *) surf->pixels, surf->w, set->image, g, color_rep); + FR_Blend_Glyph(font->renderer, &renderer.clip, + x_subpixel, y_pixel, (uint8_t *) surf->pixels, surf->w, set->image, g, color_rep); } x_subpixel += xadvance_original_cp; } } -void ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color, + +void ren_draw_text_subpixel(FontDesc *font_desc, const char *text, int x_subpixel, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color) { - const int subpixel_scale = FR_Subpixel_Scale(font->renderer); - ren_draw_text_subpixel(font, text, subpixel_scale * x, y, color, replacements, replace_color); + const int surface_scale = renderer.surface_scale; + RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale); + draw_text_impl(font, text, x_subpixel, surface_scale * y, color, replacements, replace_color); +} + +void ren_draw_text(FontDesc *font_desc, const char *text, int x, int y, RenColor color, + CPReplaceTable *replacements, RenColor replace_color) +{ + const int surface_scale = renderer.surface_scale; + RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale); + const int subpixel_scale = surface_scale * FR_Subpixel_Scale(font->renderer); + draw_text_impl(font, text, subpixel_scale * x, surface_scale * y, color, replacements, replace_color); } // Could be declared as static inline @@ -409,7 +450,8 @@ int ren_font_subpixel_round(int width, int subpixel_scale, int orientation) { } -int ren_get_font_subpixel_scale(RenFont *font) { - return FR_Subpixel_Scale(font->renderer); +int ren_get_font_subpixel_scale(FontDesc *font_desc) { + const int surface_scale = renderer.surface_scale; + RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale); + return FR_Subpixel_Scale(font->renderer) * surface_scale; } - diff --git a/src/renderer.h b/src/renderer.h index f11d8e64..7638466b 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -3,9 +3,9 @@ #include #include +#include "fontdesc.h" typedef struct RenImage RenImage; -typedef struct RenFont RenFont; enum { RenFontAntialiasingMask = 1, @@ -36,27 +36,29 @@ typedef struct CPReplaceTable CPReplaceTable; void ren_init(SDL_Window *win); -void ren_resize(); +void ren_setup_renderer(); void ren_update_rects(RenRect *rects, int count); void ren_set_clip_rect(RenRect rect); -void ren_get_size(int *x, int *y); +void ren_get_size(int *x, int *y); /* Reports the size in points. */ void ren_free_window_resources(); RenImage* ren_new_image(int width, int height); void ren_free_image(RenImage *image); RenFont* ren_load_font(const char *filename, float size, unsigned int renderer_flags); +int ren_verify_font(const char *filename); void ren_free_font(RenFont *font); void ren_set_font_tab_size(RenFont *font, int n); int ren_get_font_tab_size(RenFont *font); -int ren_get_font_width(RenFont *font, const char *text, int *subpixel_scale); -int ren_get_font_height(RenFont *font); -int ren_get_font_subpixel_scale(RenFont *font); + +int ren_get_font_width(FontDesc *font_desc, const char *text, int *subpixel_scale); +int ren_get_font_height(FontDesc *font_desc); +int ren_get_font_subpixel_scale(FontDesc *font_desc); int ren_font_subpixel_round(int width, int subpixel_scale, int orientation); void ren_draw_rect(RenRect rect, RenColor color); -void ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color); -void ren_draw_text_subpixel(RenFont *font, const char *text, int x_subpixel, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color); +void ren_draw_text(FontDesc *font_desc, const char *text, int x, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color); +void ren_draw_text_subpixel(FontDesc *font_desc, const char *text, int x_subpixel, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color); void ren_cp_replace_init(CPReplaceTable *rep_table); void ren_cp_replace_free(CPReplaceTable *rep_table);