1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* cffcmap.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* CFF character mapping table (cmap) support (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 2002 by */ 8*37da2899SCharles.Forsyth /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9*37da2899SCharles.Forsyth /* */ 10*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 11*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 12*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 14*37da2899SCharles.Forsyth /* understand and accept it fully. */ 15*37da2899SCharles.Forsyth /* */ 16*37da2899SCharles.Forsyth /***************************************************************************/ 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsyth #include "cffcmap.h" 20*37da2899SCharles.Forsyth #include "cffload.h" 21*37da2899SCharles.Forsyth 22*37da2899SCharles.Forsyth 23*37da2899SCharles.Forsyth /*************************************************************************/ 24*37da2899SCharles.Forsyth /*************************************************************************/ 25*37da2899SCharles.Forsyth /***** *****/ 26*37da2899SCharles.Forsyth /***** CFF STANDARD (AND EXPERT) ENCODING CMAPS *****/ 27*37da2899SCharles.Forsyth /***** *****/ 28*37da2899SCharles.Forsyth /*************************************************************************/ 29*37da2899SCharles.Forsyth /*************************************************************************/ 30*37da2899SCharles.Forsyth 31*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Error ) cff_cmap_encoding_init(CFF_CMapStd cmap)32*37da2899SCharles.Forsyth cff_cmap_encoding_init( CFF_CMapStd cmap ) 33*37da2899SCharles.Forsyth { 34*37da2899SCharles.Forsyth TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); 35*37da2899SCharles.Forsyth CFF_Font cff = (CFF_Font)face->extra.data; 36*37da2899SCharles.Forsyth CFF_Encoding encoding = &cff->encoding; 37*37da2899SCharles.Forsyth 38*37da2899SCharles.Forsyth 39*37da2899SCharles.Forsyth cmap->count = encoding->count; 40*37da2899SCharles.Forsyth cmap->gids = encoding->codes; 41*37da2899SCharles.Forsyth 42*37da2899SCharles.Forsyth return 0; 43*37da2899SCharles.Forsyth } 44*37da2899SCharles.Forsyth 45*37da2899SCharles.Forsyth 46*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) cff_cmap_encoding_done(CFF_CMapStd cmap)47*37da2899SCharles.Forsyth cff_cmap_encoding_done( CFF_CMapStd cmap ) 48*37da2899SCharles.Forsyth { 49*37da2899SCharles.Forsyth cmap->count = 0; 50*37da2899SCharles.Forsyth cmap->gids = NULL; 51*37da2899SCharles.Forsyth } 52*37da2899SCharles.Forsyth 53*37da2899SCharles.Forsyth 54*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) cff_cmap_encoding_char_index(CFF_CMapStd cmap,FT_UInt32 char_code)55*37da2899SCharles.Forsyth cff_cmap_encoding_char_index( CFF_CMapStd cmap, 56*37da2899SCharles.Forsyth FT_UInt32 char_code ) 57*37da2899SCharles.Forsyth { 58*37da2899SCharles.Forsyth FT_UInt result = 0; 59*37da2899SCharles.Forsyth 60*37da2899SCharles.Forsyth 61*37da2899SCharles.Forsyth if ( char_code < cmap->count ) 62*37da2899SCharles.Forsyth result = cmap->gids[char_code]; 63*37da2899SCharles.Forsyth 64*37da2899SCharles.Forsyth return result; 65*37da2899SCharles.Forsyth } 66*37da2899SCharles.Forsyth 67*37da2899SCharles.Forsyth 68*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) cff_cmap_encoding_char_next(CFF_CMapStd cmap,FT_UInt32 * pchar_code)69*37da2899SCharles.Forsyth cff_cmap_encoding_char_next( CFF_CMapStd cmap, 70*37da2899SCharles.Forsyth FT_UInt32 *pchar_code ) 71*37da2899SCharles.Forsyth { 72*37da2899SCharles.Forsyth FT_UInt result = 0; 73*37da2899SCharles.Forsyth FT_UInt32 char_code = *pchar_code; 74*37da2899SCharles.Forsyth 75*37da2899SCharles.Forsyth 76*37da2899SCharles.Forsyth *pchar_code = 0; 77*37da2899SCharles.Forsyth 78*37da2899SCharles.Forsyth if ( char_code < cmap->count ) 79*37da2899SCharles.Forsyth { 80*37da2899SCharles.Forsyth FT_UInt code = (FT_UInt)(char_code + 1); 81*37da2899SCharles.Forsyth 82*37da2899SCharles.Forsyth 83*37da2899SCharles.Forsyth for (;;) 84*37da2899SCharles.Forsyth { 85*37da2899SCharles.Forsyth if ( code >= cmap->count ) 86*37da2899SCharles.Forsyth break; 87*37da2899SCharles.Forsyth 88*37da2899SCharles.Forsyth result = cmap->gids[code]; 89*37da2899SCharles.Forsyth if ( result != 0 ) 90*37da2899SCharles.Forsyth { 91*37da2899SCharles.Forsyth *pchar_code = code; 92*37da2899SCharles.Forsyth break; 93*37da2899SCharles.Forsyth } 94*37da2899SCharles.Forsyth 95*37da2899SCharles.Forsyth code++; 96*37da2899SCharles.Forsyth } 97*37da2899SCharles.Forsyth } 98*37da2899SCharles.Forsyth return result; 99*37da2899SCharles.Forsyth } 100*37da2899SCharles.Forsyth 101*37da2899SCharles.Forsyth 102*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec 103*37da2899SCharles.Forsyth cff_cmap_encoding_class_rec = 104*37da2899SCharles.Forsyth { 105*37da2899SCharles.Forsyth sizeof ( CFF_CMapStdRec ), 106*37da2899SCharles.Forsyth 107*37da2899SCharles.Forsyth (FT_CMap_InitFunc) cff_cmap_encoding_init, 108*37da2899SCharles.Forsyth (FT_CMap_DoneFunc) cff_cmap_encoding_done, 109*37da2899SCharles.Forsyth (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index, 110*37da2899SCharles.Forsyth (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next 111*37da2899SCharles.Forsyth }; 112*37da2899SCharles.Forsyth 113*37da2899SCharles.Forsyth 114*37da2899SCharles.Forsyth /*************************************************************************/ 115*37da2899SCharles.Forsyth /*************************************************************************/ 116*37da2899SCharles.Forsyth /***** *****/ 117*37da2899SCharles.Forsyth /***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/ 118*37da2899SCharles.Forsyth /***** *****/ 119*37da2899SCharles.Forsyth /*************************************************************************/ 120*37da2899SCharles.Forsyth /*************************************************************************/ 121*37da2899SCharles.Forsyth 122*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Int ) cff_cmap_uni_pair_compare(const void * pair1,const void * pair2)123*37da2899SCharles.Forsyth cff_cmap_uni_pair_compare( const void* pair1, 124*37da2899SCharles.Forsyth const void* pair2 ) 125*37da2899SCharles.Forsyth { 126*37da2899SCharles.Forsyth FT_UInt32 u1 = ((CFF_CMapUniPair)pair1)->unicode; 127*37da2899SCharles.Forsyth FT_UInt32 u2 = ((CFF_CMapUniPair)pair2)->unicode; 128*37da2899SCharles.Forsyth 129*37da2899SCharles.Forsyth 130*37da2899SCharles.Forsyth if ( u1 < u2 ) 131*37da2899SCharles.Forsyth return -1; 132*37da2899SCharles.Forsyth 133*37da2899SCharles.Forsyth if ( u1 > u2 ) 134*37da2899SCharles.Forsyth return +1; 135*37da2899SCharles.Forsyth 136*37da2899SCharles.Forsyth return 0; 137*37da2899SCharles.Forsyth } 138*37da2899SCharles.Forsyth 139*37da2899SCharles.Forsyth 140*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_Error ) cff_cmap_unicode_init(CFF_CMapUnicode cmap)141*37da2899SCharles.Forsyth cff_cmap_unicode_init( CFF_CMapUnicode cmap ) 142*37da2899SCharles.Forsyth { 143*37da2899SCharles.Forsyth FT_Error error; 144*37da2899SCharles.Forsyth FT_UInt count; 145*37da2899SCharles.Forsyth TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); 146*37da2899SCharles.Forsyth FT_Memory memory = FT_FACE_MEMORY( face ); 147*37da2899SCharles.Forsyth CFF_Font cff = (CFF_Font)face->extra.data; 148*37da2899SCharles.Forsyth CFF_Charset charset = &cff->charset; 149*37da2899SCharles.Forsyth PSNames_Service psnames = (PSNames_Service)cff->psnames; 150*37da2899SCharles.Forsyth 151*37da2899SCharles.Forsyth 152*37da2899SCharles.Forsyth cmap->num_pairs = 0; 153*37da2899SCharles.Forsyth cmap->pairs = NULL; 154*37da2899SCharles.Forsyth 155*37da2899SCharles.Forsyth count = (FT_UInt)face->root.num_glyphs; 156*37da2899SCharles.Forsyth 157*37da2899SCharles.Forsyth if ( !FT_NEW_ARRAY( cmap->pairs, count ) ) 158*37da2899SCharles.Forsyth { 159*37da2899SCharles.Forsyth FT_UInt n, new_count; 160*37da2899SCharles.Forsyth CFF_CMapUniPair pair; 161*37da2899SCharles.Forsyth FT_UInt32 uni_code; 162*37da2899SCharles.Forsyth 163*37da2899SCharles.Forsyth 164*37da2899SCharles.Forsyth pair = cmap->pairs; 165*37da2899SCharles.Forsyth for ( n = 0; n < count; n++ ) 166*37da2899SCharles.Forsyth { 167*37da2899SCharles.Forsyth FT_UInt sid = charset->sids[n]; 168*37da2899SCharles.Forsyth const char* gname; 169*37da2899SCharles.Forsyth 170*37da2899SCharles.Forsyth 171*37da2899SCharles.Forsyth gname = cff_index_get_sid_string( &cff->string_index, sid, psnames ); 172*37da2899SCharles.Forsyth 173*37da2899SCharles.Forsyth /* build unsorted pair table by matching glyph names */ 174*37da2899SCharles.Forsyth if ( gname ) 175*37da2899SCharles.Forsyth { 176*37da2899SCharles.Forsyth uni_code = psnames->unicode_value( gname ); 177*37da2899SCharles.Forsyth 178*37da2899SCharles.Forsyth if ( uni_code != 0 ) 179*37da2899SCharles.Forsyth { 180*37da2899SCharles.Forsyth pair->unicode = uni_code; 181*37da2899SCharles.Forsyth pair->gindex = n; 182*37da2899SCharles.Forsyth pair++; 183*37da2899SCharles.Forsyth } 184*37da2899SCharles.Forsyth 185*37da2899SCharles.Forsyth FT_FREE( gname ); 186*37da2899SCharles.Forsyth } 187*37da2899SCharles.Forsyth } 188*37da2899SCharles.Forsyth 189*37da2899SCharles.Forsyth new_count = (FT_UInt)( pair - cmap->pairs ); 190*37da2899SCharles.Forsyth if ( new_count == 0 ) 191*37da2899SCharles.Forsyth { 192*37da2899SCharles.Forsyth /* there are no unicode characters in here! */ 193*37da2899SCharles.Forsyth FT_FREE( cmap->pairs ); 194*37da2899SCharles.Forsyth error = FT_Err_Invalid_Argument; 195*37da2899SCharles.Forsyth } 196*37da2899SCharles.Forsyth else 197*37da2899SCharles.Forsyth { 198*37da2899SCharles.Forsyth /* re-allocate if the new array is much smaller than the original */ 199*37da2899SCharles.Forsyth /* one */ 200*37da2899SCharles.Forsyth if ( new_count != count && new_count < count / 2 ) 201*37da2899SCharles.Forsyth { 202*37da2899SCharles.Forsyth (void)FT_RENEW_ARRAY( cmap->pairs, count, new_count ); 203*37da2899SCharles.Forsyth error = 0; 204*37da2899SCharles.Forsyth } 205*37da2899SCharles.Forsyth 206*37da2899SCharles.Forsyth /* sort the pairs table to allow efficient binary searches */ 207*37da2899SCharles.Forsyth ft_qsort( cmap->pairs, 208*37da2899SCharles.Forsyth new_count, 209*37da2899SCharles.Forsyth sizeof ( CFF_CMapUniPairRec ), 210*37da2899SCharles.Forsyth cff_cmap_uni_pair_compare ); 211*37da2899SCharles.Forsyth 212*37da2899SCharles.Forsyth cmap->num_pairs = new_count; 213*37da2899SCharles.Forsyth } 214*37da2899SCharles.Forsyth } 215*37da2899SCharles.Forsyth 216*37da2899SCharles.Forsyth return error; 217*37da2899SCharles.Forsyth } 218*37da2899SCharles.Forsyth 219*37da2899SCharles.Forsyth 220*37da2899SCharles.Forsyth FT_CALLBACK_DEF( void ) cff_cmap_unicode_done(CFF_CMapUnicode cmap)221*37da2899SCharles.Forsyth cff_cmap_unicode_done( CFF_CMapUnicode cmap ) 222*37da2899SCharles.Forsyth { 223*37da2899SCharles.Forsyth FT_Face face = FT_CMAP_FACE( cmap ); 224*37da2899SCharles.Forsyth FT_Memory memory = FT_FACE_MEMORY( face ); 225*37da2899SCharles.Forsyth 226*37da2899SCharles.Forsyth 227*37da2899SCharles.Forsyth FT_FREE( cmap->pairs ); 228*37da2899SCharles.Forsyth cmap->num_pairs = 0; 229*37da2899SCharles.Forsyth } 230*37da2899SCharles.Forsyth 231*37da2899SCharles.Forsyth 232*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) cff_cmap_unicode_char_index(CFF_CMapUnicode cmap,FT_UInt32 char_code)233*37da2899SCharles.Forsyth cff_cmap_unicode_char_index( CFF_CMapUnicode cmap, 234*37da2899SCharles.Forsyth FT_UInt32 char_code ) 235*37da2899SCharles.Forsyth { 236*37da2899SCharles.Forsyth FT_UInt min = 0; 237*37da2899SCharles.Forsyth FT_UInt max = cmap->num_pairs; 238*37da2899SCharles.Forsyth FT_UInt mid; 239*37da2899SCharles.Forsyth CFF_CMapUniPair pair; 240*37da2899SCharles.Forsyth 241*37da2899SCharles.Forsyth 242*37da2899SCharles.Forsyth while ( min < max ) 243*37da2899SCharles.Forsyth { 244*37da2899SCharles.Forsyth mid = min + ( max - min ) / 2; 245*37da2899SCharles.Forsyth pair = cmap->pairs + mid; 246*37da2899SCharles.Forsyth 247*37da2899SCharles.Forsyth if ( pair->unicode == char_code ) 248*37da2899SCharles.Forsyth return pair->gindex; 249*37da2899SCharles.Forsyth 250*37da2899SCharles.Forsyth if ( pair->unicode < char_code ) 251*37da2899SCharles.Forsyth min = mid + 1; 252*37da2899SCharles.Forsyth else 253*37da2899SCharles.Forsyth max = mid; 254*37da2899SCharles.Forsyth } 255*37da2899SCharles.Forsyth return 0; 256*37da2899SCharles.Forsyth } 257*37da2899SCharles.Forsyth 258*37da2899SCharles.Forsyth 259*37da2899SCharles.Forsyth FT_CALLBACK_DEF( FT_UInt ) cff_cmap_unicode_char_next(CFF_CMapUnicode cmap,FT_UInt32 * pchar_code)260*37da2899SCharles.Forsyth cff_cmap_unicode_char_next( CFF_CMapUnicode cmap, 261*37da2899SCharles.Forsyth FT_UInt32 *pchar_code ) 262*37da2899SCharles.Forsyth { 263*37da2899SCharles.Forsyth FT_UInt result = 0; 264*37da2899SCharles.Forsyth FT_UInt32 char_code = *pchar_code + 1; 265*37da2899SCharles.Forsyth 266*37da2899SCharles.Forsyth 267*37da2899SCharles.Forsyth Restart: 268*37da2899SCharles.Forsyth { 269*37da2899SCharles.Forsyth FT_UInt min = 0; 270*37da2899SCharles.Forsyth FT_UInt max = cmap->num_pairs; 271*37da2899SCharles.Forsyth FT_UInt mid; 272*37da2899SCharles.Forsyth CFF_CMapUniPair pair; 273*37da2899SCharles.Forsyth 274*37da2899SCharles.Forsyth 275*37da2899SCharles.Forsyth while ( min < max ) 276*37da2899SCharles.Forsyth { 277*37da2899SCharles.Forsyth mid = min + ( ( max - min ) >> 1 ); 278*37da2899SCharles.Forsyth pair = cmap->pairs + mid; 279*37da2899SCharles.Forsyth 280*37da2899SCharles.Forsyth if ( pair->unicode == char_code ) 281*37da2899SCharles.Forsyth { 282*37da2899SCharles.Forsyth result = pair->gindex; 283*37da2899SCharles.Forsyth if ( result != 0 ) 284*37da2899SCharles.Forsyth goto Exit; 285*37da2899SCharles.Forsyth 286*37da2899SCharles.Forsyth char_code++; 287*37da2899SCharles.Forsyth goto Restart; 288*37da2899SCharles.Forsyth } 289*37da2899SCharles.Forsyth 290*37da2899SCharles.Forsyth if ( pair->unicode < char_code ) 291*37da2899SCharles.Forsyth min = mid+1; 292*37da2899SCharles.Forsyth else 293*37da2899SCharles.Forsyth max = mid; 294*37da2899SCharles.Forsyth } 295*37da2899SCharles.Forsyth 296*37da2899SCharles.Forsyth /* we didn't find it, but we have a pair just above it */ 297*37da2899SCharles.Forsyth char_code = 0; 298*37da2899SCharles.Forsyth 299*37da2899SCharles.Forsyth if ( min < cmap->num_pairs ) 300*37da2899SCharles.Forsyth { 301*37da2899SCharles.Forsyth pair = cmap->pairs + min; 302*37da2899SCharles.Forsyth result = pair->gindex; 303*37da2899SCharles.Forsyth if ( result != 0 ) 304*37da2899SCharles.Forsyth char_code = pair->unicode; 305*37da2899SCharles.Forsyth } 306*37da2899SCharles.Forsyth } 307*37da2899SCharles.Forsyth 308*37da2899SCharles.Forsyth Exit: 309*37da2899SCharles.Forsyth *pchar_code = char_code; 310*37da2899SCharles.Forsyth return result; 311*37da2899SCharles.Forsyth } 312*37da2899SCharles.Forsyth 313*37da2899SCharles.Forsyth 314*37da2899SCharles.Forsyth FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec 315*37da2899SCharles.Forsyth cff_cmap_unicode_class_rec = 316*37da2899SCharles.Forsyth { 317*37da2899SCharles.Forsyth sizeof ( CFF_CMapUnicodeRec ), 318*37da2899SCharles.Forsyth 319*37da2899SCharles.Forsyth (FT_CMap_InitFunc) cff_cmap_unicode_init, 320*37da2899SCharles.Forsyth (FT_CMap_DoneFunc) cff_cmap_unicode_done, 321*37da2899SCharles.Forsyth (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index, 322*37da2899SCharles.Forsyth (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next 323*37da2899SCharles.Forsyth }; 324*37da2899SCharles.Forsyth 325*37da2899SCharles.Forsyth 326*37da2899SCharles.Forsyth /* END */ 327