(Fonts) Cleanups; declare variables at top of functions

This commit is contained in:
twinaphex 2015-01-10 16:46:58 +01:00
parent 5f26bbcfb9
commit 0ac6fee02a
10 changed files with 464 additions and 360 deletions

View File

@ -35,6 +35,8 @@ typedef struct bm_renderer
static const struct font_atlas *font_renderer_bmp_get_atlas(void *data)
{
bm_renderer_t *handle = (bm_renderer_t*)data;
if (!handle)
return NULL;
return &handle->atlas;
}
@ -42,6 +44,8 @@ static const struct font_glyph *font_renderer_bmp_get_glyph(
void *data, uint32_t code)
{
bm_renderer_t *handle = (bm_renderer_t*)data;
if (!handle)
return NULL;
return code < ATLAS_SIZE ? &handle->glyphs[code] : NULL;
}
@ -57,11 +61,11 @@ static void char_to_texture(bm_renderer_t *handle, uint8_t letter,
for (x = 0; x < FONT_WIDTH; x++)
{
unsigned font_pixel = x + y * FONT_WIDTH;
uint8_t rem = 1 << (font_pixel & 7);
unsigned offset = font_pixel >> 3;
uint8_t col = (bitmap_bin[FONT_OFFSET(letter) + offset] & rem) ? 0xff : 0;
uint8_t rem = 1 << (font_pixel & 7);
unsigned offset = font_pixel >> 3;
uint8_t col = (bitmap_bin[FONT_OFFSET(letter) + offset] & rem) ? 0xff : 0;
uint8_t *dst = target;
uint8_t *dst = target;
dst += x * handle->scale_factor;
dst += y * handle->scale_factor * handle->atlas.width;
@ -74,13 +78,14 @@ 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)
{
(void)font_path;
unsigned i;
bm_renderer_t *handle = (bm_renderer_t*)calloc(1, sizeof(*handle));
if (!handle)
return NULL;
(void)font_path;
handle->scale_factor = (unsigned)roundf(font_size / FONT_HEIGHT);
if (!handle->scale_factor)
handle->scale_factor = 1;
@ -93,6 +98,7 @@ static void *font_renderer_bmp_init(const char *font_path, float font_size)
{
unsigned x = (i % ATLAS_COLS) * handle->scale_factor * FONT_WIDTH;
unsigned y = (i / ATLAS_COLS) * handle->scale_factor * FONT_HEIGHT;
char_to_texture(handle, i, x, y);
handle->glyphs[i].width = FONT_WIDTH * handle->scale_factor;

View File

@ -40,19 +40,27 @@ typedef struct coretext_renderer
static const struct font_atlas *font_renderer_ct_get_atlas(void *data)
{
font_renderer_t *handle = (font_renderer_t*)data;
if (!handle)
return NULL;
return &handle->atlas;
}
static const struct font_glyph *font_renderer_ct_get_glyph(void *data, uint32_t code)
{
font_renderer_t *handle = (font_renderer_t*)data;
struct font_glyph *result = code < CT_ATLAS_SIZE ? &handle->glyphs[code] : NULL;
return result;
struct font_glyph *result = NULL;
font_renderer_t *handle = (font_renderer_t*)data;
if (!handle)
return NULL;
if (code >= CT_ATLAS_SIZE)
return NULL;
return &handle->glyphs[code];
}
static void font_renderer_ct_free(void *data)
{
font_renderer_t *handle = (font_renderer_t*)data;
if (!handle)
return;
@ -62,170 +70,218 @@ static void font_renderer_ct_free(void *data)
static bool font_renderer_create_atlas(CTFontRef face, font_renderer_t *handle)
{
unsigned i;
bool ret = true;
int max_width, max_height;
unsigned i;
size_t bytesPerRow;
CGGlyph glyphs[CT_ATLAS_SIZE];
CGRect bounds[CT_ATLAS_SIZE];
CGSize advances[CT_ATLAS_SIZE];
CGFloat ascent, descent;
CGContextRef offscreen;
CFStringRef keys[] = { kCTFontAttributeName };
CFDictionaryRef attr;
void *bitmapData = NULL;
bool ret = true;
size_t bitsPerComponent = 8;
UniChar characters[CT_ATLAS_SIZE] = {0};
CFTypeRef values[] = { face };
UniChar characters[CT_ATLAS_SIZE] = {0};
for (i = 0; i < CT_ATLAS_SIZE; i++) {
characters[i] = (UniChar)i;
}
for (i = 0; i < CT_ATLAS_SIZE; i++)
characters[i] = (UniChar)i;
CGGlyph glyphs[CT_ATLAS_SIZE];
CTFontGetGlyphsForCharacters(face, characters, glyphs, CT_ATLAS_SIZE);
CTFontGetGlyphsForCharacters(face, characters, glyphs, CT_ATLAS_SIZE);
CGRect bounds[CT_ATLAS_SIZE];
CTFontGetBoundingRectsForGlyphs(face, kCTFontDefaultOrientation,
glyphs, bounds, CT_ATLAS_SIZE);
CTFontGetBoundingRectsForGlyphs(face, kCTFontDefaultOrientation,
glyphs, bounds, CT_ATLAS_SIZE);
CGSize advances[CT_ATLAS_SIZE];
CTFontGetAdvancesForGlyphs(face, kCTFontDefaultOrientation,
glyphs, advances, CT_ATLAS_SIZE);
CTFontGetAdvancesForGlyphs(face, kCTFontDefaultOrientation,
glyphs, advances, CT_ATLAS_SIZE);
CGFloat ascent = CTFontGetAscent( face );
CGFloat descent = CTFontGetDescent( face );
ascent = CTFontGetAscent(face);
descent = CTFontGetDescent(face);
int max_width = 0;
int max_height = 0;
for (i = 0; i < CT_ATLAS_SIZE; i++) {
struct font_glyph *glyph = &handle->glyphs[i];
int origin_x = ceil(bounds[i].origin.x);
int origin_y = ceil(bounds[i].origin.y);
max_width = 0;
max_height = 0;
glyph->draw_offset_x = 0;
glyph->draw_offset_y = -1 * (ascent - descent);
glyph->width = ceil(bounds[i].size.width);
glyph->height = ceil(bounds[i].size.height);
glyph->advance_x = ceil(advances[i].width);
glyph->advance_y = ceil(advances[i].height);
for (i = 0; i < CT_ATLAS_SIZE; i++)
{
int origin_x, origin_y;
struct font_glyph *glyph = &handle->glyphs[i];
max_width = max(max_width, (origin_x + glyph->width));
max_height = max(max_height, (origin_y + glyph->height));
}
max_height = max(max_height, ceil(ascent+descent));
if (!glyph)
continue;
handle->atlas.width = max_width * CT_ATLAS_COLS;
handle->atlas.height = max_height * CT_ATLAS_ROWS;
origin_x = ceil(bounds[i].origin.x);
origin_y = ceil(bounds[i].origin.y);
handle->atlas.buffer = (uint8_t*)
calloc(handle->atlas.width * handle->atlas.height, 1);
glyph->draw_offset_x = 0;
glyph->draw_offset_y = -1 * (ascent - descent);
glyph->width = ceil(bounds[i].size.width);
glyph->height = ceil(bounds[i].size.height);
glyph->advance_x = ceil(advances[i].width);
glyph->advance_y = ceil(advances[i].height);
if (!handle->atlas.buffer) {
ret = false;
goto end;
}
max_width = max(max_width, (origin_x + glyph->width));
max_height = max(max_height, (origin_y + glyph->height));
}
size_t bitsPerComponent = 8;
size_t bytesPerRow = max_width;
void *bitmapData = calloc(max_height, bytesPerRow);
CGContextRef offscreen =
CGBitmapContextCreate(bitmapData, max_width, max_height,
bitsPerComponent, bytesPerRow, NULL, kCGImageAlphaOnly);
CGContextSetTextMatrix(offscreen, CGAffineTransformIdentity);
max_height = max(max_height, ceil(ascent+descent));
CFStringRef keys[] = { kCTFontAttributeName };
CFTypeRef values[] = { face };
CFDictionaryRef attr =
CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values,
sizeof(keys) / sizeof(keys[0]),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
for (i = 0; i < CT_ATLAS_SIZE; i++) {
struct font_glyph *glyph = &handle->glyphs[i];
handle->atlas.width = max_width * CT_ATLAS_COLS;
handle->atlas.height = max_height * CT_ATLAS_ROWS;
glyph->width = max_width;
glyph->height = max_height;
handle->atlas.buffer = (uint8_t*)
calloc(handle->atlas.width * handle->atlas.height, 1);
unsigned offset_x = (i % CT_ATLAS_COLS) * max_width;
unsigned offset_y = (i / CT_ATLAS_COLS) * max_height;
if (!handle->atlas.buffer)
{
ret = false;
goto end;
}
glyph->atlas_offset_x = offset_x;
glyph->atlas_offset_y = offset_y;
bytesPerRow = max_width;
bitmapData = calloc(max_height, bytesPerRow);
offscreen = CGBitmapContextCreate(bitmapData, max_width, max_height,
bitsPerComponent, bytesPerRow, NULL, kCGImageAlphaOnly);
char glyph_cstr[2];
glyph_cstr[0] = i;
glyph_cstr[1] = 0;
CFStringRef glyph_cfstr =
CFStringCreateWithCString( NULL, glyph_cstr, kCFStringEncodingASCII );
CFAttributedStringRef attrString =
CFAttributedStringCreate(NULL, glyph_cfstr, attr);
CFRelease(glyph_cfstr), glyph_cfstr = NULL;
CTLineRef line = CTLineCreateWithAttributedString(attrString);
CFRelease(attrString), attrString = NULL;
CGContextSetTextMatrix(offscreen, CGAffineTransformIdentity);
memset( bitmapData, 0, max_height * bytesPerRow );
CGContextSetTextPosition(offscreen, 0, descent);
CTLineDraw(line, offscreen);
CGContextFlush( offscreen );
attr = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values,
sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFRelease( line ), line = NULL;
for (i = 0; i < CT_ATLAS_SIZE; i++)
{
char glyph_cstr[2];
const uint8_t *src;
uint8_t *dst;
unsigned offset_x, offset_y, r, c;
CFStringRef glyph_cfstr;
CFAttributedStringRef attrString;
CTLineRef line;
struct font_glyph *glyph = &handle->glyphs[i];
if (!glyph)
continue;
uint8_t *dst = (uint8_t*)handle->atlas.buffer;
glyph->width = max_width;
glyph->height = max_height;
const uint8_t *src = (const uint8_t*)bitmapData;
for (unsigned r = 0; r < max_height; r++ ) {
for (unsigned c = 0; c < max_width; c++) {
unsigned src_idx = r * bytesPerRow + c;
unsigned dest_idx =
(r + offset_y) * (CT_ATLAS_COLS * max_width) + (c + offset_x);
uint8_t v = src[src_idx];
dst[dest_idx] = v;
offset_x = (i % CT_ATLAS_COLS) * max_width;
offset_y = (i / CT_ATLAS_COLS) * max_height;
glyph->atlas_offset_x = offset_x;
glyph->atlas_offset_y = offset_y;
glyph_cstr[0] = i;
glyph_cstr[1] = 0;
glyph_cfstr = CFStringCreateWithCString(
NULL, glyph_cstr, kCFStringEncodingASCII );
attrString =
CFAttributedStringCreate(NULL, glyph_cfstr, attr);
CFRelease(glyph_cfstr);
glyph_cfstr = NULL;
line = CTLineCreateWithAttributedString(attrString);
CFRelease(attrString);
attrString = NULL;
memset( bitmapData, 0, max_height * bytesPerRow );
CGContextSetTextPosition(offscreen, 0, descent);
CTLineDraw(line, offscreen);
CGContextFlush( offscreen );
CFRelease( line );
line = NULL;
dst = (uint8_t*)handle->atlas.buffer;
src = (const uint8_t*)bitmapData;
for (r = 0; r < max_height; r++ )
{
for (c = 0; c < max_width; c++)
{
unsigned src_idx = r * bytesPerRow + c;
unsigned dest_idx =
(r + offset_y) * (CT_ATLAS_COLS * max_width) + (c + offset_x);
uint8_t v = src[src_idx];
dst[dest_idx] = v;
}
}
}
}
}
CFRelease(attr), attr = NULL;
CGContextRelease(offscreen), offscreen = NULL;
free(bitmapData);
CFRelease(attr);
CGContextRelease(offscreen);
end:
return ret;
attr = NULL;
offscreen = NULL;
free(bitmapData);
end:
return ret;
}
static void *font_renderer_ct_init(const char *font_path, float font_size)
{
char err = 0;
CFStringRef cf_font_path = NULL;
CTFontRef face = NULL;
char err = 0;
CFStringRef cf_font_path = NULL;
CTFontRef face = NULL;
font_renderer_t *handle = (font_renderer_t*)
calloc(1, sizeof(*handle));
font_renderer_t *handle = (font_renderer_t*)
calloc(1, sizeof(*handle));
if (!handle)
{
err = 1;
goto error;
}
if (!handle) {
err = 1; goto error;
}
cf_font_path = CFStringCreateWithCString(NULL, font_path, kCFStringEncodingASCII);
if (!cf_font_path)
{
err = 1;
goto error;
}
face = CTFontCreateWithName(cf_font_path, font_size, NULL);
cf_font_path = CFStringCreateWithCString( NULL, font_path, kCFStringEncodingASCII );
if ( ! cf_font_path ) {
err = 1; goto error;
}
face = CTFontCreateWithName( cf_font_path, font_size, NULL );
if ( ! face ) {
err = 1; goto error;
}
if (! font_renderer_create_atlas(face, handle)) {
err = 1; goto error;
}
if (!face)
{
err = 1;
goto error;
}
error:
if ( err ) {
font_renderer_ct_free(handle);
handle = NULL;
}
if (!font_renderer_create_atlas(face, handle))
{
err = 1;
goto error;
}
if ( cf_font_path ) {
CFRelease( cf_font_path ), cf_font_path = NULL ; }
if ( face ) {
CFRelease(face), face = NULL; }
error:
if (err)
{
font_renderer_ct_free(handle);
handle = NULL;
}
return handle;
if (cf_font_path)
{
CFRelease(cf_font_path);
cf_font_path = NULL;
}
if (face)
{
CFRelease(face);
face = NULL;
}
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)
{
return default_font;

View File

@ -31,6 +31,7 @@ const d3d_font_renderer_t *d3d_font_init_first(void *data,
const char *font_path, unsigned font_size)
{
unsigned i;
for (i = 0; i < ARRAY_SIZE(d3d_font_backends); i++)
{
if (d3d_font_backends[i]->init(data, font_path, font_size))

View File

@ -24,8 +24,7 @@ static LPD3DXFONT d3d_font;
static bool d3dfonts_w32_init_font(void *data,
const char *font_path, unsigned font_size)
{
(void)font_path;
uint32_t r, g, b;
d3d_video_t *d3d = (d3d_video_t*)data;
D3DXFONT_DESC desc = {
static_cast<int>(font_size), 0, 400, 0,
@ -36,9 +35,12 @@ static bool d3dfonts_w32_init_font(void *data,
"Verdana" // Hardcode ftl :(
};
uint32_t r = static_cast<uint32_t>(g_settings.video.msg_color_r * 255) & 0xff;
uint32_t g = static_cast<uint32_t>(g_settings.video.msg_color_g * 255) & 0xff;
uint32_t b = static_cast<uint32_t>(g_settings.video.msg_color_b * 255) & 0xff;
(void)font_path;
r = static_cast<uint32_t>(g_settings.video.msg_color_r * 255) & 0xff;
g = static_cast<uint32_t>(g_settings.video.msg_color_g * 255) & 0xff;
b = static_cast<uint32_t>(g_settings.video.msg_color_b * 255) & 0xff;
d3d->font_color = D3DCOLOR_XRGB(r, g, b);
return SUCCEEDED(D3DXCreateFontIndirect(d3d->dev, &desc, &d3d_font));
@ -47,6 +49,7 @@ static bool d3dfonts_w32_init_font(void *data,
static void d3dfonts_w32_deinit_font(void *data)
{
(void)data;
if (d3d_font)
d3d_font->Release();
d3d_font = NULL;
@ -57,24 +60,28 @@ static void d3dfonts_w32_render_msg(void *data, const char *msg,
{
d3d_video_t *d3d = (d3d_video_t*)data;
if (msg && SUCCEEDED(d3d->dev->BeginScene()))
{
d3d_font->DrawTextA(NULL,
msg,
-1,
&d3d->font_rect_shifted,
DT_LEFT,
((d3d->font_color >> 2) & 0x3f3f3f) | 0xff000000);
if (!d3d)
return;
if (!msg)
return;
if (!(SUCCEEDED(d3d->dev->BeginScene())))
return;
d3d_font->DrawTextA(NULL,
msg,
-1,
&d3d->font_rect,
DT_LEFT,
d3d->font_color | 0xff000000);
d3d_font->DrawTextA(NULL,
msg,
-1,
&d3d->font_rect_shifted,
DT_LEFT,
((d3d->font_color >> 2) & 0x3f3f3f) | 0xff000000);
d3d->dev->EndScene();
}
d3d_font->DrawTextA(NULL,
msg,
-1,
&d3d->font_rect,
DT_LEFT,
d3d->font_color | 0xff000000);
d3d->dev->EndScene();
}
d3d_font_renderer_t d3d_win32_font = {

View File

@ -37,9 +37,11 @@ bool font_renderer_create_default(
const char *font_path, unsigned font_size)
{
unsigned i;
for (i = 0; font_backends[i]; i++)
{
const char *path = font_path;
if (!path)
path = font_backends[i]->get_default_font();
if (!path)

View File

@ -40,6 +40,8 @@ typedef struct freetype_renderer
static const struct font_atlas *font_renderer_ft_get_atlas(void *data)
{
font_renderer_t *handle = (font_renderer_t*)data;
if (!handle)
return NULL;
return &handle->atlas;
}
@ -47,6 +49,8 @@ static const struct font_glyph *font_renderer_ft_get_glyph(
void *data, uint32_t code)
{
font_renderer_t *handle = (font_renderer_t*)data;
if (!handle)
return NULL;
return code < ATLAS_SIZE ? &handle->glyphs[code] : NULL;
}
@ -80,6 +84,9 @@ static bool font_renderer_create_atlas(font_renderer_t *handle)
{
struct font_glyph *glyph = &handle->glyphs[i];
if (!glyph)
continue;
if (FT_Load_Char(handle->face, i, FT_LOAD_RENDER))
{
ret = false;
@ -124,7 +131,7 @@ static bool font_renderer_create_atlas(font_renderer_t *handle)
for (i = 0; i < ATLAS_SIZE; i++)
{
unsigned r, c;
uint8_t *dst = NULL;
uint8_t *dst = NULL;
unsigned offset_x = (i % ATLAS_COLS) * max_width;
unsigned offset_y = (i / ATLAS_COLS) * max_height;
@ -137,6 +144,7 @@ static bool font_renderer_create_atlas(font_renderer_t *handle)
if (buffer[i])
{
const uint8_t *src = (const uint8_t*)buffer[i];
for (r = 0; r < handle->glyphs[i].height;
r++, dst += handle->atlas.width, src += pitches[i])
for (c = 0; c < handle->glyphs[i].width; c++)
@ -208,6 +216,7 @@ static const char *font_paths[] = {
static const char *font_renderer_ft_get_default_font(void)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(font_paths); i++)
{
if (path_file_exists(font_paths[i]))

View File

@ -44,7 +44,11 @@ typedef struct
static void *gl_raster_font_init_font(void *gl_data,
const char *font_path, float font_size)
{
unsigned width, height;
uint8_t *tmp_buffer;
const struct font_atlas *atlas = NULL;
gl_raster_t *font = (gl_raster_t*)calloc(1, sizeof(*font));
if (!font)
return NULL;
@ -65,10 +69,10 @@ static void *gl_raster_font_init_font(void *gl_data,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
const struct font_atlas *atlas = font->font_driver->get_atlas(font->font_data);
atlas = font->font_driver->get_atlas(font->font_data);
unsigned width = next_pow2(atlas->width);
unsigned height = next_pow2(atlas->height);
width = next_pow2(atlas->width);
height = next_pow2(atlas->height);
/* Ideally, we'd use single component textures, but the
* difference in ways to do that between core GL and GLES/legacy GL
@ -76,12 +80,14 @@ static void *gl_raster_font_init_font(void *gl_data,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
uint8_t *tmp_buffer = (uint8_t*)malloc(atlas->width * atlas->height * 4);
tmp_buffer = (uint8_t*)malloc(atlas->width * atlas->height * 4);
if (tmp_buffer)
{
unsigned i;
uint8_t *dst = tmp_buffer;
uint8_t *dst = tmp_buffer;
const uint8_t *src = atlas->buffer;
for (i = 0; i < atlas->width * atlas->height; i++)
{
*dst++ = 0xff;
@ -89,6 +95,7 @@ static void *gl_raster_font_init_font(void *gl_data,
*dst++ = 0xff;
*dst++ = *src++;
}
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, atlas->width,
atlas->height, GL_RGBA, GL_UNSIGNED_BYTE, tmp_buffer);
free(tmp_buffer);
@ -118,27 +125,28 @@ static void gl_raster_font_free_font(void *data)
static void render_message(gl_raster_t *font, const char *msg, GLfloat scale,
const GLfloat color[4], GLfloat pos_x, GLfloat pos_y)
{
unsigned i;
int x, y, delta_x, delta_y;
float inv_tex_size_x, inv_tex_size_y, inv_win_width, inv_win_height;
unsigned i, msg_len_full, msg_len;
GLfloat font_tex_coords[2 * 6 * MAX_MSG_LEN_CHUNK];
GLfloat font_vertex[2 * 6 * MAX_MSG_LEN_CHUNK];
GLfloat font_color[4 * 6 * MAX_MSG_LEN_CHUNK];
gl_t *gl = font->gl;
glBindTexture(GL_TEXTURE_2D, font->tex);
GLfloat font_tex_coords[2 * 6 * MAX_MSG_LEN_CHUNK];
GLfloat font_vertex[2 * 6 * MAX_MSG_LEN_CHUNK];
GLfloat font_color[4 * 6 * MAX_MSG_LEN_CHUNK];
msg_len_full = strlen(msg);
msg_len = min(msg_len_full, MAX_MSG_LEN_CHUNK);
unsigned msg_len_full = strlen(msg);
unsigned msg_len = min(msg_len_full, MAX_MSG_LEN_CHUNK);
x = roundf(pos_x * gl->vp.width);
y = roundf(pos_y * gl->vp.height);
delta_x = 0;
delta_y = 0;
int x = roundf(pos_x * gl->vp.width);
int y = roundf(pos_y * gl->vp.height);
int delta_x = 0;
int delta_y = 0;
float inv_tex_size_x = 1.0f / font->tex_width;
float inv_tex_size_y = 1.0f / font->tex_height;
float inv_win_width = 1.0f / font->gl->vp.width;
float inv_win_height = 1.0f / font->gl->vp.height;
inv_tex_size_x = 1.0f / font->tex_width;
inv_tex_size_y = 1.0f / font->tex_height;
inv_win_width = 1.0f / font->gl->vp.width;
inv_win_height = 1.0f / font->gl->vp.height;
while (msg_len_full)
{
@ -148,19 +156,20 @@ static void render_message(gl_raster_t *font, const char *msg, GLfloat scale,
for (i = 0; i < msg_len; i++)
{
const struct font_glyph *gly =
int off_x, off_y, tex_x, tex_y, width, height;
const struct font_glyph *glyph =
font->font_driver->get_glyph(font->font_data, (uint8_t)msg[i]);
if (!gly)
gly = font->font_driver->get_glyph(font->font_data, '?'); /* Do something smarter here ... */
if (!gly)
if (!glyph)
glyph = font->font_driver->get_glyph(font->font_data, '?'); /* Do something smarter here ... */
if (!glyph)
continue;
int off_x = gly->draw_offset_x;
int off_y = gly->draw_offset_y;
int tex_x = gly->atlas_offset_x;
int tex_y = gly->atlas_offset_y;
int width = gly->width;
int height = gly->height;
off_x = glyph->draw_offset_x;
off_y = glyph->draw_offset_y;
tex_x = glyph->atlas_offset_x;
tex_y = glyph->atlas_offset_y;
width = glyph->width;
height = glyph->height;
emit(0, 0, 1); /* Bottom-left */
emit(1, 1, 1); /* Bottom-right */
@ -171,8 +180,8 @@ static void render_message(gl_raster_t *font, const char *msg, GLfloat scale,
emit(5, 1, 1); /* Bottom-right */
#undef emit
delta_x += gly->advance_x;
delta_y -= gly->advance_y;
delta_x += glyph->advance_x;
delta_y -= glyph->advance_y;
}
gl->coords.tex_coord = font_tex_coords;
@ -203,12 +212,13 @@ static void gl_raster_font_render_msg(void *data, const char *msg,
GLfloat color[4], color_dark[4];
int drop_x, drop_y;
bool full_screen;
gl_t *gl = NULL;
gl_raster_t *font = (gl_raster_t*)data;
if (!font)
return;
gl_t *gl = font->gl;
gl = font->gl;
if (params)
{
@ -276,7 +286,6 @@ static const struct font_glyph *gl_raster_font_get_glyph(
if (!font)
return NULL;
return font->font_driver->get_glyph((void*)font->font_driver, code);
}

View File

@ -35,9 +35,10 @@
static void *libdbg_font_init_font(void *gl_data, const char *font_path, float font_size)
{
gl_t *gl = (gl_t*)gl_data;
(void)font_path;
(void)font_size;
gl_t *gl = (gl_t*)gl_data;
DbgFontConfig cfg;
#if defined(SN_TARGET_PSP2)
@ -63,10 +64,11 @@ static void libdbg_font_deinit_font(void *data)
static void libdbg_font_render_msg(void *data, const char *msg,
const struct font_params *params)
{
(void)data;
float x, y, scale;
unsigned color;
(void)data;
if (params)
{
x = params->x;

View File

@ -47,7 +47,7 @@ static void xfonts_render_msg(void *data, const char *msg,
const struct font_params *params)
{
d3d_video_t *d3d = (d3d_video_t*)data;
wchar_t str[PATH_MAX];
wchar_t str[PATH_MAX_LENGTH];
float x, y;
if (params)

View File

@ -25,25 +25,25 @@
typedef struct GLYPH_ATTR
{
unsigned short tu1, tv1, tu2, tv2; // Texture coordinates for the image
short wOffset; // Pixel offset for glyph start
short wWidth; // Pixel width of the glyph
short wAdvance; // Pixels to advance after the glyph
unsigned short tu1, tv1, tu2, tv2; /* Texture coordinates for the image. */
short wOffset; /* Pixel offset for glyph start. */
short wWidth; /* Pixel width of the glyph. */
short wAdvance; /* Pixels to advance after the glyph. */
unsigned short wMask;
} GLYPH_ATTR;
typedef struct
{
unsigned long m_dwSavedState;
unsigned long m_cMaxGlyph; // Number of entries in the translator table
unsigned long m_dwNumGlyphs; // Number of valid glyphs
float m_fFontHeight; // Height of the font strike in pixels
float m_fFontTopPadding; // Padding above the strike zone
float m_fFontBottomPadding; // Padding below the strike zone
float m_fFontYAdvance; // Number of pixels to move the cursor for a line feed
wchar_t * m_TranslatorTable; // ASCII to glyph lookup table
unsigned long m_cMaxGlyph; /* Number of entries in the translator table. */
unsigned long m_dwNumGlyphs; /* Number of valid glyphs. */
float m_fFontHeight; /* Height of the font strike in pixels. */
float m_fFontTopPadding; /* Padding above the strike zone. */
float m_fFontBottomPadding; /* Padding below the strike zone. */
float m_fFontYAdvance; /* Number of pixels to move the cursor for a line feed. */
wchar_t * m_TranslatorTable; /* ASCII to glyph lookup table. */
D3DTexture* m_pFontTexture;
const GLYPH_ATTR* m_Glyphs; // Array of glyphs
const GLYPH_ATTR* m_Glyphs; /* Array of glyphs. */
} xdk360_video_font_t;
static xdk360_video_font_t m_Font;
@ -53,18 +53,18 @@ static PackedResource m_xprResource;
#define FONTFILEVERSION 5
typedef struct {
unsigned long m_dwFileVersion; // Version of the font file (Must match FONTFILEVERSION)
float m_fFontHeight; // Height of the font strike in pixels
float m_fFontTopPadding; // Padding above the strike zone
float m_fFontBottomPadding; // Padding below the strike zone
float m_fFontYAdvance; // Number of pixels to move the cursor for a line feed
unsigned short m_cMaxGlyph; // Number of font characters (Should be an odd number to maintain DWORD Alignment)
wchar_t m_TranslatorTable[1]; // ASCII to Glyph lookup table, NOTE: It's m_cMaxGlyph+1 in size.
unsigned long m_dwFileVersion; /* Version of the font file (Must match FONTFILEVERSION). */
float m_fFontHeight; /* Height of the font strike in pixels. */
float m_fFontTopPadding; /* Padding above the strike zone. */
float m_fFontBottomPadding; /* Padding below the strike zone. */
float m_fFontYAdvance; /* Number of pixels to move the cursor for a line feed. */
unsigned short m_cMaxGlyph; /* Number of font characters (Should be an odd number to maintain DWORD Alignment). */
wchar_t m_TranslatorTable[1]; /* ASCII to Glyph lookup table, NOTE: It's m_cMaxGlyph+1 in size. */
} FontFileHeaderImage_t;
typedef struct {
unsigned long m_dwNumGlyphs; // Size of font strike array (First entry is the unknown glyph)
GLYPH_ATTR m_Glyphs[1]; // Array of font strike uv's etc... NOTE: It's m_dwNumGlyphs in size
unsigned long m_dwNumGlyphs; /* Size of font strike array (First entry is the unknown glyph). */
GLYPH_ATTR m_Glyphs[1]; /* Array of font strike uv's etc... NOTE: It's m_dwNumGlyphs in size. */
} FontFileStrikesImage_t;
static const char g_strFontShader[] =
@ -113,80 +113,82 @@ static HRESULT xdk360_video_font_create_shaders(
d3d_video_t *d3d = (d3d_video_t*)data;
LPDIRECT3DDEVICE d3dr = d3d->dev;
if (!s_FontLocals.m_pFontVertexDecl)
{
do
{
static const D3DVERTEXELEMENT9 decl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 8, D3DDECLTYPE_USHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
{ 0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
D3DDECL_END()
};
hr = d3dr->CreateVertexDeclaration( decl, &s_FontLocals.m_pFontVertexDecl );
if (hr >= 0)
{
ID3DXBuffer* pShaderCode;
hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 ,
NULL, NULL, "main_vertex", "vs.2.0", 0,&pShaderCode, NULL, NULL );
if (hr >= 0)
{
hr = d3dr->CreateVertexShader( ( unsigned long * )pShaderCode->GetBufferPointer(),
&s_FontLocals.m_pFontVertexShader );
pShaderCode->Release();
if (hr >= 0)
{
hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 ,
NULL, NULL, "main_fragment", "ps.2.0", 0,&pShaderCode, NULL, NULL );
if (hr >= 0)
{
hr = d3dr->CreatePixelShader((DWORD*)pShaderCode->GetBufferPointer(),
&s_FontLocals.m_pFontPixelShader );
pShaderCode->Release();
if (hr >= 0)
{
hr = 0;
break;
}
}
s_FontLocals.m_pFontVertexShader->Release();
}
s_FontLocals.m_pFontVertexShader = NULL;
}
s_FontLocals.m_pFontVertexDecl->Release();
}
s_FontLocals.m_pFontVertexDecl = NULL;
}while (0);
}
else
if (s_FontLocals.m_pFontVertexDecl)
{
s_FontLocals.m_pFontVertexDecl->AddRef();
s_FontLocals.m_pFontVertexShader->AddRef();
s_FontLocals.m_pFontPixelShader->AddRef();
hr = 0;
return 0;
}
do
{
static const D3DVERTEXELEMENT9 decl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 8, D3DDECLTYPE_USHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
{ 0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
D3DDECL_END()
};
hr = d3dr->CreateVertexDeclaration( decl, &s_FontLocals.m_pFontVertexDecl );
if (hr >= 0)
{
ID3DXBuffer* pShaderCode;
hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 ,
NULL, NULL, "main_vertex", "vs.2.0", 0,&pShaderCode, NULL, NULL );
if (hr >= 0)
{
hr = d3dr->CreateVertexShader( ( unsigned long * )pShaderCode->GetBufferPointer(),
&s_FontLocals.m_pFontVertexShader );
pShaderCode->Release();
if (hr >= 0)
{
hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 ,
NULL, NULL, "main_fragment", "ps.2.0", 0,&pShaderCode, NULL, NULL );
if (hr >= 0)
{
hr = d3dr->CreatePixelShader((DWORD*)pShaderCode->GetBufferPointer(),
&s_FontLocals.m_pFontPixelShader );
pShaderCode->Release();
if (hr >= 0)
{
hr = 0;
break;
}
}
s_FontLocals.m_pFontVertexShader->Release();
}
s_FontLocals.m_pFontVertexShader = NULL;
}
s_FontLocals.m_pFontVertexDecl->Release();
}
s_FontLocals.m_pFontVertexDecl = NULL;
}while(0);
return hr;
}
static bool xdk360_init_font(void *data,
const char *font_path, unsigned font_size)
{
(void)font_size;
unsigned long dwFileVersion;
const void *pFontData = NULL;
D3DTexture *pFontTexture = NULL;
const unsigned char * pData = NULL;
xdk360_video_font_t *font = &m_Font;
d3d_video_t *d3d = (d3d_video_t*)data;
// Create the font
xdk360_video_font_t *font = &m_Font;
d3d_video_t *d3d = (d3d_video_t*)data;
(void)font_size;
font->m_pFontTexture = NULL;
font->m_dwNumGlyphs = 0L;
@ -194,44 +196,41 @@ static bool xdk360_init_font(void *data,
font->m_cMaxGlyph = 0;
font->m_TranslatorTable = NULL;
// Create the font
/* Create the font. */
if (FAILED( m_xprResource.Create(font_path)))
goto error;
D3DTexture *pFontTexture = m_xprResource.GetTexture( "FontTexture" );
const void *pFontData = m_xprResource.GetData( "FontData");
pFontTexture = m_xprResource.GetTexture( "FontTexture" );
pFontData = m_xprResource.GetData( "FontData");
// Save a copy of the texture
font->m_pFontTexture = pFontTexture;
/* Save a copy of the texture. */
font->m_pFontTexture = pFontTexture;
// Check version of file (to make sure it matches up with the FontMaker tool)
const unsigned char * pData = (const unsigned char*)pFontData;
unsigned long dwFileVersion = ((const FontFileHeaderImage_t *)pData)->m_dwFileVersion;
/* Check version of file (to make sure it matches up with the FontMaker tool). */
pData = (const unsigned char*)pFontData;
dwFileVersion = ((const FontFileHeaderImage_t *)pData)->m_dwFileVersion;
if (dwFileVersion == FONTFILEVERSION)
if (dwFileVersion != FONTFILEVERSION)
{
font->m_fFontHeight = ((const FontFileHeaderImage_t *)pData)->m_fFontHeight;
font->m_fFontTopPadding = ((const FontFileHeaderImage_t *)pData)->m_fFontTopPadding;
font->m_fFontBottomPadding = ((const FontFileHeaderImage_t *)pData)->m_fFontBottomPadding;
font->m_fFontYAdvance = ((const FontFileHeaderImage_t *)pData)->m_fFontYAdvance;
// Point to the translator string which immediately follows the 4 floats
font->m_cMaxGlyph = ((const FontFileHeaderImage_t *)pData)->m_cMaxGlyph;
font->m_TranslatorTable = const_cast<FontFileHeaderImage_t*>((const FontFileHeaderImage_t *)pData)->m_TranslatorTable;
pData += CALCFONTFILEHEADERSIZE( font->m_cMaxGlyph + 1 );
// Read the glyph attributes from the file
font->m_dwNumGlyphs = ((const FontFileStrikesImage_t *)pData)->m_dwNumGlyphs;
font->m_Glyphs = ((const FontFileStrikesImage_t *)pData)->m_Glyphs;
}
else
{
RARCH_ERR( "Incorrect version number on font file.\n" );
RARCH_ERR("Incorrect version number on font file.\n");
goto error;
}
font->m_fFontHeight = ((const FontFileHeaderImage_t *)pData)->m_fFontHeight;
font->m_fFontTopPadding = ((const FontFileHeaderImage_t *)pData)->m_fFontTopPadding;
font->m_fFontBottomPadding = ((const FontFileHeaderImage_t *)pData)->m_fFontBottomPadding;
font->m_fFontYAdvance = ((const FontFileHeaderImage_t *)pData)->m_fFontYAdvance;
/* Point to the translator string which immediately follows the 4 floats. */
font->m_cMaxGlyph = ((const FontFileHeaderImage_t *)pData)->m_cMaxGlyph;
font->m_TranslatorTable = const_cast<FontFileHeaderImage_t*>((const FontFileHeaderImage_t *)pData)->m_TranslatorTable;
pData += CALCFONTFILEHEADERSIZE( font->m_cMaxGlyph + 1 );
/* Read the glyph attributes from the file. */
font->m_dwNumGlyphs = ((const FontFileStrikesImage_t *)pData)->m_dwNumGlyphs;
font->m_Glyphs = ((const FontFileStrikesImage_t *)pData)->m_Glyphs;
/* Create the vertex and pixel shaders for rendering the font */
if (FAILED(xdk360_video_font_create_shaders(d3d, font)))
{
@ -287,22 +286,22 @@ static void xdk360_render_msg_post(xdk360_video_font_t * font, void *video_data)
static void xdk360_render_msg_pre(xdk360_video_font_t * font, void *video_data)
{
float vTexScale[4];
D3DSURFACE_DESC TextureDesc;
d3d_video_t *d3d = (d3d_video_t*)video_data;
LPDIRECT3DDEVICE d3dr = d3d->dev;
// Save state
/* Save state. */
d3dr->GetRenderState( D3DRS_VIEWPORTENABLE, &font->m_dwSavedState );
// Set the texture scaling factor as a vertex shader constant
D3DSURFACE_DESC TextureDesc;
/* Set the texture scaling factor as a vertex shader constant. */
D3DTexture_GetLevelDesc(font->m_pFontTexture, 0, &TextureDesc); // Get the description
// Set render state
/* Set render state. */
d3d_set_texture(d3dr, 0, font->m_pFontTexture);
// Read the TextureDesc here to ensure no load/hit/store from GetLevelDesc()
float vTexScale[4];
vTexScale[0] = 1.0f / TextureDesc.Width; // LHS due to int->float conversion
/* Read the TextureDesc here to ensure no load/hit/store from GetLevelDesc(). */
vTexScale[0] = 1.0f / TextureDesc.Width; /* LHS due to int->float conversion. */
vTexScale[1] = 1.0f / TextureDesc.Height;
vTexScale[2] = 0.0f;
vTexScale[3] = 0.0f;
@ -312,93 +311,102 @@ static void xdk360_render_msg_pre(xdk360_video_font_t * font, void *video_data)
d3d_set_vertex_shader(d3dr, 0, s_FontLocals.m_pFontVertexShader);
d3dr->SetPixelShader(s_FontLocals.m_pFontPixelShader);
// Set the texture scaling factor as a vertex shader constant
// Call here to avoid load hit store from writing to vTexScale above
/* Set the texture scaling factor as a vertex shader constant.
* Call here to avoid load hit store from writing to vTexScale above
*/
d3dr->SetVertexShaderConstantF( 2, vTexScale, 1 );
}
static void xdk360_draw_text(xdk360_video_font_t *font, void *video_data,
float x, float y, const wchar_t * strText)
{
d3d_video_t *d3d = (d3d_video_t*)video_data;
unsigned long dwNumChars;
volatile float *pVertex;
float vColor[4], m_fCursorX, m_fCursorY;
d3d_video_t *d3d = (d3d_video_t*)video_data;
LPDIRECT3DDEVICE d3dr = d3d->dev;
// Set the color as a vertex shader constant
float vColor[4];
/* Set the color as a vertex shader constant. */
vColor[0] = ( ( 0xffffffff & 0x00ff0000 ) >> 16L ) / 255.0f;
vColor[1] = ( ( 0xffffffff & 0x0000ff00 ) >> 8L ) / 255.0f;
vColor[2] = ( ( 0xffffffff & 0x000000ff ) >> 0L ) / 255.0f;
vColor[3] = ( ( 0xffffffff & 0xff000000 ) >> 24L ) / 255.0f;
// Perform the actual storing of the color constant here to prevent
// a load-hit-store by inserting work between the store and the use of
// the vColor array.
/* Perform the actual storing of the color constant here to prevent
* a load-hit-store by inserting work between the store and the use of
* the vColor array. */
d3dr->SetVertexShaderConstantF( 1, vColor, 1 );
float m_fCursorX = floorf(x);
float m_fCursorY = floorf(y);
m_fCursorX = floorf(x);
m_fCursorY = floorf(y);
// Adjust for padding
/* Adjust for padding. */
y -= font->m_fFontTopPadding;
// Begin drawing the vertices
/* Begin drawing the vertices
* Declared as volatile to force writing in ascending
* address order.
*
* It prevents out of sequence writing in write combined
* memory.
*/
// Declared as volatile to force writing in ascending
// address order. It prevents out of sequence writing in write combined
// memory.
volatile float * pVertex;
unsigned long dwNumChars = wcslen(strText);
dwNumChars = wcslen(strText);
d3dr->BeginVertices(D3DPT_QUADLIST, 4 * dwNumChars,
sizeof(XMFLOAT4), (void**)&pVertex);
// Draw four vertices for each glyph
/* Draw four vertices for each glyph. */
while (*strText)
{
// Get the current letter in the string
wchar_t letter = *strText++;
float fOffset, fAdvance, fWidth, fHeight;
unsigned long tu1, tu2, tv1, tv2;
const GLYPH_ATTR *pGlyph;
wchar_t letter = *strText++; /* Get the current letter in the string */
/* Handle the newline character. */
if (letter == L'\n')
{
// Handle the newline character
m_fCursorX = x;
m_fCursorY += font->m_fFontYAdvance * FONT_SCALE(d3d);
continue;
}
// Translate unprintable characters
const GLYPH_ATTR *pGlyph;
/* Translate unprintable characters. */
if (letter <= font->m_cMaxGlyph)
pGlyph = &font->m_Glyphs[font->m_TranslatorTable[letter]];
else
pGlyph = &font->m_Glyphs[0];
float fOffset = FONT_SCALE(d3d) * (float)pGlyph->wOffset;
float fAdvance = FONT_SCALE(d3d) * (float)pGlyph->wAdvance;
float fWidth = FONT_SCALE(d3d) * (float)pGlyph->wWidth;
float fHeight = FONT_SCALE(d3d) * font->m_fFontHeight;
fOffset = FONT_SCALE(d3d) * (float)pGlyph->wOffset;
fAdvance = FONT_SCALE(d3d) * (float)pGlyph->wAdvance;
fWidth = FONT_SCALE(d3d) * (float)pGlyph->wWidth;
fHeight = FONT_SCALE(d3d) * font->m_fFontHeight;
m_fCursorX += fOffset;
// Add the vertices to draw this glyph
/* Add the vertices to draw this glyph. */
unsigned long tu1 = pGlyph->tu1; // Convert shorts to 32 bit longs for in register merging
unsigned long tv1 = pGlyph->tv1;
unsigned long tu2 = pGlyph->tu2;
unsigned long tv2 = pGlyph->tv2;
/* Convert shorts to 32 bit longs for in register merging */
tu1 = pGlyph->tu1;
tv1 = pGlyph->tv1;
tu2 = pGlyph->tu2;
tv2 = pGlyph->tv2;
// NOTE: The vertexes are 2 floats for the screen coordinates,
// followed by two USHORTS for the u/vs of the character,
// terminated with the ARGB 32 bit color.
// This makes for 16 bytes per vertex data (Easier to read)
// Second NOTE: The uvs are merged and written using a DWORD due
// to the write combining hardware being only able to handle 32,
// 64 and 128 writes. Never store to write combined memory with
// 8 or 16 bit instructions. You've been warned.
/* NOTE: The vertexes are 2 floats for the screen coordinates,
* followed by two USHORTS for the u/vs of the character,
* terminated with the ARGB 32 bit color.
*
* This makes for 16 bytes per vertex data (Easier to read)
*
* Second NOTE: The U/V coordinates are merged and written
* using a DWORD due to the write combining hardware
* being only able to handle 32, 64 and 128 writes.
*
* Never store to write combined memory with 8 or 16bit
* instructions. You've been warned.
*/
// Setup the vertex/screen coordinates
/* Setup the vertex/screen coordinates */
pVertex[0] = m_fCursorX;
pVertex[1] = m_fCursorY;
@ -425,11 +433,15 @@ static void xdk360_draw_text(xdk360_video_font_t *font, void *video_data,
dwNumChars--;
}
// Since we allocated vertex data space based on the string length, we now need to
// add some dummy verts for any skipped characters (like newlines, etc.)
/* Since we allocated vertex data space
* based on the string length, we now need to
* add some dummy verts for any skipped
* characters (like newlines, etc.)
*/
while (dwNumChars)
{
for (unsigned i = 0; i < 16; i++)
unsigned i;
for (i = 0; i < 16; i++)
pVertex[i] = 0;
pVertex += 16;
@ -442,10 +454,10 @@ static void xdk360_draw_text(xdk360_video_font_t *font, void *video_data,
static void xdk360_render_msg(void *data, const char *str_msg,
const struct font_params *params)
{
d3d_video_t *d3d = (d3d_video_t*)data;
xdk360_video_font_t *font = &m_Font;
wchar_t msg[PATH_MAX];
float x, y;
wchar_t msg[PATH_MAX_LENGTH];
d3d_video_t *d3d = (d3d_video_t*)data;
xdk360_video_font_t *font = &m_Font;
if (params)
{