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_POSTSCRIPT_AUX_H
00021 #include FT_INTERNAL_DEBUG_H
00022 #include FT_INTERNAL_CALC_H
00023
00024 #include "psobjs.h"
00025 #include "psconv.h"
00026
00027 #include "psauxerr.h"
00028
00029
00030
00031
00032
00033
00034
00035
00036 #undef FT_COMPONENT
00037 #define FT_COMPONENT trace_psobjs
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 FT_LOCAL_DEF( FT_Error )
00069 ps_table_new( PS_Table table,
00070 FT_Int count,
00071 FT_Memory memory )
00072 {
00073 FT_Error error;
00074
00075
00076 table->memory = memory;
00077 if ( FT_NEW_ARRAY( table->elements, count ) ||
00078 FT_NEW_ARRAY( table->lengths, count ) )
00079 goto Exit;
00080
00081 table->max_elems = count;
00082 table->init = 0xDEADBEEFUL;
00083 table->num_elems = 0;
00084 table->block = 0;
00085 table->capacity = 0;
00086 table->cursor = 0;
00087
00088 *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
00089
00090 Exit:
00091 if ( error )
00092 FT_FREE( table->elements );
00093
00094 return error;
00095 }
00096
00097
00098 static void
00099 shift_elements( PS_Table table,
00100 FT_Byte* old_base )
00101 {
00102 FT_PtrDist delta = table->block - old_base;
00103 FT_Byte** offset = table->elements;
00104 FT_Byte** limit = offset + table->max_elems;
00105
00106
00107 for ( ; offset < limit; offset++ )
00108 {
00109 if ( offset[0] )
00110 offset[0] += delta;
00111 }
00112 }
00113
00114
00115 static FT_Error
00116 reallocate_t1_table( PS_Table table,
00117 FT_Long new_size )
00118 {
00119 FT_Memory memory = table->memory;
00120 FT_Byte* old_base = table->block;
00121 FT_Error error;
00122
00123
00124
00125 if ( FT_ALLOC( table->block, new_size ) )
00126 {
00127 table->block = old_base;
00128 return error;
00129 }
00130
00131
00132 if ( old_base )
00133 {
00134 FT_MEM_COPY( table->block, old_base, table->capacity );
00135 shift_elements( table, old_base );
00136 FT_FREE( old_base );
00137 }
00138
00139 table->capacity = new_size;
00140
00141 return PSaux_Err_Ok;
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 FT_LOCAL_DEF( FT_Error )
00168 ps_table_add( PS_Table table,
00169 FT_Int idx,
00170 void* object,
00171 FT_PtrDist length )
00172 {
00173 if ( idx < 0 || idx >= table->max_elems )
00174 {
00175 FT_ERROR(( "ps_table_add: invalid index\n" ));
00176 return PSaux_Err_Invalid_Argument;
00177 }
00178
00179 if ( length < 0 )
00180 {
00181 FT_ERROR(( "ps_table_add: invalid length\n" ));
00182 return PSaux_Err_Invalid_Argument;
00183 }
00184
00185
00186 if ( table->cursor + length > table->capacity )
00187 {
00188 FT_Error error;
00189 FT_Offset new_size = table->capacity;
00190 FT_Long in_offset;
00191
00192
00193 in_offset = (FT_Long)((FT_Byte*)object - table->block);
00194 if ( (FT_ULong)in_offset >= table->capacity )
00195 in_offset = -1;
00196
00197 while ( new_size < table->cursor + length )
00198 {
00199
00200
00201 new_size += ( new_size >> 2 ) + 1;
00202 new_size = FT_PAD_CEIL( new_size, 1024 );
00203 }
00204
00205 error = reallocate_t1_table( table, new_size );
00206 if ( error )
00207 return error;
00208
00209 if ( in_offset >= 0 )
00210 object = table->block + in_offset;
00211 }
00212
00213
00214 table->elements[idx] = table->block + table->cursor;
00215 table->lengths [idx] = length;
00216 FT_MEM_COPY( table->block + table->cursor, object, length );
00217
00218 table->cursor += length;
00219 return PSaux_Err_Ok;
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 FT_LOCAL_DEF( void )
00240 ps_table_done( PS_Table table )
00241 {
00242 FT_Memory memory = table->memory;
00243 FT_Error error;
00244 FT_Byte* old_base = table->block;
00245
00246
00247
00248 if ( !old_base )
00249 return;
00250
00251 if ( FT_ALLOC( table->block, table->cursor ) )
00252 return;
00253 FT_MEM_COPY( table->block, old_base, table->cursor );
00254 shift_elements( table, old_base );
00255
00256 table->capacity = table->cursor;
00257 FT_FREE( old_base );
00258
00259 FT_UNUSED( error );
00260 }
00261
00262
00263 FT_LOCAL_DEF( void )
00264 ps_table_release( PS_Table table )
00265 {
00266 FT_Memory memory = table->memory;
00267
00268
00269 if ( (FT_ULong)table->init == 0xDEADBEEFUL )
00270 {
00271 FT_FREE( table->block );
00272 FT_FREE( table->elements );
00273 FT_FREE( table->lengths );
00274 table->init = 0;
00275 }
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 static void
00291 skip_comment( FT_Byte* *acur,
00292 FT_Byte* limit )
00293 {
00294 FT_Byte* cur = *acur;
00295
00296
00297 while ( cur < limit )
00298 {
00299 if ( IS_PS_NEWLINE( *cur ) )
00300 break;
00301 cur++;
00302 }
00303
00304 *acur = cur;
00305 }
00306
00307
00308 static void
00309 skip_spaces( FT_Byte* *acur,
00310 FT_Byte* limit )
00311 {
00312 FT_Byte* cur = *acur;
00313
00314
00315 while ( cur < limit )
00316 {
00317 if ( !IS_PS_SPACE( *cur ) )
00318 {
00319 if ( *cur == '%' )
00320
00321 skip_comment( &cur, limit );
00322 else
00323 break;
00324 }
00325 cur++;
00326 }
00327
00328 *acur = cur;
00329 }
00330
00331
00332 #define IS_OCTAL_DIGIT( c ) ( '0' <= (c) && (c) <= '7' )
00333
00334
00335
00336
00337
00338 static FT_Error
00339 skip_literal_string( FT_Byte* *acur,
00340 FT_Byte* limit )
00341 {
00342 FT_Byte* cur = *acur;
00343 FT_Int embed = 0;
00344 FT_Error error = PSaux_Err_Invalid_File_Format;
00345 unsigned int i;
00346
00347
00348 while ( cur < limit )
00349 {
00350 FT_Byte c = *cur;
00351
00352
00353 ++cur;
00354
00355 if ( c == '\\' )
00356 {
00357
00358
00359
00360
00361
00362
00363
00364 if ( cur == limit )
00365
00366 break;
00367
00368 switch ( *cur )
00369 {
00370
00371 case 'n':
00372 case 'r':
00373 case 't':
00374 case 'b':
00375 case 'f':
00376 case '\\':
00377 case '(':
00378 case ')':
00379 ++cur;
00380 break;
00381
00382 default:
00383
00384 for ( i = 0; i < 3 && cur < limit; ++i )
00385 {
00386 if ( !IS_OCTAL_DIGIT( *cur ) )
00387 break;
00388
00389 ++cur;
00390 }
00391 }
00392 }
00393 else if ( c == '(' )
00394 embed++;
00395 else if ( c == ')' )
00396 {
00397 embed--;
00398 if ( embed == 0 )
00399 {
00400 error = PSaux_Err_Ok;
00401 break;
00402 }
00403 }
00404 }
00405
00406 *acur = cur;
00407
00408 return error;
00409 }
00410
00411
00412
00413
00414 static FT_Error
00415 skip_string( FT_Byte* *acur,
00416 FT_Byte* limit )
00417 {
00418 FT_Byte* cur = *acur;
00419 FT_Error err = PSaux_Err_Ok;
00420
00421
00422 while ( ++cur < limit )
00423 {
00424
00425 skip_spaces( &cur, limit );
00426 if ( cur >= limit )
00427 break;
00428
00429 if ( !IS_PS_XDIGIT( *cur ) )
00430 break;
00431 }
00432
00433 if ( cur < limit && *cur != '>' )
00434 {
00435 FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
00436 err = PSaux_Err_Invalid_File_Format;
00437 }
00438 else
00439 cur++;
00440
00441 *acur = cur;
00442 return err;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 static FT_Error
00454 skip_procedure( FT_Byte* *acur,
00455 FT_Byte* limit )
00456 {
00457 FT_Byte* cur;
00458 FT_Int embed = 0;
00459 FT_Error error = PSaux_Err_Ok;
00460
00461
00462 FT_ASSERT( **acur == '{' );
00463
00464 for ( cur = *acur; cur < limit && error == PSaux_Err_Ok; ++cur )
00465 {
00466 switch ( *cur )
00467 {
00468 case '{':
00469 ++embed;
00470 break;
00471
00472 case '}':
00473 --embed;
00474 if ( embed == 0 )
00475 {
00476 ++cur;
00477 goto end;
00478 }
00479 break;
00480
00481 case '(':
00482 error = skip_literal_string( &cur, limit );
00483 break;
00484
00485 case '<':
00486 error = skip_string( &cur, limit );
00487 break;
00488
00489 case '%':
00490 skip_comment( &cur, limit );
00491 break;
00492 }
00493 }
00494
00495 end:
00496 if ( embed != 0 )
00497 error = PSaux_Err_Invalid_File_Format;
00498
00499 *acur = cur;
00500
00501 return error;
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 FT_LOCAL_DEF( void )
00514 ps_parser_skip_PS_token( PS_Parser parser )
00515 {
00516
00517
00518
00519
00520 FT_Byte* cur = parser->cursor;
00521 FT_Byte* limit = parser->limit;
00522 FT_Error error = PSaux_Err_Ok;
00523
00524
00525 skip_spaces( &cur, limit );
00526 if ( cur >= limit )
00527 goto Exit;
00528
00529
00530 if ( *cur == '[' || *cur == ']' )
00531 {
00532 cur++;
00533 goto Exit;
00534 }
00535
00536
00537
00538 if ( *cur == '{' )
00539 {
00540 error = skip_procedure( &cur, limit );
00541 goto Exit;
00542 }
00543
00544 if ( *cur == '(' )
00545 {
00546 error = skip_literal_string( &cur, limit );
00547 goto Exit;
00548 }
00549
00550 if ( *cur == '<' )
00551 {
00552 if ( cur + 1 < limit && *(cur + 1) == '<' )
00553 {
00554 cur++;
00555 cur++;
00556 }
00557 else
00558 error = skip_string( &cur, limit );
00559
00560 goto Exit;
00561 }
00562
00563 if ( *cur == '>' )
00564 {
00565 cur++;
00566 if ( cur >= limit || *cur != '>' )
00567 {
00568 FT_ERROR(( "ps_parser_skip_PS_token:"
00569 " unexpected closing delimiter `>'\n" ));
00570 error = PSaux_Err_Invalid_File_Format;
00571 goto Exit;
00572 }
00573 cur++;
00574 goto Exit;
00575 }
00576
00577 if ( *cur == '/' )
00578 cur++;
00579
00580
00581 while ( cur < limit )
00582 {
00583
00584
00585 if ( IS_PS_DELIM( *cur ) )
00586 break;
00587
00588 cur++;
00589 }
00590
00591 Exit:
00592 if ( cur == parser->cursor )
00593 {
00594 FT_ERROR(( "ps_parser_skip_PS_token:"
00595 " current token is `%c' which is self-delimiting\n"
00596 " "
00597 " but invalid at this point\n",
00598 *cur ));
00599
00600 error = PSaux_Err_Invalid_File_Format;
00601 }
00602
00603 parser->error = error;
00604 parser->cursor = cur;
00605 }
00606
00607
00608 FT_LOCAL_DEF( void )
00609 ps_parser_skip_spaces( PS_Parser parser )
00610 {
00611 skip_spaces( &parser->cursor, parser->limit );
00612 }
00613
00614
00615
00616
00617
00618 FT_LOCAL_DEF( void )
00619 ps_parser_to_token( PS_Parser parser,
00620 T1_Token token )
00621 {
00622 FT_Byte* cur;
00623 FT_Byte* limit;
00624 FT_Int embed;
00625
00626
00627 token->type = T1_TOKEN_TYPE_NONE;
00628 token->start = 0;
00629 token->limit = 0;
00630
00631
00632 ps_parser_skip_spaces( parser );
00633
00634 cur = parser->cursor;
00635 limit = parser->limit;
00636
00637 if ( cur >= limit )
00638 return;
00639
00640 switch ( *cur )
00641 {
00642
00643 case '(':
00644 token->type = T1_TOKEN_TYPE_STRING;
00645 token->start = cur;
00646
00647 if ( skip_literal_string( &cur, limit ) == PSaux_Err_Ok )
00648 token->limit = cur;
00649 break;
00650
00651
00652 case '{':
00653 token->type = T1_TOKEN_TYPE_ARRAY;
00654 token->start = cur;
00655
00656 if ( skip_procedure( &cur, limit ) == PSaux_Err_Ok )
00657 token->limit = cur;
00658 break;
00659
00660
00661
00662
00663
00664 case '[':
00665 token->type = T1_TOKEN_TYPE_ARRAY;
00666 embed = 1;
00667 token->start = cur++;
00668
00669
00670 parser->cursor = cur;
00671 ps_parser_skip_spaces( parser );
00672 cur = parser->cursor;
00673
00674 while ( cur < limit && !parser->error )
00675 {
00676
00677
00678 if ( *cur == '[' )
00679 embed++;
00680 else if ( *cur == ']' )
00681 {
00682 embed--;
00683 if ( embed <= 0 )
00684 {
00685 token->limit = ++cur;
00686 break;
00687 }
00688 }
00689
00690 parser->cursor = cur;
00691 ps_parser_skip_PS_token( parser );
00692
00693 ps_parser_skip_spaces ( parser );
00694 cur = parser->cursor;
00695 }
00696 break;
00697
00698
00699 default:
00700 token->start = cur;
00701 token->type = ( *cur == '/' ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY );
00702 ps_parser_skip_PS_token( parser );
00703 cur = parser->cursor;
00704 if ( !parser->error )
00705 token->limit = cur;
00706 }
00707
00708 if ( !token->limit )
00709 {
00710 token->start = 0;
00711 token->type = T1_TOKEN_TYPE_NONE;
00712 }
00713
00714 parser->cursor = cur;
00715 }
00716
00717
00718
00719
00720
00721 FT_LOCAL_DEF( void )
00722 ps_parser_to_token_array( PS_Parser parser,
00723 T1_Token tokens,
00724 FT_UInt max_tokens,
00725 FT_Int* pnum_tokens )
00726 {
00727 T1_TokenRec master;
00728
00729
00730 *pnum_tokens = -1;
00731
00732
00733 ps_parser_to_token( parser, &master );
00734
00735 if ( master.type == T1_TOKEN_TYPE_ARRAY )
00736 {
00737 FT_Byte* old_cursor = parser->cursor;
00738 FT_Byte* old_limit = parser->limit;
00739 T1_Token cur = tokens;
00740 T1_Token limit = cur + max_tokens;
00741
00742
00743
00744 parser->cursor = master.start + 1;
00745 parser->limit = master.limit - 1;
00746
00747 while ( parser->cursor < parser->limit )
00748 {
00749 T1_TokenRec token;
00750
00751
00752 ps_parser_to_token( parser, &token );
00753 if ( !token.type )
00754 break;
00755
00756 if ( tokens != NULL && cur < limit )
00757 *cur = token;
00758
00759 cur++;
00760 }
00761
00762 *pnum_tokens = (FT_Int)( cur - tokens );
00763
00764 parser->cursor = old_cursor;
00765 parser->limit = old_limit;
00766 }
00767 }
00768
00769
00770
00771
00772
00773
00774 static FT_Int
00775 ps_tocoordarray( FT_Byte* *acur,
00776 FT_Byte* limit,
00777 FT_Int max_coords,
00778 FT_Short* coords )
00779 {
00780 FT_Byte* cur = *acur;
00781 FT_Int count = 0;
00782 FT_Byte c, ender;
00783
00784
00785 if ( cur >= limit )
00786 goto Exit;
00787
00788
00789
00790 c = *cur;
00791 ender = 0;
00792
00793 if ( c == '[' )
00794 ender = ']';
00795 else if ( c == '{' )
00796 ender = '}';
00797
00798 if ( ender )
00799 cur++;
00800
00801
00802 while ( cur < limit )
00803 {
00804 FT_Short dummy;
00805 FT_Byte* old_cur;
00806
00807
00808
00809 skip_spaces( &cur, limit );
00810 if ( cur >= limit )
00811 goto Exit;
00812
00813 if ( *cur == ender )
00814 {
00815 cur++;
00816 break;
00817 }
00818
00819 old_cur = cur;
00820
00821 if ( coords != NULL && count >= max_coords )
00822 break;
00823
00824
00825
00826 *( coords != NULL ? &coords[count] : &dummy ) =
00827 (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
00828
00829 if ( old_cur == cur )
00830 {
00831 count = -1;
00832 goto Exit;
00833 }
00834 else
00835 count++;
00836
00837 if ( !ender )
00838 break;
00839 }
00840
00841 Exit:
00842 *acur = cur;
00843 return count;
00844 }
00845
00846
00847
00848
00849
00850
00851 static FT_Int
00852 ps_tofixedarray( FT_Byte* *acur,
00853 FT_Byte* limit,
00854 FT_Int max_values,
00855 FT_Fixed* values,
00856 FT_Int power_ten )
00857 {
00858 FT_Byte* cur = *acur;
00859 FT_Int count = 0;
00860 FT_Byte c, ender;
00861
00862
00863 if ( cur >= limit )
00864 goto Exit;
00865
00866
00867
00868 c = *cur;
00869 ender = 0;
00870
00871 if ( c == '[' )
00872 ender = ']';
00873 else if ( c == '{' )
00874 ender = '}';
00875
00876 if ( ender )
00877 cur++;
00878
00879
00880 while ( cur < limit )
00881 {
00882 FT_Fixed dummy;
00883 FT_Byte* old_cur;
00884
00885
00886
00887 skip_spaces( &cur, limit );
00888 if ( cur >= limit )
00889 goto Exit;
00890
00891 if ( *cur == ender )
00892 {
00893 cur++;
00894 break;
00895 }
00896
00897 old_cur = cur;
00898
00899 if ( values != NULL && count >= max_values )
00900 break;
00901
00902
00903
00904 *( values != NULL ? &values[count] : &dummy ) =
00905 PS_Conv_ToFixed( &cur, limit, power_ten );
00906
00907 if ( old_cur == cur )
00908 {
00909 count = -1;
00910 goto Exit;
00911 }
00912 else
00913 count++;
00914
00915 if ( !ender )
00916 break;
00917 }
00918
00919 Exit:
00920 *acur = cur;
00921 return count;
00922 }
00923
00924
00925 #if 0
00926
00927 static FT_String*
00928 ps_tostring( FT_Byte** cursor,
00929 FT_Byte* limit,
00930 FT_Memory memory )
00931 {
00932 FT_Byte* cur = *cursor;
00933 FT_PtrDist len = 0;
00934 FT_Int count;
00935 FT_String* result;
00936 FT_Error error;
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
00949 cur++;
00950 if ( cur + 1 >= limit )
00951 return 0;
00952
00953 if ( *cur == '(' )
00954 cur++;
00955
00956 *cursor = cur;
00957 count = 0;
00958
00959
00960 for ( ; cur < limit; cur++ )
00961 {
00962 if ( *cur == '(' )
00963 count++;
00964
00965 else if ( *cur == ')' )
00966 {
00967 count--;
00968 if ( count < 0 )
00969 break;
00970 }
00971 }
00972
00973 len = cur - *cursor;
00974 if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
00975 return 0;
00976
00977
00978 FT_MEM_COPY( result, *cursor, len );
00979 result[len] = '\0';
00980 *cursor = cur;
00981 return result;
00982 }
00983
00984 #endif
00985
00986
00987 static int
00988 ps_tobool( FT_Byte* *acur,
00989 FT_Byte* limit )
00990 {
00991 FT_Byte* cur = *acur;
00992 FT_Bool result = 0;
00993
00994
00995
00996 if ( cur + 3 < limit &&
00997 cur[0] == 't' &&
00998 cur[1] == 'r' &&
00999 cur[2] == 'u' &&
01000 cur[3] == 'e' )
01001 {
01002 result = 1;
01003 cur += 5;
01004 }
01005 else if ( cur + 4 < limit &&
01006 cur[0] == 'f' &&
01007 cur[1] == 'a' &&
01008 cur[2] == 'l' &&
01009 cur[3] == 's' &&
01010 cur[4] == 'e' )
01011 {
01012 result = 0;
01013 cur += 6;
01014 }
01015
01016 *acur = cur;
01017 return result;
01018 }
01019
01020
01021
01022
01023 FT_LOCAL_DEF( FT_Error )
01024 ps_parser_load_field( PS_Parser parser,
01025 const T1_Field field,
01026 void** objects,
01027 FT_UInt max_objects,
01028 FT_ULong* pflags )
01029 {
01030 T1_TokenRec token;
01031 FT_Byte* cur;
01032 FT_Byte* limit;
01033 FT_UInt count;
01034 FT_UInt idx;
01035 FT_Error error;
01036
01037
01038
01039 ps_parser_to_token( parser, &token );
01040 if ( !token.type )
01041 goto Fail;
01042
01043 count = 1;
01044 idx = 0;
01045 cur = token.start;
01046 limit = token.limit;
01047
01048
01049 if ( field->type == T1_FIELD_TYPE_BBOX )
01050 {
01051 T1_TokenRec token2;
01052 FT_Byte* old_cur = parser->cursor;
01053 FT_Byte* old_limit = parser->limit;
01054
01055
01056
01057 parser->cursor = token.start + 1;
01058 parser->limit = token.limit - 1;
01059
01060 ps_parser_to_token( parser, &token2 );
01061 parser->cursor = old_cur;
01062 parser->limit = old_limit;
01063
01064 if ( token2.type == T1_TOKEN_TYPE_ARRAY )
01065 goto FieldArray;
01066 }
01067 else if ( token.type == T1_TOKEN_TYPE_ARRAY )
01068 {
01069 FieldArray:
01070
01071 if ( max_objects == 0 )
01072 goto Fail;
01073
01074 count = max_objects;
01075 idx = 1;
01076
01077
01078 cur++;
01079 limit--;
01080 }
01081
01082 for ( ; count > 0; count--, idx++ )
01083 {
01084 FT_Byte* q = (FT_Byte*)objects[idx] + field->offset;
01085 FT_Long val;
01086 FT_String* string;
01087
01088
01089 skip_spaces( &cur, limit );
01090
01091 switch ( field->type )
01092 {
01093 case T1_FIELD_TYPE_BOOL:
01094 val = ps_tobool( &cur, limit );
01095 goto Store_Integer;
01096
01097 case T1_FIELD_TYPE_FIXED:
01098 val = PS_Conv_ToFixed( &cur, limit, 0 );
01099 goto Store_Integer;
01100
01101 case T1_FIELD_TYPE_FIXED_1000:
01102 val = PS_Conv_ToFixed( &cur, limit, 3 );
01103 goto Store_Integer;
01104
01105 case T1_FIELD_TYPE_INTEGER:
01106 val = PS_Conv_ToInt( &cur, limit );
01107
01108
01109 Store_Integer:
01110 switch ( field->size )
01111 {
01112 case (8 / FT_CHAR_BIT):
01113 *(FT_Byte*)q = (FT_Byte)val;
01114 break;
01115
01116 case (16 / FT_CHAR_BIT):
01117 *(FT_UShort*)q = (FT_UShort)val;
01118 break;
01119
01120 case (32 / FT_CHAR_BIT):
01121 *(FT_UInt32*)q = (FT_UInt32)val;
01122 break;
01123
01124 default:
01125 *(FT_Long*)q = val;
01126 }
01127 break;
01128
01129 case T1_FIELD_TYPE_STRING:
01130 case T1_FIELD_TYPE_KEY:
01131 {
01132 FT_Memory memory = parser->memory;
01133 FT_UInt len = (FT_UInt)( limit - cur );
01134
01135
01136 if ( cur >= limit )
01137 break;
01138
01139
01140
01141 if ( token.type == T1_TOKEN_TYPE_KEY )
01142 {
01143
01144 len--;
01145 cur++;
01146 }
01147 else if ( token.type == T1_TOKEN_TYPE_STRING )
01148 {
01149
01150
01151
01152
01153 cur++;
01154 len -= 2;
01155 }
01156 else
01157 {
01158 FT_ERROR(( "ps_parser_load_field:"
01159 " expected a name or string\n"
01160 " "
01161 " but found token of type %d instead\n",
01162 token.type ));
01163 error = PSaux_Err_Invalid_File_Format;
01164 goto Exit;
01165 }
01166
01167
01168
01169 if ( *(FT_String**)q != NULL )
01170 {
01171 FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
01172 field->ident ));
01173 FT_FREE( *(FT_String**)q );
01174 *(FT_String**)q = NULL;
01175 }
01176
01177 if ( FT_ALLOC( string, len + 1 ) )
01178 goto Exit;
01179
01180 FT_MEM_COPY( string, cur, len );
01181 string[len] = 0;
01182
01183 *(FT_String**)q = string;
01184 }
01185 break;
01186
01187 case T1_FIELD_TYPE_BBOX:
01188 {
01189 FT_Fixed temp[4];
01190 FT_BBox* bbox = (FT_BBox*)q;
01191 FT_Int result;
01192
01193
01194 result = ps_tofixedarray( &cur, limit, 4, temp, 0 );
01195
01196 if ( result < 0 )
01197 {
01198 FT_ERROR(( "ps_parser_load_field:"
01199 " expected four integers in bounding box\n" ));
01200 error = PSaux_Err_Invalid_File_Format;
01201 goto Exit;
01202 }
01203
01204 bbox->xMin = FT_RoundFix( temp[0] );
01205 bbox->yMin = FT_RoundFix( temp[1] );
01206 bbox->xMax = FT_RoundFix( temp[2] );
01207 bbox->yMax = FT_RoundFix( temp[3] );
01208 }
01209 break;
01210
01211 default:
01212
01213 goto Fail;
01214 }
01215 }
01216
01217 #if 0
01218 if ( pflags )
01219 *pflags |= 1L << field->flag_bit;
01220 #else
01221 FT_UNUSED( pflags );
01222 #endif
01223
01224 error = PSaux_Err_Ok;
01225
01226 Exit:
01227 return error;
01228
01229 Fail:
01230 error = PSaux_Err_Invalid_File_Format;
01231 goto Exit;
01232 }
01233
01234
01235 #define T1_MAX_TABLE_ELEMENTS 32
01236
01237
01238 FT_LOCAL_DEF( FT_Error )
01239 ps_parser_load_field_table( PS_Parser parser,
01240 const T1_Field field,
01241 void** objects,
01242 FT_UInt max_objects,
01243 FT_ULong* pflags )
01244 {
01245 T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS];
01246 T1_Token token;
01247 FT_Int num_elements;
01248 FT_Error error = PSaux_Err_Ok;
01249 FT_Byte* old_cursor;
01250 FT_Byte* old_limit;
01251 T1_FieldRec fieldrec = *(T1_Field)field;
01252
01253
01254 fieldrec.type = T1_FIELD_TYPE_INTEGER;
01255 if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ||
01256 field->type == T1_FIELD_TYPE_BBOX )
01257 fieldrec.type = T1_FIELD_TYPE_FIXED;
01258
01259 ps_parser_to_token_array( parser, elements,
01260 T1_MAX_TABLE_ELEMENTS, &num_elements );
01261 if ( num_elements < 0 )
01262 {
01263 error = PSaux_Err_Ignore;
01264 goto Exit;
01265 }
01266 if ( (FT_UInt)num_elements > field->array_max )
01267 num_elements = field->array_max;
01268
01269 old_cursor = parser->cursor;
01270 old_limit = parser->limit;
01271
01272
01273
01274 if ( field->type != T1_FIELD_TYPE_BBOX && field->count_offset != 0 )
01275 *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
01276 (FT_Byte)num_elements;
01277
01278
01279 token = elements;
01280 for ( ; num_elements > 0; num_elements--, token++ )
01281 {
01282 parser->cursor = token->start;
01283 parser->limit = token->limit;
01284 ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );
01285 fieldrec.offset += fieldrec.size;
01286 }
01287
01288 #if 0
01289 if ( pflags )
01290 *pflags |= 1L << field->flag_bit;
01291 #else
01292 FT_UNUSED( pflags );
01293 #endif
01294
01295 parser->cursor = old_cursor;
01296 parser->limit = old_limit;
01297
01298 Exit:
01299 return error;
01300 }
01301
01302
01303 FT_LOCAL_DEF( FT_Long )
01304 ps_parser_to_int( PS_Parser parser )
01305 {
01306 ps_parser_skip_spaces( parser );
01307 return PS_Conv_ToInt( &parser->cursor, parser->limit );
01308 }
01309
01310
01311
01312
01313 FT_LOCAL_DEF( FT_Error )
01314 ps_parser_to_bytes( PS_Parser parser,
01315 FT_Byte* bytes,
01316 FT_Offset max_bytes,
01317 FT_Long* pnum_bytes,
01318 FT_Bool delimiters )
01319 {
01320 FT_Error error = PSaux_Err_Ok;
01321 FT_Byte* cur;
01322
01323
01324 ps_parser_skip_spaces( parser );
01325 cur = parser->cursor;
01326
01327 if ( cur >= parser->limit )
01328 goto Exit;
01329
01330 if ( delimiters )
01331 {
01332 if ( *cur != '<' )
01333 {
01334 FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" ));
01335 error = PSaux_Err_Invalid_File_Format;
01336 goto Exit;
01337 }
01338
01339 cur++;
01340 }
01341
01342 *pnum_bytes = PS_Conv_ASCIIHexDecode( &cur,
01343 parser->limit,
01344 bytes,
01345 max_bytes );
01346
01347 if ( delimiters )
01348 {
01349 if ( cur < parser->limit && *cur != '>' )
01350 {
01351 FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" ));
01352 error = PSaux_Err_Invalid_File_Format;
01353 goto Exit;
01354 }
01355
01356 cur++;
01357 }
01358
01359 parser->cursor = cur;
01360
01361 Exit:
01362 return error;
01363 }
01364
01365
01366 FT_LOCAL_DEF( FT_Fixed )
01367 ps_parser_to_fixed( PS_Parser parser,
01368 FT_Int power_ten )
01369 {
01370 ps_parser_skip_spaces( parser );
01371 return PS_Conv_ToFixed( &parser->cursor, parser->limit, power_ten );
01372 }
01373
01374
01375 FT_LOCAL_DEF( FT_Int )
01376 ps_parser_to_coord_array( PS_Parser parser,
01377 FT_Int max_coords,
01378 FT_Short* coords )
01379 {
01380 ps_parser_skip_spaces( parser );
01381 return ps_tocoordarray( &parser->cursor, parser->limit,
01382 max_coords, coords );
01383 }
01384
01385
01386 FT_LOCAL_DEF( FT_Int )
01387 ps_parser_to_fixed_array( PS_Parser parser,
01388 FT_Int max_values,
01389 FT_Fixed* values,
01390 FT_Int power_ten )
01391 {
01392 ps_parser_skip_spaces( parser );
01393 return ps_tofixedarray( &parser->cursor, parser->limit,
01394 max_values, values, power_ten );
01395 }
01396
01397
01398 #if 0
01399
01400 FT_LOCAL_DEF( FT_String* )
01401 T1_ToString( PS_Parser parser )
01402 {
01403 return ps_tostring( &parser->cursor, parser->limit, parser->memory );
01404 }
01405
01406
01407 FT_LOCAL_DEF( FT_Bool )
01408 T1_ToBool( PS_Parser parser )
01409 {
01410 return ps_tobool( &parser->cursor, parser->limit );
01411 }
01412
01413 #endif
01414
01415
01416 FT_LOCAL_DEF( void )
01417 ps_parser_init( PS_Parser parser,
01418 FT_Byte* base,
01419 FT_Byte* limit,
01420 FT_Memory memory )
01421 {
01422 parser->error = PSaux_Err_Ok;
01423 parser->base = base;
01424 parser->limit = limit;
01425 parser->cursor = base;
01426 parser->memory = memory;
01427 parser->funcs = ps_parser_funcs;
01428 }
01429
01430
01431 FT_LOCAL_DEF( void )
01432 ps_parser_done( PS_Parser parser )
01433 {
01434 FT_UNUSED( parser );
01435 }
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466 FT_LOCAL_DEF( void )
01467 t1_builder_init( T1_Builder builder,
01468 FT_Face face,
01469 FT_Size size,
01470 FT_GlyphSlot glyph,
01471 FT_Bool hinting )
01472 {
01473 builder->parse_state = T1_Parse_Start;
01474 builder->load_points = 1;
01475
01476 builder->face = face;
01477 builder->glyph = glyph;
01478 builder->memory = face->memory;
01479
01480 if ( glyph )
01481 {
01482 FT_GlyphLoader loader = glyph->internal->loader;
01483
01484
01485 builder->loader = loader;
01486 builder->base = &loader->base.outline;
01487 builder->current = &loader->current.outline;
01488 FT_GlyphLoader_Rewind( loader );
01489
01490 builder->hints_globals = size->internal;
01491 builder->hints_funcs = 0;
01492
01493 if ( hinting )
01494 builder->hints_funcs = glyph->internal->glyph_hints;
01495 }
01496
01497 builder->pos_x = 0;
01498 builder->pos_y = 0;
01499
01500 builder->left_bearing.x = 0;
01501 builder->left_bearing.y = 0;
01502 builder->advance.x = 0;
01503 builder->advance.y = 0;
01504
01505 builder->funcs = t1_builder_funcs;
01506 }
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522 FT_LOCAL_DEF( void )
01523 t1_builder_done( T1_Builder builder )
01524 {
01525 FT_GlyphSlot glyph = builder->glyph;
01526
01527
01528 if ( glyph )
01529 glyph->outline = *builder->base;
01530 }
01531
01532
01533
01534 FT_LOCAL_DEF( FT_Error )
01535 t1_builder_check_points( T1_Builder builder,
01536 FT_Int count )
01537 {
01538 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
01539 }
01540
01541
01542
01543 FT_LOCAL_DEF( void )
01544 t1_builder_add_point( T1_Builder builder,
01545 FT_Pos x,
01546 FT_Pos y,
01547 FT_Byte flag )
01548 {
01549 FT_Outline* outline = builder->current;
01550
01551
01552 if ( builder->load_points )
01553 {
01554 FT_Vector* point = outline->points + outline->n_points;
01555 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
01556
01557
01558 point->x = FIXED_TO_INT( x );
01559 point->y = FIXED_TO_INT( y );
01560 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
01561 }
01562 outline->n_points++;
01563 }
01564
01565
01566
01567 FT_LOCAL_DEF( FT_Error )
01568 t1_builder_add_point1( T1_Builder builder,
01569 FT_Pos x,
01570 FT_Pos y )
01571 {
01572 FT_Error error;
01573
01574
01575 error = t1_builder_check_points( builder, 1 );
01576 if ( !error )
01577 t1_builder_add_point( builder, x, y, 1 );
01578
01579 return error;
01580 }
01581
01582
01583
01584 FT_LOCAL_DEF( FT_Error )
01585 t1_builder_add_contour( T1_Builder builder )
01586 {
01587 FT_Outline* outline = builder->current;
01588 FT_Error error;
01589
01590
01591 if ( !builder->load_points )
01592 {
01593 outline->n_contours++;
01594 return PSaux_Err_Ok;
01595 }
01596
01597 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
01598 if ( !error )
01599 {
01600 if ( outline->n_contours > 0 )
01601 outline->contours[outline->n_contours - 1] =
01602 (short)( outline->n_points - 1 );
01603
01604 outline->n_contours++;
01605 }
01606
01607 return error;
01608 }
01609
01610
01611
01612 FT_LOCAL_DEF( FT_Error )
01613 t1_builder_start_point( T1_Builder builder,
01614 FT_Pos x,
01615 FT_Pos y )
01616 {
01617 FT_Error error = PSaux_Err_Invalid_File_Format;
01618
01619
01620
01621
01622 if ( builder->parse_state == T1_Parse_Have_Path )
01623 error = PSaux_Err_Ok;
01624 else if ( builder->parse_state == T1_Parse_Have_Moveto )
01625 {
01626 builder->parse_state = T1_Parse_Have_Path;
01627 error = t1_builder_add_contour( builder );
01628 if ( !error )
01629 error = t1_builder_add_point1( builder, x, y );
01630 }
01631
01632 return error;
01633 }
01634
01635
01636
01637 FT_LOCAL_DEF( void )
01638 t1_builder_close_contour( T1_Builder builder )
01639 {
01640 FT_Outline* outline = builder->current;
01641 FT_Int first;
01642
01643
01644 if ( !outline )
01645 return;
01646
01647 first = outline->n_contours <= 1
01648 ? 0 : outline->contours[outline->n_contours - 2] + 1;
01649
01650
01651
01652 if ( outline->n_points > 1 )
01653 {
01654 FT_Vector* p1 = outline->points + first;
01655 FT_Vector* p2 = outline->points + outline->n_points - 1;
01656 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
01657
01658
01659
01660
01661 if ( p1->x == p2->x && p1->y == p2->y )
01662 if ( *control == FT_CURVE_TAG_ON )
01663 outline->n_points--;
01664 }
01665
01666 if ( outline->n_contours > 0 )
01667 {
01668
01669
01670 if ( first == outline->n_points - 1 )
01671 {
01672 outline->n_contours--;
01673 outline->n_points--;
01674 }
01675 else
01676 outline->contours[outline->n_contours - 1] =
01677 (short)( outline->n_points - 1 );
01678 }
01679 }
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690 FT_LOCAL_DEF( void )
01691 t1_decrypt( FT_Byte* buffer,
01692 FT_Offset length,
01693 FT_UShort seed )
01694 {
01695 PS_Conv_EexecDecode( &buffer,
01696 buffer + length,
01697 buffer,
01698 length,
01699 &seed );
01700 }
01701
01702
01703