1 /***************************************************************************/ 2 /* */ 3 /* cffdrivr.c */ 4 /* */ 5 /* OpenType font driver implementation (body). */ 6 /* */ 7 /* Copyright 1996-2001, 2002 by */ 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9 /* */ 10 /* This file is part of the FreeType project, and may only be used, */ 11 /* modified, and distributed under the terms of the FreeType project */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13 /* this file you indicate that you have read the license and */ 14 /* understand and accept it fully. */ 15 /* */ 16 /***************************************************************************/ 17 18 19 #include <ft2build.h> 20 #include FT_FREETYPE_H 21 #include FT_INTERNAL_DEBUG_H 22 #include FT_INTERNAL_STREAM_H 23 #include FT_INTERNAL_SFNT_H 24 #include FT_TRUETYPE_IDS_H 25 #include FT_INTERNAL_POSTSCRIPT_NAMES_H 26 27 #include "cffdrivr.h" 28 #include "cffgload.h" 29 #include "cffload.h" 30 31 #include "cfferrs.h" 32 33 34 /*************************************************************************/ 35 /* */ 36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 38 /* messages during execution. */ 39 /* */ 40 #undef FT_COMPONENT 41 #define FT_COMPONENT trace_cffdriver 42 43 44 /*************************************************************************/ 45 /*************************************************************************/ 46 /*************************************************************************/ 47 /**** ****/ 48 /**** ****/ 49 /**** F A C E S ****/ 50 /**** ****/ 51 /**** ****/ 52 /*************************************************************************/ 53 /*************************************************************************/ 54 /*************************************************************************/ 55 56 57 #undef PAIR_TAG 58 #define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ 59 (FT_ULong)right ) 60 61 62 /*************************************************************************/ 63 /* */ 64 /* <Function> */ 65 /* Get_Kerning */ 66 /* */ 67 /* <Description> */ 68 /* A driver method used to return the kerning vector between two */ 69 /* glyphs of the same face. */ 70 /* */ 71 /* <Input> */ 72 /* face :: A handle to the source face object. */ 73 /* */ 74 /* left_glyph :: The index of the left glyph in the kern pair. */ 75 /* */ 76 /* right_glyph :: The index of the right glyph in the kern pair. */ 77 /* */ 78 /* <Output> */ 79 /* kerning :: The kerning vector. This is in font units for */ 80 /* scalable formats, and in pixels for fixed-sizes */ 81 /* formats. */ 82 /* */ 83 /* <Return> */ 84 /* FreeType error code. 0 means success. */ 85 /* */ 86 /* <Note> */ 87 /* Only horizontal layouts (left-to-right & right-to-left) are */ 88 /* supported by this function. Other layouts, or more sophisticated */ 89 /* kernings, are out of scope of this method (the basic driver */ 90 /* interface is meant to be simple). */ 91 /* */ 92 /* They can be implemented by format-specific interfaces. */ 93 /* */ 94 static FT_Error Get_Kerning(TT_Face face,FT_UInt left_glyph,FT_UInt right_glyph,FT_Vector * kerning)95 Get_Kerning( TT_Face face, 96 FT_UInt left_glyph, 97 FT_UInt right_glyph, 98 FT_Vector* kerning ) 99 { 100 TT_Kern0_Pair pair; 101 102 103 if ( !face ) 104 return CFF_Err_Invalid_Face_Handle; 105 106 kerning->x = 0; 107 kerning->y = 0; 108 109 if ( face->kern_pairs ) 110 { 111 /* there are some kerning pairs in this font file! */ 112 FT_ULong search_tag = PAIR_TAG( left_glyph, right_glyph ); 113 FT_Long left, right; 114 115 116 left = 0; 117 right = face->num_kern_pairs - 1; 118 119 while ( left <= right ) 120 { 121 FT_Long middle = left + ( ( right - left ) >> 1 ); 122 FT_ULong cur_pair; 123 124 125 pair = face->kern_pairs + middle; 126 cur_pair = PAIR_TAG( pair->left, pair->right ); 127 128 if ( cur_pair == search_tag ) 129 goto Found; 130 131 if ( cur_pair < search_tag ) 132 left = middle + 1; 133 else 134 right = middle - 1; 135 } 136 } 137 138 Exit: 139 return CFF_Err_Ok; 140 141 Found: 142 kerning->x = pair->value; 143 goto Exit; 144 } 145 146 147 #undef PAIR_TAG 148 149 150 /*************************************************************************/ 151 /* */ 152 /* <Function> */ 153 /* Load_Glyph */ 154 /* */ 155 /* <Description> */ 156 /* A driver method used to load a glyph within a given glyph slot. */ 157 /* */ 158 /* <Input> */ 159 /* slot :: A handle to the target slot object where the glyph */ 160 /* will be loaded. */ 161 /* */ 162 /* size :: A handle to the source face size at which the glyph */ 163 /* must be scaled, loaded, etc. */ 164 /* */ 165 /* glyph_index :: The index of the glyph in the font file. */ 166 /* */ 167 /* load_flags :: A flag indicating what to load for this glyph. The */ 168 /* FTLOAD_??? constants can be used to control the */ 169 /* glyph loading process (e.g., whether the outline */ 170 /* should be scaled, whether to load bitmaps or not, */ 171 /* whether to hint the outline, etc). */ 172 /* */ 173 /* <Return> */ 174 /* FreeType error code. 0 means success. */ 175 /* */ 176 static FT_Error Load_Glyph(CFF_GlyphSlot slot,CFF_Size size,FT_UShort glyph_index,FT_Int32 load_flags)177 Load_Glyph( CFF_GlyphSlot slot, 178 CFF_Size size, 179 FT_UShort glyph_index, 180 FT_Int32 load_flags ) 181 { 182 FT_Error error; 183 184 185 if ( !slot ) 186 return CFF_Err_Invalid_Slot_Handle; 187 188 /* check whether we want a scaled outline or bitmap */ 189 if ( !size ) 190 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 191 192 if ( load_flags & FT_LOAD_NO_SCALE ) 193 size = NULL; 194 195 /* reset the size object if necessary */ 196 if ( size ) 197 { 198 /* these two object must have the same parent */ 199 if ( size->face != slot->root.face ) 200 return CFF_Err_Invalid_Face_Handle; 201 } 202 203 /* now load the glyph outline if necessary */ 204 error = cff_slot_load( slot, size, glyph_index, load_flags ); 205 206 /* force drop-out mode to 2 - irrelevant now */ 207 /* slot->outline.dropout_mode = 2; */ 208 209 return error; 210 } 211 212 213 /*************************************************************************/ 214 /*************************************************************************/ 215 /*************************************************************************/ 216 /**** ****/ 217 /**** ****/ 218 /**** C H A R A C T E R M A P P I N G S ****/ 219 /**** ****/ 220 /**** ****/ 221 /*************************************************************************/ 222 /*************************************************************************/ 223 /*************************************************************************/ 224 225 static FT_Error cff_get_glyph_name(CFF_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)226 cff_get_glyph_name( CFF_Face face, 227 FT_UInt glyph_index, 228 FT_Pointer buffer, 229 FT_UInt buffer_max ) 230 { 231 CFF_Font font = (CFF_Font)face->extra.data; 232 FT_Memory memory = FT_FACE_MEMORY( face ); 233 FT_String* gname; 234 FT_UShort sid; 235 PSNames_Service psnames; 236 FT_Error error; 237 238 239 psnames = (PSNames_Service)FT_Get_Module_Interface( 240 face->root.driver->root.library, "psnames" ); 241 242 if ( !psnames ) 243 { 244 FT_ERROR(( "cff_get_glyph_name:" )); 245 FT_ERROR(( " cannot open CFF & CEF fonts\n" )); 246 FT_ERROR(( " " )); 247 FT_ERROR(( " without the `PSNames' module\n" )); 248 error = CFF_Err_Unknown_File_Format; 249 goto Exit; 250 } 251 252 /* first, locate the sid in the charset table */ 253 sid = font->charset.sids[glyph_index]; 254 255 /* now, lookup the name itself */ 256 gname = cff_index_get_sid_string( &font->string_index, sid, psnames ); 257 258 if ( buffer_max > 0 ) 259 { 260 FT_UInt len = (FT_UInt)ft_strlen( gname ); 261 262 263 if ( len >= buffer_max ) 264 len = buffer_max - 1; 265 266 FT_MEM_COPY( buffer, gname, len ); 267 ((FT_Byte*)buffer)[len] = 0; 268 } 269 270 FT_FREE ( gname ); 271 error = CFF_Err_Ok; 272 273 Exit: 274 return error; 275 } 276 277 278 279 /*************************************************************************/ 280 /* */ 281 /* <Function> */ 282 /* cff_get_name_index */ 283 /* */ 284 /* <Description> */ 285 /* Uses the psnames module and the CFF font's charset to to return a */ 286 /* a given glyph name's glyph index. */ 287 /* */ 288 /* <Input> */ 289 /* face :: A handle to the source face object. */ 290 /* */ 291 /* glyph_name :: The glyph name. */ 292 /* */ 293 /* <Return> */ 294 /* Glyph index. 0 means `undefined character code'. */ 295 /* */ 296 static FT_UInt cff_get_name_index(CFF_Face face,FT_String * glyph_name)297 cff_get_name_index( CFF_Face face, 298 FT_String* glyph_name ) 299 { 300 CFF_Font cff; 301 CFF_Charset charset; 302 PSNames_Service psnames; 303 FT_Memory memory = FT_FACE_MEMORY( face ); 304 FT_String* name; 305 FT_UShort sid; 306 FT_UInt i; 307 FT_Int result; 308 309 310 cff = (CFF_FontRec *)face->extra.data; 311 charset = &cff->charset; 312 313 psnames = (PSNames_Service)FT_Get_Module_Interface( 314 face->root.driver->root.library, "psnames" ); 315 316 for ( i = 0; i < cff->num_glyphs; i++ ) 317 { 318 sid = charset->sids[i]; 319 320 if ( sid > 390 ) 321 name = cff_index_get_name( &cff->string_index, sid - 391 ); 322 else 323 name = (FT_String *)psnames->adobe_std_strings( sid ); 324 325 result = ft_strcmp( glyph_name, name ); 326 327 if ( sid > 390 ) 328 FT_FREE( name ); 329 330 if ( !result ) 331 return i; 332 } 333 334 return 0; 335 } 336 337 338 /*************************************************************************/ 339 /*************************************************************************/ 340 /*************************************************************************/ 341 /**** ****/ 342 /**** ****/ 343 /**** D R I V E R I N T E R F A C E ****/ 344 /**** ****/ 345 /**** ****/ 346 /*************************************************************************/ 347 /*************************************************************************/ 348 /*************************************************************************/ 349 350 static FT_Module_Interface cff_get_interface(CFF_Driver driver,const char * module_interface)351 cff_get_interface( CFF_Driver driver, 352 const char* module_interface ) 353 { 354 FT_Module sfnt; 355 356 357 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES 358 359 if ( ft_strcmp( (const char*)module_interface, "glyph_name" ) == 0 ) 360 return (FT_Module_Interface)cff_get_glyph_name; 361 362 if ( ft_strcmp( (const char*)module_interface, "name_index" ) == 0 ) 363 return (FT_Module_Interface)cff_get_name_index; 364 365 #endif 366 367 /* we simply pass our request to the `sfnt' module */ 368 sfnt = FT_Get_Module( driver->root.root.library, "sfnt" ); 369 370 return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0; 371 } 372 373 374 /* The FT_DriverInterface structure is defined in ftdriver.h. */ 375 376 FT_CALLBACK_TABLE_DEF 377 const FT_Driver_ClassRec cff_driver_class = 378 { 379 /* begin with the FT_Module_Class fields */ 380 { 381 ft_module_font_driver | 382 ft_module_driver_scalable | 383 ft_module_driver_has_hinter, 384 385 sizeof( CFF_DriverRec ), 386 "cff", 387 0x10000L, 388 0x20000L, 389 390 0, /* module-specific interface */ 391 392 (FT_Module_Constructor)cff_driver_init, 393 (FT_Module_Destructor) cff_driver_done, 394 (FT_Module_Requester) cff_get_interface, 395 }, 396 397 /* now the specific driver fields */ 398 sizeof( TT_FaceRec ), 399 sizeof( FT_SizeRec ), 400 sizeof( CFF_GlyphSlotRec ), 401 402 (FT_Face_InitFunc) cff_face_init, 403 (FT_Face_DoneFunc) cff_face_done, 404 (FT_Size_InitFunc) cff_size_init, 405 (FT_Size_DoneFunc) cff_size_done, 406 (FT_Slot_InitFunc) cff_slot_init, 407 (FT_Slot_DoneFunc) cff_slot_done, 408 409 (FT_Size_ResetPointsFunc)cff_size_reset, 410 (FT_Size_ResetPixelsFunc)cff_size_reset, 411 412 (FT_Slot_LoadFunc) Load_Glyph, 413 414 (FT_Face_GetKerningFunc) Get_Kerning, 415 (FT_Face_AttachFunc) 0, 416 (FT_Face_GetAdvancesFunc)0, 417 }; 418 419 420 /* END */ 421