diff --git a/ChangeLog b/ChangeLog index f43422952..f40cab88e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +2002-02-04 Keith Packard + + Adding the function `FT_Get_Next_Char', doing the obvious thing + w.r.t. the selected charmap. + + * include/freetype/freetype.h: Add prototype. + * include/freetype/internal/ftdriver.h: Add `FTDriver_getNextChar' + typedef. + (FT_Driver_Class): Use it. + * include/freetype/internal/psnames.h: Add `PS_Next_Unicode_Func' + typedef. + (PSNames_Interface): Use it. + * include/freetype/internal/tttypes.h: Add `TT_CharNext_Func' + typedef. + (TT_CMapTable): Use it. + + * src/base/ftobjs.c (FT_Get_Next_Char): New function, implementing + high-level API. + * src/cff/cffdrivr.c (cff_get_next_char): New function. + (cff_driver_class): Add it. + * src/cid/cidriver.c (Cid_Get_Next_Char): New function. + (t1cid_driver_class): Add it. + * src/pcf/pcfdriver.c (PCF_Get_Next_Char): New function. + (pcf_driver_class): Add it. + * src/psnames/psmodule.c (PS_Next_Unicode): New function. + (psnames_interface): Add it. + * src/sfnt/ttcmap.c (code_to_next0, code_to_next2, code_to_next4, + code_to_next6, code_to_next_8_12, code_to_next_10): New auxiliary + functions. + (TT_CharMap_Load): Use them. + * src/truetype/ttdriver.c (Get_Next_Char): New function. + (tt_driver_class): Add it. + * src/type1/t1driver.c (Get_Next_Char): New function. + (t1_driver_class): Add it. + * src/winfnt/winfnt.c (FNT_Get_Next_Char): New function. + (winfnt_driver_class): Add it. + + * src/pcf/pcfread.c (pcf_load_font): For now, report Unicode for + Unicode and Latin 1 encodings. + 2002-02-02 Keith Packard * builds/unix/freetype-config.in: Add missing `fi'. diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index d4761a80f..d6275a6e7 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -122,6 +122,7 @@ FT_BEGIN_HEADER /* FT_Set_Transform */ /* FT_Load_Glyph */ /* FT_Get_Char_Index */ + /* FT_Get_Next_Char */ /* FT_Get_Name_Index */ /* FT_Load_Char */ /* */ @@ -2391,6 +2392,27 @@ FT_BEGIN_HEADER FT_ULong charcode ); + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Next_Char */ + /* */ + /* */ + /* Returns the next charcode that is defined in the charmap. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* The charcode. 0 means `no encoded values above charcode'. */ + /* */ + FT_EXPORT( FT_ULong ) + FT_Get_Next_Char( FT_Face face, + FT_ULong charcode ); + + /*************************************************************************/ /* */ /* */ diff --git a/include/freetype/internal/ftdriver.h b/include/freetype/internal/ftdriver.h index 6d5857342..d8c73d17a 100644 --- a/include/freetype/internal/ftdriver.h +++ b/include/freetype/internal/ftdriver.h @@ -75,6 +75,10 @@ FT_BEGIN_HEADER (*FTDriver_getCharIndex)( FT_CharMap charmap, FT_Long charcode ); + typedef FT_Long + (*FTDriver_getNextChar)( FT_CharMap charmap, + FT_Long charcode ); + typedef FT_Error (*FTDriver_getKerning)( FT_Face face, FT_UInt left_glyph, @@ -189,6 +193,7 @@ FT_BEGIN_HEADER FTDriver_getAdvances get_advances; + FTDriver_getNextChar get_next_char; } FT_Driver_Class; diff --git a/include/freetype/internal/psnames.h b/include/freetype/internal/psnames.h index 71700c192..a70b7a906 100644 --- a/include/freetype/internal/psnames.h +++ b/include/freetype/internal/psnames.h @@ -166,6 +166,10 @@ FT_BEGIN_HEADER (*PS_Lookup_Unicode_Func)( PS_Unicodes* unicodes, FT_UInt unicode ); + typedef FT_ULong + (*PS_Next_Unicode_Func)( PS_Unicodes* unicodes, + FT_ULong unicode ); + /*************************************************************************/ /* */ @@ -221,6 +225,7 @@ FT_BEGIN_HEADER const unsigned short* adobe_std_encoding; const unsigned short* adobe_expert_encoding; + PS_Next_Unicode_Func next_unicode; } PSNames_Interface; diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h index 4fc504fc7..4177d1e38 100644 --- a/include/freetype/internal/tttypes.h +++ b/include/freetype/internal/tttypes.h @@ -1049,6 +1049,10 @@ FT_BEGIN_HEADER (*TT_CharMap_Func)( TT_CMapTable* charmap, FT_ULong char_code ); + typedef FT_ULong + (*TT_CharNext_Func)( TT_CMapTable* charmap, + FT_ULong char_code ); + /* charmap table */ struct TT_CMapTable_ @@ -1072,6 +1076,7 @@ FT_BEGIN_HEADER } c; TT_CharMap_Func get_index; + TT_CharNext_Func get_next_char; }; diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index f2eb27942..21a6be0f5 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -1867,6 +1867,25 @@ return result; } + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_ULong ) + FT_Get_Next_Char( FT_Face face, + FT_ULong charcode ) + { + FT_ULong result; + FT_Driver driver; + + + result = 0; + if ( face && face->charmap ) + { + driver = face->driver; + result = driver->clazz->get_next_char( face->charmap, charcode ); + } + return result; + } + /* documentation is in freetype.h */ diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c index 6b89b2af1..24e4200b5 100644 --- a/src/cff/cffdrivr.c +++ b/src/cff/cffdrivr.c @@ -317,6 +317,50 @@ } + /*************************************************************************/ + /* */ + /* */ + /* cff_get_next_char */ + /* */ + /* */ + /* Uses a charmap to return the next encoded charcode. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Char code. 0 means `no encoded chars above the given one'. */ + /* */ + static FT_Long + cff_get_next_char( TT_CharMap charmap, + FT_Long charcode ) + { + FT_Error error; + CFF_Face face; + TT_CMapTable* cmap; + + + cmap = &charmap->cmap; + face = (CFF_Face)charmap->root.face; + + /* Load table if needed */ + if ( !cmap->loaded ) + { + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + + error = sfnt->load_charmap( face, cmap, face->root.stream ); + if ( error ) + return 0; + + cmap->loaded = TRUE; + } + + return ( cmap->get_next_char ? cmap->get_next_char( cmap, charcode ) : 0 ); + } + + /*************************************************************************/ /* */ /* */ @@ -454,7 +498,9 @@ (FTDriver_getKerning) Get_Kerning, (FTDriver_attachFile) 0, - (FTDriver_getAdvances) 0 + (FTDriver_getAdvances) 0, + + (FTDriver_getNextChar) cff_get_next_char }; diff --git a/src/cid/cidriver.c b/src/cid/cidriver.c index 9edbc698b..21f0594b1 100644 --- a/src/cid/cidriver.c +++ b/src/cid/cidriver.c @@ -185,6 +185,104 @@ } + /*************************************************************************/ + /* */ + /* */ + /* Cid_Get_Next_Char */ + /* */ + /* */ + /* Uses a charmap to return the next encoded char after. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Next char code. 0 means `no more char codes'. */ + /* */ + static FT_Long + CID_Get_Next_Char( FT_CharMap charmap, + FT_Long charcode ) + { + T1_Face face; + PSNames_Interface* psnames; + + + face = (T1_Face)charmap->face; + psnames = (PSNames_Interface*)face->psnames; + + if ( psnames ) + switch ( charmap->encoding ) + { + /*******************************************************************/ + /* */ + /* Unicode encoding support */ + /* */ + case ft_encoding_unicode: + /* use the `PSNames' module to synthetize the Unicode charmap */ + return psnames->next_unicode (&face->unicode_map, + (FT_ULong)charcode ); + + /*******************************************************************/ + /* */ + /* Custom Type 1 encoding */ + /* */ + case ft_encoding_adobe_custom: + { + T1_Encoding* encoding = &face->type1.encoding; + + + charcode++; + if ( charcode < encoding->code_first ) + charcode = encoding->code_first; + while ( charcode <= encoding->code_last ) + { + if ( encoding->char_index[charcode] ) + return charcode; + charcode++; + } + } + break; + + /*******************************************************************/ + /* */ + /* Adobe Standard & Expert encoding support */ + /* */ + default: + while ( ++charcode < 256 ) + { + FT_UInt code; + FT_Int n; + const char* glyph_name; + + + code = psnames->adobe_std_encoding[charcode]; + if ( charmap->encoding == ft_encoding_adobe_expert ) + code = psnames->adobe_expert_encoding[charcode]; + + glyph_name = psnames->adobe_std_strings( code ); + if ( !glyph_name ) + continue; + + for ( n = 0; n < face->type1.num_glyphs; n++ ) + { + const char* gname = face->type1.glyph_names[n]; + + + if ( gname && gname[0] == glyph_name[0] && + strcmp( gname, glyph_name ) == 0 ) + { + return charcode; + } + } + } + } + + return 0; + } + + FT_CALLBACK_TABLE_DEF const FT_Driver_Class t1cid_driver_class = { @@ -228,7 +326,9 @@ (FTDriver_getKerning) 0, (FTDriver_attachFile) 0, - (FTDriver_getAdvances) 0 + (FTDriver_getAdvances) 0, + + (FTDriver_getNextChar) CID_Get_Next_Char }; diff --git a/src/pcf/pcfdriver.c b/src/pcf/pcfdriver.c index 2b3ab49b3..d172879d9 100644 --- a/src/pcf/pcfdriver.c +++ b/src/pcf/pcfdriver.c @@ -276,6 +276,46 @@ THE SOFTWARE. } + static FT_Long + PCF_Get_Next_Char( FT_CharMap charmap, + FT_Long char_code ) + { + PCF_Face face = (PCF_Face)charmap->face; + PCF_Encoding en_table = face->encodings; + int low, high, mid; + + + FT_TRACE4(( "get_char_index %ld\n", char_code )); + + char_code++; + low = 0; + high = face->nencodings - 1; + + while ( low <= high ) + { + mid = ( low + high ) / 2; + if ( char_code < en_table[mid].enc ) + high = mid - 1; + else if ( char_code > en_table[mid].enc ) + low = mid + 1; + else + return char_code; + } + + if ( high < 0 ) + high = 0; + + while ( high < face->nencodings ) + { + if ( en_table[high].enc >= char_code ) + return en_table[high].enc; + high++; + } + + return 0; + } + + FT_CALLBACK_TABLE_DEF const FT_Driver_Class pcf_driver_class = { @@ -313,7 +353,9 @@ THE SOFTWARE. (FTDriver_getKerning) 0, (FTDriver_attachFile) 0, - (FTDriver_getAdvances) 0 + (FTDriver_getAdvances) 0, + + (FTDriver_getNextChar) PCF_Get_Next_Char }; diff --git a/src/pcf/pcfread.c b/src/pcf/pcfread.c index d7691260c..07acee32e 100644 --- a/src/pcf/pcfread.c +++ b/src/pcf/pcfread.c @@ -1021,10 +1021,14 @@ THE SOFTWARE. root->available_sizes->height = 12; } - /* XXX: charmaps */ + /* XXX: charmaps. For now, report unicode for Unicode and Latin 1 */ root->charmaps = &face->charmap_handle; root->num_charmaps = 1; + face->charmap.encoding = ft_encoding_none; + face->charmap.platform_id = 0; + face->charmap.encoding_id = 0; + { PCF_Property charset_registry = 0, charset_encoding = 0; @@ -1049,28 +1053,21 @@ THE SOFTWARE. strcpy( face->charset_registry, charset_registry->value.atom ); strcpy( face->charset_encoding, charset_encoding->value.atom ); -#if 0 - if ( !strcmp( charset_registry, "ISO10646" ) ) + if ( !strcmp( face->charset_registry, "ISO10646" ) || + ( !strcmp( face->charset_registry, "ISO8859" ) && + !strcmp( face->charset_encoding, "1" ) ) ) { face->charmap.encoding = ft_encoding_unicode; face->charmap.platform_id = 3; face->charmap.encoding_id = 1; - face->charmap.face = root; - face->charmap_handle - - return PCF_Err_Ok; } -#endif } } } - face->charmap.encoding = ft_encoding_none; - face->charmap.platform_id = 0; - face->charmap.encoding_id = 0; - face->charmap.face = root; - face->charmap_handle = &face->charmap; - root->charmap = face->charmap_handle; + face->charmap.face = root; + face->charmap_handle = &face->charmap; + root->charmap = face->charmap_handle; } return PCF_Err_Ok; diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c index 9f6ccf599..5b3e2de4a 100644 --- a/src/psnames/psmodule.c +++ b/src/psnames/psmodule.c @@ -238,6 +238,48 @@ } + static FT_ULong + PS_Next_Unicode( PS_Unicodes* table, + FT_ULong unicode ) + { + PS_UniMap *min, *max, *mid; + + + unicode++; + /* perform a binary search on the table */ + + min = table->maps; + max = min + table->num_maps - 1; + + while ( min <= max ) + { + mid = min + ( max - min ) / 2; + if ( mid->unicode == unicode ) + return unicode; + + if ( min == max ) + break; + + if ( mid->unicode < unicode ) + min = mid + 1; + else + max = mid - 1; + } + + if ( max < table->maps ) + max = table->maps; + + while ( max < table->maps + table->num_maps ) + { + if ( unicode < max->unicode ) + return max->unicode; + max++; + } + + return 0; + } + + #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ @@ -272,6 +314,7 @@ 0, 0, 0, + 0, #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ @@ -279,7 +322,14 @@ (PS_Adobe_Std_Strings_Func)PS_Standard_Strings, t1_standard_encoding, - t1_expert_encoding + t1_expert_encoding, + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + (PS_Next_Unicode_Func) PS_Next_Unicode +#else + 0 +#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ + }; diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c index b37faf4c2..1a3fb17f3 100644 --- a/src/sfnt/ttcmap.c +++ b/src/sfnt/ttcmap.c @@ -38,26 +38,50 @@ code_to_index0( TT_CMapTable* charmap, FT_ULong char_code ); + FT_CALLBACK_DEF( FT_ULong ) + code_to_next0( TT_CMapTable* charmap, + FT_ULong char_code ); + FT_CALLBACK_DEF( FT_UInt ) code_to_index2( TT_CMapTable* charmap, FT_ULong char_code ); + FT_CALLBACK_DEF( FT_ULong ) + code_to_next2( TT_CMapTable* charmap, + FT_ULong char_code ); + FT_CALLBACK_DEF( FT_UInt ) code_to_index4( TT_CMapTable* charmap, FT_ULong char_code ); + FT_CALLBACK_DEF( FT_ULong ) + code_to_next4( TT_CMapTable* charmap, + FT_ULong char_code ); + FT_CALLBACK_DEF( FT_UInt ) code_to_index6( TT_CMapTable* charmap, FT_ULong char_code ); + FT_CALLBACK_DEF( FT_ULong ) + code_to_next6( TT_CMapTable* charmap, + FT_ULong char_code ); + FT_CALLBACK_DEF( FT_UInt ) code_to_index8_12( TT_CMapTable* charmap, FT_ULong char_code ); + FT_CALLBACK_DEF( FT_ULong ) + code_to_next8_12( TT_CMapTable* charmap, + FT_ULong char_code ); + FT_CALLBACK_DEF( FT_UInt ) code_to_index10( TT_CMapTable* charmap, FT_ULong char_code ); + FT_CALLBACK_DEF( FT_ULong ) + code_to_next10( TT_CMapTable* charmap, + FT_ULong char_code ); + /*************************************************************************/ /* */ @@ -125,6 +149,7 @@ goto Fail; cmap->get_index = code_to_index0; + cmap->get_next_char = code_to_next0; break; case 2: @@ -196,6 +221,7 @@ FORGET_Frame(); cmap->get_index = code_to_index2; + cmap->get_next_char = code_to_next2; break; case 4: @@ -262,6 +288,7 @@ cmap4->last_segment = cmap4->segments; cmap->get_index = code_to_index4; + cmap->get_next_char = code_to_next4; break; case 6: @@ -287,6 +314,7 @@ FORGET_Frame(); cmap->get_index = code_to_index6; + cmap->get_next_char = code_to_next6; break; case 8: @@ -328,6 +356,7 @@ cmap8_12->last_group = cmap8_12->groups; cmap->get_index = code_to_index8_12; + cmap->get_next_char = code_to_next8_12; break; case 10: @@ -354,6 +383,7 @@ FORGET_Frame(); cmap->get_index = code_to_index10; + cmap->get_next_char = code_to_next10; break; default: /* corrupt character mapping table */ @@ -468,6 +498,37 @@ } + /*************************************************************************/ + /* */ + /* */ + /* code_to_next0 */ + /* */ + /* */ + /* Finds the next encoded character after the given one. Uses */ + /* format 0. `charCode' must be in the range 0x00-0xFF (otherwise 0 */ + /* is returned). */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap0 :: A pointer to a cmap table in format 0. */ + /* */ + /* */ + /* Next char code. 0 if no higher one is encoded. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next0( TT_CMapTable* cmap, + FT_ULong charCode ) + { + TT_CMap0* cmap0 = &cmap->c.cmap0; + + + while ( ++charCode <= 0xFF ) + if ( cmap0->glyphIdArray[charCode] ) + return ( charCode ); + return ( 0 ); + } + + /*************************************************************************/ /* */ /* */ @@ -533,6 +594,89 @@ } + /*************************************************************************/ + /* */ + /* */ + /* code_to_next2 */ + /* */ + /* */ + /* Find the next encoded character. Uses format 2. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap2 :: A pointer to a cmap table in format 2. */ + /* */ + /* */ + /* Next encoded character. 0 if none exists. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next2( TT_CMapTable* cmap, + FT_ULong charCode ) + { + FT_UInt index1, offset; + FT_UInt char_lo; + FT_ULong char_hi; + TT_CMap2SubHeader* sh2; + TT_CMap2* cmap2; + + + cmap2 = &cmap->c.cmap2; + charCode++; + + /* + * This is relatively simplistic -- look for a subHeader containing + * glyphs and then walk to the first glyph in that subHeader. + */ + while ( charCode < 0x10000 ) + { + char_lo = (FT_UInt)( charCode & 0xFF ); + char_hi = charCode >> 8; + + if ( char_hi == 0 ) + { + /* an 8-bit character code -- we use the subHeader 0 in this case */ + /* to test whether the character code is in the charmap */ + index1 = cmap2->subHeaderKeys[char_lo]; + if ( index1 != 0 ) + { + charCode++; + continue; + } + } + else + { + /* a 16-bit character code */ + index1 = cmap2->subHeaderKeys[char_hi & 0xFF]; + if ( index1 == 0 ) + { + charCode = ( char_hi + 1 ) << 8; + continue; + } + } + + sh2 = cmap2->subHeaders + index1; + char_lo -= sh2->firstCode; + + if ( char_lo > (FT_UInt)sh2->entryCount ) + { + charCode = ( char_hi + 1 ) << 8; + continue; + } + + offset = sh2->idRangeOffset / 2 + char_lo; + if ( offset >= (FT_UInt)cmap2->numGlyphId || + cmap2->glyphIdArray[offset] == 0 ) + { + charCode++; + continue; + } + + return charCode; + } + return 0; + } + + /*************************************************************************/ /* */ /* */ @@ -617,6 +761,73 @@ } + /*************************************************************************/ + /* */ + /* */ + /* code_to_next4 */ + /* */ + /* */ + /* Find the next encoded character. Uses format 4. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap :: A pointer to a cmap table in format 4. */ + /* */ + /* */ + /* Next encoded character. 0 if none exists. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next4( TT_CMapTable* cmap, + FT_ULong charCode ) + { + FT_UInt index1, segCount; + TT_CMap4* cmap4; + TT_CMap4Segment *seg4, *limit; + + + cmap4 = &cmap->c.cmap4; + segCount = cmap4->segCountX2 / 2; + limit = cmap4->segments + segCount; + + charCode++; + + for ( seg4 = cmap4->segments; seg4 < limit; seg4++ ) + { + /* The ranges are sorted in increasing order. If we are out of */ + /* the range here, the char code isn't in the charmap, so exit. */ + + if ( charCode <= (FT_UInt)seg4->endCount ) + goto Found; + } + return 0; + + Found: + if ( charCode < seg4->startCount ) + charCode = seg4->startCount; + + /* if the idRangeOffset is 0, all chars in the map exist */ + + if ( seg4->idRangeOffset == 0 ) + return ( charCode ); + + while ( charCode <= (FT_UInt) seg4->endCount ) + { + /* otherwise, we must use the glyphIdArray to do it */ + index1 = (FT_UInt)( seg4->idRangeOffset / 2 + + ( charCode - seg4->startCount ) + + ( seg4 - cmap4->segments ) + - segCount ); + + if ( index1 < (FT_UInt)cmap4->numGlyphId && + cmap4->glyphIdArray[index1] != 0 ) + return ( charCode ); + charCode++; + } + + return 0; + } + + /*************************************************************************/ /* */ /* */ @@ -650,6 +861,48 @@ } + /*************************************************************************/ + /* */ + /* */ + /* code_to_next6 */ + /* */ + /* */ + /* Find the next encoded character. Uses format 6. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap :: A pointer to a cmap table in format 6. */ + /* */ + /* */ + /* Next encoded character. 0 if none exists. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next6( TT_CMapTable* cmap, + FT_ULong charCode ) + { + TT_CMap6* cmap6; + + + charCode++; + + cmap6 = &cmap->c.cmap6; + + if ( charCode < cmap6->firstCode ) + charCode = cmap6->firstCode; + + charCode -= cmap6->firstCode; + + while ( charCode < (FT_UInt)cmap6->entryCount ) + { + if ( cmap6->glyphIdArray[charCode] != 0 ) + return charCode + cmap6->firstCode; + charCode++; + } + + return 0; + } + + /*************************************************************************/ /* */ /* */ @@ -715,6 +968,51 @@ } + /*************************************************************************/ + /* */ + /* */ + /* code_to_next8_12 */ + /* */ + /* */ + /* Find the next encoded character. Uses format 8 or 12. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap :: A pointer to a cmap table in format 8 or 12. */ + /* */ + /* */ + /* Next encoded character. 0 if none exists. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next8_12( TT_CMapTable* cmap, + FT_ULong charCode ) + { + TT_CMap8_12* cmap8_12; + TT_CMapGroup *group, *limit; + + + charCode++; + cmap8_12 = &cmap->c.cmap8_12; + limit = cmap8_12->groups + cmap8_12->nGroups; + + for ( group = cmap8_12->groups; group < limit; group++ ) + { + /* the ranges are sorted in increasing order. If we are out of */ + /* the range here, the char code isn't in the charmap, so exit. */ + + if ( charCode <= group->endCharCode ) + goto Found; + } + return 0; + + Found: + if ( charCode < group->startCharCode ) + charCode = group->startCharCode; + + return charCode; + } + + /*************************************************************************/ /* */ /* */ @@ -753,4 +1051,49 @@ } + /*************************************************************************/ + /* */ + /* */ + /* code_to_next10 */ + /* */ + /* */ + /* Find the next encoded character. Uses format 10. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap :: A pointer to a cmap table in format 10. */ + /* */ + /* */ + /* Next encoded character. 0 if none exists. */ + /* */ + FT_CALLBACK_DEF( FT_ULong ) + code_to_next10( TT_CMapTable* cmap, + FT_ULong charCode ) + { + TT_CMap10* cmap10; + + + charCode++; + cmap10 = &cmap->c.cmap10; + + if ( charCode < cmap10->startCharCode ) + charCode = cmap10->startCharCode; + + charCode -= cmap10->startCharCode; + + /* the overflow trick for comparison works here also since the number */ + /* of glyphs (even if numChars is specified as ULong in the specs) in */ + /* an OpenType font is limited to 64k */ + + while ( charCode < cmap10->numChars ) + { + if ( cmap10->glyphs[charCode] ) + return ( charCode + cmap10->startCharCode ); + charCode++; + } + + return 0; + } + + /* END */ diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c index 0b7d8f8d0..5df3e3180 100644 --- a/src/truetype/ttdriver.c +++ b/src/truetype/ttdriver.c @@ -393,6 +393,53 @@ } + /*************************************************************************/ + /* */ + /* */ + /* Get_Next_Char */ + /* */ + /* */ + /* Uses a charmap to return the next encoded char. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Next char code. 0 means `no more encoded characters'. */ + /* */ + static FT_UInt + Get_Next_Char( TT_CharMap charmap, + FT_Long charcode ) + { + FT_Error error; + TT_Face face; + TT_CMapTable* cmap; + + + cmap = &charmap->cmap; + face = (TT_Face)charmap->root.face; + + /* Load table if needed */ + if ( !cmap->loaded ) + { + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + + error = sfnt->load_charmap( face, cmap, face->root.stream ); + if ( error ) + return 0; + + cmap->loaded = TRUE; + } + + if ( cmap->get_next_char ) + return cmap->get_next_char ( cmap, charcode ); + else + return 0; + } + + /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ @@ -473,7 +520,9 @@ (FTDriver_getKerning) Get_Kerning, (FTDriver_attachFile) 0, - (FTDriver_getAdvances) 0 + (FTDriver_getAdvances) 0, + + (FTDriver_getNextChar) Get_Next_Char }; diff --git a/src/type1/t1driver.c b/src/type1/t1driver.c index 57e59f9a4..b5bf444bf 100644 --- a/src/type1/t1driver.c +++ b/src/type1/t1driver.c @@ -327,6 +327,100 @@ } + /*************************************************************************/ + /* */ + /* */ + /* Get_Next_Char */ + /* */ + /* */ + /* Uses a charmap to return the next encoded char. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Next char code. 0 means `no more char codes'. */ + /* */ + static FT_Long + Get_Next_Char( FT_CharMap charmap, + FT_Long charcode ) + { + T1_Face face; + PSNames_Interface* psnames; + + + face = (T1_Face)charmap->face; + psnames = (PSNames_Interface*)face->psnames; + + if ( psnames ) + switch ( charmap->encoding ) + { + /*******************************************************************/ + /* */ + /* Unicode encoding support */ + /* */ + case ft_encoding_unicode: + /* use the `PSNames' module to synthetize the Unicode charmap */ + return psnames->next_unicode( &face->unicode_map, + (FT_ULong)charcode ); + + /*******************************************************************/ + /* */ + /* Custom Type 1 encoding */ + /* */ + case ft_encoding_adobe_custom: + { + T1_Encoding* encoding = &face->type1.encoding; + + + charcode++; + if ( charcode < encoding->code_first ) + charcode = encoding->code_first; + while ( charcode <= encoding->code_last ) + { + if ( encoding->char_index[charcode] ) + return charcode; + charcode++; + } + } + + /*******************************************************************/ + /* */ + /* Adobe Standard & Expert encoding support */ + /* */ + default: + while ( ++charcode < 256 ) + { + FT_UInt code; + FT_Int n; + const char* glyph_name; + + + code = psnames->adobe_std_encoding[charcode]; + if ( charmap->encoding == ft_encoding_adobe_expert ) + code = psnames->adobe_expert_encoding[charcode]; + + glyph_name = psnames->adobe_std_strings( code ); + if ( !glyph_name ) + continue; + + for ( n = 0; n < face->type1.num_glyphs; n++ ) + { + const char* gname = face->type1.glyph_names[n]; + + + if ( gname && gname[0] == glyph_name[0] && + strcmp( gname, glyph_name ) == 0 ) + return charcode; + } + } + } + + return 0; + } + + FT_CALLBACK_TABLE_DEF const FT_Driver_Class t1_driver_class = { @@ -371,7 +465,9 @@ (FTDriver_getKerning) Get_Kerning, (FTDriver_attachFile) T1_Read_AFM, #endif - (FTDriver_getAdvances) 0 + (FTDriver_getAdvances) 0, + + (FTDriver_getNextChar) Get_Next_Char }; diff --git a/src/winfonts/winfnt.c b/src/winfonts/winfnt.c index 529769749..852978370 100644 --- a/src/winfonts/winfnt.c +++ b/src/winfonts/winfnt.c @@ -494,6 +494,27 @@ return result; } + static FT_Long + FNT_Get_Next_Char( FT_CharMap charmap, + FT_Long char_code ) + { + char_code++; + if ( charmap ) + { + FNT_Font* font = ((FNT_Face)charmap->face)->fonts; + FT_Long first = font->header.first_char; + + + if ( char_code < first ) + char_code = first; + if ( char_code <= font->header.last_char ) + return char_code; + } + else + return char_code; + return 0; + } + static FT_Error FNT_Load_Glyph( FT_GlyphSlot slot, @@ -622,7 +643,9 @@ (FTDriver_getKerning) 0, (FTDriver_attachFile) 0, - (FTDriver_getAdvances) 0 + (FTDriver_getAdvances) 0, + + (FTDriver_getNextChar) FNT_Get_Next_Char };