/*************************************************************** ** ** Broadcom Corp. Confidential ** Copyright 2002 Broadcom Corp. All Rights Reserved. ** ** THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED ** SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM. ** YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT ** SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. ** ** Description: SGIL bit map font library ** ** Created: 8/22/2002 by Jeffrey P. Fisher ** ** ** ****************************************************************/ /** include files **/ #include "bgfx.h" static bgfx_glyph_t *bgfx_init_glyph(bgfx_font_t *font_p, FT_ULong a_char, int glyph_idx); /* global SGL structure */ typedef struct bgfx_t { #ifdef CONFIG_FREETYPE FT_Library ft_library; #endif int dummy; }bgfx_t; #ifdef CONFIG_FREETYPE static bgfx_t g_bgfx = { NULL }; #endif /****************************************************************} * INPUTS: none * OUTPUTS: none * RETURNS: non-zero on failure * FUNCTION: Initialize the SGIL font library * ****************************************************************/ int bgfx_font_init() { int result = 0; BGFX_TRACE(("font_init\n")); #ifdef CONFIG_FREETYPE bgfx_lock(); { FT_Error err; err = FT_Init_FreeType( &g_bgfx.ft_library ); if (err) { g_bgfx.ft_library = NULL; result = -1; BGFX_DEBUG(("font_init - FT_Init_FreeType(%d)\n",err)); } } bgfx_unlock(); #endif BGFX_TRACE(("font_init - done\n")); return result; } /****************************************************************} * INPUTS: none * OUTPUTS: none * RETURNS: non-zero on failure * FUNCTION: release sgl global resources, primarily for handling freetype * ****************************************************************/ void bgfx_font_done() { BGFX_TRACE(("font_done\n")); #ifdef CONFIG_FREETYPE bgfx_lock(); if (g_bgfx.ft_library) FT_Done_FreeType( g_bgfx.ft_library ); g_bgfx.ft_library = NULL; bgfx_unlock(); #endif } #ifdef CONFIG_FREETYPE /**************************************************************** * INPUTS: fr_p - font ripper parameters * OUTPUTS: none * RETURNS: number of glyph entries * DESCRIPTION: Get the maximum number of glyph index entries. * ****************************************************************/ int get_max_glyph_index(bgfx_font_t *font_p) { FT_ULong charcode; FT_UInt gindex; int cnt = 0; charcode = FT_Get_First_Char( font_p->face, &gindex ); while ( gindex != 0 ) { ++cnt; charcode = FT_Get_Next_Char( font_p->face, charcode, &gindex ); } return cnt; } /**************************************************************** * INPUTS: font_p - font definition * OUTPUTS: none * RETURNS: none-zero on failure * FUNCTION: create the charmap. * ****************************************************************/ int bgfx_create_char_map(bgfx_font_t *font_p) { int i = 0; FT_ULong charcode; FT_UInt gindex; font_p->cache_size = get_max_glyph_index(font_p); if (font_p->char_map_size <= 0) { BGFX_DEBUG(("bgfx_create_char_map failed, no unicode encoding for this font.\n")); return -1; } font_p->char_map = (bgfx_glyph_t**)BGFX_MALLOC(sizeof(bgfx_glyph_t*) * font_p->cache_size ); if (!font_p->glyph_cache) { BGFX_DEBUG(("bgfx_create_char_map failed, could not allocate memory for char map.\n")); return -1; } bgfx_lock(); charcode = FT_Get_First_Char( font_p->face, &gindex ); while ( gindex != 0 ) { font_p->char_map[i++] = charcode; charcode = FT_Get_Next_Char( font_p->face, charcode, &gindex ); } bgfx_unlock(); BGFX_TRACE(("bgfx_create_char_map - %d chars.\n",i)); return 0; } #endif /* CONFIG_FREETYPE */ /**************************************************************** * INPUTS: font_p - font definition * typeface_name - name of the typeface * height - font height * OUTPUTS: none * RETURNS: none-zero on failure * FUNCTION: Load the font typeface. * * The general usage convention in SGIL is to avoid memory allocation * in SGIL functions. For example before calling bgfx_new_font a * valid font_t structure must be created and passed to bgfx_new_font. * The font_t structure is modified but not allocated by bgfx_new_font. * A primary exception is that the glyph cache and glyphs are * allocated and manage internally. Therefore, it is important to * call bgfx_free_font to allow SGIL to perform cleanup on the glyph cache. ****************************************************************/ int bgfx_new_font(bgfx_font_t *font_p, const char *typeface_name, unsigned char height,unsigned long flags) { BGFX_TRACE(("bgfx_new_font - %s:%d,%ld\n",typeface_name,height,flags)); #ifdef CONFIG_FREETYPE { FT_Error err; unsigned long i; bgfx_glyph_t *glyph; bgfx_lock(); err = FT_New_Face( g_bgfx.ft_library, typeface_name,0, &font_p->face ); if (err) { BGFX_DEBUG(("bgfx_new_font could not open typeface %s\n",typeface_name)); bgfx_unlock(); return -1; } err = FT_Select_Charmap( font_p->face, ft_encoding_unicode ); #if FREETYPE_MINOR > 0 if (err) { BGFX_DEBUG(("bgfx_new_font could not open unicode charmap, default to latin\n")); err = FT_Select_Charmap( font_p->face, ft_encoding_latin_1 ); } #endif if (err) { BGFX_DEBUG(("bgfx_new_font could not select charmap for font %s\n",typeface_name)); bgfx_unlock(); return -1; } err = FT_Set_Pixel_Sizes( font_p->face, 0, height); if (err) { BGFX_DEBUG(("bgfx_new_font could set font height to %d\n",height)); FT_Done_Face( font_p->face ); bgfx_unlock(); return -1; } if (flags & BGFX_MONO) font_p->face->generic.data = (void *) (FT_LOAD_DEFAULT | FT_LOAD_MONOCHROME); else font_p->face->generic.data = (void *) FT_LOAD_DEFAULT; font_p->ascender = font_p->face->size->metrics.ascender >> 6; font_p->descender = font_p->face->size->metrics.descender >> 6; font_p->height = (font_p->face->size->metrics.ascender - font_p->face->size->metrics.descender) >> 6; font_p->maxadvance = font_p->face->size->metrics.max_advance >> 6; /* create glyph cache */ if (flags & BGFX_CACHE_GLYPHS) { font_p->cache_size = font_p->face->num_glyphs; font_p->glyph_cache = (bgfx_glyph_t**)BGFX_MALLOC(sizeof(bgfx_glyph_t*) * font_p->cache_size); if (font_p->glyph_cache) BGFX_MEMSET(font_p->glyph_cache,0,sizeof(bgfx_glyph_t*) * font_p->cache_size); else font_p->cache_size = 0; } else { font_p->cache_size = 0; font_p->glyph_cache = NULL; } font_p->format = flags; bgfx_unlock(); if (bgfx_create_char_map(font_p) != 0) { BGFX_DEBUG(("bgfx_new_font could not create charmap\n")); FT_Done_Face( font_p->face ); return -1; } if (flags & BGFX_PRELOAD_GLYPHS) { for (i = 0; i < font_p->cache_size; ++i) glyph = bgfx_init_glyph(font_p,font_p->char_map[i],i); } } return 0; #else return -1; /* must load fonts when there is no freetype support */ #endif } /**************************************************************** * INPUTS: font_p - font definition * OUTPUTS: none * RETURNS: none * FUNCTION: Free font typeface. * ****************************************************************/ void bgfx_free_font(bgfx_font_t *font_p) { if (font_p->glyph_cache[0]->buf) BGFX_FREE(font_p->glyph_cache[0]->buf); if (font_p->glyph_cache[0]) BGFX_FREE(font_p->glyph_cache[0]); if (font_p->char_map) BGFX_FREE(font_p->char_map); if (font_p->glyph_cache) BGFX_FREE(font_p->glyph_cache); #if 0 int i; for (i = 0; i < font_p->cache_size; ++i) { bgfx_glyph_t *glyph = font_p->glyph_cache[i]; if (glyph) { BGFX_FREE(glyph->buf); BGFX_FREE(glyph); font_p->glyph_cache[i] = NULL; } } BGFX_FREE(font_p->glyph_cache); #ifdef CONFIG_FREETYPE FT_Done_Face (font_p->face); #endif #endif } /**************************************************************** * INPUTS: font_p - font * a_char - the character * glyph_idx - glyph index * OUTPUTS: info - return char info * RETURNS: glyph reference * FUNCTION: Initialize a glyph data structure (FREETYPE ONLY). * ****************************************************************/ static bgfx_glyph_t *bgfx_init_glyph(bgfx_font_t *font_p, FT_ULong a_char, int glyph_idx) { #ifdef CONFIG_FREETYPE FT_Error err; FT_Int ld_flags; FT_UInt index; bgfx_glyph_t *new_glyph; unsigned long nbytes; BGFX_TRACE(("bgfx_init_glyph 0x%08lx\n",a_char)); bgfx_lock(); index = FT_Get_Char_Index(font_p->face,a_char); if (index == 0) { BGFX_DEBUG(("bgfx_init_glyph could not find char 0x%08lx in FreeType char map\n",a_char)); bgfx_unlock(); return NULL; } ld_flags = (FT_Int) font_p->face->generic.data; ld_flags |= FT_LOAD_RENDER; err = FT_Load_Glyph( font_p->face, index, ld_flags ); if (err) { BGFX_DEBUG(("bgfx_init_glyph could not load glyph %d\n",index)); bgfx_unlock(); return NULL; } /* allocate memory for glyph */ new_glyph = (bgfx_glyph_t*)BGFX_MALLOC(sizeof(bgfx_glyph_t)); if (!new_glyph) { BGFX_DEBUG(("bgfx_init_glyph could allocate memory for glyph\n")); bgfx_unlock(); return NULL; } new_glyph->left = font_p->face->glyph->bitmap_left; new_glyph->top = font_p->face->glyph->bitmap_top; new_glyph->advance = font_p->face->glyph->advance.x >> 6; new_glyph->width = font_p->face->glyph->bitmap.width; new_glyph->height = font_p->face->glyph->bitmap.rows; new_glyph->pitch = font_p->face->glyph->bitmap.pitch; nbytes = font_p->face->glyph->bitmap.pitch * font_p->face->glyph->bitmap.rows; new_glyph->buf = (unsigned char*)BGFX_MALLOC(nbytes); if (!new_glyph->buf) { BGFX_FREE(new_glyph); BGFX_DEBUG(("bgfx_init_glyph could allocate memory for glyph\n")); bgfx_unlock(); return NULL; } /* copy glyph data */ BGFX_MEMCPY(new_glyph->buf, font_p->face->glyph->bitmap.buffer,nbytes); font_p->glyph_cache[glyph_idx] = new_glyph; bgfx_unlock(); return new_glyph; #else return NULL; #endif } /**************************************************************** * INPUTS: font_p - font * a_char - char value * OUTPUTS: none * RETURNS: glyph cache index or -1 on failure * FUNCTION: Get a glyph cache index from the char_map. * ****************************************************************/ static inline int bgfx_map_char(bgfx_font_t *font_p, unsigned long a_char) { register int i; for (i = 0; i < font_p->cache_size; ++i) { if (font_p->char_map[i] == a_char) return i; } return -1; } /**************************************************************** * INPUTS: font_p - font * a_char - char value * OUTPUTS: info - return char info * RETURNS: glyph reference * FUNCTION: Get a glyph from the glyph cache or a fresh rendering. * ****************************************************************/ bgfx_glyph_t *bgfx_get_glyph(bgfx_font_t *font_p, unsigned long a_char) { int cache_index; BGFX_TRACE(("bgfx_get_glyph 0x%08lx\n",a_char)); /* Check for glyph in glyph cache */ cache_index = bgfx_map_char(font_p,a_char); if (cache_index < 0) { BGFX_DEBUG(("bgfx_get_glyph failed 0x%08lx not in font.\n",a_char)); return NULL; } BGFX_TRACE(("bgfx_get_glyph find char in cache 0x%08lx (%ld)\n",cache_index,cache_index)); if (font_p->glyph_cache[cache_index] != NULL) { BGFX_TRACE(("bgfx_get_glyph found char in cache\n")); return font_p->glyph_cache[cache_index]; } return bgfx_init_glyph(font_p,a_char,cache_index); } /**************************************************************** * INPUTS: font_p - font definition * str_p - array of single 32-bit unicode characters * str_len - number of 32-bit characters in string * OUTPUTS: w,h - width and height in pixels of the string * RETURNS: none * FUNCTION: Caclulate the bound rectangle for the string. * ****************************************************************/ void bgfx_string_info(bgfx_font_t *font_p, /* initialized font structure */ const unsigned long *str_p, /* array of single 32-bit unicode characters */ int str_len, /* number of 32-bit characters in string */ int *w, /* width in pixels */ int *h /* height in pixels */ ) { unsigned long current; int offset; bgfx_glyph_t * bgfx_glyph; #ifdef CONFIG_FREETYPE bgfx_glyph_t info; FT_Error err; FT_Int ld_flags; FT_UInt index; #endif *w = 0; *h = 0; bgfx_glyph = NULL; BGFX_TRACE(("bgfx_string_info %s\n",str_p)); for (offset = 0; offset < str_len; offset++) { current = str_p[offset]; BGFX_TRACE(("bgfx_string_info (0x%08lx)\n",current)); /* if using glyph cache use the get glyph rather than render directly to surface buffer */ if (font_p->cache_size > 0) { bgfx_glyph = bgfx_get_glyph(font_p,current); } #ifdef CONFIG_FREETYPE if (!bgfx_glyph) { bgfx_lock(); bgfx_glyph = &info; index = FT_Get_Char_Index( font_p->face, current ); BGFX_TRACE(("bgfx_string_info %d\n",index)); ld_flags = (FT_Int) font_p->face->generic.data; ld_flags |= FT_LOAD_RENDER; err = FT_Load_Glyph( font_p->face, index, ld_flags ); if (err) { BGFX_DEBUG(("bgfx_string_info could not load glyph %p\n",bgfx_glyph)); bgfx_unlock(); return; } bgfx_unlock(); bgfx_glyph->left = font_p->face->glyph->bitmap_left; bgfx_glyph->top = font_p->face->glyph->bitmap_top; bgfx_glyph->advance = font_p->face->glyph->advance.x >> 6; bgfx_glyph->width = font_p->face->glyph->bitmap.width; bgfx_glyph->height = font_p->face->glyph->bitmap.rows; bgfx_glyph->buf = font_p->face->glyph->bitmap.buffer; bgfx_glyph->pitch = font_p->face->glyph->bitmap.pitch; } #endif if (!bgfx_glyph) { BGFX_DEBUG(("bgfx_string_info could not load glyph for char 0x%08lx\n",current)); return; } if (bgfx_glyph->height > *h) { *h = bgfx_glyph->height; } *w += bgfx_glyph->advance; } } #if 1 /**************************************************************** * INPUTS: font_p - font definition * file_p - file descriptor * OUTPUTS: none * RETURNS: none-zero on failure * FUNCTION: Load the font typeface from a binary file. * ****************************************************************/ static int bgfx_calc_mem_font(bgfx_font_t *font_p,void *file_p) { int err,size; unsigned long i; int result = -1; size = 0; size += sizeof(FT_ULong) * font_p->cache_size; /* Load bitmaps */ for (i = 0; i < font_p->cache_size; ++i) { bgfx_glyph_t glyph; BGFX_IO_CHECK (bgfx_read((void*)&glyph.left,1,sizeof(glyph.left),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph.top,1,sizeof(glyph.top),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph.advance,1,sizeof(glyph.advance),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph.width,1,sizeof(glyph.width),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph.height,1,sizeof(glyph.height),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph.pitch,1,sizeof(glyph.pitch),file_p)); BGFX_TRACE(("bgfx_load_font glyph %ld\n",i)); BGFX_TRACE(("bgfx_load_font glyph->pitch %d\n",glyph.pitch)); BGFX_TRACE(("bgfx_load_font glyph->height %d\n",glyph.height)); BGFX_TRACE(("bgfx_load_font glyph->left %d\n",glyph.left)); if ((glyph.pitch * glyph.height) > 0) { size += glyph.pitch * glyph.height; bgfx_set(file_p,bgfx_tell(file_p) + (glyph.pitch * glyph.height), 0); } } result = 0; done: if (result != 0) return -1; return size; } /**************************************************************** * INPUTS: font_p - font definition * file_p - file descriptor * OUTPUTS: none * RETURNS: none-zero on failure * FUNCTION: Load the font typeface from a binary file. * ****************************************************************/ int bgfx_load_font(bgfx_font_t *font_p,void *file_p) { int result = -1; int err; unsigned long i,fsize,pos; bgfx_glyph_t *glyph_bufs = NULL; bgfx_glyph_t *glyph = NULL; unsigned char* fbuf = NULL; /* write font header */ BGFX_MEMSET(font_p,0,sizeof(bgfx_font_t)); BGFX_IO_CHECK (bgfx_read((void*)&font_p->ascender,1, sizeof(font_p->ascender),file_p)); font_p->ascender = BGFX_SWAP_INT(font_p->ascender); BGFX_IO_CHECK (bgfx_read((void*)&font_p->descender,1, sizeof(font_p->descender),file_p)); font_p->descender = BGFX_SWAP_INT(font_p->descender); BGFX_IO_CHECK (bgfx_read((void*)&font_p->height,1, sizeof(font_p->height),file_p)); font_p->height = BGFX_SWAP_INT(font_p->height); BGFX_IO_CHECK (bgfx_read((void*)&font_p->maxadvance,1, sizeof(font_p->maxadvance),file_p)); font_p->maxadvance = BGFX_SWAP_INT(font_p->maxadvance); BGFX_IO_CHECK (bgfx_read((void*)&font_p->format,1, sizeof(font_p->format),file_p)); font_p->format = BGFX_SWAP_ULONG(font_p->format); BGFX_IO_CHECK (bgfx_read((void*)&font_p->cache_size,1, sizeof(font_p->cache_size),file_p)); font_p->cache_size = BGFX_SWAP_INT(font_p->cache_size); font_p->glyph_cache = (bgfx_glyph_t**)BGFX_MALLOC(sizeof(bgfx_glyph_t*) * font_p->cache_size ); BGFX_MEMSET(font_p->glyph_cache,0,sizeof(bgfx_glyph_t*) * font_p->cache_size); glyph_bufs = (bgfx_glyph_t*)BGFX_MALLOC(sizeof(bgfx_glyph_t) * font_p->cache_size ); font_p->char_map = (FT_ULong*)BGFX_MALLOC(sizeof(FT_ULong) * font_p->cache_size ); if (!font_p->char_map || !glyph_bufs || !font_p->glyph_cache) goto done; /* load character map */ for (i = 0; i < font_p->cache_size; ++i) { BGFX_IO_CHECK (bgfx_read((void*)&(font_p->char_map[i]),1, sizeof(FT_ULong), file_p )); font_p->char_map[i] = BGFX_SWAP_ULONG(font_p->char_map[i]); } pos = bgfx_tell(file_p); fsize = bgfx_calc_mem_font(font_p,file_p); bgfx_set(file_p,pos,0); fbuf = BGFX_MALLOC(fsize); if ((fsize <= 0) || !fbuf) goto done; /* Load bitmaps */ for (i = 0; i < font_p->cache_size; ++i) { BGFX_MEMSET(glyph_bufs,0,sizeof(bgfx_glyph_t)); glyph = glyph_bufs++; font_p->glyph_cache[i] = glyph; BGFX_IO_CHECK (bgfx_read((void*)&glyph->left,1,sizeof(glyph->left),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph->top,1,sizeof(glyph->top),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph->advance,1,sizeof(glyph->advance),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph->width,1,sizeof(glyph->width),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph->height,1,sizeof(glyph->height),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph->pitch,1,sizeof(glyph->pitch),file_p)); BGFX_TRACE(("bgfx_load_font glyph %ld\n",i)); BGFX_TRACE(("bgfx_load_font glyph->pitch %d\n",glyph->pitch)); BGFX_TRACE(("bgfx_load_font glyph->height %d\n",glyph->height)); BGFX_TRACE(("bgfx_load_font glyph->left %d\n",glyph->left)); if ((glyph->pitch * glyph->height) > 0) { glyph->buf = (char*)fbuf; BGFX_IO_CHECK (bgfx_read(glyph->buf,1, (glyph->pitch * glyph->height),file_p)); fbuf += (glyph->pitch * glyph->height); } BGFX_TRACE(("bgfx_load_font glyph->buf %p\n",glyph->buf)); } result = 0; done: if (result != 0) { if (font_p->glyph_cache) BGFX_FREE(font_p->glyph_cache); if (font_p->char_map) BGFX_FREE(font_p->char_map); if (glyph_bufs) BGFX_FREE(glyph_bufs); if (fbuf) BGFX_FREE(fbuf); } return result; } #else /**************************************************************** * INPUTS: font_p - font definition * file_p - file descriptor * OUTPUTS: none * RETURNS: none-zero on failure * FUNCTION: Load the font typeface from a binary file. * ****************************************************************/ int bgfx_load_font(bgfx_font_t *font_p,void *file_p) { int result = -1; int err; unsigned long i; bgfx_glyph_t *glyph; unsigned int size; /* write font header */ BGFX_MEMSET(font_p,0,sizeof(bgfx_font_t)); BGFX_IO_CHECK (bgfx_read((void*)&font_p->ascender,1, sizeof(font_p->ascender),file_p)); font_p->ascender = BGFX_SWAP_INT(font_p->ascender); BGFX_IO_CHECK (bgfx_read((void*)&font_p->descender,1, sizeof(font_p->descender),file_p)); font_p->descender = BGFX_SWAP_INT(font_p->descender); BGFX_IO_CHECK (bgfx_read((void*)&font_p->height,1, sizeof(font_p->height),file_p)); font_p->height = BGFX_SWAP_INT(font_p->height); BGFX_IO_CHECK (bgfx_read((void*)&font_p->maxadvance,1, sizeof(font_p->maxadvance),file_p)); font_p->maxadvance = BGFX_SWAP_INT(font_p->maxadvance); BGFX_IO_CHECK (bgfx_read((void*)&font_p->format,1, sizeof(font_p->format),file_p)); font_p->format = BGFX_SWAP_ULONG(font_p->format); BGFX_IO_CHECK (bgfx_read((void*)&font_p->cache_size,1, sizeof(font_p->cache_size),file_p)); font_p->cache_size = BGFX_SWAP_INT(font_p->cache_size); font_p->glyph_cache = (bgfx_glyph_t**)BGFX_MALLOC(sizeof(bgfx_glyph_t*) * font_p->cache_size ); size = sizeof(bgfx_glyph_t*) * font_p->cache_size; printf("%s:%d size = %d\n",__FUNCTION__,__LINE__,size); if (!font_p->glyph_cache) goto done; BGFX_MEMSET(font_p->glyph_cache,0,sizeof(bgfx_glyph_t*) * font_p->cache_size); font_p->char_map = (FT_ULong*)BGFX_MALLOC(sizeof(FT_ULong) * font_p->cache_size ); size += sizeof(FT_ULong) * font_p->cache_size; printf("%s:%d size = %d\n",__FUNCTION__,__LINE__,size); if (!font_p->char_map) goto done; /* load character map */ for (i = 0; i < font_p->cache_size; ++i) { BGFX_IO_CHECK (bgfx_read((void*)&(font_p->char_map[i]),1, sizeof(FT_ULong), file_p )); font_p->char_map[i] = BGFX_SWAP_ULONG(font_p->char_map[i]); } /* Load bitmaps */ for (i = 0; i < font_p->cache_size; ++i) { glyph = (bgfx_glyph_t*)BGFX_MALLOC(sizeof(bgfx_glyph_t)); size += sizeof(bgfx_glyph_t); printf("%s:%d size = %d\n",__FUNCTION__,__LINE__,size); if (!glyph) goto done; BGFX_MEMSET(glyph,0,sizeof(bgfx_glyph_t)); font_p->glyph_cache[i] = glyph; BGFX_IO_CHECK (bgfx_read((void*)&glyph->left,1,sizeof(glyph->left),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph->top,1,sizeof(glyph->top),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph->advance,1,sizeof(glyph->advance),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph->width,1,sizeof(glyph->width),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph->height,1,sizeof(glyph->height),file_p)); BGFX_IO_CHECK (bgfx_read((void*)&glyph->pitch,1,sizeof(glyph->pitch),file_p)); BGFX_TRACE(("bgfx_load_font glyph %ld\n",i)); BGFX_TRACE(("bgfx_load_font glyph->pitch %d\n",glyph->pitch)); BGFX_TRACE(("bgfx_load_font glyph->height %d\n",glyph->height)); BGFX_TRACE(("bgfx_load_font glyph->left %d\n",glyph->left)); if ((glyph->pitch * glyph->height) > 0) { glyph->buf = (char*)BGFX_MALLOC((glyph->pitch * glyph->height)); size += glyph->pitch * glyph->height; printf("%s:%d size = %d(%d,%d)\n",__FUNCTION__,__LINE__,size,glyph->pitch,glyph->height); if (!glyph->buf) goto done; BGFX_IO_CHECK (bgfx_read(glyph->buf,1, (glyph->pitch * glyph->height),file_p)); } BGFX_TRACE(("bgfx_load_font glyph->buf %p\n",glyph->buf)); } result = 0; done: if (result != 0) { if (font_p->char_map) free(font_p->char_map); for (i = 0; i < font_p->cache_size; ++i) { if (font_p->glyph_cache[i]) { if (font_p->glyph_cache[i]->buf) BGFX_FREE(font_p->glyph_cache[i]->buf); BGFX_FREE(font_p->glyph_cache[i]); } } } return result; } #endif