From 743b415ca95ad25722a2fb260920cfab21220479 Mon Sep 17 00:00:00 2001 From: Parth Wazurkar Date: Sun, 12 Aug 2018 11:36:33 +0530 Subject: [PATCH] [gf] Change `cmap' encoding scheme. * src/gf/gfdrivr.c(GF_Face_Init): - Change `gf_cmap_class' functions to use new encoding scheme. - Set charmap to `0: synthetic, platform 0, encoding 0 language 0' values. * src/gf/gflib.c(gf_set_encodings, gf_load_font): Modify to set encoding so as to load glyphs in the order they appear in the font file. --- src/gf/gfdrivr.c | 145 +++++++++++++++++++++++++++++----------- src/gf/gfdrivr.h | 15 +++++ src/gf/gflib.c | 170 +++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 270 insertions(+), 60 deletions(-) diff --git a/src/gf/gfdrivr.c b/src/gf/gfdrivr.c index 7b0153051..e51f10abc 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; + } + + if ( charcode < code ) + max = mid; + else + min = mid + 1; + } - return gindex; + 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; } @@ -145,9 +189,10 @@ memory = FT_FACE_MEMORY( face ); - gf_free_font( face ); - FT_FREE( gfface->available_sizes ); + FT_FREE( face->gf_glyph->encodings ); + + gf_free_font( face ); } @@ -270,15 +315,37 @@ 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 ); @@ -387,7 +454,7 @@ goto Exit; } - FT_TRACE1(( "GF_Glyph_Load: glyph index %d\n", glyph_index )); + FT_TRACE1(( "GF_Glyph_Load: glyph index %d charcode is %d\n", glyph_index, go->bm_table[glyph_index].code )); if ( (FT_Int)glyph_index < 0 ) glyph_index = 0; @@ -563,7 +630,7 @@ } - FT_CALLBACK_TABLE_DEF + FT_CALLBACK_TABLE_DEF const FT_Driver_ClassRec gf_driver_class = { { diff --git a/src/gf/gfdrivr.h b/src/gf/gfdrivr.h index b6e25ab28..5df04e9d6 100644 --- a/src/gf/gfdrivr.h +++ b/src/gf/gfdrivr.h @@ -27,6 +27,14 @@ 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_ { @@ -35,6 +43,8 @@ FT_BEGIN_HEADER FT_Long mv_x, mv_y; FT_Byte *bitmap; FT_UInt raster; + FT_UShort code; + FT_ULong nglyphs; } GF_BitmapRec, *GF_Bitmap; @@ -47,6 +57,11 @@ FT_BEGIN_HEADER FT_Int font_bbx_w, font_bbx_h; FT_Int font_bbx_xoff, font_bbx_yoff; + FT_ULong nencodings; + GF_Encoding encodings; + + FT_ULong nglyphs; + } GF_GlyphRec, *GF_Glyph; diff --git a/src/gf/gflib.c b/src/gf/gflib.c index 25bb3b6bb..0efbb903c 100644 --- a/src/gf/gflib.c +++ b/src/gf/gflib.c @@ -43,6 +43,14 @@ FT_Byte bit_table[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + typedef struct GF_CharOffsetRec_ + { + FT_Long char_offset; + FT_UShort code; + FT_Short gid; + + } GF_CharOffsetRec, *GF_CharOffset; + /************************************************************************** * * GF font utility functions. @@ -111,12 +119,80 @@ 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_CharOffset of, + FT_Int ngphs, + GF_Glyph go, + FT_Memory memory ) + { + FT_Error error; + FT_ULong nencoding; + FT_Int i, j; + FT_ULong k; + GF_Encoding encoding = NULL; + FT_Long *tosort; + + nencoding = ngphs; + FT_TRACE2(( "gf_set_encodings: Reached here.\n" )); + + 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( of[i].char_offset >= 0 ) + tosort[i] = of[i].char_offset; + } + + ft_qsort( (void*)tosort, ngphs, sizeof(FT_Long), + (int(*)(const void*, const void*) )compare ); + + k = 0; + for ( i = 0; i < ngphs; i++ ) + { + for ( j = 0; j < 256; j++ ) + { + if( of[j].char_offset == tosort[i] ) + break; + } + encoding[k].enc = of[j].code; + encoding[k].glyph = k; + of[j].gid = k; + k++; + } + + FT_FREE(tosort); + + go->nencodings = k; + go->encodings = encoding; + + return error; + } + FT_LOCAL_DEF( FT_Error ) gf_read_glyph( FT_Stream stream, GF_Bitmap bm, @@ -314,16 +390,17 @@ FT_Byte bit_table[] = { FT_Memory extmemory, 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_Int bc, ec, nchars, i; - FT_Error error = FT_Err_Ok; - FT_Memory memory = extmemory; /* needed for FT_NEW */ + GF_Glyph go; + GF_Bitmap bm; + GF_CharOffset of; + 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, rptr; + FT_Int bc, ec, nchars, i, ngphs, idx; + FT_Error error = FT_Err_Ok; + FT_Memory memory = extmemory; /* needed for FT_NEW */ go = NULL; nchars = -1; @@ -502,11 +579,16 @@ 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_ALLOC_MULT(of, sizeof(GF_CharOffsetRec), nchars) ) + goto Exit; + + for( i = 0; i < 256 ; i++) + of[i].char_offset = -1; + + rptr = stream->pos; + i=0; ngphs=0; for ( ; ; ) { if ((instr = READ_UINT1( stream )) == GF_POST_POST) @@ -533,27 +615,73 @@ FT_Byte bit_table[] = { goto Exit; } - /* - if( w > max_m) Defined to use w + of[i].char_offset = (FT_ULong)ptr; + of[i].code = (FT_UShort)code; + of[i].gid = -1; + ngphs += 1; + i++; + } + + error = gf_set_encodings( of, ngphs, go, memory ); + if( error ) + goto Exit; + + if( FT_STREAM_SEEK( rptr ) ) + goto Exit; + + for ( ; ; ) + { + if ((instr = READ_UINT1( stream )) == GF_POST_POST) + break; + switch ((FT_Int)instr) { - FT_ERROR(( "gf_load_font: invalid width in charloc\n" )); + case GF_CHAR_LOC: + code = READ_UINT1( stream ); + dx = (FT_UInt)READ_INT4( stream )/(FT_UInt)(1<<16); + dy = (FT_UInt)READ_INT4( stream )/(FT_UInt)(1<<16); + w = READ_INT4( stream ); + ptr = READ_INT4( stream ); + break; + case GF_CHAR_LOC0: + code = READ_UINT1( stream ); + dx = (FT_UInt)READ_INT1( stream ); + dy = (FT_UInt)0; + w = READ_INT4( stream ); + ptr = READ_INT4( stream ); + break; + default: + FT_ERROR(( "gf_load_font: missing character locators in postamble\n" )); + error = FT_THROW( Unknown_File_Format ); goto Exit; } - */ optr = stream->pos; if( FT_STREAM_SEEK( ptr ) ) goto Exit; - bm = &go->bm_table[code - bc]; + for ( i = 0; i < 256; i++ ) + { + if( of[i].code == code && of[i].char_offset == ptr ) + { + idx = of[i].gid; + break; + } + } + bm = &go->bm_table[idx]; + + bm->mv_x = dx; + bm->mv_y = dy; + bm->code = code; + go->nglyphs += 1; + if (gf_read_glyph( stream, bm, memory ) < 0) goto Exit; - bm->mv_x = dx; - bm->mv_y = dy; if(FT_STREAM_SEEK( optr )) goto Exit; } + + FT_FREE(of); *goptr = go; return error;