Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencidload.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* cidload.c */ 00004 /* */ 00005 /* CID-keyed Type1 font loader (body). */ 00006 /* */ 00007 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2009 by */ 00008 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00009 /* */ 00010 /* This file is part of the FreeType project, and may only be used, */ 00011 /* modified, and distributed under the terms of the FreeType project */ 00012 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00013 /* this file you indicate that you have read the license and */ 00014 /* understand and accept it fully. */ 00015 /* */ 00016 /***************************************************************************/ 00017 00018 00019 #include <ft2build.h> 00020 #include FT_INTERNAL_DEBUG_H 00021 #include FT_CONFIG_CONFIG_H 00022 #include FT_MULTIPLE_MASTERS_H 00023 #include FT_INTERNAL_TYPE1_TYPES_H 00024 00025 #include "cidload.h" 00026 00027 #include "ciderrs.h" 00028 00029 00030 /*************************************************************************/ 00031 /* */ 00032 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00033 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00034 /* messages during execution. */ 00035 /* */ 00036 #undef FT_COMPONENT 00037 #define FT_COMPONENT trace_cidload 00038 00039 00040 /* read a single offset */ 00041 FT_LOCAL_DEF( FT_Long ) 00042 cid_get_offset( FT_Byte* *start, 00043 FT_Byte offsize ) 00044 { 00045 FT_Long result; 00046 FT_Byte* p = *start; 00047 00048 00049 for ( result = 0; offsize > 0; offsize-- ) 00050 { 00051 result <<= 8; 00052 result |= *p++; 00053 } 00054 00055 *start = p; 00056 return result; 00057 } 00058 00059 00060 /*************************************************************************/ 00061 /*************************************************************************/ 00062 /***** *****/ 00063 /***** TYPE 1 SYMBOL PARSING *****/ 00064 /***** *****/ 00065 /*************************************************************************/ 00066 /*************************************************************************/ 00067 00068 00069 static FT_Error 00070 cid_load_keyword( CID_Face face, 00071 CID_Loader* loader, 00072 const T1_Field keyword ) 00073 { 00074 FT_Error error; 00075 CID_Parser* parser = &loader->parser; 00076 FT_Byte* object; 00077 void* dummy_object; 00078 CID_FaceInfo cid = &face->cid; 00079 00080 00081 /* if the keyword has a dedicated callback, call it */ 00082 if ( keyword->type == T1_FIELD_TYPE_CALLBACK ) 00083 { 00084 keyword->reader( (FT_Face)face, parser ); 00085 error = parser->root.error; 00086 goto Exit; 00087 } 00088 00089 /* we must now compute the address of our target object */ 00090 switch ( keyword->location ) 00091 { 00092 case T1_FIELD_LOCATION_CID_INFO: 00093 object = (FT_Byte*)cid; 00094 break; 00095 00096 case T1_FIELD_LOCATION_FONT_INFO: 00097 object = (FT_Byte*)&cid->font_info; 00098 break; 00099 00100 case T1_FIELD_LOCATION_FONT_EXTRA: 00101 object = (FT_Byte*)&face->font_extra; 00102 break; 00103 00104 case T1_FIELD_LOCATION_BBOX: 00105 object = (FT_Byte*)&cid->font_bbox; 00106 break; 00107 00108 default: 00109 { 00110 CID_FaceDict dict; 00111 00112 00113 if ( parser->num_dict < 0 ) 00114 { 00115 FT_ERROR(( "cid_load_keyword: invalid use of `%s'\n", 00116 keyword->ident )); 00117 error = CID_Err_Syntax_Error; 00118 goto Exit; 00119 } 00120 00121 dict = cid->font_dicts + parser->num_dict; 00122 switch ( keyword->location ) 00123 { 00124 case T1_FIELD_LOCATION_PRIVATE: 00125 object = (FT_Byte*)&dict->private_dict; 00126 break; 00127 00128 default: 00129 object = (FT_Byte*)dict; 00130 } 00131 } 00132 } 00133 00134 dummy_object = object; 00135 00136 /* now, load the keyword data in the object's field(s) */ 00137 if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY || 00138 keyword->type == T1_FIELD_TYPE_FIXED_ARRAY ) 00139 error = cid_parser_load_field_table( &loader->parser, keyword, 00140 &dummy_object ); 00141 else 00142 error = cid_parser_load_field( &loader->parser, 00143 keyword, &dummy_object ); 00144 Exit: 00145 return error; 00146 } 00147 00148 00149 FT_CALLBACK_DEF( FT_Error ) 00150 parse_font_matrix( CID_Face face, 00151 CID_Parser* parser ) 00152 { 00153 FT_Matrix* matrix; 00154 FT_Vector* offset; 00155 CID_FaceDict dict; 00156 FT_Face root = (FT_Face)&face->root; 00157 FT_Fixed temp[6]; 00158 FT_Fixed temp_scale; 00159 00160 00161 if ( parser->num_dict >= 0 ) 00162 { 00163 dict = face->cid.font_dicts + parser->num_dict; 00164 matrix = &dict->font_matrix; 00165 offset = &dict->font_offset; 00166 00167 (void)cid_parser_to_fixed_array( parser, 6, temp, 3 ); 00168 00169 temp_scale = FT_ABS( temp[3] ); 00170 00171 /* Set units per EM based on FontMatrix values. We set the value to */ 00172 /* `1000/temp_scale', because temp_scale was already multiplied by */ 00173 /* 1000 (in `t1_tofixed', from psobjs.c). */ 00174 root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L, 00175 FT_DivFix( temp_scale, 1000 ) ) ); 00176 00177 /* we need to scale the values by 1.0/temp[3] */ 00178 if ( temp_scale != 0x10000L ) 00179 { 00180 temp[0] = FT_DivFix( temp[0], temp_scale ); 00181 temp[1] = FT_DivFix( temp[1], temp_scale ); 00182 temp[2] = FT_DivFix( temp[2], temp_scale ); 00183 temp[4] = FT_DivFix( temp[4], temp_scale ); 00184 temp[5] = FT_DivFix( temp[5], temp_scale ); 00185 temp[3] = 0x10000L; 00186 } 00187 00188 matrix->xx = temp[0]; 00189 matrix->yx = temp[1]; 00190 matrix->xy = temp[2]; 00191 matrix->yy = temp[3]; 00192 00193 /* note that the font offsets are expressed in integer font units */ 00194 offset->x = temp[4] >> 16; 00195 offset->y = temp[5] >> 16; 00196 } 00197 00198 return CID_Err_Ok; /* this is a callback function; */ 00199 /* we must return an error code */ 00200 } 00201 00202 00203 FT_CALLBACK_DEF( FT_Error ) 00204 parse_fd_array( CID_Face face, 00205 CID_Parser* parser ) 00206 { 00207 CID_FaceInfo cid = &face->cid; 00208 FT_Memory memory = face->root.memory; 00209 FT_Error error = CID_Err_Ok; 00210 FT_Long num_dicts; 00211 00212 00213 num_dicts = cid_parser_to_int( parser ); 00214 00215 if ( !cid->font_dicts ) 00216 { 00217 FT_Int n; 00218 00219 00220 if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) ) 00221 goto Exit; 00222 00223 cid->num_dicts = (FT_UInt)num_dicts; 00224 00225 /* don't forget to set a few defaults */ 00226 for ( n = 0; n < cid->num_dicts; n++ ) 00227 { 00228 CID_FaceDict dict = cid->font_dicts + n; 00229 00230 00231 /* default value for lenIV */ 00232 dict->private_dict.lenIV = 4; 00233 } 00234 } 00235 00236 Exit: 00237 return error; 00238 } 00239 00240 00241 /* by mistake, `expansion_factor' appears both in PS_PrivateRec */ 00242 /* and CID_FaceDictRec (both are public header files and can't */ 00243 /* changed); we simply copy the value */ 00244 00245 FT_CALLBACK_DEF( FT_Error ) 00246 parse_expansion_factor( CID_Face face, 00247 CID_Parser* parser ) 00248 { 00249 CID_FaceDict dict; 00250 00251 00252 if ( parser->num_dict >= 0 ) 00253 { 00254 dict = face->cid.font_dicts + parser->num_dict; 00255 00256 dict->expansion_factor = cid_parser_to_fixed( parser, 0 ); 00257 dict->private_dict.expansion_factor = dict->expansion_factor; 00258 } 00259 00260 return CID_Err_Ok; 00261 } 00262 00263 00264 static 00265 const T1_FieldRec cid_field_records[] = 00266 { 00267 00268 #include "cidtoken.h" 00269 00270 T1_FIELD_CALLBACK( "FDArray", parse_fd_array, 0 ) 00271 T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix, 0 ) 00272 T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 ) 00273 00274 { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 } 00275 }; 00276 00277 00278 static FT_Error 00279 cid_parse_dict( CID_Face face, 00280 CID_Loader* loader, 00281 FT_Byte* base, 00282 FT_Long size ) 00283 { 00284 CID_Parser* parser = &loader->parser; 00285 00286 00287 parser->root.cursor = base; 00288 parser->root.limit = base + size; 00289 parser->root.error = CID_Err_Ok; 00290 00291 { 00292 FT_Byte* cur = base; 00293 FT_Byte* limit = cur + size; 00294 00295 00296 for (;;) 00297 { 00298 FT_Byte* newlimit; 00299 00300 00301 parser->root.cursor = cur; 00302 cid_parser_skip_spaces( parser ); 00303 00304 if ( parser->root.cursor >= limit ) 00305 newlimit = limit - 1 - 17; 00306 else 00307 newlimit = parser->root.cursor - 17; 00308 00309 /* look for `%ADOBeginFontDict' */ 00310 for ( ; cur < newlimit; cur++ ) 00311 { 00312 if ( *cur == '%' && 00313 ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 ) 00314 { 00315 /* if /FDArray was found, then cid->num_dicts is > 0, and */ 00316 /* we can start increasing parser->num_dict */ 00317 if ( face->cid.num_dicts > 0 ) 00318 parser->num_dict++; 00319 } 00320 } 00321 00322 cur = parser->root.cursor; 00323 /* no error can occur in cid_parser_skip_spaces */ 00324 if ( cur >= limit ) 00325 break; 00326 00327 cid_parser_skip_PS_token( parser ); 00328 if ( parser->root.cursor >= limit || parser->root.error ) 00329 break; 00330 00331 /* look for immediates */ 00332 if ( *cur == '/' && cur + 2 < limit ) 00333 { 00334 FT_PtrDist len; 00335 00336 00337 cur++; 00338 len = parser->root.cursor - cur; 00339 00340 if ( len > 0 && len < 22 ) 00341 { 00342 /* now compare the immediate name to the keyword table */ 00343 T1_Field keyword = (T1_Field)cid_field_records; 00344 00345 00346 for (;;) 00347 { 00348 FT_Byte* name; 00349 00350 00351 name = (FT_Byte*)keyword->ident; 00352 if ( !name ) 00353 break; 00354 00355 if ( cur[0] == name[0] && 00356 len == (FT_PtrDist)ft_strlen( (const char*)name ) ) 00357 { 00358 FT_PtrDist n; 00359 00360 00361 for ( n = 1; n < len; n++ ) 00362 if ( cur[n] != name[n] ) 00363 break; 00364 00365 if ( n >= len ) 00366 { 00367 /* we found it - run the parsing callback */ 00368 parser->root.error = cid_load_keyword( face, 00369 loader, 00370 keyword ); 00371 if ( parser->root.error ) 00372 return parser->root.error; 00373 break; 00374 } 00375 } 00376 keyword++; 00377 } 00378 } 00379 } 00380 00381 cur = parser->root.cursor; 00382 } 00383 } 00384 return parser->root.error; 00385 } 00386 00387 00388 /* read the subrmap and the subrs of each font dict */ 00389 static FT_Error 00390 cid_read_subrs( CID_Face face ) 00391 { 00392 CID_FaceInfo cid = &face->cid; 00393 FT_Memory memory = face->root.memory; 00394 FT_Stream stream = face->cid_stream; 00395 FT_Error error; 00396 FT_Int n; 00397 CID_Subrs subr; 00398 FT_UInt max_offsets = 0; 00399 FT_ULong* offsets = 0; 00400 PSAux_Service psaux = (PSAux_Service)face->psaux; 00401 00402 00403 if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) ) 00404 goto Exit; 00405 00406 subr = face->subrs; 00407 for ( n = 0; n < cid->num_dicts; n++, subr++ ) 00408 { 00409 CID_FaceDict dict = cid->font_dicts + n; 00410 FT_Int lenIV = dict->private_dict.lenIV; 00411 FT_UInt count, num_subrs = dict->num_subrs; 00412 FT_ULong data_len; 00413 FT_Byte* p; 00414 00415 00416 /* reallocate offsets array if needed */ 00417 if ( num_subrs + 1 > max_offsets ) 00418 { 00419 FT_UInt new_max = FT_PAD_CEIL( num_subrs + 1, 4 ); 00420 00421 00422 if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) ) 00423 goto Fail; 00424 00425 max_offsets = new_max; 00426 } 00427 00428 /* read the subrmap's offsets */ 00429 if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) || 00430 FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes ) ) 00431 goto Fail; 00432 00433 p = (FT_Byte*)stream->cursor; 00434 for ( count = 0; count <= num_subrs; count++ ) 00435 offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes ); 00436 00437 FT_FRAME_EXIT(); 00438 00439 /* now, compute the size of subrs charstrings, */ 00440 /* allocate, and read them */ 00441 data_len = offsets[num_subrs] - offsets[0]; 00442 00443 if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) || 00444 FT_ALLOC( subr->code[0], data_len ) ) 00445 goto Fail; 00446 00447 if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) || 00448 FT_STREAM_READ( subr->code[0], data_len ) ) 00449 goto Fail; 00450 00451 /* set up pointers */ 00452 for ( count = 1; count <= num_subrs; count++ ) 00453 { 00454 FT_ULong len; 00455 00456 00457 len = offsets[count] - offsets[count - 1]; 00458 subr->code[count] = subr->code[count - 1] + len; 00459 } 00460 00461 /* decrypt subroutines, but only if lenIV >= 0 */ 00462 if ( lenIV >= 0 ) 00463 { 00464 for ( count = 0; count < num_subrs; count++ ) 00465 { 00466 FT_ULong len; 00467 00468 00469 len = offsets[count + 1] - offsets[count]; 00470 psaux->t1_decrypt( subr->code[count], len, 4330 ); 00471 } 00472 } 00473 00474 subr->num_subrs = num_subrs; 00475 } 00476 00477 Exit: 00478 FT_FREE( offsets ); 00479 return error; 00480 00481 Fail: 00482 if ( face->subrs ) 00483 { 00484 for ( n = 0; n < cid->num_dicts; n++ ) 00485 { 00486 if ( face->subrs[n].code ) 00487 FT_FREE( face->subrs[n].code[0] ); 00488 00489 FT_FREE( face->subrs[n].code ); 00490 } 00491 FT_FREE( face->subrs ); 00492 } 00493 goto Exit; 00494 } 00495 00496 00497 static void 00498 t1_init_loader( CID_Loader* loader, 00499 CID_Face face ) 00500 { 00501 FT_UNUSED( face ); 00502 00503 FT_MEM_ZERO( loader, sizeof ( *loader ) ); 00504 } 00505 00506 00507 static void 00508 t1_done_loader( CID_Loader* loader ) 00509 { 00510 CID_Parser* parser = &loader->parser; 00511 00512 00513 /* finalize parser */ 00514 cid_parser_done( parser ); 00515 } 00516 00517 00518 static FT_Error 00519 cid_hex_to_binary( FT_Byte* data, 00520 FT_Long data_len, 00521 FT_ULong offset, 00522 CID_Face face ) 00523 { 00524 FT_Stream stream = face->root.stream; 00525 FT_Error error; 00526 00527 FT_Byte buffer[256]; 00528 FT_Byte *p, *plimit; 00529 FT_Byte *d, *dlimit; 00530 FT_Byte val; 00531 00532 FT_Bool upper_nibble, done; 00533 00534 00535 if ( FT_STREAM_SEEK( offset ) ) 00536 goto Exit; 00537 00538 d = data; 00539 dlimit = d + data_len; 00540 p = buffer; 00541 plimit = p; 00542 00543 upper_nibble = 1; 00544 done = 0; 00545 00546 while ( d < dlimit ) 00547 { 00548 if ( p >= plimit ) 00549 { 00550 FT_ULong oldpos = FT_STREAM_POS(); 00551 FT_ULong size = stream->size - oldpos; 00552 00553 00554 if ( size == 0 ) 00555 { 00556 error = CID_Err_Syntax_Error; 00557 goto Exit; 00558 } 00559 00560 if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) ) 00561 goto Exit; 00562 p = buffer; 00563 plimit = p + FT_STREAM_POS() - oldpos; 00564 } 00565 00566 if ( ft_isdigit( *p ) ) 00567 val = (FT_Byte)( *p - '0' ); 00568 else if ( *p >= 'a' && *p <= 'f' ) 00569 val = (FT_Byte)( *p - 'a' ); 00570 else if ( *p >= 'A' && *p <= 'F' ) 00571 val = (FT_Byte)( *p - 'A' + 10 ); 00572 else if ( *p == ' ' || 00573 *p == '\t' || 00574 *p == '\r' || 00575 *p == '\n' || 00576 *p == '\f' || 00577 *p == '\0' ) 00578 { 00579 p++; 00580 continue; 00581 } 00582 else if ( *p == '>' ) 00583 { 00584 val = 0; 00585 done = 1; 00586 } 00587 else 00588 { 00589 error = CID_Err_Syntax_Error; 00590 goto Exit; 00591 } 00592 00593 if ( upper_nibble ) 00594 *d = (FT_Byte)( val << 4 ); 00595 else 00596 { 00597 *d = (FT_Byte)( *d + val ); 00598 d++; 00599 } 00600 00601 upper_nibble = (FT_Byte)( 1 - upper_nibble ); 00602 00603 if ( done ) 00604 break; 00605 00606 p++; 00607 } 00608 00609 error = CID_Err_Ok; 00610 00611 Exit: 00612 return error; 00613 } 00614 00615 00616 FT_LOCAL_DEF( FT_Error ) 00617 cid_face_open( CID_Face face, 00618 FT_Int face_index ) 00619 { 00620 CID_Loader loader; 00621 CID_Parser* parser; 00622 FT_Memory memory = face->root.memory; 00623 FT_Error error; 00624 00625 00626 t1_init_loader( &loader, face ); 00627 00628 parser = &loader.parser; 00629 error = cid_parser_new( parser, face->root.stream, face->root.memory, 00630 (PSAux_Service)face->psaux ); 00631 if ( error ) 00632 goto Exit; 00633 00634 error = cid_parse_dict( face, &loader, 00635 parser->postscript, 00636 parser->postscript_len ); 00637 if ( error ) 00638 goto Exit; 00639 00640 if ( face_index < 0 ) 00641 goto Exit; 00642 00643 if ( FT_NEW( face->cid_stream ) ) 00644 goto Exit; 00645 00646 if ( parser->binary_length ) 00647 { 00648 /* we must convert the data section from hexadecimal to binary */ 00649 if ( FT_ALLOC( face->binary_data, parser->binary_length ) || 00650 cid_hex_to_binary( face->binary_data, parser->binary_length, 00651 parser->data_offset, face ) ) 00652 goto Exit; 00653 00654 FT_Stream_OpenMemory( face->cid_stream, 00655 face->binary_data, parser->binary_length ); 00656 face->cid.data_offset = 0; 00657 } 00658 else 00659 { 00660 *face->cid_stream = *face->root.stream; 00661 face->cid.data_offset = loader.parser.data_offset; 00662 } 00663 00664 error = cid_read_subrs( face ); 00665 00666 Exit: 00667 t1_done_loader( &loader ); 00668 return error; 00669 } 00670 00671 00672 /* END */ Generated on Sat May 26 2012 04:32:41 for ReactOS by
1.7.6.1
|