| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 | 8 |
| 9 #include "SkData.h" | 9 #include "SkData.h" |
| 10 #include "SkFixed.h" | 10 #include "SkFixed.h" |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 return j + 1; | 275 return j + 1; |
| 276 } | 276 } |
| 277 | 277 |
| 278 void SkPDFUtils::AppendScalar(SkScalar value, SkWStream* stream) { | 278 void SkPDFUtils::AppendScalar(SkScalar value, SkWStream* stream) { |
| 279 char result[kMaximumFloatDecimalLength]; | 279 char result[kMaximumFloatDecimalLength]; |
| 280 size_t len = SkPDFUtils::FloatToDecimal(SkScalarToFloat(value), result); | 280 size_t len = SkPDFUtils::FloatToDecimal(SkScalarToFloat(value), result); |
| 281 SkASSERT(len < kMaximumFloatDecimalLength); | 281 SkASSERT(len < kMaximumFloatDecimalLength); |
| 282 stream->write(result, len); | 282 stream->write(result, len); |
| 283 } | 283 } |
| 284 | 284 |
| 285 // Return pow(10.0, e), optimized for common cases. |
| 286 inline double pow10(int e) { |
| 287 switch (e) { |
| 288 case 0: return 1.0; // common cases |
| 289 case 1: return 10.0; |
| 290 case 2: return 100.0; |
| 291 case 3: return 1e+03; |
| 292 case 4: return 1e+04; |
| 293 case 5: return 1e+05; |
| 294 case 6: return 1e+06; |
| 295 case 7: return 1e+07; |
| 296 case 8: return 1e+08; |
| 297 case 9: return 1e+09; |
| 298 case 10: return 1e+10; |
| 299 case 11: return 1e+11; |
| 300 case 12: return 1e+12; |
| 301 case 13: return 1e+13; |
| 302 case 14: return 1e+14; |
| 303 case 15: return 1e+15; |
| 304 default: |
| 305 if (e > 15) { |
| 306 double value = 1e+15; |
| 307 while (e-- > 15) { value *= 10.0; } |
| 308 return value; |
| 309 } else { |
| 310 SkASSERT(e < 0); |
| 311 double value = 1.0; |
| 312 while (e++ < 0) { value /= 10.0; } |
| 313 return value; |
| 314 } |
| 315 } |
| 316 } |
| 317 |
| 285 /** Write a string into result, includeing a terminating '\0' (for | 318 /** Write a string into result, includeing a terminating '\0' (for |
| 286 unit testing). Return strlen(result) (for SkWStream::write) The | 319 unit testing). Return strlen(result) (for SkWStream::write) The |
| 287 resulting string will be in the form /[-]?([0-9]*.)?[0-9]+/ and | 320 resulting string will be in the form /[-]?([0-9]*.)?[0-9]+/ and |
| 288 sscanf(result, "%f", &x) will return the original value iff the | 321 sscanf(result, "%f", &x) will return the original value iff the |
| 289 value is finite. This function accepts all possible input values. | 322 value is finite. This function accepts all possible input values. |
| 290 | 323 |
| 291 Motivation: "PDF does not support [numbers] in exponential format | 324 Motivation: "PDF does not support [numbers] in exponential format |
| 292 (such as 6.02e23)." Otherwise, this function would rely on a | 325 (such as 6.02e23)." Otherwise, this function would rely on a |
| 293 sprintf-type function from the standard library. */ | 326 sprintf-type function from the standard library. */ |
| 294 size_t SkPDFUtils::FloatToDecimal(float value, | 327 size_t SkPDFUtils::FloatToDecimal(float value, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 320 if (value == SK_FloatNegativeInfinity) { | 353 if (value == SK_FloatNegativeInfinity) { |
| 321 value = -FLT_MAX; // nearest finite float. | 354 value = -FLT_MAX; // nearest finite float. |
| 322 } | 355 } |
| 323 if (!std::isfinite(value) || value == 0.0f) { | 356 if (!std::isfinite(value) || value == 0.0f) { |
| 324 // NAN is unsupported in PDF. Always output a valid number. | 357 // NAN is unsupported in PDF. Always output a valid number. |
| 325 // Also catch zero here, as a special case. | 358 // Also catch zero here, as a special case. |
| 326 *output++ = '0'; | 359 *output++ = '0'; |
| 327 *output = '\0'; | 360 *output = '\0'; |
| 328 return output - result; | 361 return output - result; |
| 329 } | 362 } |
| 330 // Inspired by: | |
| 331 // http://www.exploringbinary.com/quick-and-dirty-floating-point-to-decimal-
conversion/ | |
| 332 | |
| 333 if (value < 0.0) { | 363 if (value < 0.0) { |
| 334 *output++ = '-'; | 364 *output++ = '-'; |
| 335 value = -value; | 365 value = -value; |
| 336 } | 366 } |
| 337 SkASSERT(value >= 0.0f); | 367 SkASSERT(value >= 0.0f); |
| 338 | 368 |
| 339 // Must use double math to keep precision right. | 369 int binaryExponent; |
| 340 double intPart; | 370 (void)std::frexp(value, &binaryExponent); |
| 341 double fracPart = std::modf(static_cast<double>(value), &intPart); | 371 static const double kLog2 = 0.3010299956639812; // log10(2.0); |
| 342 SkASSERT(intPart + fracPart == static_cast<double>(value)); | 372 int decimalExponent = static_cast<int>(std::floor(kLog2 * binaryExponent)); |
| 343 size_t significantDigits = 0; | 373 int decimalShift = decimalExponent - 8; |
| 344 const size_t maxSignificantDigits = 9; | 374 double power = pow10(-decimalShift); |
| 345 // Any fewer significant digits loses precision. The unit test | 375 int32_t d = static_cast<int32_t>(value * power + 0.5); |
| 346 // checks round-trip correctness. | 376 // SkASSERT(value == (float)(d * pow(10.0, decimalShift))); |
| 347 SkASSERT(intPart >= 0.0 && fracPart >= 0.0); // negative handled already. | 377 SkASSERT(d <= 999999999); |
| 348 SkASSERT(intPart > 0.0 || fracPart > 0.0); // zero already caught. | 378 if (d > 167772159) { // floor(pow(10,1+log10(1<<24))) |
| 349 if (intPart > 0.0) { | 379 // need one fewer decimal digits for 24-bit precision. |
| 350 // put the intPart digits onto a stack for later reversal. | 380 decimalShift = decimalExponent - 7; |
| 351 char reversed[1 + FLT_MAX_10_EXP]; // 39 == 1 + FLT_MAX_10_EXP | 381 // SkASSERT(power * 0.1 = pow10(-decimalShift)); |
| 352 // the largest integer part is FLT_MAX; it has 39 decimal digits. | 382 // recalculate to get rounding right. |
| 353 size_t reversedIndex = 0; | 383 d = static_cast<int32_t>(value * (power * 0.1) + 0.5); |
| 384 SkASSERT(d <= 99999999); |
| 385 } |
| 386 while (d % 10 == 0) { |
| 387 d /= 10; |
| 388 ++decimalShift; |
| 389 } |
| 390 SkASSERT(d > 0); |
| 391 // SkASSERT(value == (float)(d * pow(10.0, decimalShift))); |
| 392 uint8_t buffer[9]; // decimal value buffer. |
| 393 int bufferIndex = 0; |
| 394 do { |
| 395 buffer[bufferIndex++] = d % 10; |
| 396 d /= 10; |
| 397 } while (d != 0); |
| 398 SkASSERT(bufferIndex <= (int)sizeof(buffer) && bufferIndex > 0); |
| 399 if (decimalShift >= 0) { |
| 354 do { | 400 do { |
| 355 SkASSERT(reversedIndex < sizeof(reversed)); | 401 --bufferIndex; |
| 356 int digit = static_cast<int>(std::fmod(intPart, 10.0)); | 402 *output++ = '0' + buffer[bufferIndex]; |
| 357 SkASSERT(digit >= 0 && digit <= 9); | 403 } while (bufferIndex); |
| 358 reversed[reversedIndex++] = '0' + digit; | 404 for (int i = 0; i < decimalShift; ++i) { |
| 359 intPart = std::floor(intPart / 10.0); | 405 *output++ = '0'; |
| 360 } while (intPart > 0.0); | |
| 361 significantDigits = reversedIndex; | |
| 362 SkASSERT(reversedIndex <= sizeof(reversed)); | |
| 363 SkASSERT(output + reversedIndex <= end); | |
| 364 while (reversedIndex-- > 0) { // pop from stack, append to result | |
| 365 *output++ = reversed[reversedIndex]; | |
| 366 } | 406 } |
| 367 } | 407 } else { |
| 368 if (fracPart > 0 && significantDigits < maxSignificantDigits) { | 408 int placesBeforeDecimal = bufferIndex + decimalShift; |
| 369 *output++ = '.'; | 409 if (placesBeforeDecimal > 0) { |
| 370 SkASSERT(output <= end); | 410 while (placesBeforeDecimal-- > 0) { |
| 371 do { | 411 --bufferIndex; |
| 372 fracPart = std::modf(fracPart * 10.0, &intPart); | 412 *output++ = '0' + buffer[bufferIndex]; |
| 373 int digit = static_cast<int>(intPart); | |
| 374 SkASSERT(digit >= 0 && digit <= 9); | |
| 375 *output++ = '0' + digit; | |
| 376 SkASSERT(output <= end); | |
| 377 if (digit > 0 || significantDigits > 0) { | |
| 378 // start counting significantDigits after first non-zero digit. | |
| 379 ++significantDigits; | |
| 380 } | 413 } |
| 381 } while (fracPart > 0.0 | 414 *output++ = '.'; |
| 382 && significantDigits < maxSignificantDigits | 415 } else { |
| 383 && output < end); | 416 *output++ = '.'; |
| 384 // When fracPart == 0, additional digits will be zero. | 417 int placesAfterDecimal = -placesBeforeDecimal; |
| 385 // When significantDigits == maxSignificantDigits, we can stop. | 418 while (placesAfterDecimal-- > 0) { |
| 386 // when output == end, we have filed the string. | 419 *output++ = '0'; |
| 387 // Note: denormalized numbers will not have the same number of | 420 } |
| 388 // significantDigits, but do not need them to round-trip. | 421 } |
| 422 while (bufferIndex > 0) { |
| 423 --bufferIndex; |
| 424 *output++ = '0' + buffer[bufferIndex]; |
| 425 if (output == end) { |
| 426 break; // denormalized: don't need extra precision. |
| 427 // Note: denormalized numbers will not have the same number of |
| 428 // significantDigits, but do not need them to round-trip. |
| 429 } |
| 430 } |
| 389 } | 431 } |
| 390 SkASSERT(output <= end); | 432 SkASSERT(output <= end); |
| 391 *output = '\0'; | 433 *output = '\0'; |
| 392 return output - result; | 434 return output - result; |
| 393 } | 435 } |
| 394 | 436 |
| 395 void SkPDFUtils::WriteString(SkWStream* wStream, const char* cin, size_t len) { | 437 void SkPDFUtils::WriteString(SkWStream* wStream, const char* cin, size_t len) { |
| 396 SkDEBUGCODE(static const size_t kMaxLen = 65535;) | 438 SkDEBUGCODE(static const size_t kMaxLen = 65535;) |
| 397 SkASSERT(len <= kMaxLen); | 439 SkASSERT(len <= kMaxLen); |
| 398 | 440 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 uint8_t c = static_cast<uint8_t>(cin[i]); | 472 uint8_t c = static_cast<uint8_t>(cin[i]); |
| 431 static const char gHex[] = "0123456789ABCDEF"; | 473 static const char gHex[] = "0123456789ABCDEF"; |
| 432 char hexValue[2]; | 474 char hexValue[2]; |
| 433 hexValue[0] = gHex[(c >> 4) & 0xF]; | 475 hexValue[0] = gHex[(c >> 4) & 0xF]; |
| 434 hexValue[1] = gHex[ c & 0xF]; | 476 hexValue[1] = gHex[ c & 0xF]; |
| 435 wStream->write(hexValue, 2); | 477 wStream->write(hexValue, 2); |
| 436 } | 478 } |
| 437 wStream->writeText(">"); | 479 wStream->writeText(">"); |
| 438 } | 480 } |
| 439 } | 481 } |
| OLD | NEW |