00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00033
00034
00035
00036 #undef FT_COMPONENT
00037 #define FT_COMPONENT trace_cidload
00038
00039
00040
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
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
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
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
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
00172
00173
00174 root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L,
00175 FT_DivFix( temp_scale, 1000 ) ) );
00176
00177
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
00194 offset->x = temp[4] >> 16;
00195 offset->y = temp[5] >> 16;
00196 }
00197
00198 return CID_Err_Ok;
00199
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
00226 for ( n = 0; n < cid->num_dicts; n++ )
00227 {
00228 CID_FaceDict dict = cid->font_dicts + n;
00229
00230
00231
00232 dict->private_dict.lenIV = 4;
00233 }
00234 }
00235
00236 Exit:
00237 return error;
00238 }
00239
00240
00241
00242
00243
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
00310 for ( ; cur < newlimit; cur++ )
00311 {
00312 if ( *cur == '%' &&
00313 ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
00314 {
00315
00316
00317 if ( face->cid.num_dicts > 0 )
00318 parser->num_dict++;
00319 }
00320 }
00321
00322 cur = parser->root.cursor;
00323
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
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
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
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
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
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
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
00440
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
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
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
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
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