1 /**************************************************************************** 2 * 3 * psconv.c 4 * 5 * Some convenience conversions (body). 6 * 7 * Copyright 2006-2018 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 ) PS_Conv_Strtol(FT_Byte ** cursor,FT_Byte * limit,FT_Long base)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 /* only a single sign is allowed */ 116 if ( *p == '-' || *p == '+' ) 117 return 0; 118 } 119 120 num_limit = 0x7FFFFFFFL / base; 121 c_limit = (FT_Char)( 0x7FFFFFFFL % base ); 122 123 for ( ; p < limit; p++ ) 124 { 125 FT_Char c; 126 127 128 if ( IS_PS_SPACE( *p ) || *p OP 0x80 ) 129 break; 130 131 c = ft_char_table[*p & 0x7F]; 132 133 if ( c < 0 || c >= base ) 134 break; 135 136 if ( num > num_limit || ( num == num_limit && c > c_limit ) ) 137 have_overflow = 1; 138 else 139 num = num * base + c; 140 } 141 142 *cursor = p; 143 144 if ( have_overflow ) 145 { 146 num = 0x7FFFFFFFL; 147 FT_TRACE4(( "!!!OVERFLOW:!!!" )); 148 } 149 150 if ( sign ) 151 num = -num; 152 153 return num; 154 155 Bad: 156 FT_TRACE4(( "!!!END OF DATA:!!!" )); 157 return 0; 158 } 159 160 161 FT_LOCAL_DEF( FT_Long ) PS_Conv_ToInt(FT_Byte ** cursor,FT_Byte * limit)162 PS_Conv_ToInt( FT_Byte** cursor, 163 FT_Byte* limit ) 164 165 { 166 FT_Byte* p = *cursor; 167 FT_Byte* curp; 168 169 FT_Long num; 170 171 172 curp = p; 173 num = PS_Conv_Strtol( &p, limit, 10 ); 174 175 if ( p == curp ) 176 return 0; 177 178 if ( p < limit && *p == '#' ) 179 { 180 p++; 181 182 curp = p; 183 num = PS_Conv_Strtol( &p, limit, num ); 184 185 if ( p == curp ) 186 return 0; 187 } 188 189 *cursor = p; 190 191 return num; 192 } 193 194 195 FT_LOCAL_DEF( FT_Fixed ) PS_Conv_ToFixed(FT_Byte ** cursor,FT_Byte * limit,FT_Long power_ten)196 PS_Conv_ToFixed( FT_Byte** cursor, 197 FT_Byte* limit, 198 FT_Long power_ten ) 199 { 200 FT_Byte* p = *cursor; 201 FT_Byte* curp; 202 203 FT_Fixed integral = 0; 204 FT_Long decimal = 0; 205 FT_Long divider = 1; 206 207 FT_Bool sign = 0; 208 FT_Bool have_overflow = 0; 209 FT_Bool have_underflow = 0; 210 211 212 if ( p >= limit ) 213 goto Bad; 214 215 if ( *p == '-' || *p == '+' ) 216 { 217 sign = FT_BOOL( *p == '-' ); 218 219 p++; 220 if ( p == limit ) 221 goto Bad; 222 223 /* only a single sign is allowed */ 224 if ( *p == '-' || *p == '+' ) 225 return 0; 226 } 227 228 /* read the integer part */ 229 if ( *p != '.' ) 230 { 231 curp = p; 232 integral = PS_Conv_ToInt( &p, limit ); 233 234 if ( p == curp ) 235 return 0; 236 237 if ( integral > 0x7FFF ) 238 have_overflow = 1; 239 else 240 integral = (FT_Fixed)( (FT_UInt32)integral << 16 ); 241 } 242 243 /* read the decimal part */ 244 if ( p < limit && *p == '.' ) 245 { 246 p++; 247 248 for ( ; p < limit; p++ ) 249 { 250 FT_Char c; 251 252 253 if ( IS_PS_SPACE( *p ) || *p OP 0x80 ) 254 break; 255 256 c = ft_char_table[*p & 0x7F]; 257 258 if ( c < 0 || c >= 10 ) 259 break; 260 261 /* only add digit if we don't overflow */ 262 if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL ) 263 { 264 decimal = decimal * 10 + c; 265 266 if ( !integral && power_ten > 0 ) 267 power_ten--; 268 else 269 divider *= 10; 270 } 271 } 272 } 273 274 /* read exponent, if any */ 275 if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) ) 276 { 277 FT_Long exponent; 278 279 280 p++; 281 282 curp = p; 283 exponent = PS_Conv_ToInt( &p, limit ); 284 285 if ( curp == p ) 286 return 0; 287 288 /* arbitrarily limit exponent */ 289 if ( exponent > 1000 ) 290 have_overflow = 1; 291 else if ( exponent < -1000 ) 292 have_underflow = 1; 293 else 294 power_ten += exponent; 295 } 296 297 *cursor = p; 298 299 if ( !integral && !decimal ) 300 return 0; 301 302 if ( have_overflow ) 303 goto Overflow; 304 if ( have_underflow ) 305 goto Underflow; 306 307 while ( power_ten > 0 ) 308 { 309 if ( integral >= 0xCCCCCCCL ) 310 goto Overflow; 311 integral *= 10; 312 313 if ( decimal >= 0xCCCCCCCL ) 314 { 315 if ( divider == 1 ) 316 goto Overflow; 317 divider /= 10; 318 } 319 else 320 decimal *= 10; 321 322 power_ten--; 323 } 324 325 while ( power_ten < 0 ) 326 { 327 integral /= 10; 328 if ( divider < 0xCCCCCCCL ) 329 divider *= 10; 330 else 331 decimal /= 10; 332 333 if ( !integral && !decimal ) 334 goto Underflow; 335 336 power_ten++; 337 } 338 339 if ( decimal ) 340 { 341 decimal = FT_DivFix( decimal, divider ); 342 /* it's not necessary to check this addition for overflow */ 343 /* due to the structure of the real number representation */ 344 integral += decimal; 345 } 346 347 Exit: 348 if ( sign ) 349 integral = -integral; 350 351 return integral; 352 353 Bad: 354 FT_TRACE4(( "!!!END OF DATA:!!!" )); 355 return 0; 356 357 Overflow: 358 integral = 0x7FFFFFFFL; 359 FT_TRACE4(( "!!!OVERFLOW:!!!" )); 360 goto Exit; 361 362 Underflow: 363 FT_TRACE4(( "!!!UNDERFLOW:!!!" )); 364 return 0; 365 } 366 367 368 #if 0 369 FT_LOCAL_DEF( FT_UInt ) 370 PS_Conv_StringDecode( FT_Byte** cursor, 371 FT_Byte* limit, 372 FT_Byte* buffer, 373 FT_Offset n ) 374 { 375 FT_Byte* p; 376 FT_UInt r = 0; 377 378 379 for ( p = *cursor; r < n && p < limit; p++ ) 380 { 381 FT_Byte b; 382 383 384 if ( *p != '\\' ) 385 { 386 buffer[r++] = *p; 387 388 continue; 389 } 390 391 p++; 392 393 switch ( *p ) 394 { 395 case 'n': 396 b = '\n'; 397 break; 398 case 'r': 399 b = '\r'; 400 break; 401 case 't': 402 b = '\t'; 403 break; 404 case 'b': 405 b = '\b'; 406 break; 407 case 'f': 408 b = '\f'; 409 break; 410 case '\r': 411 p++; 412 if ( *p != '\n' ) 413 { 414 b = *p; 415 416 break; 417 } 418 /* no break */ 419 case '\n': 420 continue; 421 break; 422 default: 423 if ( IS_PS_DIGIT( *p ) ) 424 { 425 b = *p - '0'; 426 427 p++; 428 429 if ( IS_PS_DIGIT( *p ) ) 430 { 431 b = b * 8 + *p - '0'; 432 433 p++; 434 435 if ( IS_PS_DIGIT( *p ) ) 436 b = b * 8 + *p - '0'; 437 else 438 { 439 buffer[r++] = b; 440 b = *p; 441 } 442 } 443 else 444 { 445 buffer[r++] = b; 446 b = *p; 447 } 448 } 449 else 450 b = *p; 451 break; 452 } 453 454 buffer[r++] = b; 455 } 456 457 *cursor = p; 458 459 return r; 460 } 461 #endif /* 0 */ 462 463 464 FT_LOCAL_DEF( FT_UInt ) PS_Conv_ASCIIHexDecode(FT_Byte ** cursor,FT_Byte * limit,FT_Byte * buffer,FT_Offset n)465 PS_Conv_ASCIIHexDecode( FT_Byte** cursor, 466 FT_Byte* limit, 467 FT_Byte* buffer, 468 FT_Offset n ) 469 { 470 FT_Byte* p; 471 FT_UInt r = 0; 472 FT_UInt w = 0; 473 FT_UInt pad = 0x01; 474 475 476 n *= 2; 477 478 #if 1 479 480 p = *cursor; 481 482 if ( p >= limit ) 483 return 0; 484 485 if ( n > (FT_UInt)( limit - p ) ) 486 n = (FT_UInt)( limit - p ); 487 488 /* we try to process two nibbles at a time to be as fast as possible */ 489 for ( ; r < n; r++ ) 490 { 491 FT_UInt c = p[r]; 492 493 494 if ( IS_PS_SPACE( c ) ) 495 continue; 496 497 if ( c OP 0x80 ) 498 break; 499 500 c = (FT_UInt)ft_char_table[c & 0x7F]; 501 if ( c >= 16 ) 502 break; 503 504 pad = ( pad << 4 ) | c; 505 if ( pad & 0x100 ) 506 { 507 buffer[w++] = (FT_Byte)pad; 508 pad = 0x01; 509 } 510 } 511 512 if ( pad != 0x01 ) 513 buffer[w++] = (FT_Byte)( pad << 4 ); 514 515 *cursor = p + r; 516 517 return w; 518 519 #else /* 0 */ 520 521 for ( r = 0; r < n; r++ ) 522 { 523 FT_Char c; 524 525 526 if ( IS_PS_SPACE( *p ) ) 527 continue; 528 529 if ( *p OP 0x80 ) 530 break; 531 532 c = ft_char_table[*p & 0x7F]; 533 534 if ( (unsigned)c >= 16 ) 535 break; 536 537 if ( r & 1 ) 538 { 539 *buffer = (FT_Byte)(*buffer + c); 540 buffer++; 541 } 542 else 543 *buffer = (FT_Byte)(c << 4); 544 545 r++; 546 } 547 548 *cursor = p; 549 550 return ( r + 1 ) / 2; 551 552 #endif /* 0 */ 553 554 } 555 556 557 FT_LOCAL_DEF( FT_UInt ) PS_Conv_EexecDecode(FT_Byte ** cursor,FT_Byte * limit,FT_Byte * buffer,FT_Offset n,FT_UShort * seed)558 PS_Conv_EexecDecode( FT_Byte** cursor, 559 FT_Byte* limit, 560 FT_Byte* buffer, 561 FT_Offset n, 562 FT_UShort* seed ) 563 { 564 FT_Byte* p; 565 FT_UInt r; 566 FT_UInt s = *seed; 567 568 569 #if 1 570 571 p = *cursor; 572 573 if ( p >= limit ) 574 return 0; 575 576 if ( n > (FT_UInt)(limit - p) ) 577 n = (FT_UInt)(limit - p); 578 579 for ( r = 0; r < n; r++ ) 580 { 581 FT_UInt val = p[r]; 582 FT_UInt b = ( val ^ ( s >> 8 ) ); 583 584 585 s = ( (val + s)*52845U + 22719 ) & 0xFFFFU; 586 buffer[r] = (FT_Byte) b; 587 } 588 589 *cursor = p + n; 590 *seed = (FT_UShort)s; 591 592 #else /* 0 */ 593 594 for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ ) 595 { 596 FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) ); 597 598 599 s = (FT_UShort)( ( *p + s ) * 52845U + 22719 ); 600 *buffer++ = b; 601 } 602 *cursor = p; 603 *seed = s; 604 605 #endif /* 0 */ 606 607 return r; 608 } 609 610 611 /* END */ 612