1 /***************************************************************************/ 2 /* */ 3 /* sfdriver.c */ 4 /* */ 5 /* High-level SFNT driver interface (body). */ 6 /* */ 7 /* Copyright 1996-2007, 2009-2014 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_INTERNAL_DEBUG_H 21 #include FT_INTERNAL_SFNT_H 22 #include FT_INTERNAL_OBJECTS_H 23 24 #include "sfdriver.h" 25 #include "ttload.h" 26 #include "sfobjs.h" 27 #include "sfntpic.h" 28 29 #include "sferrors.h" 30 31 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 32 #include "ttsbit.h" 33 #endif 34 35 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 36 #include "ttpost.h" 37 #endif 38 39 #ifdef TT_CONFIG_OPTION_BDF 40 #include "ttbdf.h" 41 #include FT_SERVICE_BDF_H 42 #endif 43 44 #include "ttcmap.h" 45 #include "ttkern.h" 46 #include "ttmtx.h" 47 48 #include FT_SERVICE_GLYPH_DICT_H 49 #include FT_SERVICE_POSTSCRIPT_NAME_H 50 #include FT_SERVICE_SFNT_H 51 #include FT_SERVICE_TT_CMAP_H 52 53 54 /*************************************************************************/ 55 /* */ 56 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 57 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 58 /* messages during execution. */ 59 /* */ 60 #undef FT_COMPONENT 61 #define FT_COMPONENT trace_sfdriver 62 63 64 /* 65 * SFNT TABLE SERVICE 66 * 67 */ 68 69 static void* get_sfnt_table(TT_Face face,FT_Sfnt_Tag tag)70 get_sfnt_table( TT_Face face, 71 FT_Sfnt_Tag tag ) 72 { 73 void* table; 74 75 76 switch ( tag ) 77 { 78 case ft_sfnt_head: 79 table = &face->header; 80 break; 81 82 case ft_sfnt_hhea: 83 table = &face->horizontal; 84 break; 85 86 case ft_sfnt_vhea: 87 table = face->vertical_info ? &face->vertical : 0; 88 break; 89 90 case ft_sfnt_os2: 91 table = face->os2.version == 0xFFFFU ? 0 : &face->os2; 92 break; 93 94 case ft_sfnt_post: 95 table = &face->postscript; 96 break; 97 98 case ft_sfnt_maxp: 99 table = &face->max_profile; 100 break; 101 102 case ft_sfnt_pclt: 103 table = face->pclt.Version ? &face->pclt : 0; 104 break; 105 106 default: 107 table = 0; 108 } 109 110 return table; 111 } 112 113 114 static FT_Error sfnt_table_info(TT_Face face,FT_UInt idx,FT_ULong * tag,FT_ULong * offset,FT_ULong * length)115 sfnt_table_info( TT_Face face, 116 FT_UInt idx, 117 FT_ULong *tag, 118 FT_ULong *offset, 119 FT_ULong *length ) 120 { 121 if ( !offset || !length ) 122 return FT_THROW( Invalid_Argument ); 123 124 if ( !tag ) 125 *length = face->num_tables; 126 else 127 { 128 if ( idx >= face->num_tables ) 129 return FT_THROW( Table_Missing ); 130 131 *tag = face->dir_tables[idx].Tag; 132 *offset = face->dir_tables[idx].Offset; 133 *length = face->dir_tables[idx].Length; 134 } 135 136 return FT_Err_Ok; 137 } 138 139 140 FT_DEFINE_SERVICE_SFNT_TABLEREC( 141 sfnt_service_sfnt_table, 142 (FT_SFNT_TableLoadFunc)tt_face_load_any, 143 (FT_SFNT_TableGetFunc) get_sfnt_table, 144 (FT_SFNT_TableInfoFunc)sfnt_table_info ) 145 146 147 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 148 149 /* 150 * GLYPH DICT SERVICE 151 * 152 */ 153 154 static FT_Error sfnt_get_glyph_name(TT_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)155 sfnt_get_glyph_name( TT_Face face, 156 FT_UInt glyph_index, 157 FT_Pointer buffer, 158 FT_UInt buffer_max ) 159 { 160 FT_String* gname; 161 FT_Error error; 162 163 164 error = tt_face_get_ps_name( face, glyph_index, &gname ); 165 if ( !error ) 166 FT_STRCPYN( buffer, gname, buffer_max ); 167 168 return error; 169 } 170 171 172 static FT_UInt sfnt_get_name_index(TT_Face face,FT_String * glyph_name)173 sfnt_get_name_index( TT_Face face, 174 FT_String* glyph_name ) 175 { 176 FT_Face root = &face->root; 177 178 FT_UInt i, max_gid = FT_UINT_MAX; 179 180 181 if ( root->num_glyphs < 0 ) 182 return 0; 183 else if ( (FT_ULong)root->num_glyphs < FT_UINT_MAX ) 184 max_gid = (FT_UInt)root->num_glyphs; 185 else 186 FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n", 187 FT_UINT_MAX, root->num_glyphs )); 188 189 for ( i = 0; i < max_gid; i++ ) 190 { 191 FT_String* gname; 192 FT_Error error = tt_face_get_ps_name( face, i, &gname ); 193 194 195 if ( error ) 196 continue; 197 198 if ( !ft_strcmp( glyph_name, gname ) ) 199 return i; 200 } 201 202 return 0; 203 } 204 205 206 FT_DEFINE_SERVICE_GLYPHDICTREC( 207 sfnt_service_glyph_dict, 208 (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, 209 (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index ) 210 211 212 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 213 214 215 /* 216 * POSTSCRIPT NAME SERVICE 217 * 218 */ 219 220 static const char* sfnt_get_ps_name(TT_Face face)221 sfnt_get_ps_name( TT_Face face ) 222 { 223 FT_Int n, found_win, found_apple; 224 const char* result = NULL; 225 226 227 /* shouldn't happen, but just in case to avoid memory leaks */ 228 if ( face->postscript_name ) 229 return face->postscript_name; 230 231 /* scan the name table to see whether we have a Postscript name here, */ 232 /* either in Macintosh or Windows platform encodings */ 233 found_win = -1; 234 found_apple = -1; 235 236 for ( n = 0; n < face->num_names; n++ ) 237 { 238 TT_NameEntryRec* name = face->name_table.names + n; 239 240 241 if ( name->nameID == 6 && name->stringLength > 0 ) 242 { 243 if ( name->platformID == 3 && 244 name->encodingID == 1 && 245 name->languageID == 0x409 ) 246 found_win = n; 247 248 if ( name->platformID == 1 && 249 name->encodingID == 0 && 250 name->languageID == 0 ) 251 found_apple = n; 252 } 253 } 254 255 if ( found_win != -1 ) 256 { 257 FT_Memory memory = face->root.memory; 258 TT_NameEntryRec* name = face->name_table.names + found_win; 259 FT_UInt len = name->stringLength / 2; 260 FT_Error error = FT_Err_Ok; 261 262 FT_UNUSED( error ); 263 264 265 if ( !FT_ALLOC( result, name->stringLength + 1 ) ) 266 { 267 FT_Stream stream = face->name_table.stream; 268 FT_String* r = (FT_String*)result; 269 FT_Byte* p; 270 271 272 if ( FT_STREAM_SEEK( name->stringOffset ) || 273 FT_FRAME_ENTER( name->stringLength ) ) 274 { 275 FT_FREE( result ); 276 name->stringLength = 0; 277 name->stringOffset = 0; 278 FT_FREE( name->string ); 279 280 goto Exit; 281 } 282 283 p = (FT_Byte*)stream->cursor; 284 285 for ( ; len > 0; len--, p += 2 ) 286 { 287 if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 ) 288 *r++ = p[1]; 289 } 290 *r = '\0'; 291 292 FT_FRAME_EXIT(); 293 } 294 goto Exit; 295 } 296 297 if ( found_apple != -1 ) 298 { 299 FT_Memory memory = face->root.memory; 300 TT_NameEntryRec* name = face->name_table.names + found_apple; 301 FT_UInt len = name->stringLength; 302 FT_Error error = FT_Err_Ok; 303 304 FT_UNUSED( error ); 305 306 307 if ( !FT_ALLOC( result, len + 1 ) ) 308 { 309 FT_Stream stream = face->name_table.stream; 310 311 312 if ( FT_STREAM_SEEK( name->stringOffset ) || 313 FT_STREAM_READ( result, len ) ) 314 { 315 name->stringOffset = 0; 316 name->stringLength = 0; 317 FT_FREE( name->string ); 318 FT_FREE( result ); 319 goto Exit; 320 } 321 ((char*)result)[len] = '\0'; 322 } 323 } 324 325 Exit: 326 face->postscript_name = result; 327 return result; 328 } 329 330 331 FT_DEFINE_SERVICE_PSFONTNAMEREC( 332 sfnt_service_ps_name, 333 (FT_PsName_GetFunc)sfnt_get_ps_name ) 334 335 336 /* 337 * TT CMAP INFO 338 */ 339 FT_DEFINE_SERVICE_TTCMAPSREC( 340 tt_service_get_cmap_info, 341 (TT_CMap_Info_GetFunc)tt_get_cmap_info ) 342 343 344 #ifdef TT_CONFIG_OPTION_BDF 345 346 static FT_Error sfnt_get_charset_id(TT_Face face,const char ** acharset_encoding,const char ** acharset_registry)347 sfnt_get_charset_id( TT_Face face, 348 const char* *acharset_encoding, 349 const char* *acharset_registry ) 350 { 351 BDF_PropertyRec encoding, registry; 352 FT_Error error; 353 354 355 /* XXX: I don't know whether this is correct, since 356 * tt_face_find_bdf_prop only returns something correct if we have 357 * previously selected a size that is listed in the BDF table. 358 * Should we change the BDF table format to include single offsets 359 * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'? 360 */ 361 error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", ®istry ); 362 if ( !error ) 363 { 364 error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding ); 365 if ( !error ) 366 { 367 if ( registry.type == BDF_PROPERTY_TYPE_ATOM && 368 encoding.type == BDF_PROPERTY_TYPE_ATOM ) 369 { 370 *acharset_encoding = encoding.u.atom; 371 *acharset_registry = registry.u.atom; 372 } 373 else 374 error = FT_THROW( Invalid_Argument ); 375 } 376 } 377 378 return error; 379 } 380 381 382 FT_DEFINE_SERVICE_BDFRec( 383 sfnt_service_bdf, 384 (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, 385 (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop ) 386 387 388 #endif /* TT_CONFIG_OPTION_BDF */ 389 390 391 /* 392 * SERVICE LIST 393 */ 394 395 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF 396 FT_DEFINE_SERVICEDESCREC5( 397 sfnt_services, 398 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET, 399 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET, 400 FT_SERVICE_ID_GLYPH_DICT, &SFNT_SERVICE_GLYPH_DICT_GET, 401 FT_SERVICE_ID_BDF, &SFNT_SERVICE_BDF_GET, 402 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET ) 403 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES 404 FT_DEFINE_SERVICEDESCREC4( 405 sfnt_services, 406 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET, 407 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET, 408 FT_SERVICE_ID_GLYPH_DICT, &SFNT_SERVICE_GLYPH_DICT_GET, 409 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET ) 410 #elif defined TT_CONFIG_OPTION_BDF 411 FT_DEFINE_SERVICEDESCREC4( 412 sfnt_services, 413 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET, 414 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET, 415 FT_SERVICE_ID_BDF, &SFNT_SERVICE_BDF_GET, 416 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET ) 417 #else 418 FT_DEFINE_SERVICEDESCREC3( 419 sfnt_services, 420 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET, 421 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET, 422 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET ) 423 #endif 424 425 FT_CALLBACK_DEF(FT_Module_Interface)426 FT_CALLBACK_DEF( FT_Module_Interface ) 427 sfnt_get_interface( FT_Module module, 428 const char* module_interface ) 429 { 430 /* SFNT_SERVICES_GET derefers `library' in PIC mode */ 431 #ifdef FT_CONFIG_OPTION_PIC 432 FT_Library library; 433 434 435 if ( !module ) 436 return NULL; 437 library = module->library; 438 if ( !library ) 439 return NULL; 440 #else 441 FT_UNUSED( module ); 442 #endif 443 444 return ft_service_list_lookup( SFNT_SERVICES_GET, module_interface ); 445 } 446 447 448 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 449 #define PUT_EMBEDDED_BITMAPS( a ) a 450 #else 451 #define PUT_EMBEDDED_BITMAPS( a ) NULL 452 #endif 453 454 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 455 #define PUT_PS_NAMES( a ) a 456 #else 457 #define PUT_PS_NAMES( a ) NULL 458 #endif 459 460 FT_DEFINE_SFNT_INTERFACE( 461 sfnt_interface, 462 tt_face_goto_table, 463 464 sfnt_init_face, 465 sfnt_load_face, 466 sfnt_done_face, 467 sfnt_get_interface, 468 469 tt_face_load_any, 470 471 tt_face_load_head, 472 tt_face_load_hhea, 473 tt_face_load_cmap, 474 tt_face_load_maxp, 475 tt_face_load_os2, 476 tt_face_load_post, 477 478 tt_face_load_name, 479 tt_face_free_name, 480 481 tt_face_load_kern, 482 tt_face_load_gasp, 483 tt_face_load_pclt, 484 485 /* see `ttload.h' */ 486 PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ), 487 488 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ), 489 490 /* see `ttpost.h' */ 491 PUT_PS_NAMES( tt_face_get_ps_name ), 492 PUT_PS_NAMES( tt_face_free_ps_names ), 493 494 /* since version 2.1.8 */ 495 tt_face_get_kerning, 496 497 /* since version 2.2 */ 498 tt_face_load_font_dir, 499 tt_face_load_hmtx, 500 501 /* see `ttsbit.h' and `sfnt.h' */ 502 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ), 503 PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ), 504 505 PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ), 506 PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ), 507 508 tt_face_get_metrics 509 ) 510 511 512 FT_DEFINE_MODULE( 513 sfnt_module_class, 514 515 0, /* not a font driver or renderer */ 516 sizeof ( FT_ModuleRec ), 517 518 "sfnt", /* driver name */ 519 0x10000L, /* driver version 1.0 */ 520 0x20000L, /* driver requires FreeType 2.0 or higher */ 521 522 (const void*)&SFNT_INTERFACE_GET, /* module specific interface */ 523 524 (FT_Module_Constructor)0, 525 (FT_Module_Destructor) 0, 526 (FT_Module_Requester) sfnt_get_interface ) 527 528 529 /* END */ 530