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