Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencffload.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* cffload.c */ 00004 /* */ 00005 /* OpenType and CFF data/program tables loader (body). */ 00006 /* */ 00007 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ 00008 /* 2010 by */ 00009 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00010 /* */ 00011 /* This file is part of the FreeType project, and may only be used, */ 00012 /* modified, and distributed under the terms of the FreeType project */ 00013 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00014 /* this file you indicate that you have read the license and */ 00015 /* understand and accept it fully. */ 00016 /* */ 00017 /***************************************************************************/ 00018 00019 00020 #include <ft2build.h> 00021 #include FT_INTERNAL_DEBUG_H 00022 #include FT_INTERNAL_OBJECTS_H 00023 #include FT_INTERNAL_STREAM_H 00024 #include FT_TRUETYPE_TAGS_H 00025 #include FT_TYPE1_TABLES_H 00026 00027 #include "cffload.h" 00028 #include "cffparse.h" 00029 00030 #include "cfferrs.h" 00031 00032 00033 #if 1 00034 00035 static const FT_UShort cff_isoadobe_charset[229] = 00036 { 00037 0, 1, 2, 3, 4, 5, 6, 7, 00038 8, 9, 10, 11, 12, 13, 14, 15, 00039 16, 17, 18, 19, 20, 21, 22, 23, 00040 24, 25, 26, 27, 28, 29, 30, 31, 00041 32, 33, 34, 35, 36, 37, 38, 39, 00042 40, 41, 42, 43, 44, 45, 46, 47, 00043 48, 49, 50, 51, 52, 53, 54, 55, 00044 56, 57, 58, 59, 60, 61, 62, 63, 00045 64, 65, 66, 67, 68, 69, 70, 71, 00046 72, 73, 74, 75, 76, 77, 78, 79, 00047 80, 81, 82, 83, 84, 85, 86, 87, 00048 88, 89, 90, 91, 92, 93, 94, 95, 00049 96, 97, 98, 99, 100, 101, 102, 103, 00050 104, 105, 106, 107, 108, 109, 110, 111, 00051 112, 113, 114, 115, 116, 117, 118, 119, 00052 120, 121, 122, 123, 124, 125, 126, 127, 00053 128, 129, 130, 131, 132, 133, 134, 135, 00054 136, 137, 138, 139, 140, 141, 142, 143, 00055 144, 145, 146, 147, 148, 149, 150, 151, 00056 152, 153, 154, 155, 156, 157, 158, 159, 00057 160, 161, 162, 163, 164, 165, 166, 167, 00058 168, 169, 170, 171, 172, 173, 174, 175, 00059 176, 177, 178, 179, 180, 181, 182, 183, 00060 184, 185, 186, 187, 188, 189, 190, 191, 00061 192, 193, 194, 195, 196, 197, 198, 199, 00062 200, 201, 202, 203, 204, 205, 206, 207, 00063 208, 209, 210, 211, 212, 213, 214, 215, 00064 216, 217, 218, 219, 220, 221, 222, 223, 00065 224, 225, 226, 227, 228 00066 }; 00067 00068 static const FT_UShort cff_expert_charset[166] = 00069 { 00070 0, 1, 229, 230, 231, 232, 233, 234, 00071 235, 236, 237, 238, 13, 14, 15, 99, 00072 239, 240, 241, 242, 243, 244, 245, 246, 00073 247, 248, 27, 28, 249, 250, 251, 252, 00074 253, 254, 255, 256, 257, 258, 259, 260, 00075 261, 262, 263, 264, 265, 266, 109, 110, 00076 267, 268, 269, 270, 271, 272, 273, 274, 00077 275, 276, 277, 278, 279, 280, 281, 282, 00078 283, 284, 285, 286, 287, 288, 289, 290, 00079 291, 292, 293, 294, 295, 296, 297, 298, 00080 299, 300, 301, 302, 303, 304, 305, 306, 00081 307, 308, 309, 310, 311, 312, 313, 314, 00082 315, 316, 317, 318, 158, 155, 163, 319, 00083 320, 321, 322, 323, 324, 325, 326, 150, 00084 164, 169, 327, 328, 329, 330, 331, 332, 00085 333, 334, 335, 336, 337, 338, 339, 340, 00086 341, 342, 343, 344, 345, 346, 347, 348, 00087 349, 350, 351, 352, 353, 354, 355, 356, 00088 357, 358, 359, 360, 361, 362, 363, 364, 00089 365, 366, 367, 368, 369, 370, 371, 372, 00090 373, 374, 375, 376, 377, 378 00091 }; 00092 00093 static const FT_UShort cff_expertsubset_charset[87] = 00094 { 00095 0, 1, 231, 232, 235, 236, 237, 238, 00096 13, 14, 15, 99, 239, 240, 241, 242, 00097 243, 244, 245, 246, 247, 248, 27, 28, 00098 249, 250, 251, 253, 254, 255, 256, 257, 00099 258, 259, 260, 261, 262, 263, 264, 265, 00100 266, 109, 110, 267, 268, 269, 270, 272, 00101 300, 301, 302, 305, 314, 315, 158, 155, 00102 163, 320, 321, 322, 323, 324, 325, 326, 00103 150, 164, 169, 327, 328, 329, 330, 331, 00104 332, 333, 334, 335, 336, 337, 338, 339, 00105 340, 341, 342, 343, 344, 345, 346 00106 }; 00107 00108 static const FT_UShort cff_standard_encoding[256] = 00109 { 00110 0, 0, 0, 0, 0, 0, 0, 0, 00111 0, 0, 0, 0, 0, 0, 0, 0, 00112 0, 0, 0, 0, 0, 0, 0, 0, 00113 0, 0, 0, 0, 0, 0, 0, 0, 00114 1, 2, 3, 4, 5, 6, 7, 8, 00115 9, 10, 11, 12, 13, 14, 15, 16, 00116 17, 18, 19, 20, 21, 22, 23, 24, 00117 25, 26, 27, 28, 29, 30, 31, 32, 00118 33, 34, 35, 36, 37, 38, 39, 40, 00119 41, 42, 43, 44, 45, 46, 47, 48, 00120 49, 50, 51, 52, 53, 54, 55, 56, 00121 57, 58, 59, 60, 61, 62, 63, 64, 00122 65, 66, 67, 68, 69, 70, 71, 72, 00123 73, 74, 75, 76, 77, 78, 79, 80, 00124 81, 82, 83, 84, 85, 86, 87, 88, 00125 89, 90, 91, 92, 93, 94, 95, 0, 00126 0, 0, 0, 0, 0, 0, 0, 0, 00127 0, 0, 0, 0, 0, 0, 0, 0, 00128 0, 0, 0, 0, 0, 0, 0, 0, 00129 0, 0, 0, 0, 0, 0, 0, 0, 00130 0, 96, 97, 98, 99, 100, 101, 102, 00131 103, 104, 105, 106, 107, 108, 109, 110, 00132 0, 111, 112, 113, 114, 0, 115, 116, 00133 117, 118, 119, 120, 121, 122, 0, 123, 00134 0, 124, 125, 126, 127, 128, 129, 130, 00135 131, 0, 132, 133, 0, 134, 135, 136, 00136 137, 0, 0, 0, 0, 0, 0, 0, 00137 0, 0, 0, 0, 0, 0, 0, 0, 00138 0, 138, 0, 139, 0, 0, 0, 0, 00139 140, 141, 142, 143, 0, 0, 0, 0, 00140 0, 144, 0, 0, 0, 145, 0, 0, 00141 146, 147, 148, 149, 0, 0, 0, 0 00142 }; 00143 00144 static const FT_UShort cff_expert_encoding[256] = 00145 { 00146 0, 0, 0, 0, 0, 0, 0, 0, 00147 0, 0, 0, 0, 0, 0, 0, 0, 00148 0, 0, 0, 0, 0, 0, 0, 0, 00149 0, 0, 0, 0, 0, 0, 0, 0, 00150 1, 229, 230, 0, 231, 232, 233, 234, 00151 235, 236, 237, 238, 13, 14, 15, 99, 00152 239, 240, 241, 242, 243, 244, 245, 246, 00153 247, 248, 27, 28, 249, 250, 251, 252, 00154 0, 253, 254, 255, 256, 257, 0, 0, 00155 0, 258, 0, 0, 259, 260, 261, 262, 00156 0, 0, 263, 264, 265, 0, 266, 109, 00157 110, 267, 268, 269, 0, 270, 271, 272, 00158 273, 274, 275, 276, 277, 278, 279, 280, 00159 281, 282, 283, 284, 285, 286, 287, 288, 00160 289, 290, 291, 292, 293, 294, 295, 296, 00161 297, 298, 299, 300, 301, 302, 303, 0, 00162 0, 0, 0, 0, 0, 0, 0, 0, 00163 0, 0, 0, 0, 0, 0, 0, 0, 00164 0, 0, 0, 0, 0, 0, 0, 0, 00165 0, 0, 0, 0, 0, 0, 0, 0, 00166 0, 304, 305, 306, 0, 0, 307, 308, 00167 309, 310, 311, 0, 312, 0, 0, 312, 00168 0, 0, 314, 315, 0, 0, 316, 317, 00169 318, 0, 0, 0, 158, 155, 163, 319, 00170 320, 321, 322, 323, 324, 325, 0, 0, 00171 326, 150, 164, 169, 327, 328, 329, 330, 00172 331, 332, 333, 334, 335, 336, 337, 338, 00173 339, 340, 341, 342, 343, 344, 345, 346, 00174 347, 348, 349, 350, 351, 352, 353, 354, 00175 355, 356, 357, 358, 359, 360, 361, 362, 00176 363, 364, 365, 366, 367, 368, 369, 370, 00177 371, 372, 373, 374, 375, 376, 377, 378 00178 }; 00179 00180 #endif /* 1 */ 00181 00182 00183 FT_LOCAL_DEF( FT_UShort ) 00184 cff_get_standard_encoding( FT_UInt charcode ) 00185 { 00186 return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode] 00187 : 0 ); 00188 } 00189 00190 00191 /*************************************************************************/ 00192 /* */ 00193 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00194 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00195 /* messages during execution. */ 00196 /* */ 00197 #undef FT_COMPONENT 00198 #define FT_COMPONENT trace_cffload 00199 00200 00201 /* read an offset from the index's stream current position */ 00202 static FT_ULong 00203 cff_index_read_offset( CFF_Index idx, 00204 FT_Error *errorp ) 00205 { 00206 FT_Error error; 00207 FT_Stream stream = idx->stream; 00208 FT_Byte tmp[4]; 00209 FT_ULong result = 0; 00210 00211 00212 if ( !FT_STREAM_READ( tmp, idx->off_size ) ) 00213 { 00214 FT_Int nn; 00215 00216 00217 for ( nn = 0; nn < idx->off_size; nn++ ) 00218 result = ( result << 8 ) | tmp[nn]; 00219 } 00220 00221 *errorp = error; 00222 return result; 00223 } 00224 00225 00226 static FT_Error 00227 cff_index_init( CFF_Index idx, 00228 FT_Stream stream, 00229 FT_Bool load ) 00230 { 00231 FT_Error error; 00232 FT_Memory memory = stream->memory; 00233 FT_UShort count; 00234 00235 00236 FT_MEM_ZERO( idx, sizeof ( *idx ) ); 00237 00238 idx->stream = stream; 00239 idx->start = FT_STREAM_POS(); 00240 if ( !FT_READ_USHORT( count ) && 00241 count > 0 ) 00242 { 00243 FT_Byte offsize; 00244 FT_ULong size; 00245 00246 00247 /* there is at least one element; read the offset size, */ 00248 /* then access the offset table to compute the index's total size */ 00249 if ( FT_READ_BYTE( offsize ) ) 00250 goto Exit; 00251 00252 if ( offsize < 1 || offsize > 4 ) 00253 { 00254 error = CFF_Err_Invalid_Table; 00255 goto Exit; 00256 } 00257 00258 idx->count = count; 00259 idx->off_size = offsize; 00260 size = (FT_ULong)( count + 1 ) * offsize; 00261 00262 idx->data_offset = idx->start + 3 + size; 00263 00264 if ( FT_STREAM_SKIP( size - offsize ) ) 00265 goto Exit; 00266 00267 size = cff_index_read_offset( idx, &error ); 00268 if ( error ) 00269 goto Exit; 00270 00271 if ( size == 0 ) 00272 { 00273 error = CFF_Err_Invalid_Table; 00274 goto Exit; 00275 } 00276 00277 idx->data_size = --size; 00278 00279 if ( load ) 00280 { 00281 /* load the data */ 00282 if ( FT_FRAME_EXTRACT( size, idx->bytes ) ) 00283 goto Exit; 00284 } 00285 else 00286 { 00287 /* skip the data */ 00288 if ( FT_STREAM_SKIP( size ) ) 00289 goto Exit; 00290 } 00291 } 00292 00293 Exit: 00294 if ( error ) 00295 FT_FREE( idx->offsets ); 00296 00297 return error; 00298 } 00299 00300 00301 static void 00302 cff_index_done( CFF_Index idx ) 00303 { 00304 if ( idx->stream ) 00305 { 00306 FT_Stream stream = idx->stream; 00307 FT_Memory memory = stream->memory; 00308 00309 00310 if ( idx->bytes ) 00311 FT_FRAME_RELEASE( idx->bytes ); 00312 00313 FT_FREE( idx->offsets ); 00314 FT_MEM_ZERO( idx, sizeof ( *idx ) ); 00315 } 00316 } 00317 00318 00319 static FT_Error 00320 cff_index_load_offsets( CFF_Index idx ) 00321 { 00322 FT_Error error = CFF_Err_Ok; 00323 FT_Stream stream = idx->stream; 00324 FT_Memory memory = stream->memory; 00325 00326 00327 if ( idx->count > 0 && idx->offsets == NULL ) 00328 { 00329 FT_Byte offsize = idx->off_size; 00330 FT_ULong data_size; 00331 FT_Byte* p; 00332 FT_Byte* p_end; 00333 FT_ULong* poff; 00334 00335 00336 data_size = (FT_ULong)( idx->count + 1 ) * offsize; 00337 00338 if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) || 00339 FT_STREAM_SEEK( idx->start + 3 ) || 00340 FT_FRAME_ENTER( data_size ) ) 00341 goto Exit; 00342 00343 poff = idx->offsets; 00344 p = (FT_Byte*)stream->cursor; 00345 p_end = p + data_size; 00346 00347 switch ( offsize ) 00348 { 00349 case 1: 00350 for ( ; p < p_end; p++, poff++ ) 00351 poff[0] = p[0]; 00352 break; 00353 00354 case 2: 00355 for ( ; p < p_end; p += 2, poff++ ) 00356 poff[0] = FT_PEEK_USHORT( p ); 00357 break; 00358 00359 case 3: 00360 for ( ; p < p_end; p += 3, poff++ ) 00361 poff[0] = FT_PEEK_OFF3( p ); 00362 break; 00363 00364 default: 00365 for ( ; p < p_end; p += 4, poff++ ) 00366 poff[0] = FT_PEEK_ULONG( p ); 00367 } 00368 00369 FT_FRAME_EXIT(); 00370 } 00371 00372 Exit: 00373 if ( error ) 00374 FT_FREE( idx->offsets ); 00375 00376 return error; 00377 } 00378 00379 00380 /* Allocate a table containing pointers to an index's elements. */ 00381 /* The `pool' argument makes this function convert the index */ 00382 /* entries to C-style strings (this is, NULL-terminated). */ 00383 static FT_Error 00384 cff_index_get_pointers( CFF_Index idx, 00385 FT_Byte*** table, 00386 FT_Byte** pool ) 00387 { 00388 FT_Error error = CFF_Err_Ok; 00389 FT_Memory memory = idx->stream->memory; 00390 FT_Byte** t; 00391 FT_Byte* new_bytes = NULL; 00392 00393 00394 *table = NULL; 00395 00396 if ( idx->offsets == NULL ) 00397 { 00398 error = cff_index_load_offsets( idx ); 00399 if ( error ) 00400 goto Exit; 00401 } 00402 00403 if ( idx->count > 0 && 00404 !FT_NEW_ARRAY( t, idx->count + 1 ) && 00405 ( !pool || !FT_ALLOC( new_bytes, 00406 idx->data_size + idx->count ) ) ) 00407 { 00408 FT_ULong n, cur_offset; 00409 FT_ULong extra = 0; 00410 FT_Byte* org_bytes = idx->bytes; 00411 00412 00413 /* at this point, `idx->offsets' can't be NULL */ 00414 cur_offset = idx->offsets[0] - 1; 00415 00416 /* sanity check */ 00417 if ( cur_offset >= idx->data_size ) 00418 { 00419 FT_TRACE0(( "cff_index_get_pointers:" 00420 " invalid first offset value %d set to zero\n", 00421 cur_offset )); 00422 cur_offset = 0; 00423 } 00424 00425 if ( !pool ) 00426 t[0] = org_bytes + cur_offset; 00427 else 00428 t[0] = new_bytes + cur_offset; 00429 00430 for ( n = 1; n <= idx->count; n++ ) 00431 { 00432 FT_ULong next_offset = idx->offsets[n] - 1; 00433 00434 00435 /* empty slot + two sanity checks for invalid offset tables */ 00436 if ( next_offset == 0 || 00437 next_offset < cur_offset || 00438 ( next_offset >= idx->data_size && n < idx->count ) ) 00439 next_offset = cur_offset; 00440 00441 if ( !pool ) 00442 t[n] = org_bytes + next_offset; 00443 else 00444 { 00445 t[n] = new_bytes + next_offset + extra; 00446 00447 if ( next_offset != cur_offset ) 00448 { 00449 FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] ); 00450 t[n][0] = '\0'; 00451 t[n] += 1; 00452 extra++; 00453 } 00454 } 00455 00456 cur_offset = next_offset; 00457 } 00458 *table = t; 00459 00460 if ( pool ) 00461 *pool = new_bytes; 00462 } 00463 00464 Exit: 00465 return error; 00466 } 00467 00468 00469 FT_LOCAL_DEF( FT_Error ) 00470 cff_index_access_element( CFF_Index idx, 00471 FT_UInt element, 00472 FT_Byte** pbytes, 00473 FT_ULong* pbyte_len ) 00474 { 00475 FT_Error error = CFF_Err_Ok; 00476 00477 00478 if ( idx && idx->count > element ) 00479 { 00480 /* compute start and end offsets */ 00481 FT_Stream stream = idx->stream; 00482 FT_ULong off1, off2 = 0; 00483 00484 00485 /* load offsets from file or the offset table */ 00486 if ( !idx->offsets ) 00487 { 00488 FT_ULong pos = element * idx->off_size; 00489 00490 00491 if ( FT_STREAM_SEEK( idx->start + 3 + pos ) ) 00492 goto Exit; 00493 00494 off1 = cff_index_read_offset( idx, &error ); 00495 if ( error ) 00496 goto Exit; 00497 00498 if ( off1 != 0 ) 00499 { 00500 do 00501 { 00502 element++; 00503 off2 = cff_index_read_offset( idx, &error ); 00504 } 00505 while ( off2 == 0 && element < idx->count ); 00506 } 00507 } 00508 else /* use offsets table */ 00509 { 00510 off1 = idx->offsets[element]; 00511 if ( off1 ) 00512 { 00513 do 00514 { 00515 element++; 00516 off2 = idx->offsets[element]; 00517 00518 } while ( off2 == 0 && element < idx->count ); 00519 } 00520 } 00521 00522 /* XXX: should check off2 does not exceed the end of this entry; */ 00523 /* at present, only truncate off2 at the end of this stream */ 00524 if ( off2 > stream->size + 1 || 00525 idx->data_offset > stream->size - off2 + 1 ) 00526 { 00527 FT_ERROR(( "cff_index_access_element:" 00528 " offset to next entry (%d)" 00529 " exceeds the end of stream (%d)\n", 00530 off2, stream->size - idx->data_offset + 1 )); 00531 off2 = stream->size - idx->data_offset + 1; 00532 } 00533 00534 /* access element */ 00535 if ( off1 && off2 > off1 ) 00536 { 00537 *pbyte_len = off2 - off1; 00538 00539 if ( idx->bytes ) 00540 { 00541 /* this index was completely loaded in memory, that's easy */ 00542 *pbytes = idx->bytes + off1 - 1; 00543 } 00544 else 00545 { 00546 /* this index is still on disk/file, access it through a frame */ 00547 if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) || 00548 FT_FRAME_EXTRACT( off2 - off1, *pbytes ) ) 00549 goto Exit; 00550 } 00551 } 00552 else 00553 { 00554 /* empty index element */ 00555 *pbytes = 0; 00556 *pbyte_len = 0; 00557 } 00558 } 00559 else 00560 error = CFF_Err_Invalid_Argument; 00561 00562 Exit: 00563 return error; 00564 } 00565 00566 00567 FT_LOCAL_DEF( void ) 00568 cff_index_forget_element( CFF_Index idx, 00569 FT_Byte** pbytes ) 00570 { 00571 if ( idx->bytes == 0 ) 00572 { 00573 FT_Stream stream = idx->stream; 00574 00575 00576 FT_FRAME_RELEASE( *pbytes ); 00577 } 00578 } 00579 00580 00581 /* get an entry from Name INDEX */ 00582 FT_LOCAL_DEF( FT_String* ) 00583 cff_index_get_name( CFF_Font font, 00584 FT_UInt element ) 00585 { 00586 CFF_Index idx = &font->name_index; 00587 FT_Memory memory = idx->stream->memory; 00588 FT_Byte* bytes; 00589 FT_ULong byte_len; 00590 FT_Error error; 00591 FT_String* name = 0; 00592 00593 00594 error = cff_index_access_element( idx, element, &bytes, &byte_len ); 00595 if ( error ) 00596 goto Exit; 00597 00598 if ( !FT_ALLOC( name, byte_len + 1 ) ) 00599 { 00600 FT_MEM_COPY( name, bytes, byte_len ); 00601 name[byte_len] = 0; 00602 } 00603 cff_index_forget_element( idx, &bytes ); 00604 00605 Exit: 00606 return name; 00607 } 00608 00609 00610 /* get an entry from String INDEX */ 00611 FT_LOCAL_DEF( FT_String* ) 00612 cff_index_get_string( CFF_Font font, 00613 FT_UInt element ) 00614 { 00615 return ( element < font->num_strings ) 00616 ? (FT_String*)font->strings[element] 00617 : NULL; 00618 } 00619 00620 00621 FT_LOCAL_DEF( FT_String* ) 00622 cff_index_get_sid_string( CFF_Font font, 00623 FT_UInt sid ) 00624 { 00625 /* value 0xFFFFU indicates a missing dictionary entry */ 00626 if ( sid == 0xFFFFU ) 00627 return NULL; 00628 00629 /* if it is not a standard string, return it */ 00630 if ( sid > 390 ) 00631 return cff_index_get_string( font, sid - 391 ); 00632 00633 /* CID-keyed CFF fonts don't have glyph names */ 00634 if ( !font->psnames ) 00635 return NULL; 00636 00637 /* this is a standard string */ 00638 return (FT_String *)font->psnames->adobe_std_strings( sid ); 00639 } 00640 00641 00642 /*************************************************************************/ 00643 /*************************************************************************/ 00644 /*** ***/ 00645 /*** FD Select table support ***/ 00646 /*** ***/ 00647 /*************************************************************************/ 00648 /*************************************************************************/ 00649 00650 00651 static void 00652 CFF_Done_FD_Select( CFF_FDSelect fdselect, 00653 FT_Stream stream ) 00654 { 00655 if ( fdselect->data ) 00656 FT_FRAME_RELEASE( fdselect->data ); 00657 00658 fdselect->data_size = 0; 00659 fdselect->format = 0; 00660 fdselect->range_count = 0; 00661 } 00662 00663 00664 static FT_Error 00665 CFF_Load_FD_Select( CFF_FDSelect fdselect, 00666 FT_UInt num_glyphs, 00667 FT_Stream stream, 00668 FT_ULong offset ) 00669 { 00670 FT_Error error; 00671 FT_Byte format; 00672 FT_UInt num_ranges; 00673 00674 00675 /* read format */ 00676 if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) ) 00677 goto Exit; 00678 00679 fdselect->format = format; 00680 fdselect->cache_count = 0; /* clear cache */ 00681 00682 switch ( format ) 00683 { 00684 case 0: /* format 0, that's simple */ 00685 fdselect->data_size = num_glyphs; 00686 goto Load_Data; 00687 00688 case 3: /* format 3, a tad more complex */ 00689 if ( FT_READ_USHORT( num_ranges ) ) 00690 goto Exit; 00691 00692 fdselect->data_size = num_ranges * 3 + 2; 00693 00694 Load_Data: 00695 if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) ) 00696 goto Exit; 00697 break; 00698 00699 default: /* hmm... that's wrong */ 00700 error = CFF_Err_Invalid_File_Format; 00701 } 00702 00703 Exit: 00704 return error; 00705 } 00706 00707 00708 FT_LOCAL_DEF( FT_Byte ) 00709 cff_fd_select_get( CFF_FDSelect fdselect, 00710 FT_UInt glyph_index ) 00711 { 00712 FT_Byte fd = 0; 00713 00714 00715 switch ( fdselect->format ) 00716 { 00717 case 0: 00718 fd = fdselect->data[glyph_index]; 00719 break; 00720 00721 case 3: 00722 /* first, compare to cache */ 00723 if ( (FT_UInt)( glyph_index - fdselect->cache_first ) < 00724 fdselect->cache_count ) 00725 { 00726 fd = fdselect->cache_fd; 00727 break; 00728 } 00729 00730 /* then, lookup the ranges array */ 00731 { 00732 FT_Byte* p = fdselect->data; 00733 FT_Byte* p_limit = p + fdselect->data_size; 00734 FT_Byte fd2; 00735 FT_UInt first, limit; 00736 00737 00738 first = FT_NEXT_USHORT( p ); 00739 do 00740 { 00741 if ( glyph_index < first ) 00742 break; 00743 00744 fd2 = *p++; 00745 limit = FT_NEXT_USHORT( p ); 00746 00747 if ( glyph_index < limit ) 00748 { 00749 fd = fd2; 00750 00751 /* update cache */ 00752 fdselect->cache_first = first; 00753 fdselect->cache_count = limit-first; 00754 fdselect->cache_fd = fd2; 00755 break; 00756 } 00757 first = limit; 00758 00759 } while ( p < p_limit ); 00760 } 00761 break; 00762 00763 default: 00764 ; 00765 } 00766 00767 return fd; 00768 } 00769 00770 00771 /*************************************************************************/ 00772 /*************************************************************************/ 00773 /*** ***/ 00774 /*** CFF font support ***/ 00775 /*** ***/ 00776 /*************************************************************************/ 00777 /*************************************************************************/ 00778 00779 static FT_Error 00780 cff_charset_compute_cids( CFF_Charset charset, 00781 FT_UInt num_glyphs, 00782 FT_Memory memory ) 00783 { 00784 FT_Error error = CFF_Err_Ok; 00785 FT_UInt i; 00786 FT_Long j; 00787 FT_UShort max_cid = 0; 00788 00789 00790 if ( charset->max_cid > 0 ) 00791 goto Exit; 00792 00793 for ( i = 0; i < num_glyphs; i++ ) 00794 { 00795 if ( charset->sids[i] > max_cid ) 00796 max_cid = charset->sids[i]; 00797 } 00798 00799 if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) ) 00800 goto Exit; 00801 00802 /* When multiple GIDs map to the same CID, we choose the lowest */ 00803 /* GID. This is not described in any spec, but it matches the */ 00804 /* behaviour of recent Acroread versions. */ 00805 for ( j = num_glyphs - 1; j >= 0 ; j-- ) 00806 charset->cids[charset->sids[j]] = (FT_UShort)j; 00807 00808 charset->max_cid = max_cid; 00809 charset->num_glyphs = num_glyphs; 00810 00811 Exit: 00812 return error; 00813 } 00814 00815 00816 FT_LOCAL_DEF( FT_UInt ) 00817 cff_charset_cid_to_gindex( CFF_Charset charset, 00818 FT_UInt cid ) 00819 { 00820 FT_UInt result = 0; 00821 00822 00823 if ( cid <= charset->max_cid ) 00824 result = charset->cids[cid]; 00825 00826 return result; 00827 } 00828 00829 00830 static void 00831 cff_charset_free_cids( CFF_Charset charset, 00832 FT_Memory memory ) 00833 { 00834 FT_FREE( charset->cids ); 00835 charset->max_cid = 0; 00836 } 00837 00838 00839 static void 00840 cff_charset_done( CFF_Charset charset, 00841 FT_Stream stream ) 00842 { 00843 FT_Memory memory = stream->memory; 00844 00845 00846 cff_charset_free_cids( charset, memory ); 00847 00848 FT_FREE( charset->sids ); 00849 charset->format = 0; 00850 charset->offset = 0; 00851 } 00852 00853 00854 static FT_Error 00855 cff_charset_load( CFF_Charset charset, 00856 FT_UInt num_glyphs, 00857 FT_Stream stream, 00858 FT_ULong base_offset, 00859 FT_ULong offset, 00860 FT_Bool invert ) 00861 { 00862 FT_Memory memory = stream->memory; 00863 FT_Error error = CFF_Err_Ok; 00864 FT_UShort glyph_sid; 00865 00866 00867 /* If the the offset is greater than 2, we have to parse the */ 00868 /* charset table. */ 00869 if ( offset > 2 ) 00870 { 00871 FT_UInt j; 00872 00873 00874 charset->offset = base_offset + offset; 00875 00876 /* Get the format of the table. */ 00877 if ( FT_STREAM_SEEK( charset->offset ) || 00878 FT_READ_BYTE( charset->format ) ) 00879 goto Exit; 00880 00881 /* Allocate memory for sids. */ 00882 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) 00883 goto Exit; 00884 00885 /* assign the .notdef glyph */ 00886 charset->sids[0] = 0; 00887 00888 switch ( charset->format ) 00889 { 00890 case 0: 00891 if ( num_glyphs > 0 ) 00892 { 00893 if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) ) 00894 goto Exit; 00895 00896 for ( j = 1; j < num_glyphs; j++ ) 00897 charset->sids[j] = FT_GET_USHORT(); 00898 00899 FT_FRAME_EXIT(); 00900 } 00901 break; 00902 00903 case 1: 00904 case 2: 00905 { 00906 FT_UInt nleft; 00907 FT_UInt i; 00908 00909 00910 j = 1; 00911 00912 while ( j < num_glyphs ) 00913 { 00914 /* Read the first glyph sid of the range. */ 00915 if ( FT_READ_USHORT( glyph_sid ) ) 00916 goto Exit; 00917 00918 /* Read the number of glyphs in the range. */ 00919 if ( charset->format == 2 ) 00920 { 00921 if ( FT_READ_USHORT( nleft ) ) 00922 goto Exit; 00923 } 00924 else 00925 { 00926 if ( FT_READ_BYTE( nleft ) ) 00927 goto Exit; 00928 } 00929 00930 /* try to rescue some of the SIDs if `nleft' is too large */ 00931 if ( glyph_sid > 0xFFFFL - nleft ) 00932 { 00933 FT_ERROR(( "cff_charset_load: invalid SID range trimmed" 00934 " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid )); 00935 nleft = ( FT_UInt )( 0xFFFFL - glyph_sid ); 00936 } 00937 00938 /* Fill in the range of sids -- `nleft + 1' glyphs. */ 00939 for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ ) 00940 charset->sids[j] = glyph_sid; 00941 } 00942 } 00943 break; 00944 00945 default: 00946 FT_ERROR(( "cff_charset_load: invalid table format\n" )); 00947 error = CFF_Err_Invalid_File_Format; 00948 goto Exit; 00949 } 00950 } 00951 else 00952 { 00953 /* Parse default tables corresponding to offset == 0, 1, or 2. */ 00954 /* CFF specification intimates the following: */ 00955 /* */ 00956 /* In order to use a predefined charset, the following must be */ 00957 /* true: The charset constructed for the glyphs in the font's */ 00958 /* charstrings dictionary must match the predefined charset in */ 00959 /* the first num_glyphs. */ 00960 00961 charset->offset = offset; /* record charset type */ 00962 00963 switch ( (FT_UInt)offset ) 00964 { 00965 case 0: 00966 if ( num_glyphs > 229 ) 00967 { 00968 FT_ERROR(( "cff_charset_load: implicit charset larger than\n" 00969 "predefined charset (Adobe ISO-Latin)\n" )); 00970 error = CFF_Err_Invalid_File_Format; 00971 goto Exit; 00972 } 00973 00974 /* Allocate memory for sids. */ 00975 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) 00976 goto Exit; 00977 00978 /* Copy the predefined charset into the allocated memory. */ 00979 FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs ); 00980 00981 break; 00982 00983 case 1: 00984 if ( num_glyphs > 166 ) 00985 { 00986 FT_ERROR(( "cff_charset_load: implicit charset larger than\n" 00987 "predefined charset (Adobe Expert)\n" )); 00988 error = CFF_Err_Invalid_File_Format; 00989 goto Exit; 00990 } 00991 00992 /* Allocate memory for sids. */ 00993 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) 00994 goto Exit; 00995 00996 /* Copy the predefined charset into the allocated memory. */ 00997 FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs ); 00998 00999 break; 01000 01001 case 2: 01002 if ( num_glyphs > 87 ) 01003 { 01004 FT_ERROR(( "cff_charset_load: implicit charset larger than\n" 01005 "predefined charset (Adobe Expert Subset)\n" )); 01006 error = CFF_Err_Invalid_File_Format; 01007 goto Exit; 01008 } 01009 01010 /* Allocate memory for sids. */ 01011 if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) 01012 goto Exit; 01013 01014 /* Copy the predefined charset into the allocated memory. */ 01015 FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs ); 01016 01017 break; 01018 01019 default: 01020 error = CFF_Err_Invalid_File_Format; 01021 goto Exit; 01022 } 01023 } 01024 01025 /* we have to invert the `sids' array for subsetted CID-keyed fonts */ 01026 if ( invert ) 01027 error = cff_charset_compute_cids( charset, num_glyphs, memory ); 01028 01029 Exit: 01030 /* Clean up if there was an error. */ 01031 if ( error ) 01032 { 01033 FT_FREE( charset->sids ); 01034 FT_FREE( charset->cids ); 01035 charset->format = 0; 01036 charset->offset = 0; 01037 charset->sids = 0; 01038 } 01039 01040 return error; 01041 } 01042 01043 01044 static void 01045 cff_encoding_done( CFF_Encoding encoding ) 01046 { 01047 encoding->format = 0; 01048 encoding->offset = 0; 01049 encoding->count = 0; 01050 } 01051 01052 01053 static FT_Error 01054 cff_encoding_load( CFF_Encoding encoding, 01055 CFF_Charset charset, 01056 FT_UInt num_glyphs, 01057 FT_Stream stream, 01058 FT_ULong base_offset, 01059 FT_ULong offset ) 01060 { 01061 FT_Error error = CFF_Err_Ok; 01062 FT_UInt count; 01063 FT_UInt j; 01064 FT_UShort glyph_sid; 01065 FT_UInt glyph_code; 01066 01067 01068 /* Check for charset->sids. If we do not have this, we fail. */ 01069 if ( !charset->sids ) 01070 { 01071 error = CFF_Err_Invalid_File_Format; 01072 goto Exit; 01073 } 01074 01075 /* Zero out the code to gid/sid mappings. */ 01076 for ( j = 0; j < 256; j++ ) 01077 { 01078 encoding->sids [j] = 0; 01079 encoding->codes[j] = 0; 01080 } 01081 01082 /* Note: The encoding table in a CFF font is indexed by glyph index; */ 01083 /* the first encoded glyph index is 1. Hence, we read the character */ 01084 /* code (`glyph_code') at index j and make the assignment: */ 01085 /* */ 01086 /* encoding->codes[glyph_code] = j + 1 */ 01087 /* */ 01088 /* We also make the assignment: */ 01089 /* */ 01090 /* encoding->sids[glyph_code] = charset->sids[j + 1] */ 01091 /* */ 01092 /* This gives us both a code to GID and a code to SID mapping. */ 01093 01094 if ( offset > 1 ) 01095 { 01096 encoding->offset = base_offset + offset; 01097 01098 /* we need to parse the table to determine its size */ 01099 if ( FT_STREAM_SEEK( encoding->offset ) || 01100 FT_READ_BYTE( encoding->format ) || 01101 FT_READ_BYTE( count ) ) 01102 goto Exit; 01103 01104 switch ( encoding->format & 0x7F ) 01105 { 01106 case 0: 01107 { 01108 FT_Byte* p; 01109 01110 01111 /* By convention, GID 0 is always ".notdef" and is never */ 01112 /* coded in the font. Hence, the number of codes found */ 01113 /* in the table is `count+1'. */ 01114 /* */ 01115 encoding->count = count + 1; 01116 01117 if ( FT_FRAME_ENTER( count ) ) 01118 goto Exit; 01119 01120 p = (FT_Byte*)stream->cursor; 01121 01122 for ( j = 1; j <= count; j++ ) 01123 { 01124 glyph_code = *p++; 01125 01126 /* Make sure j is not too big. */ 01127 if ( j < num_glyphs ) 01128 { 01129 /* Assign code to GID mapping. */ 01130 encoding->codes[glyph_code] = (FT_UShort)j; 01131 01132 /* Assign code to SID mapping. */ 01133 encoding->sids[glyph_code] = charset->sids[j]; 01134 } 01135 } 01136 01137 FT_FRAME_EXIT(); 01138 } 01139 break; 01140 01141 case 1: 01142 { 01143 FT_UInt nleft; 01144 FT_UInt i = 1; 01145 FT_UInt k; 01146 01147 01148 encoding->count = 0; 01149 01150 /* Parse the Format1 ranges. */ 01151 for ( j = 0; j < count; j++, i += nleft ) 01152 { 01153 /* Read the first glyph code of the range. */ 01154 if ( FT_READ_BYTE( glyph_code ) ) 01155 goto Exit; 01156 01157 /* Read the number of codes in the range. */ 01158 if ( FT_READ_BYTE( nleft ) ) 01159 goto Exit; 01160 01161 /* Increment nleft, so we read `nleft + 1' codes/sids. */ 01162 nleft++; 01163 01164 /* compute max number of character codes */ 01165 if ( (FT_UInt)nleft > encoding->count ) 01166 encoding->count = nleft; 01167 01168 /* Fill in the range of codes/sids. */ 01169 for ( k = i; k < nleft + i; k++, glyph_code++ ) 01170 { 01171 /* Make sure k is not too big. */ 01172 if ( k < num_glyphs && glyph_code < 256 ) 01173 { 01174 /* Assign code to GID mapping. */ 01175 encoding->codes[glyph_code] = (FT_UShort)k; 01176 01177 /* Assign code to SID mapping. */ 01178 encoding->sids[glyph_code] = charset->sids[k]; 01179 } 01180 } 01181 } 01182 01183 /* simple check; one never knows what can be found in a font */ 01184 if ( encoding->count > 256 ) 01185 encoding->count = 256; 01186 } 01187 break; 01188 01189 default: 01190 FT_ERROR(( "cff_encoding_load: invalid table format\n" )); 01191 error = CFF_Err_Invalid_File_Format; 01192 goto Exit; 01193 } 01194 01195 /* Parse supplemental encodings, if any. */ 01196 if ( encoding->format & 0x80 ) 01197 { 01198 FT_UInt gindex; 01199 01200 01201 /* count supplements */ 01202 if ( FT_READ_BYTE( count ) ) 01203 goto Exit; 01204 01205 for ( j = 0; j < count; j++ ) 01206 { 01207 /* Read supplemental glyph code. */ 01208 if ( FT_READ_BYTE( glyph_code ) ) 01209 goto Exit; 01210 01211 /* Read the SID associated with this glyph code. */ 01212 if ( FT_READ_USHORT( glyph_sid ) ) 01213 goto Exit; 01214 01215 /* Assign code to SID mapping. */ 01216 encoding->sids[glyph_code] = glyph_sid; 01217 01218 /* First, look up GID which has been assigned to */ 01219 /* SID glyph_sid. */ 01220 for ( gindex = 0; gindex < num_glyphs; gindex++ ) 01221 { 01222 if ( charset->sids[gindex] == glyph_sid ) 01223 { 01224 encoding->codes[glyph_code] = (FT_UShort)gindex; 01225 break; 01226 } 01227 } 01228 } 01229 } 01230 } 01231 else 01232 { 01233 /* We take into account the fact a CFF font can use a predefined */ 01234 /* encoding without containing all of the glyphs encoded by this */ 01235 /* encoding (see the note at the end of section 12 in the CFF */ 01236 /* specification). */ 01237 01238 switch ( (FT_UInt)offset ) 01239 { 01240 case 0: 01241 /* First, copy the code to SID mapping. */ 01242 FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 ); 01243 goto Populate; 01244 01245 case 1: 01246 /* First, copy the code to SID mapping. */ 01247 FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 ); 01248 01249 Populate: 01250 /* Construct code to GID mapping from code to SID mapping */ 01251 /* and charset. */ 01252 01253 encoding->count = 0; 01254 01255 error = cff_charset_compute_cids( charset, num_glyphs, 01256 stream->memory ); 01257 if ( error ) 01258 goto Exit; 01259 01260 for ( j = 0; j < 256; j++ ) 01261 { 01262 FT_UInt sid = encoding->sids[j]; 01263 FT_UInt gid = 0; 01264 01265 01266 if ( sid ) 01267 gid = cff_charset_cid_to_gindex( charset, sid ); 01268 01269 if ( gid != 0 ) 01270 { 01271 encoding->codes[j] = (FT_UShort)gid; 01272 encoding->count = j + 1; 01273 } 01274 else 01275 { 01276 encoding->codes[j] = 0; 01277 encoding->sids [j] = 0; 01278 } 01279 } 01280 break; 01281 01282 default: 01283 FT_ERROR(( "cff_encoding_load: invalid table format\n" )); 01284 error = CFF_Err_Invalid_File_Format; 01285 goto Exit; 01286 } 01287 } 01288 01289 Exit: 01290 01291 /* Clean up if there was an error. */ 01292 return error; 01293 } 01294 01295 01296 static FT_Error 01297 cff_subfont_load( CFF_SubFont font, 01298 CFF_Index idx, 01299 FT_UInt font_index, 01300 FT_Stream stream, 01301 FT_ULong base_offset, 01302 FT_Library library ) 01303 { 01304 FT_Error error; 01305 CFF_ParserRec parser; 01306 FT_Byte* dict = NULL; 01307 FT_ULong dict_len; 01308 CFF_FontRecDict top = &font->font_dict; 01309 CFF_Private priv = &font->private_dict; 01310 01311 01312 cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library ); 01313 01314 /* set defaults */ 01315 FT_MEM_ZERO( top, sizeof ( *top ) ); 01316 01317 top->underline_position = -100L << 16; 01318 top->underline_thickness = 50L << 16; 01319 top->charstring_type = 2; 01320 top->font_matrix.xx = 0x10000L; 01321 top->font_matrix.yy = 0x10000L; 01322 top->cid_count = 8720; 01323 01324 /* we use the implementation specific SID value 0xFFFF to indicate */ 01325 /* missing entries */ 01326 top->version = 0xFFFFU; 01327 top->notice = 0xFFFFU; 01328 top->copyright = 0xFFFFU; 01329 top->full_name = 0xFFFFU; 01330 top->family_name = 0xFFFFU; 01331 top->weight = 0xFFFFU; 01332 top->embedded_postscript = 0xFFFFU; 01333 01334 top->cid_registry = 0xFFFFU; 01335 top->cid_ordering = 0xFFFFU; 01336 top->cid_font_name = 0xFFFFU; 01337 01338 error = cff_index_access_element( idx, font_index, &dict, &dict_len ); 01339 if ( !error ) 01340 error = cff_parser_run( &parser, dict, dict + dict_len ); 01341 01342 cff_index_forget_element( idx, &dict ); 01343 01344 if ( error ) 01345 goto Exit; 01346 01347 /* if it is a CID font, we stop there */ 01348 if ( top->cid_registry != 0xFFFFU ) 01349 goto Exit; 01350 01351 /* parse the private dictionary, if any */ 01352 if ( top->private_offset && top->private_size ) 01353 { 01354 /* set defaults */ 01355 FT_MEM_ZERO( priv, sizeof ( *priv ) ); 01356 01357 priv->blue_shift = 7; 01358 priv->blue_fuzz = 1; 01359 priv->lenIV = -1; 01360 priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); 01361 priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); 01362 01363 cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library ); 01364 01365 if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) || 01366 FT_FRAME_ENTER( font->font_dict.private_size ) ) 01367 goto Exit; 01368 01369 error = cff_parser_run( &parser, 01370 (FT_Byte*)stream->cursor, 01371 (FT_Byte*)stream->limit ); 01372 FT_FRAME_EXIT(); 01373 if ( error ) 01374 goto Exit; 01375 01376 /* ensure that `num_blue_values' is even */ 01377 priv->num_blue_values &= ~1; 01378 } 01379 01380 /* read the local subrs, if any */ 01381 if ( priv->local_subrs_offset ) 01382 { 01383 if ( FT_STREAM_SEEK( base_offset + top->private_offset + 01384 priv->local_subrs_offset ) ) 01385 goto Exit; 01386 01387 error = cff_index_init( &font->local_subrs_index, stream, 1 ); 01388 if ( error ) 01389 goto Exit; 01390 01391 error = cff_index_get_pointers( &font->local_subrs_index, 01392 &font->local_subrs, NULL ); 01393 if ( error ) 01394 goto Exit; 01395 } 01396 01397 Exit: 01398 return error; 01399 } 01400 01401 01402 static void 01403 cff_subfont_done( FT_Memory memory, 01404 CFF_SubFont subfont ) 01405 { 01406 if ( subfont ) 01407 { 01408 cff_index_done( &subfont->local_subrs_index ); 01409 FT_FREE( subfont->local_subrs ); 01410 } 01411 } 01412 01413 01414 FT_LOCAL_DEF( FT_Error ) 01415 cff_font_load( FT_Library library, 01416 FT_Stream stream, 01417 FT_Int face_index, 01418 CFF_Font font, 01419 FT_Bool pure_cff ) 01420 { 01421 static const FT_Frame_Field cff_header_fields[] = 01422 { 01423 #undef FT_STRUCTURE 01424 #define FT_STRUCTURE CFF_FontRec 01425 01426 FT_FRAME_START( 4 ), 01427 FT_FRAME_BYTE( version_major ), 01428 FT_FRAME_BYTE( version_minor ), 01429 FT_FRAME_BYTE( header_size ), 01430 FT_FRAME_BYTE( absolute_offsize ), 01431 FT_FRAME_END 01432 }; 01433 01434 FT_Error error; 01435 FT_Memory memory = stream->memory; 01436 FT_ULong base_offset; 01437 CFF_FontRecDict dict; 01438 CFF_IndexRec string_index; 01439 01440 01441 FT_ZERO( font ); 01442 FT_ZERO( &string_index ); 01443 01444 font->stream = stream; 01445 font->memory = memory; 01446 dict = &font->top_font.font_dict; 01447 base_offset = FT_STREAM_POS(); 01448 01449 /* read CFF font header */ 01450 if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) ) 01451 goto Exit; 01452 01453 /* check format */ 01454 if ( font->version_major != 1 || 01455 font->header_size < 4 || 01456 font->absolute_offsize > 4 ) 01457 { 01458 FT_TRACE2(( "[not a CFF font header]\n" )); 01459 error = CFF_Err_Unknown_File_Format; 01460 goto Exit; 01461 } 01462 01463 /* skip the rest of the header */ 01464 if ( FT_STREAM_SKIP( font->header_size - 4 ) ) 01465 goto Exit; 01466 01467 /* read the name, top dict, string and global subrs index */ 01468 if ( FT_SET_ERROR( cff_index_init( &font->name_index, 01469 stream, 0 ) ) || 01470 FT_SET_ERROR( cff_index_init( &font->font_dict_index, 01471 stream, 0 ) ) || 01472 FT_SET_ERROR( cff_index_init( &string_index, 01473 stream, 1 ) ) || 01474 FT_SET_ERROR( cff_index_init( &font->global_subrs_index, 01475 stream, 1 ) ) || 01476 FT_SET_ERROR( cff_index_get_pointers( &string_index, 01477 &font->strings, 01478 &font->string_pool ) ) ) 01479 goto Exit; 01480 01481 font->num_strings = string_index.count; 01482 01483 /* well, we don't really forget the `disabled' fonts... */ 01484 font->num_faces = font->name_index.count; 01485 if ( face_index >= (FT_Int)font->num_faces ) 01486 { 01487 FT_ERROR(( "cff_font_load: incorrect face index = %d\n", 01488 face_index )); 01489 error = CFF_Err_Invalid_Argument; 01490 } 01491 01492 /* in case of a font format check, simply exit now */ 01493 if ( face_index < 0 ) 01494 goto Exit; 01495 01496 /* now, parse the top-level font dictionary */ 01497 error = cff_subfont_load( &font->top_font, 01498 &font->font_dict_index, 01499 face_index, 01500 stream, 01501 base_offset, 01502 library ); 01503 if ( error ) 01504 goto Exit; 01505 01506 if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) ) 01507 goto Exit; 01508 01509 error = cff_index_init( &font->charstrings_index, stream, 0 ); 01510 if ( error ) 01511 goto Exit; 01512 01513 /* now, check for a CID font */ 01514 if ( dict->cid_registry != 0xFFFFU ) 01515 { 01516 CFF_IndexRec fd_index; 01517 CFF_SubFont sub; 01518 FT_UInt idx; 01519 01520 01521 /* this is a CID-keyed font, we must now allocate a table of */ 01522 /* sub-fonts, then load each of them separately */ 01523 if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) ) 01524 goto Exit; 01525 01526 error = cff_index_init( &fd_index, stream, 0 ); 01527 if ( error ) 01528 goto Exit; 01529 01530 if ( fd_index.count > CFF_MAX_CID_FONTS ) 01531 { 01532 FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" )); 01533 goto Fail_CID; 01534 } 01535 01536 /* allocate & read each font dict independently */ 01537 font->num_subfonts = fd_index.count; 01538 if ( FT_NEW_ARRAY( sub, fd_index.count ) ) 01539 goto Fail_CID; 01540 01541 /* set up pointer table */ 01542 for ( idx = 0; idx < fd_index.count; idx++ ) 01543 font->subfonts[idx] = sub + idx; 01544 01545 /* now load each subfont independently */ 01546 for ( idx = 0; idx < fd_index.count; idx++ ) 01547 { 01548 sub = font->subfonts[idx]; 01549 error = cff_subfont_load( sub, &fd_index, idx, 01550 stream, base_offset, library ); 01551 if ( error ) 01552 goto Fail_CID; 01553 } 01554 01555 /* now load the FD Select array */ 01556 error = CFF_Load_FD_Select( &font->fd_select, 01557 font->charstrings_index.count, 01558 stream, 01559 base_offset + dict->cid_fd_select_offset ); 01560 01561 Fail_CID: 01562 cff_index_done( &fd_index ); 01563 01564 if ( error ) 01565 goto Exit; 01566 } 01567 else 01568 font->num_subfonts = 0; 01569 01570 /* read the charstrings index now */ 01571 if ( dict->charstrings_offset == 0 ) 01572 { 01573 FT_ERROR(( "cff_font_load: no charstrings offset\n" )); 01574 error = CFF_Err_Unknown_File_Format; 01575 goto Exit; 01576 } 01577 01578 font->num_glyphs = font->charstrings_index.count; 01579 01580 error = cff_index_get_pointers( &font->global_subrs_index, 01581 &font->global_subrs, NULL ); 01582 01583 if ( error ) 01584 goto Exit; 01585 01586 /* read the Charset and Encoding tables if available */ 01587 if ( font->num_glyphs > 0 ) 01588 { 01589 FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff ); 01590 01591 01592 error = cff_charset_load( &font->charset, font->num_glyphs, stream, 01593 base_offset, dict->charset_offset, invert ); 01594 if ( error ) 01595 goto Exit; 01596 01597 /* CID-keyed CFFs don't have an encoding */ 01598 if ( dict->cid_registry == 0xFFFFU ) 01599 { 01600 error = cff_encoding_load( &font->encoding, 01601 &font->charset, 01602 font->num_glyphs, 01603 stream, 01604 base_offset, 01605 dict->encoding_offset ); 01606 if ( error ) 01607 goto Exit; 01608 } 01609 } 01610 01611 /* get the font name (/CIDFontName for CID-keyed fonts, */ 01612 /* /FontName otherwise) */ 01613 font->font_name = cff_index_get_name( font, face_index ); 01614 01615 Exit: 01616 cff_index_done( &string_index ); 01617 01618 return error; 01619 } 01620 01621 01622 FT_LOCAL_DEF( void ) 01623 cff_font_done( CFF_Font font ) 01624 { 01625 FT_Memory memory = font->memory; 01626 FT_UInt idx; 01627 01628 01629 cff_index_done( &font->global_subrs_index ); 01630 cff_index_done( &font->font_dict_index ); 01631 cff_index_done( &font->name_index ); 01632 cff_index_done( &font->charstrings_index ); 01633 01634 /* release font dictionaries, but only if working with */ 01635 /* a CID keyed CFF font */ 01636 if ( font->num_subfonts > 0 ) 01637 { 01638 for ( idx = 0; idx < font->num_subfonts; idx++ ) 01639 cff_subfont_done( memory, font->subfonts[idx] ); 01640 01641 /* the subfonts array has been allocated as a single block */ 01642 FT_FREE( font->subfonts[0] ); 01643 } 01644 01645 cff_encoding_done( &font->encoding ); 01646 cff_charset_done( &font->charset, font->stream ); 01647 01648 cff_subfont_done( memory, &font->top_font ); 01649 01650 CFF_Done_FD_Select( &font->fd_select, font->stream ); 01651 01652 FT_FREE( font->font_info ); 01653 01654 FT_FREE( font->font_name ); 01655 FT_FREE( font->global_subrs ); 01656 FT_FREE( font->strings ); 01657 FT_FREE( font->string_pool ); 01658 } 01659 01660 01661 /* END */ Generated on Sat May 26 2012 04:32:40 for ReactOS by
1.7.6.1
|