First implementation of scaling for retina display

Introduce a new approach that discriminate coordinates in
points and pixels. Now all the logic from the Lua side and in
rencache is to always use points. The coordinates are converted
to pixels only within the renderer, in the file renderer.c.
In this way the application logic does not need to care about the
scaling of the retina displays.

For non-retina display the scaling between points and pixels is
equal to one so nothing will change.

There is nevertheless a change that leak into the Lua side. The
subpixel coordinates are in sub-pixel, not sub-points so they are
scaled by the retina scaling factor. But no change in the code is
required because the subpixel scaling factor take into account the
retina scaling, when present.

Because the retina scaling factor is not know when the application
starts but only when a window is actually available we introduce a
mechanism to render the font with a given scaling factor only from
the renderer when they are needed. We use therefore FontDesc to
describe the font information but without actually rasterizing the
font at a given scale.
This commit is contained in:
Francesco Abbate
2021-04-26 15:16:34 +02:00
parent 57e6de978b
commit 46c3bdea67
10 changed files with 272 additions and 126 deletions
+4 -4
View File
@@ -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 }
};
+35 -20
View File
@@ -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;
}
+3 -4
View File
@@ -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;
}