Cleanups for font drivers

This commit is contained in:
libretroadmin 2023-06-15 12:36:44 +02:00
parent 1fc5c600a4
commit ae3ac72356
6 changed files with 167 additions and 167 deletions

View File

@ -37,16 +37,16 @@
typedef struct d3d9x_font_desc typedef struct d3d9x_font_desc
{ {
INT Height; INT Height;
UINT Width; UINT Width;
UINT Weight; UINT Weight;
UINT MipLevels; UINT MipLevels;
BOOL Italic; BOOL Italic;
BYTE CharSet; BYTE CharSet;
BYTE OutputPrecision; BYTE OutputPrecision;
BYTE Quality; BYTE Quality;
BYTE PitchAndFamily; BYTE PitchAndFamily;
CHAR FaceName[32]; CHAR FaceName[32];
} d3d9x_font_desc_t; } d3d9x_font_desc_t;
typedef struct typedef struct
@ -57,42 +57,28 @@ typedef struct
uint32_t ascent; uint32_t ascent;
} d3dfonts_t; } d3dfonts_t;
static void d3d9x_font_release(ID3DXFont *font)
{
font->lpVtbl->Release(font);
}
static void d3d9x_font_get_text_metrics(ID3DXFont *font, TEXTMETRICA *metrics)
{
font->lpVtbl->GetTextMetrics(font, metrics);
}
static void d3d9x_font_draw_text(ID3DXFont *font, LPD3DXSPRITE sprite_data, LPCTSTR string_data,
unsigned count, LPRECT rect_data, DWORD format, D3DCOLOR color)
{
font->lpVtbl->DrawText(font, sprite_data,
string_data, count, rect_data, format, color);
}
static void *d3d9x_win32_font_init(void *video_data, static void *d3d9x_win32_font_init(void *video_data,
const char *font_path, float font_size, const char *font_path, float font_size,
bool is_threaded) bool is_threaded)
{ {
TEXTMETRICA metrics; TEXTMETRICA metrics;
d3d9x_font_desc_t desc; d3d9x_font_desc_t desc;
d3dfonts_t *d3dfonts = (d3dfonts_t*)calloc(1, sizeof(*d3dfonts)); uint32_t new_font_size = 0;
ID3DXFont *font = NULL;
d3dfonts_t *d3dfonts = (d3dfonts_t*)calloc(1, sizeof(*d3dfonts));
if (!d3dfonts) if (!d3dfonts)
return NULL; return NULL;
desc.Height = (int)font_size; desc.Height = (int)font_size;
desc.Width = 0; desc.Width = 0;
desc.Weight = 400; desc.Weight = 400;
desc.MipLevels = 0; desc.MipLevels = 0;
desc.Italic = FALSE; desc.Italic = FALSE;
desc.CharSet = DEFAULT_CHARSET; desc.CharSet = DEFAULT_CHARSET;
desc.OutputPrecision = OUT_TT_PRECIS; desc.OutputPrecision = OUT_TT_PRECIS;
desc.Quality = CLIP_DEFAULT_PRECIS; desc.Quality = CLIP_DEFAULT_PRECIS;
desc.PitchAndFamily = DEFAULT_PITCH; desc.PitchAndFamily = DEFAULT_PITCH;
/* TODO/FIXME - don't hardcode this font */ /* TODO/FIXME - don't hardcode this font */
#ifdef UNICODE #ifdef UNICODE
strlcpy(desc.FaceName, T(L"Verdana"), sizeof(desc.FaceName)); strlcpy(desc.FaceName, T(L"Verdana"), sizeof(desc.FaceName));
@ -100,18 +86,21 @@ static void *d3d9x_win32_font_init(void *video_data,
strlcpy(desc.FaceName, (const char*)_T("Verdana"), sizeof(desc.FaceName)); strlcpy(desc.FaceName, (const char*)_T("Verdana"), sizeof(desc.FaceName));
#endif #endif
d3dfonts->font_size = font_size * 1.2; /* To match the other font drivers */ new_font_size = font_size * 1.2; /* To match the other font drivers */
d3dfonts->d3d = (d3d9_video_t*)video_data; d3dfonts->font_size = new_font_size;
d3dfonts->d3d = (d3d9_video_t*)video_data;
desc.Height = d3dfonts->font_size; desc.Height = new_font_size;
if (!d3d9x_create_font_indirect(d3dfonts->d3d->dev, if (!d3d9x_create_font_indirect(d3dfonts->d3d->dev,
&desc, (void**)&d3dfonts->font)) &desc, (void**)&d3dfonts->font))
goto error; goto error;
d3d9x_font_get_text_metrics(d3dfonts->font, &metrics); font = d3dfonts->font;
d3dfonts->ascent = metrics.tmAscent; font->lpVtbl->GetTextMetrics(font, &metrics);
d3dfonts->ascent = metrics.tmAscent;
return d3dfonts; return d3dfonts;
@ -122,13 +111,16 @@ error:
static void d3d9x_win32_font_free(void *data, bool is_threaded) static void d3d9x_win32_font_free(void *data, bool is_threaded)
{ {
ID3DXFont *font = NULL;
d3dfonts_t *d3dfonts = (d3dfonts_t*)data; d3dfonts_t *d3dfonts = (d3dfonts_t*)data;
if (!d3dfonts) if (!d3dfonts)
return; return;
if (d3dfonts->font) font = d3dfonts->font;
d3d9x_font_release((ID3DXFont*)d3dfonts->font);
if (font)
font->lpVtbl->Release(font);
free(d3dfonts); free(d3dfonts);
} }
@ -138,12 +130,15 @@ static int d3d9x_win32_font_get_message_width(void* data, const char* msg,
{ {
RECT box = {0,0,0,0}; RECT box = {0,0,0,0};
d3dfonts_t *d3dfonts = (d3dfonts_t*)data; d3dfonts_t *d3dfonts = (d3dfonts_t*)data;
ID3DXFont *font = NULL;
if (!d3dfonts || !msg) if (!d3dfonts || !msg)
return 0; return 0;
d3d9x_font_draw_text(d3dfonts->font, NULL, (void*)msg, font = d3dfonts->font;
msg_len ? msg_len : -1, &box, DT_CALCRECT, 0);
font->lpVtbl->DrawText(font, NULL,
(void*)msg, msg_len ? (INT)msg_len : -1, &box, DT_CALCRECT, 0);
return box.right - box.left; return box.right - box.left;
} }
@ -159,6 +154,7 @@ static void d3d9x_win32_font_render_msg(
RECT rect, rect_shifted; RECT rect, rect_shifted;
RECT *p_rect_shifted = NULL; RECT *p_rect_shifted = NULL;
RECT *p_rect = NULL; RECT *p_rect = NULL;
ID3DXFont *font = NULL;
d3dfonts_t *d3dfonts = (d3dfonts_t*)data; d3dfonts_t *d3dfonts = (d3dfonts_t*)data;
float drop_mod = 0.3f; float drop_mod = 0.3f;
float drop_alpha = 1.0f; float drop_alpha = 1.0f;
@ -168,6 +164,8 @@ static void d3d9x_win32_font_render_msg(
if (!d3dfonts || !msg) if (!d3dfonts || !msg)
return; return;
font = d3dfonts->font;
width = d3dfonts->d3d->video_info.width; width = d3dfonts->d3d->video_info.width;
height = d3dfonts->d3d->video_info.height; height = d3dfonts->d3d->video_info.height;
@ -242,13 +240,14 @@ static void d3d9x_win32_font_render_msg(
unsigned drop_g = g * drop_mod; unsigned drop_g = g * drop_mod;
unsigned drop_b = b * drop_mod; unsigned drop_b = b * drop_mod;
d3d9x_font_draw_text(d3dfonts->font, NULL, font->lpVtbl->DrawText(font, NULL,
(void*)msg, -1, p_rect_shifted, format, (void*)msg, -1, p_rect_shifted, format,
D3DCOLOR_ARGB(drop_a , drop_r, drop_g, drop_b)); D3DCOLOR_ARGB(drop_a , drop_r, drop_g, drop_b));
} }
d3d9x_font_draw_text(d3dfonts->font, NULL, (void*)msg, -1, font->lpVtbl->DrawText(font, NULL,
p_rect, format, D3DCOLOR_ARGB(a, r, g, b)); (void*)msg, -1, p_rect, format,
D3DCOLOR_ARGB(a, r, g, b));
} }
font_renderer_t d3d9x_win32_font = { font_renderer_t d3d9x_win32_font = {

View File

@ -55,8 +55,7 @@ bitmapfont_lut_t *bitmapfont_get_lut(void)
size_t i, j; size_t i, j;
/* Initialise font struct */ /* Initialise font struct */
font = (bitmapfont_lut_t*)calloc(1, sizeof(bitmapfont_lut_t)); if (!(font = (bitmapfont_lut_t*)calloc(1, sizeof(bitmapfont_lut_t))))
if (!font)
goto error; goto error;
font->glyph_min = 0; font->glyph_min = 0;
@ -109,8 +108,8 @@ void bitmapfont_free_lut(bitmapfont_lut_t *font)
if (font->lut) if (font->lut)
{ {
size_t num_glyphs = (font->glyph_max - font->glyph_min) + 1;
size_t i; size_t i;
size_t num_glyphs = (font->glyph_max - font->glyph_min) + 1;
for (i = 0; i < num_glyphs; i++) for (i = 0; i < num_glyphs; i++)
{ {
@ -137,9 +136,9 @@ static const struct font_glyph *font_renderer_bmp_get_glyph(
void *data, uint32_t code) void *data, uint32_t code)
{ {
bm_renderer_t *handle = (bm_renderer_t*)data; bm_renderer_t *handle = (bm_renderer_t*)data;
if (!handle) if (handle && (code < BMP_ATLAS_SIZE))
return NULL; return &handle->glyphs[code];
return code < BMP_ATLAS_SIZE ? &handle->glyphs[code] : NULL; return NULL;
} }
static void char_to_texture(bm_renderer_t *handle, uint8_t letter, static void char_to_texture(bm_renderer_t *handle, uint8_t letter,
@ -174,26 +173,23 @@ static void char_to_texture(bm_renderer_t *handle, uint8_t letter,
static void *font_renderer_bmp_init(const char *font_path, float font_size) static void *font_renderer_bmp_init(const char *font_path, float font_size)
{ {
unsigned i; unsigned i;
bm_renderer_t *handle = (bm_renderer_t*)calloc(1, sizeof(*handle)); bm_renderer_t *handle = (bm_renderer_t*)calloc(1, sizeof(*handle));
if (!handle) if (!handle)
return NULL; return NULL;
(void)font_path; if (!(handle->scale_factor = (unsigned)roundf(font_size / FONT_HEIGHT)))
handle->scale_factor = (unsigned)roundf(font_size / FONT_HEIGHT);
if (!handle->scale_factor)
handle->scale_factor = 1; handle->scale_factor = 1;
handle->atlas.width = (BMP_ATLAS_PADDING + (FONT_WIDTH * handle->scale_factor)) * BMP_ATLAS_COLS; handle->atlas.width = (BMP_ATLAS_PADDING + (FONT_WIDTH * handle->scale_factor)) * BMP_ATLAS_COLS;
handle->atlas.height = (BMP_ATLAS_PADDING + (FONT_HEIGHT * handle->scale_factor)) * BMP_ATLAS_ROWS; handle->atlas.height = (BMP_ATLAS_PADDING + (FONT_HEIGHT * handle->scale_factor)) * BMP_ATLAS_ROWS;
handle->atlas.buffer = (uint8_t*)calloc(handle->atlas.width * handle->atlas.height, 1); handle->atlas.buffer = (uint8_t*)calloc(handle->atlas.width * handle->atlas.height, 1);
for (i = 0; i < BMP_ATLAS_SIZE; i++) for (i = 0; i < BMP_ATLAS_SIZE; i++)
{ {
unsigned x = (i % BMP_ATLAS_COLS) * unsigned x = (i % BMP_ATLAS_COLS) *
(BMP_ATLAS_PADDING + (handle->scale_factor * FONT_WIDTH)); (BMP_ATLAS_PADDING + (handle->scale_factor * FONT_WIDTH));
unsigned y = (i / BMP_ATLAS_COLS) * unsigned y = (i / BMP_ATLAS_COLS) *
(BMP_ATLAS_PADDING + (handle->scale_factor * FONT_HEIGHT)); (BMP_ATLAS_PADDING + (handle->scale_factor * FONT_HEIGHT));
char_to_texture(handle, i, x, y); char_to_texture(handle, i, x, y);

View File

@ -41,10 +41,10 @@
typedef struct coretext_atlas_slot typedef struct coretext_atlas_slot
{ {
struct font_glyph glyph; struct font_glyph glyph;
unsigned charcode; unsigned charcode;
unsigned last_used; unsigned last_used;
struct coretext_atlas_slot *next; struct coretext_atlas_slot *next;
} coretext_atlas_slot_t; } coretext_atlas_slot_t;
typedef struct coretext_renderer typedef struct coretext_renderer
@ -90,7 +90,6 @@ static void font_renderer_ct_free(void *data)
static bool coretext_font_renderer_create_atlas(CTFontRef face, ct_font_renderer_t *handle) static bool coretext_font_renderer_create_atlas(CTFontRef face, ct_font_renderer_t *handle)
{ {
int max_width, max_height;
unsigned i; unsigned i;
size_t bytesPerRow; size_t bytesPerRow;
CGGlyph glyphs[CT_ATLAS_SIZE]; CGGlyph glyphs[CT_ATLAS_SIZE];
@ -101,6 +100,8 @@ static bool coretext_font_renderer_create_atlas(CTFontRef face, ct_font_renderer
CFDictionaryRef attr; CFDictionaryRef attr;
CFTypeRef values[1]; CFTypeRef values[1];
CFStringRef keys[1]; CFStringRef keys[1];
int max_height = 0;
int max_width = 0;
void *bitmapData = NULL; void *bitmapData = NULL;
bool ret = true; bool ret = true;
size_t bitsPerComponent = 8; size_t bitsPerComponent = 8;
@ -130,39 +131,36 @@ static bool coretext_font_renderer_create_atlas(CTFontRef face, ct_font_renderer
#endif #endif
glyphs, advances, CT_ATLAS_SIZE); glyphs, advances, CT_ATLAS_SIZE);
ascent = CTFontGetAscent(face); ascent = CTFontGetAscent(face);
descent = CTFontGetDescent(face); descent = CTFontGetDescent(face);
max_width = 0;
max_height = 0;
for (i = 0; i < CT_ATLAS_SIZE; i++) for (i = 0; i < CT_ATLAS_SIZE; i++)
{ {
int origin_x, origin_y; int origin_x, origin_y;
struct font_glyph *glyph = &handle->atlas_slots[i].glyph; struct font_glyph *glyph = &handle->atlas_slots[i].glyph;
if (!glyph) if (!glyph)
continue; continue;
origin_x = ceil(bounds[i].origin.x); origin_x = ceil(bounds[i].origin.x);
origin_y = ceil(bounds[i].origin.y); origin_y = ceil(bounds[i].origin.y);
glyph->draw_offset_x = 0; glyph->draw_offset_x = 0;
glyph->draw_offset_y = -ascent; glyph->draw_offset_y = -ascent;
glyph->width = ceil(bounds[i].size.width); glyph->width = ceil(bounds[i].size.width);
glyph->height = ceil(bounds[i].size.height); glyph->height = ceil(bounds[i].size.height);
glyph->advance_x = ceil(advances[i].width); glyph->advance_x = ceil(advances[i].width);
glyph->advance_y = ceil(advances[i].height); glyph->advance_y = ceil(advances[i].height);
max_width = MAX(max_width, (origin_x + glyph->width)); max_width = MAX(max_width, (origin_x + glyph->width));
max_height = MAX(max_height, (origin_y + glyph->height)); max_height = MAX(max_height, (origin_y + glyph->height));
} }
max_height = MAX(max_height, ceil(ascent+descent)); max_height = MAX(max_height, ceil(ascent+descent));
handle->atlas.width = max_width * CT_ATLAS_COLS;
handle->atlas.height = max_height * CT_ATLAS_ROWS;
handle->atlas.width = max_width * CT_ATLAS_COLS;
handle->atlas.height = max_height * CT_ATLAS_ROWS;
handle->line_metrics.ascender = (float)CTFontGetAscent(face); handle->line_metrics.ascender = (float)CTFontGetAscent(face);
handle->line_metrics.descender = (float)CTFontGetDescent(face); handle->line_metrics.descender = (float)CTFontGetDescent(face);
/* CTFontGetDescent() should return a positive value, /* CTFontGetDescent() should return a positive value,
@ -176,15 +174,16 @@ static bool coretext_font_renderer_create_atlas(CTFontRef face, ct_font_renderer
handle->line_metrics.ascender + handle->line_metrics.descender + handle->line_metrics.ascender + handle->line_metrics.descender +
(float)CTFontGetLeading(face); (float)CTFontGetLeading(face);
handle->atlas.buffer = (uint8_t*) handle->atlas.buffer = (uint8_t*)calloc(
calloc(handle->atlas.width * handle->atlas.height, 1); handle->atlas.width * handle->atlas.height, 1);
if (!handle->atlas.buffer) if (!handle->atlas.buffer)
return false; return false;
bytesPerRow = max_width; bytesPerRow = max_width;
bitmapData = calloc(max_height, bytesPerRow); bitmapData = calloc(max_height, bytesPerRow);
offscreen = CGBitmapContextCreate(bitmapData, max_width, max_height, offscreen = CGBitmapContextCreate(
bitmapData, max_width, max_height,
bitsPerComponent, bytesPerRow, NULL, kCGImageAlphaOnly); bitsPerComponent, bytesPerRow, NULL, kCGImageAlphaOnly);
CGContextSetTextMatrix(offscreen, CGAffineTransformIdentity); CGContextSetTextMatrix(offscreen, CGAffineTransformIdentity);
@ -195,60 +194,60 @@ static bool coretext_font_renderer_create_atlas(CTFontRef face, ct_font_renderer
for (i = 0; i < CT_ATLAS_SIZE; i++) for (i = 0; i < CT_ATLAS_SIZE; i++)
{ {
unsigned offset_x, offset_y, r, c;
char glyph_cstr[2]; char glyph_cstr[2];
const uint8_t *src; const uint8_t *src;
uint8_t *dst; uint8_t *dst;
unsigned offset_x, offset_y, r, c; CTLineRef line;
CFStringRef glyph_cfstr; CFStringRef glyph_cfstr;
CFAttributedStringRef attrString; CFAttributedStringRef attrString;
CTLineRef line;
struct font_glyph *glyph = &handle->atlas_slots[i].glyph; struct font_glyph *glyph = &handle->atlas_slots[i].glyph;
if (!glyph) if (!glyph)
continue; continue;
glyph->width = max_width; glyph->width = max_width;
glyph->height = max_height; glyph->height = max_height;
offset_x = (i % CT_ATLAS_COLS) * max_width; offset_x = (i % CT_ATLAS_COLS) * max_width;
offset_y = (i / CT_ATLAS_COLS) * max_height; offset_y = (i / CT_ATLAS_COLS) * max_height;
glyph->atlas_offset_x = offset_x; glyph->atlas_offset_x = offset_x;
glyph->atlas_offset_y = offset_y; glyph->atlas_offset_y = offset_y;
glyph_cstr[0] = i; glyph_cstr[0] = i;
glyph_cstr[1] = 0; glyph_cstr[1] = 0;
glyph_cfstr = CFStringCreateWithCString( glyph_cfstr = CFStringCreateWithCString(
NULL, glyph_cstr, kCFStringEncodingASCII ); NULL, glyph_cstr, kCFStringEncodingASCII);
attrString = attrString = CFAttributedStringCreate(
CFAttributedStringCreate(NULL, glyph_cfstr, attr); NULL, glyph_cfstr, attr);
CFRelease(glyph_cfstr); CFRelease(glyph_cfstr);
glyph_cfstr = NULL; glyph_cfstr = NULL;
line = CTLineCreateWithAttributedString(attrString); line = CTLineCreateWithAttributedString(
attrString);
CFRelease(attrString); CFRelease(attrString);
attrString = NULL; attrString = NULL;
memset( bitmapData, 0, max_height * bytesPerRow ); memset(bitmapData, 0, max_height * bytesPerRow);
CGContextSetTextPosition(offscreen, 0, descent); CGContextSetTextPosition(offscreen, 0, descent);
CTLineDraw(line, offscreen); CTLineDraw(line, offscreen);
CGContextFlush( offscreen ); CGContextFlush(offscreen);
CFRelease( line ); CFRelease(line);
line = NULL; line = NULL;
dst = (uint8_t*)handle->atlas.buffer; dst = (uint8_t*)handle->atlas.buffer;
src = (const uint8_t*)bitmapData; src = (const uint8_t*)bitmapData;
for (r = 0; r < max_height; r++ ) for (r = 0; r < max_height; r++)
{ {
for (c = 0; c < max_width; c++) for (c = 0; c < max_width; c++)
{ {
unsigned src_idx = (unsigned)(r * bytesPerRow + c); unsigned src_idx = (unsigned)(r * bytesPerRow + c);
unsigned dest_idx = unsigned dest_idx =
(r + offset_y) * (CT_ATLAS_COLS * max_width) + (c + offset_x); (r + offset_y) * (CT_ATLAS_COLS * max_width) + (c + offset_x);
uint8_t v = src[src_idx]; uint8_t v = src[src_idx];
dst[dest_idx] = v;
dst[dest_idx] = v;
} }
} }
} }
@ -256,7 +255,7 @@ static bool coretext_font_renderer_create_atlas(CTFontRef face, ct_font_renderer
CFRelease(attr); CFRelease(attr);
CGContextRelease(offscreen); CGContextRelease(offscreen);
attr = NULL; attr = NULL;
offscreen = NULL; offscreen = NULL;
free(bitmapData); free(bitmapData);
@ -271,7 +270,7 @@ static void *font_renderer_ct_init(const char *font_path, float font_size)
CFURLRef url = NULL; CFURLRef url = NULL;
CGDataProviderRef dataProvider = NULL; CGDataProviderRef dataProvider = NULL;
CGFontRef theCGFont = NULL; CGFontRef theCGFont = NULL;
ct_font_renderer_t *handle = (ct_font_renderer_t*) ct_font_renderer_t *handle = (ct_font_renderer_t*)
calloc(1, sizeof(*handle)); calloc(1, sizeof(*handle));
if (!handle || !path_is_valid(font_path)) if (!handle || !path_is_valid(font_path))
@ -280,10 +279,8 @@ static void *font_renderer_ct_init(const char *font_path, float font_size)
goto error; goto error;
} }
cf_font_path = CFStringCreateWithCString( if (!(cf_font_path = CFStringCreateWithCString(
NULL, font_path, kCFStringEncodingASCII); NULL, font_path, kCFStringEncodingASCII)))
if (!cf_font_path)
{ {
err = 1; err = 1;
goto error; goto error;
@ -319,21 +316,25 @@ error:
CFRelease(cf_font_path); CFRelease(cf_font_path);
cf_font_path = NULL; cf_font_path = NULL;
} }
if (face) if (face)
{ {
CFRelease(face); CFRelease(face);
face = NULL; face = NULL;
} }
if (url) if (url)
{ {
CFRelease(url); CFRelease(url);
url = NULL; url = NULL;
} }
if (dataProvider) if (dataProvider)
{ {
CFRelease(dataProvider); CFRelease(dataProvider);
dataProvider = NULL; dataProvider = NULL;
} }
if (theCGFont) if (theCGFont)
{ {
CFRelease(theCGFont); CFRelease(theCGFont);
@ -343,14 +344,12 @@ error:
return handle; return handle;
} }
/* We can't tell if a font is going to be there until we actually
initialize CoreText and the best way to get fonts is by name, not
by path. */
static const char *default_font = "Verdana";
static const char *font_renderer_ct_get_default_font(void) static const char *font_renderer_ct_get_default_font(void)
{ {
return default_font; /* We can't tell if a font is going to be there until we actually
initialize CoreText and the best way to get fonts is by name, not
by path. */
return "Verdana";
} }
static void font_renderer_ct_get_line_metrics( static void font_renderer_ct_get_line_metrics(

View File

@ -157,10 +157,10 @@ static const struct font_glyph *font_renderer_ft_get_glyph(
FT_Render_Glyph(handle->face->glyph, FT_RENDER_MODE_NORMAL); FT_Render_Glyph(handle->face->glyph, FT_RENDER_MODE_NORMAL);
slot = handle->face->glyph; slot = handle->face->glyph;
atlas_slot = font_renderer_get_slot(handle); atlas_slot = font_renderer_get_slot(handle);
atlas_slot->charcode = charcode; atlas_slot->charcode = charcode;
atlas_slot->next = handle->uc_map[map_id]; atlas_slot->next = handle->uc_map[map_id];
handle->uc_map[map_id] = atlas_slot; handle->uc_map[map_id] = atlas_slot;
/* Some glyphs can be blank. */ /* Some glyphs can be blank. */
atlas_slot->glyph.width = slot->bitmap.width; atlas_slot->glyph.width = slot->bitmap.width;
@ -216,14 +216,15 @@ static bool font_renderer_create_atlas(ft_font_renderer_t *handle, float font_si
unsigned i, x, y; unsigned i, x, y;
freetype_atlas_slot_t* slot = NULL; freetype_atlas_slot_t* slot = NULL;
unsigned max_width = round((handle->face->bbox.xMax - handle->face->bbox.xMin) * font_size / handle->face->units_per_EM); unsigned max_width = round((handle->face->bbox.xMax - handle->face->bbox.xMin)
unsigned max_height = round((handle->face->bbox.yMax - handle->face->bbox.yMin) * font_size / handle->face->units_per_EM); * font_size / handle->face->units_per_EM);
unsigned max_height = round((handle->face->bbox.yMax - handle->face->bbox.yMin)
* font_size / handle->face->units_per_EM);
unsigned atlas_width = (max_width + FT_ATLAS_PADDING) * FT_ATLAS_COLS; unsigned atlas_width = (max_width + FT_ATLAS_PADDING) * FT_ATLAS_COLS;
unsigned atlas_height = (max_height + FT_ATLAS_PADDING) * FT_ATLAS_ROWS; unsigned atlas_height = (max_height + FT_ATLAS_PADDING) * FT_ATLAS_ROWS;
uint8_t *atlas_buffer = (uint8_t*) uint8_t *atlas_buffer = (uint8_t*)calloc(atlas_width * atlas_height, 1);
calloc(atlas_width * atlas_height, 1);
if (!atlas_buffer) if (!atlas_buffer)
return false; return false;

View File

@ -66,7 +66,7 @@ static bool font_renderer_stb_create_atlas(stb_font_renderer_t *self,
uint8_t *font_data, float font_size, unsigned width, unsigned height) uint8_t *font_data, float font_size, unsigned width, unsigned height)
{ {
int i; int i;
stbtt_packedchar chardata[256]; stbtt_packedchar chardata[256];
stbtt_pack_context pc = {NULL}; stbtt_pack_context pc = {NULL};
if (width > 2048 || height > 2048) if (width > 2048 || height > 2048)
@ -128,11 +128,11 @@ static bool font_renderer_stb_create_atlas(stb_font_renderer_t *self,
return true; return true;
error: error:
self->atlas.width = self->atlas.height = 0;
if (self->atlas.buffer) if (self->atlas.buffer)
free(self->atlas.buffer); free(self->atlas.buffer);
self->atlas.width = 0;
self->atlas.height = 0;
self->atlas.buffer = NULL; self->atlas.buffer = NULL;
return false; return false;
@ -140,17 +140,17 @@ error:
static void *font_renderer_stb_init(const char *font_path, float font_size) static void *font_renderer_stb_init(const char *font_path, float font_size)
{ {
int ascent, descent, line_gap;
float scale_factor; float scale_factor;
stbtt_fontinfo info; stbtt_fontinfo info;
uint8_t *font_data = NULL; int ascent, descent, line_gap;
uint8_t *font_data = NULL;
stb_font_renderer_t *self = (stb_font_renderer_t*) calloc(1, sizeof(*self)); stb_font_renderer_t *self = (stb_font_renderer_t*) calloc(1, sizeof(*self));
/* See https://github.com/nothings/stb/blob/master/stb_truetype.h#L539 */ /* See https://github.com/nothings/stb/blob/master/stb_truetype.h#L539 */
font_size = STBTT_POINT_SIZE(font_size); font_size = STBTT_POINT_SIZE(font_size);
if (!self) if (!self)
goto error; return NULL;
if (!path_is_valid(font_path) || !filestream_read_file(font_path, (void**)&font_data, NULL)) if (!path_is_valid(font_path) || !filestream_read_file(font_path, (void**)&font_data, NULL))
goto error; goto error;
@ -163,9 +163,9 @@ static void *font_renderer_stb_init(const char *font_path, float font_size)
stbtt_GetFontVMetrics(&info, &ascent, &descent, &line_gap); stbtt_GetFontVMetrics(&info, &ascent, &descent, &line_gap);
scale_factor = (font_size < 0) ? scale_factor = (font_size < 0)
stbtt_ScaleForMappingEmToPixels(&info, -font_size) : ? stbtt_ScaleForMappingEmToPixels(&info, -font_size)
stbtt_ScaleForPixelHeight(&info, font_size); : stbtt_ScaleForPixelHeight(&info, font_size);
/* Ascender, descender and line_gap values always /* Ascender, descender and line_gap values always
* end up ~0.5 pixels too small when scaled... * end up ~0.5 pixels too small when scaled...

View File

@ -52,7 +52,7 @@ typedef struct stb_unicode_atlas_slot
struct font_glyph glyph; /* unsigned alignment */ struct font_glyph glyph; /* unsigned alignment */
unsigned charcode; unsigned charcode;
unsigned last_used; unsigned last_used;
}stb_unicode_atlas_slot_t; } stb_unicode_atlas_slot_t;
typedef struct typedef struct
{ {
@ -150,11 +150,10 @@ static const struct font_glyph *font_renderer_stb_unicode_get_glyph(
+ atlas_slot->glyph.atlas_offset_y * self->atlas.width; + atlas_slot->glyph.atlas_offset_y * self->atlas.width;
stbtt_GetGlyphHMetrics(&self->info, glyph_index, &advance_width, &left_side_bearing); stbtt_GetGlyphHMetrics(&self->info, glyph_index, &advance_width, &left_side_bearing);
if (stbtt_GetGlyphBox(&self->info, glyph_index, &x0, NULL, NULL, &y1)) if (stbtt_GetGlyphBox(&self->info, glyph_index, &x0, NULL, NULL, &y1))
{
stbtt_MakeGlyphBitmap(&self->info, dst, self->max_glyph_width, self->max_glyph_height, stbtt_MakeGlyphBitmap(&self->info, dst, self->max_glyph_width, self->max_glyph_height,
self->atlas.width, self->scale_factor, self->scale_factor, glyph_index); self->atlas.width, self->scale_factor, self->scale_factor, glyph_index);
}
else else
{ {
/* This means the glyph is empty. In this case, stbtt_MakeGlyphBitmap() /* This means the glyph is empty. In this case, stbtt_MakeGlyphBitmap()
@ -168,24 +167,29 @@ static const struct font_glyph *font_renderer_stb_unicode_get_glyph(
atlas_slot->glyph.width = self->max_glyph_width; atlas_slot->glyph.width = self->max_glyph_width;
atlas_slot->glyph.height = self->max_glyph_height; atlas_slot->glyph.height = self->max_glyph_height;
/* advance_x must always be rounded to the /* advance_x must always be rounded to the
* *nearest* integer */ * *nearest* integer */
glyph_advance_x = (float)advance_width * self->scale_factor; glyph_advance_x = (float)advance_width * self->scale_factor;
atlas_slot->glyph.advance_x = (int)((glyph_advance_x > 0.0f) ? atlas_slot->glyph.advance_x = (int)((glyph_advance_x > 0.0f)
(glyph_advance_x + 0.5f) : (glyph_advance_x - 0.5f)); ? (glyph_advance_x + 0.5f)
: (glyph_advance_x - 0.5f));
/* advance_y is always zero */ /* advance_y is always zero */
atlas_slot->glyph.advance_y = 0; atlas_slot->glyph.advance_y = 0;
/* draw_offset_x must always be rounded *down* /* draw_offset_x must always be rounded *down*
* to the nearest integer */ * to the nearest integer */
atlas_slot->glyph.draw_offset_x = (int)((float)x0 * self->scale_factor); atlas_slot->glyph.draw_offset_x = (int)((float)x0 * self->scale_factor);
/* draw_offset_y must always be rounded *up* /* draw_offset_y must always be rounded *up*
* to the nearest integer */ * to the nearest integer */
glyph_draw_offset_y = (float)(-y1) * self->scale_factor; glyph_draw_offset_y = (float)(-y1) * self->scale_factor;
atlas_slot->glyph.draw_offset_y = (int)((glyph_draw_offset_y < 0.0f) ? atlas_slot->glyph.draw_offset_y = (int)((glyph_draw_offset_y < 0.0f)
floor((double)glyph_draw_offset_y) : ceil((double)glyph_draw_offset_y)); ? floor((double)glyph_draw_offset_y)
: ceil((double)glyph_draw_offset_y));
self->atlas.dirty = true; self->atlas.dirty = true;
atlas_slot->last_used = self->usage_counter++; atlas_slot->last_used = self->usage_counter++;
return &atlas_slot->glyph; return &atlas_slot->glyph;
} }
@ -194,15 +198,16 @@ static bool font_renderer_stb_unicode_create_atlas(
{ {
unsigned i, x, y; unsigned i, x, y;
stb_unicode_atlas_slot_t* slot = NULL; stb_unicode_atlas_slot_t* slot = NULL;
int max_glyph_size = (font_size < 0) ? -font_size : font_size;
self->max_glyph_width = font_size < 0 ? -font_size : font_size; self->max_glyph_width = max_glyph_size;
self->max_glyph_height = font_size < 0 ? -font_size : font_size; self->max_glyph_height = max_glyph_size;
self->atlas.width = (self->max_glyph_width + STB_UNICODE_ATLAS_PADDING) * STB_UNICODE_ATLAS_COLS; self->atlas.width = (self->max_glyph_width + STB_UNICODE_ATLAS_PADDING) * STB_UNICODE_ATLAS_COLS;
self->atlas.height = (self->max_glyph_height + STB_UNICODE_ATLAS_PADDING) * STB_UNICODE_ATLAS_ROWS; self->atlas.height = (self->max_glyph_height + STB_UNICODE_ATLAS_PADDING) * STB_UNICODE_ATLAS_ROWS;
self->atlas.buffer = (uint8_t*) self->atlas.buffer = (uint8_t*)calloc(
calloc(self->atlas.width * self->atlas.height, sizeof(uint8_t)); self->atlas.width * self->atlas.height, sizeof(uint8_t));
if (!self->atlas.buffer) if (!self->atlas.buffer)
return false; return false;