From 7ea68ac9f3bfc20f2c6408f21ae82c880c217ba2 Mon Sep 17 00:00:00 2001 From: Parth Wazurkar Date: Fri, 10 Aug 2018 00:54:24 +0530 Subject: [gf] Change logic to load bitmap on demand. Also load glyphs in the order they appear in the font file by changing the cmap scheme and implementing a proper `gf cmap'. --- src/gf/gfdrivr.c | 197 +++++++++++++++++++++++++++++----------------- src/gf/gfdrivr.h | 36 ++++++--- src/gf/gflib.c | 234 +++++++++++++++++++++++++++++++++---------------------- 3 files changed, 291 insertions(+), 176 deletions(-) diff --git a/src/gf/gfdrivr.c b/src/gf/gfdrivr.c index 2994b3bb4..50de121a8 100644 --- a/src/gf/gfdrivr.c +++ b/src/gf/gfdrivr.c @@ -43,9 +43,9 @@ typedef struct GF_CMapRec_ { - FT_CMapRec cmap; - FT_UInt32 bc; /* Beginning Character */ - FT_UInt32 ec; /* End Character */ + FT_CMapRec cmap; + FT_ULong num_encodings; + GF_Encoding encodings; } GF_CMapRec, *GF_CMap; @@ -57,8 +57,8 @@ GF_Face face = (GF_Face)FT_CMAP_FACE( cmap ); FT_UNUSED( init_data ); - cmap->bc = face->gf_glyph->code_min; - cmap->ec = face->gf_glyph->code_max; + cmap->num_encodings = face->gf_glyph->nencodings; + cmap->encodings = face->gf_glyph->encodings; return FT_Err_Ok; } @@ -69,54 +69,98 @@ { GF_CMap cmap = (GF_CMap)gfcmap; - cmap->bc = 0; - cmap->ec = -1; + cmap->encodings = NULL; + cmap->num_encodings = 0; } FT_CALLBACK_DEF( FT_UInt ) gf_cmap_char_index( FT_CMap gfcmap, - FT_UInt32 char_code ) + FT_UInt32 charcode ) { - FT_UInt gindex = 0; - GF_CMap cmap = (GF_CMap)gfcmap; + GF_CMap cmap = (GF_CMap)gfcmap; + GF_Encoding encodings = cmap->encodings; + FT_ULong min, max, mid; + FT_UInt result = 0; - char_code -= cmap->bc; + min = 0; + max = cmap->num_encodings; - if ( char_code < cmap->ec - cmap->bc + 1 ) - gindex = (FT_UInt)( char_code ); + while ( min < max ) + { + FT_ULong code; + + + mid = ( min + max ) >> 1; + code = (FT_ULong)encodings[mid].enc; + + if ( charcode == code ) + { + result = encodings[mid].glyph; + break; + } - return gindex; + if ( charcode < code ) + max = mid; + else + min = mid + 1; + } + + return result; } FT_CALLBACK_DEF( FT_UInt ) gf_cmap_char_next( FT_CMap gfcmap, - FT_UInt32 *achar_code ) + FT_UInt32 *acharcode ) { - GF_CMap cmap = (GF_CMap)gfcmap; - FT_UInt gindex = 0; - FT_UInt32 result = 0; - FT_UInt32 char_code = *achar_code + 1; + GF_CMap cmap = (GF_CMap)gfcmap; + GF_Encoding encodings = cmap->encodings; + FT_ULong min, max, mid; + FT_ULong charcode = *acharcode + 1; + FT_UInt result = 0; - if ( char_code <= cmap->bc ) - { - result = cmap->bc; - gindex = 1; - } - else + min = 0; + max = cmap->num_encodings; + + while ( min < max ) { - char_code -= cmap->bc; - if ( char_code < cmap->ec - cmap->bc + 1 ) + FT_ULong code; + + + mid = ( min + max ) >> 1; + code = (FT_ULong)encodings[mid].enc; + + if ( charcode == code ) { - result = char_code; - gindex = (FT_UInt)( char_code ); + result = encodings[mid].glyph + 1; + goto Exit; } + + if ( charcode < code ) + max = mid; + else + min = mid + 1; } - *achar_code = result; - return gindex; + charcode = 0; + if ( min < cmap->num_encodings ) + { + charcode = (FT_ULong)encodings[min].enc; + result = encodings[min].glyph ; + } + + Exit: + if ( charcode > 0xFFFFFFFFUL ) + { + FT_TRACE1(( "gf_cmap_char_next: charcode 0x%x > 32bit API" )); + *acharcode = 0; + /* XXX: result should be changed to indicate an overflow error */ + } + else + *acharcode = (FT_UInt32)charcode; + return result; } @@ -163,7 +207,6 @@ FT_Error error = FT_Err_Ok; FT_Memory memory = FT_FACE_MEMORY( face ); GF_Glyph go=NULL; - FT_UInt16 i,count; TFM_Service tfm; @@ -197,9 +240,9 @@ face->gf_glyph = go ; /* sanity check */ - if ( !face->gf_glyph->bm_table ) + if ( !face->gf_glyph->metrics ) { - FT_TRACE2(( "glyph bitmaps not allocated\n" )); + FT_TRACE2(( "glyph metrics missing\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } @@ -230,13 +273,7 @@ */ gfface->family_name = NULL; - count=0; - for (i = 0; i < 256; i++) - { - if(go->bm_table[i].bitmap != NULL) - count++; - } - gfface->num_glyphs = (FT_Long)count; + gfface->num_glyphs = (FT_Long)face->gf_glyph->nglyphs; FT_TRACE4(( " number of glyphs: allocated %d\n",gfface->num_glyphs )); @@ -270,15 +307,36 @@ y_res ); ; } + /* set up charmap */ + { + /* FT_Bool unicode_charmap ; */ + + /* XXX: TO-DO + Currently the unicode_charmap is set to `0' + The functionality of extracting coding scheme + from `xxx' and `yyy' commands will be used to + set the unicode_charmap. + */ + } + /* Charmaps */ { FT_CharMapRec charmap; + FT_Bool unicode_charmap = 0; - /* Unicode Charmap */ - charmap.encoding = FT_ENCODING_UNICODE; - charmap.platform_id = TT_PLATFORM_MICROSOFT; - charmap.encoding_id = TT_MS_ID_UNICODE_CS; charmap.face = FT_FACE( face ); + charmap.encoding = FT_ENCODING_NONE; + /* initial platform/encoding should indicate unset status? */ + charmap.platform_id = TT_PLATFORM_APPLE_UNICODE; + charmap.encoding_id = TT_APPLE_ID_DEFAULT; + + if( unicode_charmap ) + { + /* Unicode Charmap */ + charmap.encoding = FT_ENCODING_UNICODE; + charmap.platform_id = TT_PLATFORM_MICROSOFT; + charmap.encoding_id = TT_MS_ID_UNICODE_CS; + } error = FT_CMap_New( &gf_cmap_class, NULL, &charmap, NULL ); @@ -365,10 +423,13 @@ { GF_Face gf = (GF_Face)FT_SIZE_FACE( size ); FT_Face face = FT_FACE( gf ); + FT_Stream stream; FT_Error error = FT_Err_Ok; FT_Bitmap* bitmap = &slot->bitmap; - GF_BitmapRec bm; + GF_MetricRec metric; GF_Glyph go; + FT_ULong bytes; + FT_Byte *bitmp; go = gf->gf_glyph; @@ -387,7 +448,7 @@ goto Exit; } - FT_TRACE1(( "GF_Glyph_Load: glyph index %d\n", glyph_index )); + FT_TRACE1(( "GF_Glyph_Load: glyph index %d and charcode is %d\n", glyph_index, go->metrics[glyph_index].code )); if ( (FT_Int)glyph_index < 0 ) glyph_index = 0; @@ -399,44 +460,36 @@ goto Exit; } - if ( !go->bm_table ) - { - FT_TRACE2(( "invalid bitmap table\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } + stream = gf->root.stream; + metric = gf->gf_glyph->metrics[glyph_index]; - /* slot, bitmap => freetype, bm => gflib */ - bm = gf->gf_glyph->bm_table[glyph_index]; + error = gf_read_glyph( stream, + &metric ); - bitmap->rows = bm.bbx_height; - bitmap->width = bm.bbx_width; + bitmap->rows = metric.bbx_height; + bitmap->width = metric.bbx_width; bitmap->pixel_mode = FT_PIXEL_MODE_MONO; - if ( !bm.raster ) - { - FT_TRACE2(( "invalid bitmap width\n" )); - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - - bitmap->pitch = (int)bm.raster ; + bitmap->pitch = (int)( metric.raster ); /* note: we don't allocate a new array to hold the bitmap; */ /* we can simply point to it */ - ft_glyphslot_set_bitmap( slot, bm.bitmap ); + ft_glyphslot_set_bitmap( slot, metric.bitmap ); + slot->format = FT_GLYPH_FORMAT_BITMAP; - slot->bitmap_left = bm.off_x ; - slot->bitmap_top = bm.off_y ; + slot->bitmap_left = metric.off_x ; + slot->bitmap_top = metric.off_y ; - slot->metrics.horiAdvance = (FT_Pos) (bm.mv_x ) * 64; - slot->metrics.horiBearingX = (FT_Pos) (bm.off_x ) * 64; - slot->metrics.horiBearingY = (FT_Pos) (bm.bbx_height) * 64; + slot->metrics.horiAdvance = (FT_Pos) ( metric.mv_x ) * 64; + slot->metrics.horiBearingX = (FT_Pos) ( metric.off_x ) * 64; + slot->metrics.horiBearingY = (FT_Pos) ( metric.bbx_height) * 64; slot->metrics.width = (FT_Pos) ( bitmap->width * 64 ); slot->metrics.height = (FT_Pos) ( bitmap->rows * 64 ); - ft_synthesize_vertical_metrics( &slot->metrics, bm.bbx_height * 64 ); + ft_synthesize_vertical_metrics( &slot->metrics, metric.bbx_height * 64 ); + + /* XXX: to do: are there cases that need repadding the bitmap? */ Exit: return error; diff --git a/src/gf/gfdrivr.h b/src/gf/gfdrivr.h index 4fd8d2e27..34145ff45 100644 --- a/src/gf/gfdrivr.h +++ b/src/gf/gfdrivr.h @@ -27,25 +27,43 @@ FT_BEGIN_HEADER + + typedef struct GF_EncodingRec_ + { + FT_Long enc; + FT_UShort glyph; + + } GF_EncodingRec, *GF_Encoding; + /* BitmapRec for GF format specific glyphs */ - typedef struct GF_BitmapRec_ + typedef struct GF_MetricRec_ { - FT_Int bbx_width, bbx_height; - FT_Int off_x, off_y; - FT_Int mv_x, mv_y; + FT_Long bbx_width, bbx_height; + FT_Long off_x, off_y; + FT_Long mv_x, mv_y; FT_Byte *bitmap; FT_UInt raster; + FT_Long char_offset; + FT_UShort code; - } GF_BitmapRec, *GF_Bitmap; - + } GF_MetricRec, *GF_Metric; typedef struct GF_GlyphRec_ { FT_UInt code_min, code_max; - GF_Bitmap bm_table; + + FT_ULong nmetrics; + GF_Metric metrics; + FT_ULong nglyphs; + FT_ULong nencodings; + GF_Encoding encodings; + + FT_Short defaultChar; /* To be checked */ + FT_Int ds, hppp, vppp; - FT_Int font_bbx_w, font_bbx_h; - FT_Int font_bbx_xoff, font_bbx_yoff; + FT_Int font_bbx_w, font_bbx_h; + FT_Int font_bbx_xoff, font_bbx_yoff; + FT_Int check_sum; } GF_GlyphRec, *GF_Glyph; diff --git a/src/gf/gflib.c b/src/gf/gflib.c index 25bb3b6bb..9e922a34d 100644 --- a/src/gf/gflib.c +++ b/src/gf/gflib.c @@ -111,26 +111,116 @@ FT_Byte bit_table[] = { return v; } + static int + compare( FT_Long* a, + FT_Long* b ) + { + if ( *a < *b ) + return -1; + else if ( *a > *b ) + return 1; + else + return 0; + } + /************************************************************************** * * API. * */ + static FT_Error + gf_set_encodings( GF_Glyph go, + FT_Memory memory ) + { + FT_Error error; + FT_ULong nencoding; + FT_UInt i, j; + FT_ULong k; + GF_Encoding encoding = NULL; + GF_Metric metric; + FT_Long *tosort; + + nencoding = go->nglyphs; + FT_TRACE2(( "gf_set_encodings: Reached here.\n" )); + + if ( FT_NEW_ARRAY( metric, go->code_max - go->code_min + 1 ) ) + return error; + + if ( FT_NEW_ARRAY( encoding, nencoding ) ) + return error; + + if ( FT_NEW_ARRAY( tosort, nencoding ) ) + return error; + + + FT_TRACE2(( "gf_set_encodings: Allocated sufficient memory.\n" )); + + for( i = 0 ; i < 256 ; i++ ) + { + if( go->metrics[i].char_offset >= 0 ) + tosort[i] = go->metrics[i].char_offset; + } + + ft_qsort( (void*)tosort, go->nglyphs, sizeof(FT_Long), + (int(*)(const void*, const void*) )compare ); + + for( i = 0 ; i < go->nglyphs ; i++ ) + { + /* FT_TRACE2(( "tosort[%d]is %ld\n",i,tosort[i] )); */ + } + + k = 0; + for ( i = 0; i < go->nglyphs; i++ ) + { + for ( j = 0; j < 256; j++ ) + { + if( go->metrics[j].char_offset == tosort[i] ) + break; + } + metric[k].char_offset = go->metrics[j].char_offset; + metric[k].code = go->metrics[j].code; + /* FT_TRACE2(( "metric[%d].char_offset is %ld %ld% ld\n",k,metric[k].char_offset,metric[k].code,k )); */ + encoding[k].enc = go->metrics[j].code; + encoding[k].glyph = k; + k++; + } + + for( i = 0 ; i < go->nglyphs ; i++ ) + { + go->metrics[i].char_offset = metric[i].char_offset; + go->metrics[i].code = metric[i].code; + /* FT_TRACE2(( "Hi I am here go->metrics[%d].char_offset is %ld %ld% ld\n",i, + go->metrics[i].char_offset,go->metrics[i].code,i )); */ + } + + FT_FREE(metric); + + go->nencodings = k; + go->encodings = encoding; + + return error; + } + FT_LOCAL_DEF( FT_Error ) gf_read_glyph( FT_Stream stream, - GF_Bitmap bm, - FT_Memory memory ) + GF_MetricRec *metrics ) { FT_Long m, n; FT_Int paint_sw; FT_Int instr,inst; FT_Long min_m, max_m, min_n, max_n, del_m, del_n; FT_Long w, h, d; - FT_Int m_b, k; - FT_Byte *ptr; + FT_Int k; + /* FT_Int m_b; + FT_Byte *ptr; */ FT_Error error = FT_Err_Ok; + if( FT_STREAM_SEEK( metrics->char_offset ) ) + return 0; + + FT_TRACE2(( "In gf_read_glyph\n" )); + for ( ; ; ) { inst = READ_UINT1( stream ); @@ -203,19 +293,25 @@ FT_Byte bit_table[] = { return -1; } + /* FT_TRACE2(( "w is %ld\n" + "h is %ld\n" + "-min_m is %ld\n" + "max_n is %ld\n\n", w, h, -min_m, max_n )); + */ + /* allocate and build bitmap */ - if ((bm->bitmap = (FT_Byte*)malloc(h*((w+7)/8))) == NULL) + if ((metrics->bitmap = (FT_Byte*)malloc(h*((w+7)/8))) == NULL) { error = FT_THROW( Invalid_File_Format ); return -1; } - memset(bm->bitmap, 0, h*((w+7)/8)); - bm->raster = (FT_UInt)(w+7)/8; - bm->bbx_width = w; - bm->bbx_height = h; - bm->off_x = -min_m; - bm->off_y = max_n; + memset(metrics->bitmap, 0, h*((w+7)/8)); + metrics->raster = (FT_UInt)(w+7)/8; + metrics->bbx_width = w; + metrics->bbx_height = h; + metrics->off_x = -min_m; + metrics->off_y = max_n; #if 0 bm->mv_x = -min_m; bm->mv_y = max_n; @@ -256,6 +352,7 @@ FT_Byte bit_table[] = { } else { + /* ptr = &bm->bitmap[(max_n - n) * bm->raster + (m - min_m)/8]; m_b = (m - min_m) % 8; while (d > 0) @@ -269,6 +366,7 @@ FT_Byte bit_table[] = { } d--; } + */ } paint_sw = 1 - paint_sw; break; @@ -299,8 +397,6 @@ FT_Byte bit_table[] = { case GF_NO_OP: break; default: - FT_FREE(bm->bitmap); - bm->bitmap = NULL; error = FT_THROW( Invalid_File_Format ); return -1; } @@ -315,12 +411,11 @@ FT_Byte bit_table[] = { GF_Glyph *goptr ) { GF_Glyph go; - GF_Bitmap bm; FT_Byte instr, d, pre, id, k, code; FT_Long ds, check_sum, hppp, vppp; FT_Long min_m, max_m, min_n, max_n, w; FT_UInt dx, dy; - FT_Long ptr_post, ptr_p, ptr, optr; + FT_Long ptr_post, ptr_p, ptr; FT_Int bc, ec, nchars, i; FT_Error error = FT_Err_Ok; FT_Memory memory = extmemory; /* needed for FT_NEW */ @@ -428,70 +523,29 @@ FT_Byte bit_table[] = { FT_TRACE5(( "gf_load_font: checksum is %ld\n",check_sum )); - if( ptr_p < 0 ) /* Defined to use ptr_p */ + if( ptr_p < 0 ) { FT_ERROR(( "gf_load_font: invalid pointer in postamble\n" )); goto Exit; } - if( check_sum < 0 ) /* Defined to use check_sum */ + if( check_sum < 0 ) { FT_ERROR(( "gf_load_font: invalid check sum value\n" )); goto Exit; } - #if 0 - gptr = ftell(fp); - #endif - - #if 0 - /* read min & max char code */ - bc = 256; - ec = -1; - for ( ; ; ) - { - instr = READ_UINT1(fp); - if (instr == GF_POST_POST) - { - break; - } - else if (instr == GF_CHAR_LOC) - { - code = READ_UINT1(fp); - (void)SKIP_N(fp, 16); - } - else if (instr == GF_CHAR_LOC0) - { - code = READ_UINT1(fp); - (void)SKIP_N(fp, 9); - } - else - { - error = FT_THROW( Invalid_File_Format ); - goto Exit; - } - if (code < bc) - bc = code; - if (code > ec) - ec = code; - } - #else - bc = 0; - ec = 255; - #endif + + bc = 0; + ec = 255; nchars = ec - bc + 1; if( FT_ALLOC(go, sizeof(GF_GlyphRec)) ) goto Exit; - if( FT_ALLOC_MULT(go->bm_table, sizeof(GF_BitmapRec), nchars) ) - goto Exit; - - FT_TRACE2(( "gf_load_font: Allocated bitmap table\n" )); - - for (i = 0; i < nchars; i++) - go->bm_table[i].bitmap = NULL; + FT_TRACE5(( "gf_load_font: Allocated GF_GlyphRec\n" )); + go->check_sum = check_sum; go->ds = (FT_UInt)ds/(1<<20); go->hppp = (FT_UInt)hppp/(1<<16); go->vppp = (FT_UInt)vppp/(1<<16); @@ -502,10 +556,15 @@ FT_Byte bit_table[] = { go->code_min = bc; go->code_max = ec; - /* read glyph */ - #if 0 - fseek(fp, gptr, SEEK_SET); - #endif + go->nglyphs = 0; + + if ( FT_NEW_ARRAY( go->metrics, nchars ) ) + goto Exit; + + FT_TRACE5(( "gf_load_font: Allocated go->metrics array\n" )); + + for( i = 0; i < 256 ; i++) + go->metrics[i].char_offset = -1; for ( ; ; ) { @@ -533,39 +592,27 @@ FT_Byte bit_table[] = { goto Exit; } - /* - if( w > max_m) Defined to use w - { - FT_ERROR(( "gf_load_font: invalid width in charloc\n" )); - goto Exit; - } - */ - - optr = stream->pos; - if( FT_STREAM_SEEK( ptr ) ) - goto Exit; + go->metrics[code - bc].mv_x = dx; + go->metrics[code - bc].mv_y = dy; + go->metrics[code - bc].char_offset = (FT_ULong)ptr; + go->metrics[code - bc].code = (FT_UShort)code; + go->nglyphs += 1; + } - bm = &go->bm_table[code - bc]; - if (gf_read_glyph( stream, bm, memory ) < 0) - goto Exit; + error = gf_set_encodings( go, memory ); + if( error ) + goto Exit; - bm->mv_x = dx; - bm->mv_y = dy; - if(FT_STREAM_SEEK( optr )) - goto Exit; - } *goptr = go; return error; Exit: if (go != NULL) { - if( go->bm_table ) + if(go->metrics != NULL) { - for (i = 0; i < nchars; i++) - FT_FREE(go->bm_table[i].bitmap); + FT_FREE(go->metrics); } - FT_FREE(go->bm_table); FT_FREE(go); } return error; @@ -577,17 +624,14 @@ FT_Byte bit_table[] = { { FT_Memory memory = FT_FACE( face )->memory; GF_Glyph go = face->gf_glyph; - FT_UInt nchars = FT_FACE( face )->num_glyphs,i; if ( !go ) return; - if( go->bm_table ) + if(go->metrics != NULL) { - for (i = 0; i < nchars; i++) - FT_FREE(go->bm_table[i].bitmap); + FT_FREE(go->metrics); } - FT_FREE(go->bm_table); FT_FREE(go); } -- cgit v1.2.1