Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenafmparse.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* afmparse.c */ 00004 /* */ 00005 /* AFM parser (body). */ 00006 /* */ 00007 /* Copyright 2006, 2007, 2008, 2009, 2010 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 #include <ft2build.h> 00019 #include FT_FREETYPE_H 00020 #include FT_INTERNAL_POSTSCRIPT_AUX_H 00021 00022 #include "afmparse.h" 00023 #include "psconv.h" 00024 00025 #include "psauxerr.h" 00026 00027 00028 /***************************************************************************/ 00029 /* */ 00030 /* AFM_Stream */ 00031 /* */ 00032 /* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib. */ 00033 /* */ 00034 /* */ 00035 00036 enum 00037 { 00038 AFM_STREAM_STATUS_NORMAL, 00039 AFM_STREAM_STATUS_EOC, 00040 AFM_STREAM_STATUS_EOL, 00041 AFM_STREAM_STATUS_EOF 00042 }; 00043 00044 00045 typedef struct AFM_StreamRec_ 00046 { 00047 FT_Byte* cursor; 00048 FT_Byte* base; 00049 FT_Byte* limit; 00050 00051 FT_Int status; 00052 00053 } AFM_StreamRec; 00054 00055 00056 #ifndef EOF 00057 #define EOF -1 00058 #endif 00059 00060 00061 /* this works because empty lines are ignored */ 00062 #define AFM_IS_NEWLINE( ch ) ( (ch) == '\r' || (ch) == '\n' ) 00063 00064 #define AFM_IS_EOF( ch ) ( (ch) == EOF || (ch) == '\x1a' ) 00065 #define AFM_IS_SPACE( ch ) ( (ch) == ' ' || (ch) == '\t' ) 00066 00067 /* column separator; there is no `column' in the spec actually */ 00068 #define AFM_IS_SEP( ch ) ( (ch) == ';' ) 00069 00070 #define AFM_GETC() \ 00071 ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \ 00072 : EOF ) 00073 00074 #define AFM_STREAM_KEY_BEGIN( stream ) \ 00075 (char*)( (stream)->cursor - 1 ) 00076 00077 #define AFM_STREAM_KEY_LEN( stream, key ) \ 00078 ( (char*)(stream)->cursor - key - 1 ) 00079 00080 #define AFM_STATUS_EOC( stream ) \ 00081 ( (stream)->status >= AFM_STREAM_STATUS_EOC ) 00082 00083 #define AFM_STATUS_EOL( stream ) \ 00084 ( (stream)->status >= AFM_STREAM_STATUS_EOL ) 00085 00086 #define AFM_STATUS_EOF( stream ) \ 00087 ( (stream)->status >= AFM_STREAM_STATUS_EOF ) 00088 00089 00090 static int 00091 afm_stream_skip_spaces( AFM_Stream stream ) 00092 { 00093 int ch = 0; /* make stupid compiler happy */ 00094 00095 00096 if ( AFM_STATUS_EOC( stream ) ) 00097 return ';'; 00098 00099 while ( 1 ) 00100 { 00101 ch = AFM_GETC(); 00102 if ( !AFM_IS_SPACE( ch ) ) 00103 break; 00104 } 00105 00106 if ( AFM_IS_NEWLINE( ch ) ) 00107 stream->status = AFM_STREAM_STATUS_EOL; 00108 else if ( AFM_IS_SEP( ch ) ) 00109 stream->status = AFM_STREAM_STATUS_EOC; 00110 else if ( AFM_IS_EOF( ch ) ) 00111 stream->status = AFM_STREAM_STATUS_EOF; 00112 00113 return ch; 00114 } 00115 00116 00117 /* read a key or value in current column */ 00118 static char* 00119 afm_stream_read_one( AFM_Stream stream ) 00120 { 00121 char* str; 00122 int ch; 00123 00124 00125 afm_stream_skip_spaces( stream ); 00126 if ( AFM_STATUS_EOC( stream ) ) 00127 return NULL; 00128 00129 str = AFM_STREAM_KEY_BEGIN( stream ); 00130 00131 while ( 1 ) 00132 { 00133 ch = AFM_GETC(); 00134 if ( AFM_IS_SPACE( ch ) ) 00135 break; 00136 else if ( AFM_IS_NEWLINE( ch ) ) 00137 { 00138 stream->status = AFM_STREAM_STATUS_EOL; 00139 break; 00140 } 00141 else if ( AFM_IS_SEP( ch ) ) 00142 { 00143 stream->status = AFM_STREAM_STATUS_EOC; 00144 break; 00145 } 00146 else if ( AFM_IS_EOF( ch ) ) 00147 { 00148 stream->status = AFM_STREAM_STATUS_EOF; 00149 break; 00150 } 00151 } 00152 00153 return str; 00154 } 00155 00156 00157 /* read a string (i.e., read to EOL) */ 00158 static char* 00159 afm_stream_read_string( AFM_Stream stream ) 00160 { 00161 char* str; 00162 int ch; 00163 00164 00165 afm_stream_skip_spaces( stream ); 00166 if ( AFM_STATUS_EOL( stream ) ) 00167 return NULL; 00168 00169 str = AFM_STREAM_KEY_BEGIN( stream ); 00170 00171 /* scan to eol */ 00172 while ( 1 ) 00173 { 00174 ch = AFM_GETC(); 00175 if ( AFM_IS_NEWLINE( ch ) ) 00176 { 00177 stream->status = AFM_STREAM_STATUS_EOL; 00178 break; 00179 } 00180 else if ( AFM_IS_EOF( ch ) ) 00181 { 00182 stream->status = AFM_STREAM_STATUS_EOF; 00183 break; 00184 } 00185 } 00186 00187 return str; 00188 } 00189 00190 00191 /*************************************************************************/ 00192 /* */ 00193 /* AFM_Parser */ 00194 /* */ 00195 /* */ 00196 00197 /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */ 00198 typedef enum AFM_Token_ 00199 { 00200 AFM_TOKEN_ASCENDER, 00201 AFM_TOKEN_AXISLABEL, 00202 AFM_TOKEN_AXISTYPE, 00203 AFM_TOKEN_B, 00204 AFM_TOKEN_BLENDAXISTYPES, 00205 AFM_TOKEN_BLENDDESIGNMAP, 00206 AFM_TOKEN_BLENDDESIGNPOSITIONS, 00207 AFM_TOKEN_C, 00208 AFM_TOKEN_CC, 00209 AFM_TOKEN_CH, 00210 AFM_TOKEN_CAPHEIGHT, 00211 AFM_TOKEN_CHARWIDTH, 00212 AFM_TOKEN_CHARACTERSET, 00213 AFM_TOKEN_CHARACTERS, 00214 AFM_TOKEN_DESCENDER, 00215 AFM_TOKEN_ENCODINGSCHEME, 00216 AFM_TOKEN_ENDAXIS, 00217 AFM_TOKEN_ENDCHARMETRICS, 00218 AFM_TOKEN_ENDCOMPOSITES, 00219 AFM_TOKEN_ENDDIRECTION, 00220 AFM_TOKEN_ENDFONTMETRICS, 00221 AFM_TOKEN_ENDKERNDATA, 00222 AFM_TOKEN_ENDKERNPAIRS, 00223 AFM_TOKEN_ENDTRACKKERN, 00224 AFM_TOKEN_ESCCHAR, 00225 AFM_TOKEN_FAMILYNAME, 00226 AFM_TOKEN_FONTBBOX, 00227 AFM_TOKEN_FONTNAME, 00228 AFM_TOKEN_FULLNAME, 00229 AFM_TOKEN_ISBASEFONT, 00230 AFM_TOKEN_ISCIDFONT, 00231 AFM_TOKEN_ISFIXEDPITCH, 00232 AFM_TOKEN_ISFIXEDV, 00233 AFM_TOKEN_ITALICANGLE, 00234 AFM_TOKEN_KP, 00235 AFM_TOKEN_KPH, 00236 AFM_TOKEN_KPX, 00237 AFM_TOKEN_KPY, 00238 AFM_TOKEN_L, 00239 AFM_TOKEN_MAPPINGSCHEME, 00240 AFM_TOKEN_METRICSSETS, 00241 AFM_TOKEN_N, 00242 AFM_TOKEN_NOTICE, 00243 AFM_TOKEN_PCC, 00244 AFM_TOKEN_STARTAXIS, 00245 AFM_TOKEN_STARTCHARMETRICS, 00246 AFM_TOKEN_STARTCOMPOSITES, 00247 AFM_TOKEN_STARTDIRECTION, 00248 AFM_TOKEN_STARTFONTMETRICS, 00249 AFM_TOKEN_STARTKERNDATA, 00250 AFM_TOKEN_STARTKERNPAIRS, 00251 AFM_TOKEN_STARTKERNPAIRS0, 00252 AFM_TOKEN_STARTKERNPAIRS1, 00253 AFM_TOKEN_STARTTRACKKERN, 00254 AFM_TOKEN_STDHW, 00255 AFM_TOKEN_STDVW, 00256 AFM_TOKEN_TRACKKERN, 00257 AFM_TOKEN_UNDERLINEPOSITION, 00258 AFM_TOKEN_UNDERLINETHICKNESS, 00259 AFM_TOKEN_VV, 00260 AFM_TOKEN_VVECTOR, 00261 AFM_TOKEN_VERSION, 00262 AFM_TOKEN_W, 00263 AFM_TOKEN_W0, 00264 AFM_TOKEN_W0X, 00265 AFM_TOKEN_W0Y, 00266 AFM_TOKEN_W1, 00267 AFM_TOKEN_W1X, 00268 AFM_TOKEN_W1Y, 00269 AFM_TOKEN_WX, 00270 AFM_TOKEN_WY, 00271 AFM_TOKEN_WEIGHT, 00272 AFM_TOKEN_WEIGHTVECTOR, 00273 AFM_TOKEN_XHEIGHT, 00274 N_AFM_TOKENS, 00275 AFM_TOKEN_UNKNOWN 00276 00277 } AFM_Token; 00278 00279 00280 static const char* const afm_key_table[N_AFM_TOKENS] = 00281 { 00282 "Ascender", 00283 "AxisLabel", 00284 "AxisType", 00285 "B", 00286 "BlendAxisTypes", 00287 "BlendDesignMap", 00288 "BlendDesignPositions", 00289 "C", 00290 "CC", 00291 "CH", 00292 "CapHeight", 00293 "CharWidth", 00294 "CharacterSet", 00295 "Characters", 00296 "Descender", 00297 "EncodingScheme", 00298 "EndAxis", 00299 "EndCharMetrics", 00300 "EndComposites", 00301 "EndDirection", 00302 "EndFontMetrics", 00303 "EndKernData", 00304 "EndKernPairs", 00305 "EndTrackKern", 00306 "EscChar", 00307 "FamilyName", 00308 "FontBBox", 00309 "FontName", 00310 "FullName", 00311 "IsBaseFont", 00312 "IsCIDFont", 00313 "IsFixedPitch", 00314 "IsFixedV", 00315 "ItalicAngle", 00316 "KP", 00317 "KPH", 00318 "KPX", 00319 "KPY", 00320 "L", 00321 "MappingScheme", 00322 "MetricsSets", 00323 "N", 00324 "Notice", 00325 "PCC", 00326 "StartAxis", 00327 "StartCharMetrics", 00328 "StartComposites", 00329 "StartDirection", 00330 "StartFontMetrics", 00331 "StartKernData", 00332 "StartKernPairs", 00333 "StartKernPairs0", 00334 "StartKernPairs1", 00335 "StartTrackKern", 00336 "StdHW", 00337 "StdVW", 00338 "TrackKern", 00339 "UnderlinePosition", 00340 "UnderlineThickness", 00341 "VV", 00342 "VVector", 00343 "Version", 00344 "W", 00345 "W0", 00346 "W0X", 00347 "W0Y", 00348 "W1", 00349 "W1X", 00350 "W1Y", 00351 "WX", 00352 "WY", 00353 "Weight", 00354 "WeightVector", 00355 "XHeight" 00356 }; 00357 00358 00359 /* 00360 * `afm_parser_read_vals' and `afm_parser_next_key' provide 00361 * high-level operations to an AFM_Stream. The rest of the 00362 * parser functions should use them without accessing the 00363 * AFM_Stream directly. 00364 */ 00365 00366 FT_LOCAL_DEF( FT_Int ) 00367 afm_parser_read_vals( AFM_Parser parser, 00368 AFM_Value vals, 00369 FT_UInt n ) 00370 { 00371 AFM_Stream stream = parser->stream; 00372 char* str; 00373 FT_UInt i; 00374 00375 00376 if ( n > AFM_MAX_ARGUMENTS ) 00377 return 0; 00378 00379 for ( i = 0; i < n; i++ ) 00380 { 00381 FT_Offset len; 00382 AFM_Value val = vals + i; 00383 00384 00385 if ( val->type == AFM_VALUE_TYPE_STRING ) 00386 str = afm_stream_read_string( stream ); 00387 else 00388 str = afm_stream_read_one( stream ); 00389 00390 if ( !str ) 00391 break; 00392 00393 len = AFM_STREAM_KEY_LEN( stream, str ); 00394 00395 switch ( val->type ) 00396 { 00397 case AFM_VALUE_TYPE_STRING: 00398 case AFM_VALUE_TYPE_NAME: 00399 { 00400 FT_Memory memory = parser->memory; 00401 FT_Error error; 00402 00403 00404 if ( !FT_QALLOC( val->u.s, len + 1 ) ) 00405 { 00406 ft_memcpy( val->u.s, str, len ); 00407 val->u.s[len] = '\0'; 00408 } 00409 } 00410 break; 00411 00412 case AFM_VALUE_TYPE_FIXED: 00413 val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str, 00414 (FT_Byte*)str + len, 0 ); 00415 break; 00416 00417 case AFM_VALUE_TYPE_INTEGER: 00418 val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str, 00419 (FT_Byte*)str + len ); 00420 break; 00421 00422 case AFM_VALUE_TYPE_BOOL: 00423 val->u.b = FT_BOOL( len == 4 && 00424 !ft_strncmp( str, "true", 4 ) ); 00425 break; 00426 00427 case AFM_VALUE_TYPE_INDEX: 00428 if ( parser->get_index ) 00429 val->u.i = parser->get_index( str, len, parser->user_data ); 00430 else 00431 val->u.i = 0; 00432 break; 00433 } 00434 } 00435 00436 return i; 00437 } 00438 00439 00440 FT_LOCAL_DEF( char* ) 00441 afm_parser_next_key( AFM_Parser parser, 00442 FT_Bool line, 00443 FT_Offset* len ) 00444 { 00445 AFM_Stream stream = parser->stream; 00446 char* key = 0; /* make stupid compiler happy */ 00447 00448 00449 if ( line ) 00450 { 00451 while ( 1 ) 00452 { 00453 /* skip current line */ 00454 if ( !AFM_STATUS_EOL( stream ) ) 00455 afm_stream_read_string( stream ); 00456 00457 stream->status = AFM_STREAM_STATUS_NORMAL; 00458 key = afm_stream_read_one( stream ); 00459 00460 /* skip empty line */ 00461 if ( !key && 00462 !AFM_STATUS_EOF( stream ) && 00463 AFM_STATUS_EOL( stream ) ) 00464 continue; 00465 00466 break; 00467 } 00468 } 00469 else 00470 { 00471 while ( 1 ) 00472 { 00473 /* skip current column */ 00474 while ( !AFM_STATUS_EOC( stream ) ) 00475 afm_stream_read_one( stream ); 00476 00477 stream->status = AFM_STREAM_STATUS_NORMAL; 00478 key = afm_stream_read_one( stream ); 00479 00480 /* skip empty column */ 00481 if ( !key && 00482 !AFM_STATUS_EOF( stream ) && 00483 AFM_STATUS_EOC( stream ) ) 00484 continue; 00485 00486 break; 00487 } 00488 } 00489 00490 if ( len ) 00491 *len = ( key ) ? (FT_Offset)AFM_STREAM_KEY_LEN( stream, key ) 00492 : 0; 00493 00494 return key; 00495 } 00496 00497 00498 static AFM_Token 00499 afm_tokenize( const char* key, 00500 FT_Offset len ) 00501 { 00502 int n; 00503 00504 00505 for ( n = 0; n < N_AFM_TOKENS; n++ ) 00506 { 00507 if ( *( afm_key_table[n] ) == *key ) 00508 { 00509 for ( ; n < N_AFM_TOKENS; n++ ) 00510 { 00511 if ( *( afm_key_table[n] ) != *key ) 00512 return AFM_TOKEN_UNKNOWN; 00513 00514 if ( ft_strncmp( afm_key_table[n], key, len ) == 0 ) 00515 return (AFM_Token) n; 00516 } 00517 } 00518 } 00519 00520 return AFM_TOKEN_UNKNOWN; 00521 } 00522 00523 00524 FT_LOCAL_DEF( FT_Error ) 00525 afm_parser_init( AFM_Parser parser, 00526 FT_Memory memory, 00527 FT_Byte* base, 00528 FT_Byte* limit ) 00529 { 00530 AFM_Stream stream = NULL; 00531 FT_Error error; 00532 00533 00534 if ( FT_NEW( stream ) ) 00535 return error; 00536 00537 stream->cursor = stream->base = base; 00538 stream->limit = limit; 00539 00540 /* don't skip the first line during the first call */ 00541 stream->status = AFM_STREAM_STATUS_EOL; 00542 00543 parser->memory = memory; 00544 parser->stream = stream; 00545 parser->FontInfo = NULL; 00546 parser->get_index = NULL; 00547 00548 return PSaux_Err_Ok; 00549 } 00550 00551 00552 FT_LOCAL( void ) 00553 afm_parser_done( AFM_Parser parser ) 00554 { 00555 FT_Memory memory = parser->memory; 00556 00557 00558 FT_FREE( parser->stream ); 00559 } 00560 00561 00562 FT_LOCAL_DEF( FT_Error ) 00563 afm_parser_read_int( AFM_Parser parser, 00564 FT_Int* aint ) 00565 { 00566 AFM_ValueRec val; 00567 00568 00569 val.type = AFM_VALUE_TYPE_INTEGER; 00570 00571 if ( afm_parser_read_vals( parser, &val, 1 ) == 1 ) 00572 { 00573 *aint = val.u.i; 00574 00575 return PSaux_Err_Ok; 00576 } 00577 else 00578 return PSaux_Err_Syntax_Error; 00579 } 00580 00581 00582 static FT_Error 00583 afm_parse_track_kern( AFM_Parser parser ) 00584 { 00585 AFM_FontInfo fi = parser->FontInfo; 00586 AFM_TrackKern tk; 00587 char* key; 00588 FT_Offset len; 00589 int n = -1; 00590 00591 00592 if ( afm_parser_read_int( parser, &fi->NumTrackKern ) ) 00593 goto Fail; 00594 00595 if ( fi->NumTrackKern ) 00596 { 00597 FT_Memory memory = parser->memory; 00598 FT_Error error; 00599 00600 00601 if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) ) 00602 return error; 00603 } 00604 00605 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 00606 { 00607 AFM_ValueRec shared_vals[5]; 00608 00609 00610 switch ( afm_tokenize( key, len ) ) 00611 { 00612 case AFM_TOKEN_TRACKKERN: 00613 n++; 00614 00615 if ( n >= fi->NumTrackKern ) 00616 goto Fail; 00617 00618 tk = fi->TrackKerns + n; 00619 00620 shared_vals[0].type = AFM_VALUE_TYPE_INTEGER; 00621 shared_vals[1].type = AFM_VALUE_TYPE_FIXED; 00622 shared_vals[2].type = AFM_VALUE_TYPE_FIXED; 00623 shared_vals[3].type = AFM_VALUE_TYPE_FIXED; 00624 shared_vals[4].type = AFM_VALUE_TYPE_FIXED; 00625 if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 ) 00626 goto Fail; 00627 00628 tk->degree = shared_vals[0].u.i; 00629 tk->min_ptsize = shared_vals[1].u.f; 00630 tk->min_kern = shared_vals[2].u.f; 00631 tk->max_ptsize = shared_vals[3].u.f; 00632 tk->max_kern = shared_vals[4].u.f; 00633 00634 /* is this correct? */ 00635 if ( tk->degree < 0 && tk->min_kern > 0 ) 00636 tk->min_kern = -tk->min_kern; 00637 break; 00638 00639 case AFM_TOKEN_ENDTRACKKERN: 00640 case AFM_TOKEN_ENDKERNDATA: 00641 case AFM_TOKEN_ENDFONTMETRICS: 00642 fi->NumTrackKern = n + 1; 00643 return PSaux_Err_Ok; 00644 00645 case AFM_TOKEN_UNKNOWN: 00646 break; 00647 00648 default: 00649 goto Fail; 00650 } 00651 } 00652 00653 Fail: 00654 return PSaux_Err_Syntax_Error; 00655 } 00656 00657 00658 #undef KERN_INDEX 00659 #define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) 00660 00661 00662 /* compare two kerning pairs */ 00663 FT_CALLBACK_DEF( int ) 00664 afm_compare_kern_pairs( const void* a, 00665 const void* b ) 00666 { 00667 AFM_KernPair kp1 = (AFM_KernPair)a; 00668 AFM_KernPair kp2 = (AFM_KernPair)b; 00669 00670 FT_ULong index1 = KERN_INDEX( kp1->index1, kp1->index2 ); 00671 FT_ULong index2 = KERN_INDEX( kp2->index1, kp2->index2 ); 00672 00673 00674 if ( index1 > index2 ) 00675 return 1; 00676 else if ( index1 < index2 ) 00677 return -1; 00678 else 00679 return 0; 00680 } 00681 00682 00683 static FT_Error 00684 afm_parse_kern_pairs( AFM_Parser parser ) 00685 { 00686 AFM_FontInfo fi = parser->FontInfo; 00687 AFM_KernPair kp; 00688 char* key; 00689 FT_Offset len; 00690 int n = -1; 00691 00692 00693 if ( afm_parser_read_int( parser, &fi->NumKernPair ) ) 00694 goto Fail; 00695 00696 if ( fi->NumKernPair ) 00697 { 00698 FT_Memory memory = parser->memory; 00699 FT_Error error; 00700 00701 00702 if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) ) 00703 return error; 00704 } 00705 00706 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 00707 { 00708 AFM_Token token = afm_tokenize( key, len ); 00709 00710 00711 switch ( token ) 00712 { 00713 case AFM_TOKEN_KP: 00714 case AFM_TOKEN_KPX: 00715 case AFM_TOKEN_KPY: 00716 { 00717 FT_Int r; 00718 AFM_ValueRec shared_vals[4]; 00719 00720 00721 n++; 00722 00723 if ( n >= fi->NumKernPair ) 00724 goto Fail; 00725 00726 kp = fi->KernPairs + n; 00727 00728 shared_vals[0].type = AFM_VALUE_TYPE_INDEX; 00729 shared_vals[1].type = AFM_VALUE_TYPE_INDEX; 00730 shared_vals[2].type = AFM_VALUE_TYPE_INTEGER; 00731 shared_vals[3].type = AFM_VALUE_TYPE_INTEGER; 00732 r = afm_parser_read_vals( parser, shared_vals, 4 ); 00733 if ( r < 3 ) 00734 goto Fail; 00735 00736 kp->index1 = shared_vals[0].u.i; 00737 kp->index2 = shared_vals[1].u.i; 00738 if ( token == AFM_TOKEN_KPY ) 00739 { 00740 kp->x = 0; 00741 kp->y = shared_vals[2].u.i; 00742 } 00743 else 00744 { 00745 kp->x = shared_vals[2].u.i; 00746 kp->y = ( token == AFM_TOKEN_KP && r == 4 ) 00747 ? shared_vals[3].u.i : 0; 00748 } 00749 } 00750 break; 00751 00752 case AFM_TOKEN_ENDKERNPAIRS: 00753 case AFM_TOKEN_ENDKERNDATA: 00754 case AFM_TOKEN_ENDFONTMETRICS: 00755 fi->NumKernPair = n + 1; 00756 ft_qsort( fi->KernPairs, fi->NumKernPair, 00757 sizeof( AFM_KernPairRec ), 00758 afm_compare_kern_pairs ); 00759 return PSaux_Err_Ok; 00760 00761 case AFM_TOKEN_UNKNOWN: 00762 break; 00763 00764 default: 00765 goto Fail; 00766 } 00767 } 00768 00769 Fail: 00770 return PSaux_Err_Syntax_Error; 00771 } 00772 00773 00774 static FT_Error 00775 afm_parse_kern_data( AFM_Parser parser ) 00776 { 00777 FT_Error error; 00778 char* key; 00779 FT_Offset len; 00780 00781 00782 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 00783 { 00784 switch ( afm_tokenize( key, len ) ) 00785 { 00786 case AFM_TOKEN_STARTTRACKKERN: 00787 error = afm_parse_track_kern( parser ); 00788 if ( error ) 00789 return error; 00790 break; 00791 00792 case AFM_TOKEN_STARTKERNPAIRS: 00793 case AFM_TOKEN_STARTKERNPAIRS0: 00794 error = afm_parse_kern_pairs( parser ); 00795 if ( error ) 00796 return error; 00797 break; 00798 00799 case AFM_TOKEN_ENDKERNDATA: 00800 case AFM_TOKEN_ENDFONTMETRICS: 00801 return PSaux_Err_Ok; 00802 00803 case AFM_TOKEN_UNKNOWN: 00804 break; 00805 00806 default: 00807 goto Fail; 00808 } 00809 } 00810 00811 Fail: 00812 return PSaux_Err_Syntax_Error; 00813 } 00814 00815 00816 static FT_Error 00817 afm_parser_skip_section( AFM_Parser parser, 00818 FT_UInt n, 00819 AFM_Token end_section ) 00820 { 00821 char* key; 00822 FT_Offset len; 00823 00824 00825 while ( n-- > 0 ) 00826 { 00827 key = afm_parser_next_key( parser, 1, NULL ); 00828 if ( !key ) 00829 goto Fail; 00830 } 00831 00832 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 00833 { 00834 AFM_Token token = afm_tokenize( key, len ); 00835 00836 00837 if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS ) 00838 return PSaux_Err_Ok; 00839 } 00840 00841 Fail: 00842 return PSaux_Err_Syntax_Error; 00843 } 00844 00845 00846 FT_LOCAL_DEF( FT_Error ) 00847 afm_parser_parse( AFM_Parser parser ) 00848 { 00849 FT_Memory memory = parser->memory; 00850 AFM_FontInfo fi = parser->FontInfo; 00851 FT_Error error = PSaux_Err_Syntax_Error; 00852 char* key; 00853 FT_Offset len; 00854 FT_Int metrics_sets = 0; 00855 00856 00857 if ( !fi ) 00858 return PSaux_Err_Invalid_Argument; 00859 00860 key = afm_parser_next_key( parser, 1, &len ); 00861 if ( !key || len != 16 || 00862 ft_strncmp( key, "StartFontMetrics", 16 ) != 0 ) 00863 return PSaux_Err_Unknown_File_Format; 00864 00865 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 00866 { 00867 AFM_ValueRec shared_vals[4]; 00868 00869 00870 switch ( afm_tokenize( key, len ) ) 00871 { 00872 case AFM_TOKEN_METRICSSETS: 00873 if ( afm_parser_read_int( parser, &metrics_sets ) ) 00874 goto Fail; 00875 00876 if ( metrics_sets != 0 && metrics_sets != 2 ) 00877 { 00878 error = PSaux_Err_Unimplemented_Feature; 00879 00880 goto Fail; 00881 } 00882 break; 00883 00884 case AFM_TOKEN_ISCIDFONT: 00885 shared_vals[0].type = AFM_VALUE_TYPE_BOOL; 00886 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) 00887 goto Fail; 00888 00889 fi->IsCIDFont = shared_vals[0].u.b; 00890 break; 00891 00892 case AFM_TOKEN_FONTBBOX: 00893 shared_vals[0].type = AFM_VALUE_TYPE_FIXED; 00894 shared_vals[1].type = AFM_VALUE_TYPE_FIXED; 00895 shared_vals[2].type = AFM_VALUE_TYPE_FIXED; 00896 shared_vals[3].type = AFM_VALUE_TYPE_FIXED; 00897 if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 ) 00898 goto Fail; 00899 00900 fi->FontBBox.xMin = shared_vals[0].u.f; 00901 fi->FontBBox.yMin = shared_vals[1].u.f; 00902 fi->FontBBox.xMax = shared_vals[2].u.f; 00903 fi->FontBBox.yMax = shared_vals[3].u.f; 00904 break; 00905 00906 case AFM_TOKEN_ASCENDER: 00907 shared_vals[0].type = AFM_VALUE_TYPE_FIXED; 00908 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) 00909 goto Fail; 00910 00911 fi->Ascender = shared_vals[0].u.f; 00912 break; 00913 00914 case AFM_TOKEN_DESCENDER: 00915 shared_vals[0].type = AFM_VALUE_TYPE_FIXED; 00916 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) 00917 goto Fail; 00918 00919 fi->Descender = shared_vals[0].u.f; 00920 break; 00921 00922 case AFM_TOKEN_STARTCHARMETRICS: 00923 { 00924 FT_Int n = 0; 00925 00926 00927 if ( afm_parser_read_int( parser, &n ) ) 00928 goto Fail; 00929 00930 error = afm_parser_skip_section( parser, n, 00931 AFM_TOKEN_ENDCHARMETRICS ); 00932 if ( error ) 00933 return error; 00934 } 00935 break; 00936 00937 case AFM_TOKEN_STARTKERNDATA: 00938 error = afm_parse_kern_data( parser ); 00939 if ( error ) 00940 goto Fail; 00941 /* fall through since we only support kern data */ 00942 00943 case AFM_TOKEN_ENDFONTMETRICS: 00944 return PSaux_Err_Ok; 00945 00946 default: 00947 break; 00948 } 00949 } 00950 00951 Fail: 00952 FT_FREE( fi->TrackKerns ); 00953 fi->NumTrackKern = 0; 00954 00955 FT_FREE( fi->KernPairs ); 00956 fi->NumKernPair = 0; 00957 00958 fi->IsCIDFont = 0; 00959 00960 return error; 00961 } 00962 00963 00964 /* END */ Generated on Sat May 26 2012 04:32:53 for ReactOS by
1.7.6.1
|