1/***************************************************************************/ 2/* */ 3/* psconv.c */ 4/* */ 5/* Some convenience conversions (body). */ 6/* */ 7/* Copyright 2006-2015 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 /* only add digit if we don't overflow */ 254 if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL ) 255 { 256 decimal = decimal * 10 + c; 257 258 if ( !integral && power_ten > 0 ) 259 power_ten--; 260 else 261 divider *= 10; 262 } 263 } 264 } 265 266 /* read exponent, if any */ 267 if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) ) 268 { 269 FT_Long exponent; 270 271 272 p++; 273 274 curp = p; 275 exponent = PS_Conv_ToInt( &p, limit ); 276 277 if ( curp == p ) 278 return 0; 279 280 /* arbitrarily limit exponent */ 281 if ( exponent > 1000 ) 282 have_overflow = 1; 283 else if ( exponent < -1000 ) 284 have_underflow = 1; 285 else 286 power_ten += exponent; 287 } 288 289 *cursor = p; 290 291 if ( !integral && !decimal ) 292 return 0; 293 294 if ( have_overflow ) 295 goto Overflow; 296 if ( have_underflow ) 297 goto Underflow; 298 299 while ( power_ten > 0 ) 300 { 301 if ( integral >= 0xCCCCCCCL ) 302 goto Overflow; 303 integral *= 10; 304 305 if ( decimal >= 0xCCCCCCCL ) 306 { 307 if ( divider == 1 ) 308 goto Overflow; 309 divider /= 10; 310 } 311 else 312 decimal *= 10; 313 314 power_ten--; 315 } 316 317 while ( power_ten < 0 ) 318 { 319 integral /= 10; 320 if ( divider < 0xCCCCCCCL ) 321 divider *= 10; 322 else 323 decimal /= 10; 324 325 if ( !integral && !decimal ) 326 goto Underflow; 327 328 power_ten++; 329 } 330 331 if ( decimal ) 332 { 333 decimal = FT_DivFix( decimal, divider ); 334 /* it's not necessary to check this addition for overflow */ 335 /* due to the structure of the real number representation */ 336 integral += decimal; 337 } 338 339 Exit: 340 if ( sign ) 341 integral = -integral; 342 343 return integral; 344 345 Bad: 346 FT_TRACE4(( "!!!END OF DATA:!!!" )); 347 return 0; 348 349 Overflow: 350 integral = 0x7FFFFFFFL; 351 FT_TRACE4(( "!!!OVERFLOW:!!!" )); 352 goto Exit; 353 354 Underflow: 355 FT_TRACE4(( "!!!UNDERFLOW:!!!" )); 356 return 0; 357 } 358 359 360#if 0 361 FT_LOCAL_DEF( FT_UInt ) 362 PS_Conv_StringDecode( FT_Byte** cursor, 363 FT_Byte* limit, 364 FT_Byte* buffer, 365 FT_Offset n ) 366 { 367 FT_Byte* p; 368 FT_UInt r = 0; 369 370 371 for ( p = *cursor; r < n && p < limit; p++ ) 372 { 373 FT_Byte b; 374 375 376 if ( *p != '\\' ) 377 { 378 buffer[r++] = *p; 379 380 continue; 381 } 382 383 p++; 384 385 switch ( *p ) 386 { 387 case 'n': 388 b = '\n'; 389 break; 390 case 'r': 391 b = '\r'; 392 break; 393 case 't': 394 b = '\t'; 395 break; 396 case 'b': 397 b = '\b'; 398 break; 399 case 'f': 400 b = '\f'; 401 break; 402 case '\r': 403 p++; 404 if ( *p != '\n' ) 405 { 406 b = *p; 407 408 break; 409 } 410 /* no break */ 411 case '\n': 412 continue; 413 break; 414 default: 415 if ( IS_PS_DIGIT( *p ) ) 416 { 417 b = *p - '0'; 418 419 p++; 420 421 if ( IS_PS_DIGIT( *p ) ) 422 { 423 b = b * 8 + *p - '0'; 424 425 p++; 426 427 if ( IS_PS_DIGIT( *p ) ) 428 b = b * 8 + *p - '0'; 429 else 430 { 431 buffer[r++] = b; 432 b = *p; 433 } 434 } 435 else 436 { 437 buffer[r++] = b; 438 b = *p; 439 } 440 } 441 else 442 b = *p; 443 break; 444 } 445 446 buffer[r++] = b; 447 } 448 449 *cursor = p; 450 451 return r; 452 } 453#endif /* 0 */ 454 455 456 FT_LOCAL_DEF( FT_UInt ) 457 PS_Conv_ASCIIHexDecode( FT_Byte** cursor, 458 FT_Byte* limit, 459 FT_Byte* buffer, 460 FT_Offset n ) 461 { 462 FT_Byte* p; 463 FT_UInt r = 0; 464 FT_UInt w = 0; 465 FT_UInt pad = 0x01; 466 467 468 n *= 2; 469 470#if 1 471 472 p = *cursor; 473 474 if ( p >= limit ) 475 return 0; 476 477 if ( n > (FT_UInt)( limit - p ) ) 478 n = (FT_UInt)( limit - p ); 479 480 /* we try to process two nibbles at a time to be as fast as possible */ 481 for ( ; r < n; r++ ) 482 { 483 FT_UInt c = p[r]; 484 485 486 if ( IS_PS_SPACE( c ) ) 487 continue; 488 489 if ( c OP 0x80 ) 490 break; 491 492 c = (FT_UInt)ft_char_table[c & 0x7F]; 493 if ( c >= 16 ) 494 break; 495 496 pad = ( pad << 4 ) | c; 497 if ( pad & 0x100 ) 498 { 499 buffer[w++] = (FT_Byte)pad; 500 pad = 0x01; 501 } 502 } 503 504 if ( pad != 0x01 ) 505 buffer[w++] = (FT_Byte)( pad << 4 ); 506 507 *cursor = p + r; 508 509 return w; 510 511#else /* 0 */ 512 513 for ( r = 0; r < n; r++ ) 514 { 515 FT_Char c; 516 517 518 if ( IS_PS_SPACE( *p ) ) 519 continue; 520 521 if ( *p OP 0x80 ) 522 break; 523 524 c = ft_char_table[*p & 0x7F]; 525 526 if ( (unsigned)c >= 16 ) 527 break; 528 529 if ( r & 1 ) 530 { 531 *buffer = (FT_Byte)(*buffer + c); 532 buffer++; 533 } 534 else 535 *buffer = (FT_Byte)(c << 4); 536 537 r++; 538 } 539 540 *cursor = p; 541 542 return ( r + 1 ) / 2; 543 544#endif /* 0 */ 545 546 } 547 548 549 FT_LOCAL_DEF( FT_UInt ) 550 PS_Conv_EexecDecode( FT_Byte** cursor, 551 FT_Byte* limit, 552 FT_Byte* buffer, 553 FT_Offset n, 554 FT_UShort* seed ) 555 { 556 FT_Byte* p; 557 FT_UInt r; 558 FT_UInt s = *seed; 559 560 561#if 1 562 563 p = *cursor; 564 565 if ( p >= limit ) 566 return 0; 567 568 if ( n > (FT_UInt)(limit - p) ) 569 n = (FT_UInt)(limit - p); 570 571 for ( r = 0; r < n; r++ ) 572 { 573 FT_UInt val = p[r]; 574 FT_UInt b = ( val ^ ( s >> 8 ) ); 575 576 577 s = ( (val + s)*52845U + 22719 ) & 0xFFFFU; 578 buffer[r] = (FT_Byte) b; 579 } 580 581 *cursor = p + n; 582 *seed = (FT_UShort)s; 583 584#else /* 0 */ 585 586 for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ ) 587 { 588 FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) ); 589 590 591 s = (FT_UShort)( ( *p + s ) * 52845U + 22719 ); 592 *buffer++ = b; 593 } 594 *cursor = p; 595 *seed = s; 596 597#endif /* 0 */ 598 599 return r; 600 } 601 602 603/* END */ 604