diff options
author | Aaron Giles <aaron@aarongiles.com> | 2010-10-23 06:39:13 +0000 |
---|---|---|
committer | Aaron Giles <aaron@aarongiles.com> | 2010-10-23 06:39:13 +0000 |
commit | 43eca9d9c87831cf3efc7119a1c1cc46f9fd7ac0 (patch) | |
tree | 085ba17f5971125abbf106ca00c66e2fb67eaeb4 | |
parent | b6647f7ae1d6d4d957c50fc9d4cef581e8425fd4 (diff) |
Convert rendfont to C++.
-rw-r--r-- | src/emu/debugint/debugint.c | 6 | ||||
-rw-r--r-- | src/emu/render.c | 22 | ||||
-rw-r--r-- | src/emu/render.h | 6 | ||||
-rw-r--r-- | src/emu/rendfont.c | 1040 | ||||
-rw-r--r-- | src/emu/rendfont.h | 117 | ||||
-rw-r--r-- | src/emu/rendlay.c | 10 | ||||
-rw-r--r-- | src/emu/ui.c | 11 | ||||
-rw-r--r-- | src/emu/uigfx.c | 22 |
8 files changed, 629 insertions, 605 deletions
diff --git a/src/emu/debugint/debugint.c b/src/emu/debugint/debugint.c index 54973eb082f..5fa4987140e 100644 --- a/src/emu/debugint/debugint.c +++ b/src/emu/debugint/debugint.c @@ -889,7 +889,7 @@ static void debugint_exit(running_machine &machine) } if (debug_font != NULL) { - render_font_free(debug_font); + machine.render().font_free(debug_font); debug_font = NULL; } @@ -899,7 +899,7 @@ void debugint_init(running_machine *machine) { unicode_char ch; int chw; - debug_font = render_font_alloc(*machine, "ui.bdf"); //ui_get_font(); + debug_font = machine->render().font_alloc("ui.bdf"); //ui_get_font(); debug_font_width = 0; debug_font_height = 15; @@ -912,7 +912,7 @@ void debugint_init(running_machine *machine) for (ch=0;ch<=127;ch++) { - chw = render_font_get_char_width(debug_font, debug_font_height, debug_font_aspect, ch); + chw = debug_font->char_width(debug_font_height, debug_font_aspect, ch); if (chw>debug_font_width) debug_font_width = chw; } diff --git a/src/emu/render.c b/src/emu/render.c index 106fa80cd6a..91da225c469 100644 --- a/src/emu/render.c +++ b/src/emu/render.c @@ -789,7 +789,7 @@ void render_container::add_char(float x0, float y0, float height, float aspect, render_bounds bounds; bounds.x0 = x0; bounds.y0 = y0; - render_texture *texture = render_font_get_char_texture_and_bounds(&font, height, aspect, ch, &bounds); + render_texture *texture = font.get_char_texture_and_bounds(height, aspect, ch, bounds); // add it like a quad item &newitem = add_generic(CONTAINER_ITEM_QUAD, bounds.x0, bounds.y0, bounds.x1, bounds.y1, argb); @@ -2514,6 +2514,26 @@ void render_manager::texture_free(render_texture *texture) //------------------------------------------------- +// font_alloc - allocate a new font instance +//------------------------------------------------- + +render_font *render_manager::font_alloc(const char *filename) +{ + return auto_alloc(&m_machine, render_font(*this, filename)); +} + + +//------------------------------------------------- +// font_free - release a font instance +//------------------------------------------------- + +void render_manager::font_free(render_font *font) +{ + auto_free(&m_machine, font); +} + + +//------------------------------------------------- // invalidate_all - remove all refs to a // particular reference pointer //------------------------------------------------- diff --git a/src/emu/render.h b/src/emu/render.h index 0fd44be7214..a4d92250fa4 100644 --- a/src/emu/render.h +++ b/src/emu/render.h @@ -168,7 +168,7 @@ class screen_device; class render_container; class render_manager; typedef struct _xml_data_node xml_data_node; -typedef struct _render_font render_font; +class render_font; struct object_transform; class layout_element; class layout_view; @@ -741,6 +741,10 @@ public: // textures render_texture *texture_alloc(texture_scaler_func scaler = NULL, void *param = NULL); void texture_free(render_texture *texture); + + // fonts + render_font *font_alloc(const char *filename = NULL); + void font_free(render_font *font); // reference tracking void invalidate_all(void *refptr); diff --git a/src/emu/rendfont.c b/src/emu/rendfont.c index 2fa5ba6f4ba..836526ef36e 100644 --- a/src/emu/rendfont.c +++ b/src/emu/rendfont.c @@ -4,8 +4,36 @@ Rendering system font management. - Copyright Nicola Salmoria and the MAME Team. - Visit http://mamedev.org for licensing and usage restrictions. +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ @@ -18,223 +46,148 @@ #include "uismall.fh" -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -#define FONT_FORMAT_TEXT 1 -#define FONT_FORMAT_CACHED 2 - -#define CACHED_CHAR_SIZE 12 -#define CACHED_HEADER_SIZE 16 -#define CACHED_BDF_HASH_SIZE 1024 - - - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -/* a render_font contains information about a single character in a font */ -typedef struct _render_font_char render_font_char; -struct _render_font_char -{ - INT32 width; /* width from this character to the next */ - INT32 xoffs, yoffs; /* X and Y offset from baseline to top,left of bitmap */ - INT32 bmwidth, bmheight; /* width and height of bitmap */ - const char * rawdata; /* pointer to the raw data for this one */ - bitmap_t * bitmap; /* pointer to the bitmap containing the raw data */ - render_texture * texture; /* pointer to a texture for rendering and sizing */ -}; - - -/* a render_font contains information about a font */ -/*typedef struct _render_font render_font; -- defined in rendfont.h */ -struct _render_font -{ - running_machine * machine; - int format; /* format of font data */ - int height; /* height of the font, from ascent to descent */ - int yoffs; /* y offset from baseline to descent */ - float scale; /* 1 / height precomputed */ - render_font_char * chars[256]; /* array of character subtables */ - const char * rawdata; /* pointer to the raw data for the font */ - UINT64 rawsize; /* size of the raw font data */ -}; +//************************************************************************** +// INLINE FUNCTIONS +//************************************************************************** +//------------------------------------------------- +// next_line - return a pointer to the start of +// the next line +//------------------------------------------------- - -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ - -static void render_font_char_expand(render_font *font, render_font_char *ch); -static int render_font_load_cached_bdf(render_font *font, const char *filename); -static int render_font_load_bdf(render_font *font); -static int render_font_load_cached(render_font *font, mame_file *file, UINT32 hash); -static int render_font_save_cached(render_font *font, const char *filename, UINT32 hash); - - - -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ - -/*------------------------------------------------- - next_line - return a pointer to the start of - the next line --------------------------------------------------*/ - -INLINE const char *next_line(const char *ptr) +inline const char *next_line(const char *ptr) { - /* scan forward until we hit the end or a carriage return */ + // scan forward until we hit the end or a carriage return while (*ptr != 13 && *ptr != 10 && *ptr != 0) ptr++; - /* if we hit the end, return NULL */ + // if we hit the end, return NULL if (*ptr == 0) return NULL; - /* eat the trailing linefeed if present */ + // eat the trailing linefeed if present if (*++ptr == 10) ptr++; return ptr; } -/*------------------------------------------------- - get_char - return a pointer to a character - in a font, expanding if necessary --------------------------------------------------*/ +//------------------------------------------------- +// get_char - return a pointer to a character +// in a font, expanding if necessary +//------------------------------------------------- -INLINE render_font_char *get_char(render_font *font, unicode_char chnum) +inline render_font::glyph &render_font::get_char(unicode_char chnum) { - static render_font_char dummy_char; - render_font_char *chtable; - render_font_char *ch; - - /* grab the table; if none, return the dummy character */ - chtable = font->chars[chnum / 256]; - if (chtable == NULL) - return &dummy_char; - - /* if the character isn't generated yet, do it now */ - ch = &chtable[chnum % 256]; - if (ch->bitmap == NULL) - render_font_char_expand(font, ch); - - /* return the resulting character */ - return ch; -} + static glyph dummy_glyph; + // grab the table; if none, return the dummy character + glyph *glyphtable = m_glyphs[chnum / 256]; + if (glyphtable == NULL) + return dummy_glyph; + // if the character isn't generated yet, do it now + glyph &gl = glyphtable[chnum % 256]; + if (gl.bitmap == NULL) + char_expand(gl); -/*************************************************************************** - RENDER FONTS -***************************************************************************/ + // return the resulting character + return gl; +} -/*------------------------------------------------- - render_font_alloc - allocate a new font - and load the BDF file --------------------------------------------------*/ -render_font *render_font_alloc(running_machine &machine, const char *filename) -{ - file_error filerr; - mame_file *ramfile; - render_font *font; - /* allocate and clear memory */ - font = global_alloc_clear(render_font); - font->machine = &machine; +//************************************************************************** +// RENDER FONT +//************************************************************************** + +//------------------------------------------------- +// render_font - constructor +//------------------------------------------------- - /* attempt to load the cached version of the font first */ - if (filename != NULL && render_font_load_cached_bdf(font, filename) == 0) - return font; +render_font::render_font(render_manager &manager, const char *filename) + : m_manager(manager), + m_format(FF_UNKNOWN), + m_height(0), + m_yoffs(0), + m_scale(1.0f), + m_rawdata(NULL), + m_rawsize(0) +{ + memset(m_glyphs, 0, sizeof(m_glyphs)); - /* if we failed, clean up and realloc */ - render_font_free(font); - font = global_alloc_clear(render_font); - font->machine = &machine; + // attempt to load the cached version of the font first + if (filename != NULL && load_cached_bdf(filename)) + return; - /* load the raw data instead */ - filerr = mame_fopen_ram(font_uismall, sizeof(font_uismall), OPEN_FLAG_READ, &ramfile); + // load the raw data instead + mame_file *ramfile; + file_error filerr = mame_fopen_ram(font_uismall, sizeof(font_uismall), OPEN_FLAG_READ, &ramfile); if (filerr == FILERR_NONE) { - render_font_load_cached(font, ramfile, 0); + load_cached(ramfile, 0); mame_fclose(ramfile); } - return font; } -/*------------------------------------------------- - render_font_free - free an allocated font and - all of its owned subobjects --------------------------------------------------*/ +//------------------------------------------------- +// ~render_font - destructor +//------------------------------------------------- -void render_font_free(render_font *font) +render_font::~render_font() { - int tablenum; - - /* free all the subtables */ - for (tablenum = 0; tablenum < 256; tablenum++) - if (font->chars[tablenum] != NULL) + // free all the subtables + for (int tablenum = 0; tablenum < 256; tablenum++) + if (m_glyphs[tablenum] != NULL) { - int charnum; - - /* loop over characters */ - for (charnum = 0; charnum < 256; charnum++) + // loop over characters + for (int charnum = 0; charnum < 256; charnum++) { - render_font_char *ch = &font->chars[tablenum][charnum]; - font->machine->render().texture_free(ch->texture); - global_free(ch->bitmap); + glyph &gl = m_glyphs[tablenum][charnum]; + m_manager.texture_free(gl.texture); + auto_free(&m_manager.machine(), gl.bitmap); } - /* free the subtable itself */ - global_free(font->chars[tablenum]); + // free the subtable itself + auto_free(&m_manager.machine(), m_glyphs[tablenum]); } - /* free the raw data and the size itself */ - if (font->rawdata != NULL) - global_free((void *)font->rawdata); - global_free(font); + // free the raw data and the size itself + auto_free(&m_manager.machine(), m_rawdata); } -/*------------------------------------------------- - render_font_char_expand - expand the raw data - for a character into a bitmap --------------------------------------------------*/ +//------------------------------------------------- +// char_expand - expand the raw data for a +// character into a bitmap +//------------------------------------------------- -static void render_font_char_expand(render_font *font, render_font_char *ch) +void render_font::char_expand(glyph &gl) { - const char *ptr = ch->rawdata; - UINT8 accum = 0, accumbit = 7; - int x, y; - - /* punt if nothing there */ - if (ch->bmwidth == 0 || ch->bmheight == 0 || ch->rawdata == NULL) + // punt if nothing there + if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == NULL) return; - /* allocate a new bitmap of the size we need */ - ch->bitmap = global_alloc(bitmap_t(ch->bmwidth, font->height, BITMAP_FORMAT_ARGB32)); - bitmap_fill(ch->bitmap, NULL, 0); + // allocate a new bitmap of the size we need + gl.bitmap = auto_alloc(&m_manager.machine(), bitmap_t(gl.bmwidth, m_height, BITMAP_FORMAT_ARGB32)); + bitmap_fill(gl.bitmap, NULL, 0); - /* extract the data */ - for (y = 0; y < ch->bmheight; y++) + // extract the data + const char *ptr = gl.rawdata; + UINT8 accum = 0, accumbit = 7; + for (int y = 0; y < gl.bmheight; y++) { - int desty = y + font->height + font->yoffs - ch->yoffs - ch->bmheight; - UINT32 *dest = (desty >= 0 && desty < font->height) ? BITMAP_ADDR32(ch->bitmap, desty, 0) : NULL; + int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight; + UINT32 *dest = (desty >= 0 && desty < m_height) ? BITMAP_ADDR32(gl.bitmap, desty, 0) : NULL; - /* text format */ - if (font->format == FONT_FORMAT_TEXT) + // text format + if (m_format == FF_TEXT) { - /* loop over bytes */ - for (x = 0; x < ch->bmwidth; x += 4) + // loop over bytes + for (int x = 0; x < gl.bmwidth; x += 4) { + // scan for the next hex digit int bits = -1; - - /* scan for the next hex digit */ while (*ptr != 13 && bits == -1) { if (*ptr >= '0' && *ptr <= '9') @@ -247,7 +200,7 @@ static void render_font_char_expand(render_font *font, render_font_char *ch) ptr++; } - /* expand the four bits */ + // expand the four bits if (dest != NULL) { *dest++ = (bits & 8) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); @@ -257,14 +210,14 @@ static void render_font_char_expand(render_font *font, render_font_char *ch) } } - /* advance to the next line */ + // advance to the next line ptr = next_line(ptr); } - /* cached format */ - else if (font->format == FONT_FORMAT_CACHED) + // cached format + else if (m_format == FF_CACHED) { - for (x = 0; x < ch->bmwidth; x++) + for (int x = 0; x < gl.bmwidth; x++) { if (accumbit == 7) accum = *ptr++; @@ -275,588 +228,545 @@ static void render_font_char_expand(render_font *font, render_font_char *ch) } } - /* wrap a texture around the bitmap */ - ch->texture = font->machine->render().texture_alloc(render_texture::hq_scale); - ch->texture->set_bitmap(ch->bitmap, NULL, TEXFORMAT_ARGB32); + // wrap a texture around the bitmap + gl.texture = m_manager.texture_alloc(render_texture::hq_scale); + gl.texture->set_bitmap(gl.bitmap, NULL, TEXFORMAT_ARGB32); } -/*------------------------------------------------- - render_font_get_pixel_height - return the - height of the font in pixels --------------------------------------------------*/ +//------------------------------------------------- +// get_char_texture_and_bounds - return the +// texture for a character and compute the +// bounds of the final bitmap +//------------------------------------------------- -INT32 render_font_get_pixel_height(render_font *font) +render_texture *render_font::get_char_texture_and_bounds(float height, float aspect, unicode_char chnum, render_bounds &bounds) { - return font->height; -} - + glyph &gl = get_char(chnum); -/*------------------------------------------------- - render_font_get_char_texture_and_bounds - - return the texture for a character and compute - the bounds of the final bitmap --------------------------------------------------*/ + // on entry, assume x0,y0 are the top,left coordinate of the cell and add + // the character bounding box to that position + float scale = m_scale * height; + bounds.x0 += (float)gl.xoffs * scale * aspect; -render_texture *render_font_get_char_texture_and_bounds(render_font *font, float height, float aspect, unicode_char chnum, render_bounds *bounds) -{ - render_font_char *ch = get_char(font, chnum); - float scale = font->scale * height; + // compute x1,y1 from there based on the bitmap size + bounds.x1 = bounds.x0 + (float)gl.bmwidth * scale * aspect; + bounds.y1 = bounds.y0 + (float)m_height * scale; - /* on entry, assume x0,y0 are the top,left coordinate of the cell and add */ - /* the character bounding box to that position */ - bounds->x0 += (float)ch->xoffs * scale * aspect; - - /* compute x1,y1 from there based on the bitmap size */ - bounds->x1 = bounds->x0 + (float)ch->bmwidth * scale * aspect; - bounds->y1 = bounds->y0 + (float)font->height * scale; - - /* return the texture */ - return ch->texture; + // return the texture + return gl.texture; } -/*------------------------------------------------- - render_font_draw_string_to_bitmap - draw a - string to a bitmap --------------------------------------------------*/ +//------------------------------------------------- +// get_scaled_bitmap_and_bounds - return a +// scaled bitmap and bounding rect for a char +//------------------------------------------------- -void render_font_get_scaled_bitmap_and_bounds(render_font *font, bitmap_t *dest, float height, float aspect, unicode_char chnum, rectangle *bounds) +void render_font::get_scaled_bitmap_and_bounds(bitmap_t &dest, float height, float aspect, unicode_char chnum, rectangle &bounds) { - render_font_char *ch = get_char(font, chnum); - float scale = font->scale * height; - INT32 origwidth, origheight; + glyph &gl = get_char(chnum); - /* on entry, assume x0,y0 are the top,left coordinate of the cell and add */ - /* the character bounding box to that position */ - bounds->min_x = (float)ch->xoffs * scale * aspect; - bounds->min_y = 0; + // on entry, assume x0,y0 are the top,left coordinate of the cell and add + // the character bounding box to that position + float scale = m_scale * height; + bounds.min_x = (float)gl.xoffs * scale * aspect; + bounds.min_y = 0; - /* compute x1,y1 from there based on the bitmap size */ - bounds->max_x = bounds->min_x + (float)ch->bmwidth * scale * aspect; - bounds->max_y = bounds->min_y + (float)font->height * scale; + // compute x1,y1 from there based on the bitmap size + bounds.max_x = bounds.min_x + (float)gl.bmwidth * scale * aspect; + bounds.max_y = bounds.min_y + (float)m_height * scale; - /* if the bitmap isn't big enough, bail */ - if (dest->width < bounds->max_x - bounds->min_x || dest->height < bounds->max_y - bounds->min_y) + // if the bitmap isn't big enough, bail + if (dest.width < bounds.max_x - bounds.min_x || dest.height < bounds.max_y - bounds.min_y) return; - /* scale the font */ - origwidth = dest->width; - origheight = dest->height; - dest->width = bounds->max_x - bounds->min_x; - dest->height = bounds->max_y - bounds->min_y; + // scale the font + INT32 origwidth = dest.width; + INT32 origheight = dest.height; + dest.width = bounds.max_x - bounds.min_x; + dest.height = bounds.max_y - bounds.min_y; rectangle clip; clip.min_x = clip.min_y = 0; - clip.max_x = ch->bitmap->width - 1; - clip.max_y = ch->bitmap->height - 1; - render_texture::hq_scale(*dest, *ch->bitmap, clip, NULL); - dest->width = origwidth; - dest->height = origheight; + clip.max_x = gl.bitmap->width - 1; + clip.max_y = gl.bitmap->height - 1; + render_texture::hq_scale(dest, *gl.bitmap, clip, NULL); + dest.width = origwidth; + dest.height = origheight; } -/*------------------------------------------------- - render_font_char_width - return the width of - a character at the given height --------------------------------------------------*/ +//------------------------------------------------- +// char_width - return the width of a character +// at the given height +//------------------------------------------------- -float render_font_get_char_width(render_font *font, float height, float aspect, unicode_char ch) +float render_font::char_width(float height, float aspect, unicode_char ch) { - return (float)get_char(font, ch)->width * font->scale * height * aspect; + return (float)get_char(ch).width * m_scale * height * aspect; } -/*------------------------------------------------- - render_font_string_width - return the width of - a string at the given height --------------------------------------------------*/ +//------------------------------------------------- +// string_width - return the width of a string +// at the given height +//------------------------------------------------- -float render_font_get_string_width(render_font *font, float height, float aspect, const char *string) +float render_font::string_width(float height, float aspect, const char *string) { - const unsigned char *ptr; + // loop over the string and accumulate widths int totwidth = 0; + for (const unsigned char *ptr = (const unsigned char *)string; *ptr != 0; ptr++) + totwidth += get_char(*ptr).width; - /* loop over the string and accumulate widths */ - for (ptr = (const unsigned char *)string; *ptr != 0; ptr++) - totwidth += get_char(font, *ptr)->width; - - /* scale the final result based on height */ - return (float)totwidth * font->scale * height * aspect; + // scale the final result based on height + return (float)totwidth * m_scale * height * aspect; } -/*------------------------------------------------- - render_font_get_utf8string_width - return the - width of a UTF8-encoded string at the given - height --------------------------------------------------*/ +//------------------------------------------------- +// utf8string_width - return the width of a +// UTF8-encoded string at the given height +//------------------------------------------------- -float render_font_get_utf8string_width(render_font *font, float height, float aspect, const char *utf8string) +float render_font::utf8string_width(float height, float aspect, const char *utf8string) { int length = strlen(utf8string); - unicode_char uchar; - int totwidth = 0; - int count = 0; - int offset; - /* loop over the string and accumulate widths */ - for (offset = 0; offset < length; offset += count) + // loop over the string and accumulate widths + int count; + int totwidth = 0; + for (int offset = 0; offset < length; offset += count) { + unicode_char uchar; count = uchar_from_utf8(&uchar, utf8string + offset, length - offset); if (count == -1) break; if (uchar < 0x10000) - totwidth += get_char(font, uchar)->width; + totwidth += get_char(uchar).width; } - /* scale the final result based on height */ - return (float)totwidth * font->scale * height * aspect; + // scale the final result based on height + return (float)totwidth * m_scale * height * aspect; } -/*------------------------------------------------- - render_font_load_cached_bdf - attempt to load - a cached version of the BDF font 'filename'; - if that fails, fall back on the regular BDF - loader and create a new cached version --------------------------------------------------*/ +//------------------------------------------------- +// load_cached_bdf - attempt to load a cached +// version of the BDF font 'filename'; if that +// fails, fall back on the regular BDF loader +// and create a new cached version +//------------------------------------------------- -static int render_font_load_cached_bdf(render_font *font, const char *filename) +bool render_font::load_cached_bdf(const char *filename) { - file_error filerr; - char *cachedname = NULL; - char *data = NULL; - mame_file *cachefile; + // first try to open the BDF itself mame_file *file; - int result = 1; - UINT32 bytes; - UINT32 hash; - - /* first try to open the BDF itself */ - filerr = mame_fopen(SEARCHPATH_FONT, filename, OPEN_FLAG_READ, &file); + file_error filerr = mame_fopen(SEARCHPATH_FONT, filename, OPEN_FLAG_READ, &file); if (filerr != FILERR_NONE) - return 1; - - /* determine the file size and allocate memory */ - font->rawsize = mame_fsize(file); - data = global_alloc_array_clear(char, font->rawsize + 1); + return false; - /* read and hash the first chunk */ - bytes = mame_fread(file, data, MIN(CACHED_BDF_HASH_SIZE, font->rawsize)); - if (bytes != MIN(CACHED_BDF_HASH_SIZE, font->rawsize)) - goto error; - hash = crc32(0, (const UINT8*)data, bytes) ^ (UINT32)font->rawsize; + // determine the file size and allocate memory + m_rawsize = mame_fsize(file); + char *data = auto_alloc_array_clear(&m_manager.machine(), char, m_rawsize + 1); - /* create the cached filename */ - cachedname = mame_strdup(filename); - if (cachedname == NULL) - goto error; + // read the first chunk + UINT32 bytes = mame_fread(file, data, MIN(CACHED_BDF_HASH_SIZE, m_rawsize)); + if (bytes != MIN(CACHED_BDF_HASH_SIZE, m_rawsize)) + { + mame_fclose(file); + return false; + } + + // has the chunk + UINT32 hash = crc32(0, (const UINT8 *)data, bytes) ^ (UINT32)m_rawsize; - /* change the 'F' to a 'C' on the extension */ - cachedname[strlen(cachedname) - 1] -= 3; + // create the cached filename, changing the 'F' to a 'C' on the extension + astring cachedname(filename); + cachedname.del(cachedname.len() - 3, 3).cat("bdc"); - /* attempt to load a cached version of the font */ + // attempt to open the cached version of the font + mame_file *cachefile; filerr = mame_fopen(SEARCHPATH_FONT, cachedname, OPEN_FLAG_READ, &cachefile); if (filerr == FILERR_NONE) { - result = render_font_load_cached(font, cachefile, hash); + // if we have a cached version, load it + bool result = load_cached(cachefile, hash); mame_fclose(cachefile); + + // if that worked, we're done + if (result) + { + mame_fclose(file); + auto_free(&m_manager.machine(), data); + return true; + } } - if (result != 0) + + // read in the rest of the font + if (bytes < m_rawsize) { - /* if that failed, read the rest of the font and parse it */ - if (bytes < font->rawsize) + UINT32 read = mame_fread(file, data + bytes, m_rawsize - bytes); + if (read != m_rawsize - bytes) { - UINT32 read = mame_fread(file, data + bytes, font->rawsize - bytes); - if (read != font->rawsize - bytes) - goto error; + mame_fclose(file); + auto_free(&m_manager.machine(), data); + return false; } + } - /* NULL-terminate the data and attach it to the font */ - data[font->rawsize] = 0; - font->rawdata = data; + // NULL-terminate the data and attach it to the font + data[m_rawsize] = 0; + m_rawdata = data; - /* load the BDF */ - result = render_font_load_bdf(font); + // load the BDF + bool result = load_bdf(); - /* if we loaded okay, create a cached one */ - if (result == 0) - render_font_save_cached(font, cachedname, hash); - } - else - global_free(data); + // if we loaded okay, create a cached one + if (result) + save_cached(cachedname, hash); - /* close the file */ - osd_free(cachedname); + // close the file mame_fclose(file); return result; - -error: - /* close the file */ - if (cachedname != NULL) - osd_free(cachedname); - if (data != NULL) - global_free(data); - mame_fclose(file); - return 1; } -/*------------------------------------------------- - render_font_load_bdf - parse and load a BDF - font --------------------------------------------------*/ +//------------------------------------------------- +// load_bdf - parse and load a BDF font +//------------------------------------------------- -static int render_font_load_bdf(render_font *font) +bool render_font::load_bdf() { - const char *ptr; - int charcount = 0; + // set the format to text + m_format = FF_TEXT; - /* set the format to text */ - font->format = FONT_FORMAT_TEXT; - - /* first find the FONTBOUNDINGBOX tag */ - for (ptr = font->rawdata; ptr != NULL; ptr = next_line(ptr)) + // first find the FONTBOUNDINGBOX tag + const char *ptr; + for (ptr = m_rawdata; ptr != NULL; ptr = next_line(ptr)) { - int dummy1, dummy2; - - /* we only care about a tiny few fields */ + // we only care about a tiny few fields if (strncmp(ptr, "FONTBOUNDINGBOX ", 16) == 0) { - if (sscanf(ptr + 16, "%d %d %d %d", &dummy1, &font->height, &dummy2, &font->yoffs) != 4) - return 1; + int dummy1, dummy2; + if (sscanf(ptr + 16, "%d %d %d %d", &dummy1, &m_height, &dummy2, &m_yoffs) != 4) + return false; break; } } - /* compute the scale factor */ - font->scale = 1.0f / (float)font->height; + // compute the scale factor + m_scale = 1.0f / (float)m_height; - /* now scan for characters */ + // now scan for characters + int charcount = 0; for ( ; ptr != NULL; ptr = next_line(ptr)) { - /* stop at ENDFONT */ + // stop at ENDFONT if (strncmp(ptr, "ENDFONT", 7) == 0) break; - /* once we hit a STARTCHAR, parse until the end */ + // once we hit a STARTCHAR, parse until the end if (strncmp(ptr, "STARTCHAR ", 10) == 0) { int bmwidth = -1, bmheight = -1, xoffs = -1, yoffs = -1; const char *rawdata = NULL; int charnum = -1; int width = -1; - int dummy1; - /* scan for interesting per-character tags */ + // scan for interesting per-character tags for ( ; ptr != NULL; ptr = next_line(ptr)) { - /* ENCODING tells us which character */ + // ENCODING tells us which character if (strncmp(ptr, "ENCODING ", 9) == 0) { if (sscanf(ptr + 9, "%d", &charnum) != 1) return 1; } - /* DWIDTH tells us the width to the next character */ + // DWIDTH tells us the width to the next character else if (strncmp(ptr, "DWIDTH ", 7) == 0) { + int dummy1; if (sscanf(ptr + 7, "%d %d", &width, &dummy1) != 2) return 1; } - /* BBX tells us the height/width of the bitmap and the offsets */ + // BBX tells us the height/width of the bitmap and the offsets else if (strncmp(ptr, "BBX ", 4) == 0) { if (sscanf(ptr + 4, "%d %d %d %d", &bmwidth, &bmheight, &xoffs, &yoffs) != 4) return 1; } - /* BITMAP is the start of the data */ + // BITMAP is the start of the data else if (strncmp(ptr, "BITMAP", 6) == 0) { - /* stash the raw pointer and scan for the end of the character */ + // stash the raw pointer and scan for the end of the character for (rawdata = ptr = next_line(ptr); ptr != NULL && strncmp(ptr, "ENDCHAR", 7) != 0; ptr = next_line(ptr)) ; break; } } - /* if we have everything, allocate a new character */ + // if we have everything, allocate a new character if (charnum >= 0 && charnum < 65536 && rawdata != NULL && bmwidth >= 0 && bmheight >= 0) { - render_font_char *ch; - - /* if we don't have a subtable yet, make one */ - if (font->chars[charnum / 256] == NULL) - font->chars[charnum / 256] = global_alloc_array_clear(render_font_char, 256); - - /* fill in the entry */ - ch = &font->chars[charnum / 256][charnum % 256]; - ch->width = width; - ch->bmwidth = bmwidth; - ch->bmheight = bmheight; - ch->xoffs = xoffs; - ch->yoffs = yoffs; - ch->rawdata = rawdata; + // if we don't have a subtable yet, make one + if (m_glyphs[charnum / 256] == NULL) + m_glyphs[charnum / 256] = auto_alloc_array_clear(&m_manager.machine(), glyph, 256); + + // fill in the entry + glyph &gl = m_glyphs[charnum / 256][charnum % 256]; + gl.width = width; + gl.bmwidth = bmwidth; + gl.bmheight = bmheight; + gl.xoffs = xoffs; + gl.yoffs = yoffs; + gl.rawdata = rawdata; } - /* some progress for big fonts */ + // some progress for big fonts if (++charcount % 256 == 0) mame_printf_warning("Loading BDF font... (%d characters loaded)\n", charcount); } } - /* make sure all the numbers are the same width */ - if (font->chars[0] != NULL) + // make sure all the numbers are the same width + if (m_glyphs[0] != NULL) { int maxwidth = 0; for (int ch = '0'; ch <= '9'; ch++) - if (font->chars[0][ch].bmwidth > maxwidth) - maxwidth = font->chars[0][ch].width; + if (m_glyphs[0][ch].bmwidth > maxwidth) + maxwidth = m_glyphs[0][ch].width; for (int ch = '0'; ch <= '9'; ch++) - font->chars[0][ch].width = maxwidth; + m_glyphs[0][ch].width = maxwidth; } - return 0; + return true; } -/*------------------------------------------------- - render_font_load_cached - load a font in - cached format --------------------------------------------------*/ +//------------------------------------------------- +// load_cached - load a font in cached format +//------------------------------------------------- -static int render_font_load_cached(render_font *font, mame_file *file, UINT32 hash) +bool render_font::load_cached(mame_file *file, UINT32 hash) { - UINT8 header[CACHED_HEADER_SIZE]; - UINT64 offset, filesize; - UINT8 *data = NULL; - UINT32 bytes_read; - int numchars; - int chindex; - - /* get the file size */ - filesize = mame_fsize(file); + // get the file size + UINT64 filesize = mame_fsize(file); - /* first read the header */ - bytes_read = mame_fread(file, header, CACHED_HEADER_SIZE); + // first read the header + UINT8 header[CACHED_HEADER_SIZE]; + UINT32 bytes_read = mame_fread(file, header, CACHED_HEADER_SIZE); if (bytes_read != CACHED_HEADER_SIZE) - goto error; + return false; - /* validate the header */ + // validate the header if (header[0] != 'f' || header[1] != 'o' || header[2] != 'n' || header[3] != 't') - goto error; + return false; if (header[4] != (UINT8)(hash >> 24) || header[5] != (UINT8)(hash >> 16) || header[6] != (UINT8)(hash >> 8) || header[7] != (UINT8)hash) - goto error; - font->height = (header[8] << 8) | header[9]; - font->scale = 1.0f / (float)font->height; - font->yoffs = (INT16)((header[10] << 8) | header[11]); - numchars = (header[12] << 24) | (header[13] << 16) | (header[14] << 8) | header[15]; + return false; + m_height = (header[8] << 8) | header[9]; + m_scale = 1.0f / (float)m_height; + m_yoffs = (INT16)((header[10] << 8) | header[11]); + int numchars = (header[12] << 24) | (header[13] << 16) | (header[14] << 8) | header[15]; if (filesize - CACHED_HEADER_SIZE < numchars * CACHED_CHAR_SIZE) - goto error; + return false; - /* now read the rest of the data */ - data = global_alloc_array(UINT8, filesize - CACHED_HEADER_SIZE); + // now read the rest of the data + UINT8 *data = auto_alloc_array(&m_manager.machine(), UINT8, filesize - CACHED_HEADER_SIZE); bytes_read = mame_fread(file, data, filesize - CACHED_HEADER_SIZE); if (bytes_read != filesize - CACHED_HEADER_SIZE) - goto error; + { + auto_free(&m_manager.machine(), data); + return false; + } - /* extract the data from the data */ - offset = numchars * CACHED_CHAR_SIZE; - for (chindex = 0; chindex < numchars; chindex++) + // extract the data from the data + UINT64 offset = numchars * CACHED_CHAR_SIZE; + for (int chindex = 0; chindex < numchars; chindex++) { const UINT8 *info = &data[chindex * CACHED_CHAR_SIZE]; int chnum = (info[0] << 8) | info[1]; - render_font_char *ch; - - /* if we don't have a subtable yet, make one */ - if (font->chars[chnum / 256] == NULL) - font->chars[chnum / 256] = global_alloc_array_clear(render_font_char, 256); - - /* fill in the entry */ - ch = &font->chars[chnum / 256][chnum % 256]; - ch->width = (info[2] << 8) | info[3]; - ch->xoffs = (INT16)((info[4] << 8) | info[5]); - ch->yoffs = (INT16)((info[6] << 8) | info[7]); - ch->bmwidth = (info[8] << 8) | info[9]; - ch->bmheight = (info[10] << 8) | info[11]; - ch->rawdata = (char *)data + offset; - - /* advance the offset past the character */ - offset += (ch->bmwidth * ch->bmheight + 7) / 8; + + // if we don't have a subtable yet, make one + if (m_glyphs[chnum / 256] == NULL) + m_glyphs[chnum / 256] = auto_alloc_array_clear(&m_manager.machine(), glyph, 256); + + // fill in the entry + glyph &gl = m_glyphs[chnum / 256][chnum % 256]; + gl.width = (info[2] << 8) | info[3]; + gl.xoffs = (INT16)((info[4] << 8) | info[5]); + gl.yoffs = (INT16)((info[6] << 8) | info[7]); + gl.bmwidth = (info[8] << 8) | info[9]; + gl.bmheight = (info[10] << 8) | info[11]; + gl.rawdata = (char *)data + offset; + + // advance the offset past the character + offset += (gl.bmwidth * gl.bmheight + 7) / 8; if (offset > filesize - CACHED_HEADER_SIZE) - goto error; + { + auto_free(&m_manager.machine(), data); + return false; + } } - /* reuse the chartable as a temporary buffer */ - font->format = FONT_FORMAT_CACHED; - font->rawdata = (char *)data; - return 0; - -error: - if (data != NULL) - global_free(data); - return 1; + // reuse the chartable as a temporary buffer + m_format = FF_CACHED; + m_rawdata = (char *)data; + return true; } -/*------------------------------------------------- - render_font_save_cached - save a font in - cached format --------------------------------------------------*/ +//------------------------------------------------- +// save_cached - save a font in cached format +//------------------------------------------------- -static int render_font_save_cached(render_font *font, const char *filename, UINT32 hash) +bool render_font::save_cached(const char *filename, UINT32 hash) { - file_error filerr; - render_font_char *ch; - UINT32 bytes_written; - UINT8 *tempbuffer; - UINT8 *chartable; - mame_file *file; - int numchars; - UINT8 *dest; - int tableindex; - int chnum; - mame_printf_warning("Generating cached BDF font...\n"); - /* attempt to open the file */ - filerr = mame_fopen(SEARCHPATH_FONT, filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file); + // attempt to open the file + mame_file *file; + file_error filerr = mame_fopen(SEARCHPATH_FONT, filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file); if (filerr != FILERR_NONE) - return 1; + return false; - /* determine the number of characters */ - numchars = 0; - for (chnum = 0; chnum < 65536; chnum++) + // determine the number of characters + int numchars = 0; + for (int chnum = 0; chnum < 65536; chnum++) { - render_font_char *chtable = font->chars[chnum / 256]; + glyph *chtable = m_glyphs[chnum / 256]; if (chtable != NULL) { - ch = &chtable[chnum % 256]; - if (ch->width > 0) + glyph &gl = chtable[chnum % 256]; + if (gl.width > 0) numchars++; } } - /* allocate an array to hold the character data */ - chartable = global_alloc_array_clear(UINT8, numchars * CACHED_CHAR_SIZE); - - /* allocate a temp buffer to compress into */ - tempbuffer = global_alloc_array(UINT8, 65536); - - /* write the header */ - dest = tempbuffer; - *dest++ = 'f'; - *dest++ = 'o'; - *dest++ = 'n'; - *dest++ = 't'; - *dest++ = hash >> 24; - *dest++ = hash >> 16; - *dest++ = hash >> 8; - *dest++ = hash & 0xff; - *dest++ = font->height >> 8; - *dest++ = font->height & 0xff; - *dest++ = font->yoffs >> 8; - *dest++ = font->yoffs & 0xff; - *dest++ = numchars >> 24; - *dest++ = numchars >> 16; - *dest++ = numchars >> 8; - *dest++ = numchars & 0xff; - assert(dest - tempbuffer == CACHED_HEADER_SIZE); - bytes_written = mame_fwrite(file, tempbuffer, dest - tempbuffer); - if (bytes_written != dest - tempbuffer) - goto error; - - /* write the empty table to the beginning of the file */ - bytes_written = mame_fwrite(file, chartable, numchars * CACHED_CHAR_SIZE); - if (bytes_written != numchars * CACHED_CHAR_SIZE) - goto error; - - /* loop over all characters */ - tableindex = 0; - for (chnum = 0; chnum < 65536; chnum++) + UINT8 *chartable = NULL; + UINT8 *tempbuffer = NULL; + try { - ch = get_char(font, chnum); - if (ch != NULL && ch->width > 0) + // allocate an array to hold the character data + UINT8 *chartable = auto_alloc_array_clear(&m_manager.machine(), UINT8, numchars * CACHED_CHAR_SIZE); + + // allocate a temp buffer to compress into + UINT8 *tempbuffer = auto_alloc_array(&m_manager.machine(), UINT8, 65536); + + // write the header + UINT8 *dest = tempbuffer; + *dest++ = 'f'; + *dest++ = 'o'; + *dest++ = 'n'; + *dest++ = 't'; + *dest++ = hash >> 24; + *dest++ = hash >> 16; + *dest++ = hash >> 8; + *dest++ = hash & 0xff; + *dest++ = m_height >> 8; + *dest++ = m_height & 0xff; + *dest++ = m_yoffs >> 8; + *dest++ = m_yoffs & 0xff; + *dest++ = numchars >> 24; + *dest++ = numchars >> 16; + *dest++ = numchars >> 8; + *dest++ = numchars & 0xff; + assert(dest - tempbuffer == CACHED_HEADER_SIZE); + UINT32 bytes_written = mame_fwrite(file, tempbuffer, dest - tempbuffer); + if (bytes_written != dest - tempbuffer) + throw emu_fatalerror("Error writing cached file"); + + // write the empty table to the beginning of the file + bytes_written = mame_fwrite(file, chartable, numchars * CACHED_CHAR_SIZE); + if (bytes_written != numchars * CACHED_CHAR_SIZE) + throw emu_fatalerror("Error writing cached file"); + + // loop over all characters + int tableindex = 0; + for (int chnum = 0; chnum < 65536; chnum++) { - UINT8 accum, accbit; - int x, y; - - /* write out a bit-compressed bitmap if we have one */ - if (ch->bitmap != NULL) + glyph &gl = get_char(chnum); + if (gl.width > 0) { - /* write the data to the tempbuffer */ - dest = tempbuffer; - accum = 0; - accbit = 7; - - /* bit-encode the character data */ - for (y = 0; y < ch->bmheight; y++) + // write out a bit-compressed bitmap if we have one + if (gl.bitmap != NULL) { - int desty = y + font->height + font->yoffs - ch->yoffs - ch->bmheight; - const UINT32 *src = (desty >= 0 && desty < font->height) ? BITMAP_ADDR32(ch->bitmap, desty, 0) : NULL; - for (x = 0; x < ch->bmwidth; x++) + // write the data to the tempbuffer + dest = tempbuffer; + UINT8 accum = 0; + UINT8 accbit = 7; + + // bit-encode the character data + for (int y = 0; y < gl.bmheight; y++) { - if (src != NULL && RGB_ALPHA(src[x]) != 0) - accum |= 1 << accbit; - if (accbit-- == 0) + int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight; + const UINT32 *src = (desty >= 0 && desty < m_height) ? BITMAP_ADDR32(gl.bitmap, desty, 0) : NULL; + for (int x = 0; x < gl.bmwidth; x++) { - *dest++ = accum; - accum = 0; - accbit = 7; + if (src != NULL && RGB_ALPHA(src[x]) != 0) + accum |= 1 << accbit; + if (accbit-- == 0) + { + *dest++ = accum; + accum = 0; + accbit = 7; + } } } - } - /* flush any extra */ - if (accbit != 7) - *dest++ = accum; + // flush any extra + if (accbit != 7) + *dest++ = accum; - /* write the data */ - bytes_written = mame_fwrite(file, tempbuffer, dest - tempbuffer); - if (bytes_written != dest - tempbuffer) - goto error; + // write the data + bytes_written = mame_fwrite(file, tempbuffer, dest - tempbuffer); + if (bytes_written != dest - tempbuffer) + throw emu_fatalerror("Error writing cached file"); - /* free the bitmap and texture */ - font->machine->render().texture_free(ch->texture); - ch->texture = NULL; - global_free(ch->bitmap); - ch->bitmap = NULL; - } + // free the bitmap and texture + m_manager.texture_free(gl.texture); + auto_free(&m_manager.machine(), gl.bitmap); + gl.texture = NULL; + gl.bitmap = NULL; + } - /* compute the table entry */ - dest = &chartable[tableindex++ * CACHED_CHAR_SIZE]; - *dest++ = chnum >> 8; - *dest++ = chnum & 0xff; - *dest++ = ch->width >> 8; - *dest++ = ch->width & 0xff; - *dest++ = ch->xoffs >> 8; - *dest++ = ch->xoffs & 0xff; - *dest++ = ch->yoffs >> 8; - *dest++ = ch->yoffs & 0xff; - *dest++ = ch->bmwidth >> 8; - *dest++ = ch->bmwidth & 0xff; - *dest++ = ch->bmheight >> 8; - *dest++ = ch->bmheight & 0xff; + // compute the table entry + dest = &chartable[tableindex++ * CACHED_CHAR_SIZE]; + *dest++ = chnum >> 8; + *dest++ = chnum & 0xff; + *dest++ = gl.width >> 8; + *dest++ = gl.width & 0xff; + *dest++ = gl.xoffs >> 8; + *dest++ = gl.xoffs & 0xff; + *dest++ = gl.yoffs >> 8; + *dest++ = gl.yoffs & 0xff; + *dest++ = gl.bmwidth >> 8; + *dest++ = gl.bmwidth & 0xff; + *dest++ = gl.bmheight >> 8; + *dest++ = gl.bmheight & 0xff; + } } - } - - /* seek back to the beginning and rewrite the table */ - mame_fseek(file, CACHED_HEADER_SIZE, SEEK_SET); - bytes_written = mame_fwrite(file, chartable, numchars * CACHED_CHAR_SIZE); - if (bytes_written != numchars * CACHED_CHAR_SIZE) - goto error; - /* all done */ - mame_fclose(file); - global_free(tempbuffer); - global_free(chartable); - return 0; - -error: - mame_fclose(file); - osd_rmfile(filename); - global_free(tempbuffer); - global_free(chartable); - return 1; + // seek back to the beginning and rewrite the table + mame_fseek(file, CACHED_HEADER_SIZE, SEEK_SET); + bytes_written = mame_fwrite(file, chartable, numchars * CACHED_CHAR_SIZE); + if (bytes_written != numchars * CACHED_CHAR_SIZE) + throw emu_fatalerror("Error writing cached file"); + + // all done + mame_fclose(file); + auto_free(&m_manager.machine(), tempbuffer); + auto_free(&m_manager.machine(), chartable); + return true; + } + catch (...) + { + mame_fclose(file); + osd_rmfile(filename); + auto_free(&m_manager.machine(), tempbuffer); + auto_free(&m_manager.machine(), chartable); + return false; + } } diff --git a/src/emu/rendfont.h b/src/emu/rendfont.h index d8656b1ac0e..1eba3bc1a71 100644 --- a/src/emu/rendfont.h +++ b/src/emu/rendfont.h @@ -4,8 +4,36 @@ Rendering system font management. - Copyright Nicola Salmoria and the MAME Team. - Visit http://mamedev.org for licensing and usage restrictions. +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ @@ -15,18 +43,81 @@ #include "render.h" +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ -render_font *render_font_alloc(running_machine &machine, const char *filename); -void render_font_free(render_font *font); -INT32 render_font_get_pixel_height(render_font *font); -render_texture *render_font_get_char_texture_and_bounds(render_font *font, float height, float aspect, unicode_char ch, render_bounds *bounds); -void render_font_get_scaled_bitmap_and_bounds(render_font *font, bitmap_t *dest, float height, float aspect, unicode_char chnum, rectangle *bounds); -float render_font_get_char_width(render_font *font, float height, float aspect, unicode_char ch); -float render_font_get_string_width(render_font *font, float height, float aspect, const char *string); -float render_font_get_utf8string_width(render_font *font, float height, float aspect, const char *utf8string); +// ======================> render_font + +// a render_font describes and provides an interface to a font +class render_font +{ + friend class render_manager; + friend resource_pool_object<render_font>::~resource_pool_object(); + + // construction/destruction + render_font(render_manager &manager, const char *filename); + virtual ~render_font(); + +public: + // getters + render_manager &manager() const { return m_manager; } + + // size queries + INT32 pixel_height() const { return m_height; } + float char_width(float height, float aspect, unicode_char ch); + float string_width(float height, float aspect, const char *string); + float utf8string_width(float height, float aspect, const char *utf8string); + + // texture/bitmap queries + render_texture *get_char_texture_and_bounds(float height, float aspect, unicode_char ch, render_bounds &bounds); + void get_scaled_bitmap_and_bounds(bitmap_t &dest, float height, float aspect, unicode_char chnum, rectangle &bounds); + +private: + // a glyph describes a single glyph + class glyph + { + public: + INT32 width; /* width from this character to the next */ + INT32 xoffs, yoffs; /* X and Y offset from baseline to top,left of bitmap */ + INT32 bmwidth, bmheight; /* width and height of bitmap */ + const char * rawdata; /* pointer to the raw data for this one */ + bitmap_t * bitmap; /* pointer to the bitmap containing the raw data */ + render_texture * texture; /* pointer to a texture for rendering and sizing */ + }; + + // internal format + enum format + { + FF_UNKNOWN, + FF_TEXT, + FF_CACHED + }; + + // helpers + glyph &get_char(unicode_char chnum); + void char_expand(glyph &ch); + bool load_cached_bdf(const char *filename); + bool load_bdf(); + bool load_cached(mame_file *file, UINT32 hash); + bool save_cached(const char *filename, UINT32 hash); + + // internal state + render_manager & m_manager; + format m_format; /* format of font data */ + int m_height; /* height of the font, from ascent to descent */ + int m_yoffs; /* y offset from baseline to descent */ + float m_scale; /* 1 / height precomputed */ + glyph * m_glyphs[256]; /* array of glyph subtables */ + const char * m_rawdata; /* pointer to the raw data for the font */ + UINT64 m_rawsize; /* size of the raw font data */ + + // constants + static const int CACHED_CHAR_SIZE = 12; + static const int CACHED_HEADER_SIZE = 16; + static const int CACHED_BDF_HASH_SIZE = 1024; +}; + #endif /* __RENDFONT_H__ */ diff --git a/src/emu/rendlay.c b/src/emu/rendlay.c index 963426f2286..633d2abce0d 100644 --- a/src/emu/rendlay.c +++ b/src/emu/rendlay.c @@ -827,12 +827,12 @@ void layout_element::component::draw_text(running_machine &machine, bitmap_t &de UINT32 a = m_color.a * 255.0; // get the width of the string - render_font *font = render_font_alloc(machine, NULL); + render_font *font = machine.render().font_alloc(); float aspect = 1.0f; INT32 width; while (1) { - width = render_font_get_string_width(font, bounds.max_y - bounds.min_y, aspect, m_string); + width = font->string_width(bounds.max_y - bounds.min_y, aspect, m_string); if (width < bounds.max_x - bounds.min_x) break; aspect *= 0.9f; @@ -847,7 +847,7 @@ void layout_element::component::draw_text(running_machine &machine, bitmap_t &de { // get the font bitmap rectangle chbounds; - render_font_get_scaled_bitmap_and_bounds(font, tempbitmap, bounds.max_y - bounds.min_y, aspect, *s, &chbounds); + font->get_scaled_bitmap_and_bounds(*tempbitmap, bounds.max_y - bounds.min_y, aspect, *s, chbounds); // copy the data into the target for (int y = 0; y < chbounds.max_y - chbounds.min_y; y++) @@ -878,12 +878,12 @@ void layout_element::component::draw_text(running_machine &machine, bitmap_t &de } // advance in the X direction - curx += render_font_get_char_width(font, bounds.max_y - bounds.min_y, aspect, *s); + curx += font->char_width(bounds.max_y - bounds.min_y, aspect, *s); } // free the temporary bitmap and font global_free(tempbitmap); - render_font_free(font); + machine.render().font_free(font); } diff --git a/src/emu/ui.c b/src/emu/ui.c index 872b34b43fe..61031514f1a 100644 --- a/src/emu/ui.c +++ b/src/emu/ui.c @@ -240,7 +240,7 @@ int ui_init(running_machine *machine) machine->add_notifier(MACHINE_NOTIFY_EXIT, ui_exit); /* allocate the font and messagebox string */ - ui_font = render_font_alloc(*machine, "ui.bdf"); + ui_font = machine->render().font_alloc("ui.bdf"); /* initialize the other UI bits */ ui_menu_init(machine); @@ -263,8 +263,7 @@ int ui_init(running_machine *machine) static void ui_exit(running_machine &machine) { /* free the font */ - if (ui_font != NULL) - render_font_free(ui_font); + machine.render().font_free(ui_font); ui_font = NULL; } @@ -424,7 +423,7 @@ render_font *ui_get_font(void) float ui_get_line_height(running_machine &machine) { - INT32 raw_font_pixel_height = render_font_get_pixel_height(ui_font); + INT32 raw_font_pixel_height = ui_font->pixel_height(); render_target &ui_target = machine.render().ui_target(); INT32 target_pixel_height = ui_target.height(); float one_to_one_line_height; @@ -469,7 +468,7 @@ float ui_get_line_height(running_machine &machine) float ui_get_char_width(running_machine &machine, unicode_char ch) { - return render_font_get_char_width(ui_font, ui_get_line_height(machine), machine.render().ui_aspect(), ch); + return ui_font->char_width(ui_get_line_height(machine), machine.render().ui_aspect(), ch); } @@ -480,7 +479,7 @@ float ui_get_char_width(running_machine &machine, unicode_char ch) float ui_get_string_width(running_machine &machine, const char *s) { - return render_font_get_utf8string_width(ui_font, ui_get_line_height(machine), machine.render().ui_aspect(), s); + return ui_font->utf8string_width(ui_get_line_height(machine), machine.render().ui_aspect(), s); } diff --git a/src/emu/uigfx.c b/src/emu/uigfx.c index 0e2f786ff4c..cb366c194c8 100644 --- a/src/emu/uigfx.c +++ b/src/emu/uigfx.c @@ -253,7 +253,7 @@ static void palette_handler(running_machine *machine, render_container *containe /* add a half character padding for the box */ chheight = ui_get_line_height(*machine); - chwidth = render_font_get_char_width(ui_font, chheight, machine->render().ui_aspect(), '0'); + chwidth = ui_font->char_width(chheight, machine->render().ui_aspect(), '0'); boxbounds.x0 = 0.0f + 0.5f * chwidth; boxbounds.x1 = 1.0f - 0.5f * chwidth; boxbounds.y0 = 0.0f + 0.5f * chheight; @@ -273,7 +273,7 @@ static void palette_handler(running_machine *machine, render_container *containe cellboxbounds.y0 += 3.0f * chheight; /* figure out the title and expand the outer box to fit */ - titlewidth = render_font_get_string_width(ui_font, chheight, machine->render().ui_aspect(), title); + titlewidth = ui_font->string_width(chheight, machine->render().ui_aspect(), title); x0 = 0.0f; if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth) x0 = boxbounds.x0 - (0.5f - 0.5f * (titlewidth + chwidth)); @@ -287,7 +287,7 @@ static void palette_handler(running_machine *machine, render_container *containe for (x = 0; title[x] != 0; x++) { container->add_char(x0, y0, chheight, machine->render().ui_aspect(), ARGB_WHITE, *ui_font, title[x]); - x0 += render_font_get_char_width(ui_font, chheight, machine->render().ui_aspect(), title[x]); + x0 += ui_font->char_width(chheight, machine->render().ui_aspect(), title[x]); } /* compute the cell size */ @@ -328,7 +328,7 @@ static void palette_handler(running_machine *machine, render_container *containe sprintf(buffer, "%5X", state->palette.offset + y * state->palette.count); for (x = 4; x >= 0; x--) { - x0 -= render_font_get_char_width(ui_font, chheight, machine->render().ui_aspect(), buffer[x]); + x0 -= ui_font->char_width(chheight, machine->render().ui_aspect(), buffer[x]); container->add_char(x0, y0 + 0.5f * (cellheight - chheight), chheight, machine->render().ui_aspect(), ARGB_WHITE, *ui_font, buffer[x]); } } @@ -449,7 +449,7 @@ static void gfxset_handler(running_machine *machine, render_container *container /* add a half character padding for the box */ chheight = ui_get_line_height(*machine); - chwidth = render_font_get_char_width(ui_font, chheight, machine->render().ui_aspect(), '0'); + chwidth = ui_font->char_width(chheight, machine->render().ui_aspect(), '0'); boxbounds.x0 = 0.0f + 0.5f * chwidth; boxbounds.x1 = 1.0f - 0.5f * chwidth; boxbounds.y0 = 0.0f + 0.5f * chheight; @@ -514,7 +514,7 @@ static void gfxset_handler(running_machine *machine, render_container *container /* figure out the title and expand the outer box to fit */ for (x = 0; x < MAX_GFX_ELEMENTS && machine->gfx[x] != NULL; x++) ; sprintf(title, "GFX %d/%d %dx%d COLOR %X", state->gfxset.set, x - 1, gfx->width, gfx->height, state->gfxset.color[set]); - titlewidth = render_font_get_string_width(ui_font, chheight, machine->render().ui_aspect(), title); + titlewidth = ui_font->string_width(chheight, machine->render().ui_aspect(), title); x0 = 0.0f; if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth) x0 = boxbounds.x0 - (0.5f - 0.5f * (titlewidth + chwidth)); @@ -528,7 +528,7 @@ static void gfxset_handler(running_machine *machine, render_container *container for (x = 0; title[x] != 0; x++) { container->add_char(x0, y0, chheight, machine->render().ui_aspect(), ARGB_WHITE, *ui_font, title[x]); - x0 += render_font_get_char_width(ui_font, chheight, machine->render().ui_aspect(), title[x]); + x0 += ui_font->char_width(chheight, machine->render().ui_aspect(), title[x]); } /* draw the top column headers */ @@ -565,7 +565,7 @@ static void gfxset_handler(running_machine *machine, render_container *container sprintf(buffer, "%5X", state->gfxset.offset[set] + y * xcells); for (x = 4; x >= 0; x--) { - x0 -= render_font_get_char_width(ui_font, chheight, machine->render().ui_aspect(), buffer[x]); + x0 -= ui_font->char_width(chheight, machine->render().ui_aspect(), buffer[x]); container->add_char(x0, y0 + 0.5f * (cellheight - chheight), chheight, machine->render().ui_aspect(), ARGB_WHITE, *ui_font, buffer[x]); } } @@ -861,7 +861,7 @@ static void tilemap_handler(running_machine *machine, render_container *containe /* add a half character padding for the box */ chheight = ui_get_line_height(*machine); - chwidth = render_font_get_char_width(ui_font, chheight, machine->render().ui_aspect(), '0'); + chwidth = ui_font->char_width(chheight, machine->render().ui_aspect(), '0'); boxbounds.x0 = 0.0f + 0.5f * chwidth; boxbounds.x1 = 1.0f - 0.5f * chwidth; boxbounds.y0 = 0.0f + 0.5f * chheight; @@ -908,7 +908,7 @@ static void tilemap_handler(running_machine *machine, render_container *containe /* figure out the title and expand the outer box to fit */ sprintf(title, "TMAP %d/%d %dx%d OFFS %d,%d", state->tilemap.which, tilemap_count(machine) - 1, mapwidth, mapheight, state->tilemap.xoffs, state->tilemap.yoffs); - titlewidth = render_font_get_string_width(ui_font, chheight, machine->render().ui_aspect(), title); + titlewidth = ui_font->string_width(chheight, machine->render().ui_aspect(), title); if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth) { boxbounds.x0 = 0.5f - 0.5f * (titlewidth + chwidth); @@ -924,7 +924,7 @@ static void tilemap_handler(running_machine *machine, render_container *containe for (x = 0; title[x] != 0; x++) { container->add_char(x0, y0, chheight, machine->render().ui_aspect(), ARGB_WHITE, *ui_font, title[x]); - x0 += render_font_get_char_width(ui_font, chheight, machine->render().ui_aspect(), title[x]); + x0 += ui_font->char_width(chheight, machine->render().ui_aspect(), title[x]); } /* update the bitmap */ |