1 /***************************************************************************/ 2 /* */ 3 /* psconv.c */ 4 /* */ 5 /* Some convenience conversions (body). */ 6 /* */ 7 /* Copyright 2006, 2008, 2009, 2012-2013 by */ 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9 /* */ 10 /* This file is part of the FreeType project, and may only be used, */ 11 /* modified, and distributed under the terms of the FreeType project */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13 /* this file you indicate that you have read the license and */ 14 /* understand and accept it fully. */ 15 /* */ 16 /***************************************************************************/ 17 18 19 #include <ft2build.h> 20 #include FT_INTERNAL_POSTSCRIPT_AUX_H 21 #include FT_INTERNAL_DEBUG_H 22 23 #include "psconv.h" 24 #include "psauxerr.h" 25 26 27 /*************************************************************************/ 28 /* */ 29 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 30 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 31 /* messages during execution. */ 32 /* */ 33 #undef FT_COMPONENT 34 #define FT_COMPONENT trace_psconv 35 36 37 /* The following array is used by various functions to quickly convert */ 38 /* digits (both decimal and non-decimal) into numbers. */ 39 40 #if 'A' == 65 41 /* ASCII */ 42 43 static const FT_Char ft_char_table[128] = 44 { 45 /* 0x00 */ 46 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 47 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 48 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 49 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, 50 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 51 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, 52 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 53 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, 54 }; 55 56 /* no character >= 0x80 can represent a valid number */ 57 #define OP >= 58 59 #endif /* 'A' == 65 */ 60 61 #if 'A' == 193 62 /* EBCDIC */ 63 64 static const FT_Char ft_char_table[128] = 65 { 66 /* 0x80 */ 67 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1, 68 -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, 69 -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, 70 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1, 72 -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, 73 -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, 74 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, 75 }; 76 77 /* no character < 0x80 can represent a valid number */ 78 #define OP < 79 80 #endif /* 'A' == 193 */ 81 82 83 FT_LOCAL_DEF( FT_Long ) 84 PS_Conv_Strtol( FT_Byte** cursor, 85 FT_Byte* limit, 86 FT_Long base ) 87 { 88 FT_Byte* p = *cursor; 89 90 FT_Long num = 0; 91 FT_Bool sign = 0; 92 FT_Bool have_overflow = 0; 93 94 FT_Long num_limit; 95 FT_Char c_limit; 96 97 98 if ( p >= limit ) 99 goto Bad; 100 101 if ( base < 2 || base > 36 ) 102 { 103 FT_TRACE4(( "!!!INVALID BASE:!!!" )); 104 return 0; 105 } 106 107 if ( *p == '-' || *p == '+' ) 108 { 109 sign = FT_BOOL( *p == '-' ); 110 111 p++; 112 if ( p == limit ) 113 goto Bad; 114 } 115 116 num_limit = 0x7FFFFFFFL / base; 117 c_limit = (FT_Char)( 0x7FFFFFFFL % base ); 118 119 for ( ; p < limit; p++ ) 120 { 121 FT_Char c; 122 123 124 if ( IS_PS_SPACE( *p ) || *p OP 0x80 ) 125 break; 126 127 c = ft_char_table[*p & 0x7f]; 128 129 if ( c < 0 || c >= base ) 130 break; 131 132 if ( num > num_limit || ( num == num_limit && c > c_limit ) ) 133 have_overflow = 1; 134 else 135 num = num * base + c; 136 } 137 138 *cursor = p; 139 140 if ( have_overflow ) 141 { 142 num = 0x7FFFFFFFL; 143 FT_TRACE4(( "!!!OVERFLOW:!!!" )); 144 } 145 146 if ( sign ) 147 num = -num; 148 149 return num; 150 151 Bad: 152 FT_TRACE4(( "!!!END OF DATA:!!!" )); 153 return 0; 154 } 155 156 157 FT_LOCAL_DEF( FT_Long ) 158 PS_Conv_ToInt( FT_Byte** cursor, 159 FT_Byte* limit ) 160 161 { 162 FT_Byte* p = *cursor; 163 FT_Byte* curp; 164 165 FT_Long num; 166 167 168 curp = p; 169 num = PS_Conv_Strtol( &p, limit, 10 ); 170 171 if ( p == curp ) 172 return 0; 173 174 if ( p < limit && *p == '#' ) 175 { 176 p++; 177 178 curp = p; 179 num = PS_Conv_Strtol( &p, limit, num ); 180 181 if ( p == curp ) 182 return 0; 183 } 184 185 *cursor = p; 186 187 return num; 188 } 189 190 191 FT_LOCAL_DEF( FT_Fixed ) 192 PS_Conv_ToFixed( FT_Byte** cursor, 193 FT_Byte* limit, 194 FT_Long power_ten ) 195 { 196 FT_Byte* p = *cursor; 197 FT_Byte* curp; 198 199 FT_Fixed integral = 0; 200 FT_Long decimal = 0; 201 FT_Long divider = 1; 202 203 FT_Bool sign = 0; 204 FT_Bool have_overflow = 0; 205 FT_Bool have_underflow = 0; 206 207 208 if ( p >= limit ) 209 goto Bad; 210 211 if ( *p == '-' || *p == '+' ) 212 { 213 sign = FT_BOOL( *p == '-' ); 214 215 p++; 216 if ( p == limit ) 217 goto Bad; 218 } 219 220 /* read the integer part */ 221 if ( *p != '.' ) 222 { 223 curp = p; 224 integral = PS_Conv_ToInt( &p, limit ); 225 226 if ( p == curp ) 227 return 0; 228 229 if ( integral > 0x7FFF ) 230 have_overflow = 1; 231 else 232 integral = (FT_Fixed)( (FT_UInt32)integral << 16 ); 233 } 234 235 /* read the decimal part */ 236 if ( p < limit && *p == '.' ) 237 { 238 p++; 239 240 for ( ; p < limit; p++ ) 241 { 242 FT_Char c; 243 244 245 if ( IS_PS_SPACE( *p ) || *p OP 0x80 ) 246 break; 247 248 c = ft_char_table[*p & 0x7f]; 249 250 if ( c < 0 || c >= 10 ) 251 break; 252 253 if ( decimal < 0xCCCCCCCL ) 254 { 255 decimal = decimal * 10 + c; 256 257 if ( !integral && power_ten > 0 ) 258 power_ten--; 259 else 260 divider *= 10; 261 } 262 } 263 } 264 265 /* read exponent, if any */ 266 if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) ) 267 { 268 FT_Long exponent; 269 270 271 p++; 272 273 curp = p; 274 exponent = PS_Conv_ToInt( &p, limit ); 275 276 if ( curp == p ) 277 return 0; 278 279 /* arbitrarily limit exponent */ 280 if ( exponent > 1000 ) 281 have_overflow = 1; 282 else if ( exponent < -1000 ) 283 have_underflow = 1; 284 else 285 power_ten += exponent; 286 } 287 288 *cursor = p; 289 290 if ( !integral && !decimal ) 291 return 0; 292 293 if ( have_overflow ) 294 goto Overflow; 295 if ( have_underflow ) 296 goto Underflow; 297 298 while ( power_ten > 0 ) 299 { 300 if ( integral >= 0xCCCCCCCL ) 301 goto Overflow; 302 integral *= 10; 303 304 if ( decimal >= 0xCCCCCCCL ) 305 { 306 if ( divider == 1 ) 307 goto Overflow; 308 divider /= 10; 309 } 310 else 311 decimal *= 10; 312 313 power_ten--; 314 } 315 316 while ( power_ten < 0 ) 317 { 318 integral /= 10; 319 if ( divider < 0xCCCCCCCL ) 320 divider *= 10; 321 else 322 decimal /= 10; 323 324 if ( !integral && !decimal ) 325 goto Underflow; 326 327 power_ten++; 328 } 329 330 if ( decimal ) 331 { 332 decimal = FT_DivFix( decimal, divider ); 333 /* it's not necessary to check this addition for overflow */ 334 /* due to the structure of the real number representation */ 335 integral += decimal; 336 } 337 338 Exit: 339 if ( sign ) 340 integral = -integral; 341 342 return integral; 343 344 Bad: 345 FT_TRACE4(( "!!!END OF DATA:!!!" )); 346 return 0; 347 348 Overflow: 349 integral = 0x7FFFFFFFL; 350 FT_TRACE4(( "!!!OVERFLOW:!!!" )); 351 goto Exit; 352 353 Underflow: 354 FT_TRACE4(( "!!!UNDERFLOW:!!!" )); 355 return 0; 356 } 357 358 359 #if 0 360 FT_LOCAL_DEF( FT_UInt ) 361 PS_Conv_StringDecode( FT_Byte** cursor, 362 FT_Byte* limit, 363 FT_Byte* buffer, 364 FT_Offset n ) 365 { 366 FT_Byte* p; 367 FT_UInt r = 0; 368 369 370 for ( p = *cursor; r < n && p < limit; p++ ) 371 { 372 FT_Byte b; 373 374 375 if ( *p != '\\' ) 376 { 377 buffer[r++] = *p; 378 379 continue; 380 } 381 382 p++; 383 384 switch ( *p ) 385 { 386 case 'n': 387 b = '\n'; 388 break; 389 case 'r': 390 b = '\r'; 391 break; 392 case 't': 393 b = '\t'; 394 break; 395 case 'b': 396 b = '\b'; 397 break; 398 case 'f': 399 b = '\f'; 400 break; 401 case '\r': 402 p++; 403 if ( *p != '\n' ) 404 { 405 b = *p; 406 407 break; 408 } 409 /* no break */ 410 case '\n': 411 continue; 412 break; 413 default: 414 if ( IS_PS_DIGIT( *p ) ) 415 { 416 b = *p - '0'; 417 418 p++; 419 420 if ( IS_PS_DIGIT( *p ) ) 421 { 422 b = b * 8 + *p - '0'; 423 424 p++; 425 426 if ( IS_PS_DIGIT( *p ) ) 427 b = b * 8 + *p - '0'; 428 else 429 { 430 buffer[r++] = b; 431 b = *p; 432 } 433 } 434 else 435 { 436 buffer[r++] = b; 437 b = *p; 438 } 439 } 440 else 441 b = *p; 442 break; 443 } 444 445 buffer[r++] = b; 446 } 447 448 *cursor = p; 449 450 return r; 451 } 452 #endif /* 0 */ 453 454 455 FT_LOCAL_DEF( FT_UInt ) 456 PS_Conv_ASCIIHexDecode( FT_Byte** cursor, 457 FT_Byte* limit, 458 FT_Byte* buffer, 459 FT_Offset n ) 460 { 461 FT_Byte* p; 462 FT_UInt r = 0; 463 FT_UInt w = 0; 464 FT_UInt pad = 0x01; 465 466 467 n *= 2; 468 469 #if 1 470 471 p = *cursor; 472 473 if ( p >= limit ) 474 return 0; 475 476 if ( n > (FT_UInt)( limit - p ) ) 477 n = (FT_UInt)( limit - p ); 478 479 /* we try to process two nibbles at a time to be as fast as possible */ 480 for ( ; r < n; r++ ) 481 { 482 FT_UInt c = p[r]; 483 484 485 if ( IS_PS_SPACE( c ) ) 486 continue; 487 488 if ( c OP 0x80 ) 489 break; 490 491 c = ft_char_table[c & 0x7F]; 492 if ( (unsigned)c >= 16 ) 493 break; 494 495 pad = ( pad << 4 ) | c; 496 if ( pad & 0x100 ) 497 { 498 buffer[w++] = (FT_Byte)pad; 499 pad = 0x01; 500 } 501 } 502 503 if ( pad != 0x01 ) 504 buffer[w++] = (FT_Byte)( pad << 4 ); 505 506 *cursor = p + r; 507 508 return w; 509 510 #else /* 0 */ 511 512 for ( r = 0; r < n; r++ ) 513 { 514 FT_Char c; 515 516 517 if ( IS_PS_SPACE( *p ) ) 518 continue; 519 520 if ( *p OP 0x80 ) 521 break; 522 523 c = ft_char_table[*p & 0x7f]; 524 525 if ( (unsigned)c >= 16 ) 526 break; 527 528 if ( r & 1 ) 529 { 530 *buffer = (FT_Byte)(*buffer + c); 531 buffer++; 532 } 533 else 534 *buffer = (FT_Byte)(c << 4); 535 536 r++; 537 } 538 539 *cursor = p; 540 541 return ( r + 1 ) / 2; 542 543 #endif /* 0 */ 544 545 } 546 547 548 FT_LOCAL_DEF( FT_UInt ) 549 PS_Conv_EexecDecode( FT_Byte** cursor, 550 FT_Byte* limit, 551 FT_Byte* buffer, 552 FT_Offset n, 553 FT_UShort* seed ) 554 { 555 FT_Byte* p; 556 FT_UInt r; 557 FT_UInt s = *seed; 558 559 560 #if 1 561 562 p = *cursor; 563 564 if ( p >= limit ) 565 return 0; 566 567 if ( n > (FT_UInt)(limit - p) ) 568 n = (FT_UInt)(limit - p); 569 570 for ( r = 0; r < n; r++ ) 571 { 572 FT_UInt val = p[r]; 573 FT_UInt b = ( val ^ ( s >> 8 ) ); 574 575 576 s = ( (val + s)*52845U + 22719 ) & 0xFFFFU; 577 buffer[r] = (FT_Byte) b; 578 } 579 580 *cursor = p + n; 581 *seed = (FT_UShort)s; 582 583 #else /* 0 */ 584 585 for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ ) 586 { 587 FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) ); 588 589 590 s = (FT_UShort)( ( *p + s ) * 52845U + 22719 ); 591 *buffer++ = b; 592 } 593 *cursor = p; 594 *seed = s; 595 596 #endif /* 0 */ 597 598 return r; 599 } 600 601 602 /* END */ 603