| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "SkPDFTypes.h" | 9 #include "SkPDFTypes.h" |
| 10 #include "SkPDFUtils.h" |
| 10 #include "SkStream.h" | 11 #include "SkStream.h" |
| 11 | 12 |
| 12 #ifdef SK_BUILD_FOR_WIN | 13 #ifdef SK_BUILD_FOR_WIN |
| 13 #define SNPRINTF _snprintf | 14 #define SNPRINTF _snprintf |
| 14 #else | 15 #else |
| 15 #define SNPRINTF snprintf | 16 #define SNPRINTF snprintf |
| 16 #endif | 17 #endif |
| 17 | 18 |
| 18 //////////////////////////////////////////////////////////////////////////////// | 19 //////////////////////////////////////////////////////////////////////////////// |
| 19 | 20 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 | 128 |
| 128 static SkString escape_name(const SkString& name) { | 129 static SkString escape_name(const SkString& name) { |
| 129 return escape_name(name.c_str(), name.size()); | 130 return escape_name(name.c_str(), name.size()); |
| 130 } | 131 } |
| 131 | 132 |
| 132 static void write_string(SkWStream* o, const SkString& s) { | 133 static void write_string(SkWStream* o, const SkString& s) { |
| 133 o->write(s.c_str(), s.size()); | 134 o->write(s.c_str(), s.size()); |
| 134 } | 135 } |
| 135 | 136 |
| 136 static SkString format_string(const SkString& s) { | 137 static SkString format_string(const SkString& s) { |
| 137 return SkPDFString::FormatString(s.c_str(), s.size()); | 138 return SkPDFUtils::FormatString(s.c_str(), s.size()); |
| 138 } | 139 } |
| 139 | 140 |
| 140 static SkString format_string(const char* s) { | 141 static SkString format_string(const char* s) { |
| 141 return SkPDFString::FormatString(s, strlen(s)); | 142 return SkPDFUtils::FormatString(s, strlen(s)); |
| 142 } | 143 } |
| 143 | 144 |
| 144 void SkPDFUnion::emitObject(SkWStream* stream, | 145 void SkPDFUnion::emitObject(SkWStream* stream, |
| 145 const SkPDFObjNumMap& objNumMap, | 146 const SkPDFObjNumMap& objNumMap, |
| 146 const SkPDFSubstituteMap& substitutes) const { | 147 const SkPDFSubstituteMap& substitutes) const { |
| 147 switch (fType) { | 148 switch (fType) { |
| 148 case Type::kInt: | 149 case Type::kInt: |
| 149 stream->writeDecAsText(fIntValue); | 150 stream->writeDecAsText(fIntValue); |
| 150 return; | 151 return; |
| 151 case Type::kBool: | 152 case Type::kBool: |
| 152 stream->writeText(fBoolValue ? "true" : "false"); | 153 stream->writeText(fBoolValue ? "true" : "false"); |
| 153 return; | 154 return; |
| 154 case Type::kScalar: | 155 case Type::kScalar: |
| 155 SkPDFScalar::Append(fScalarValue, stream); | 156 SkPDFUtils::AppendScalar(fScalarValue, stream); |
| 156 return; | 157 return; |
| 157 case Type::kName: | 158 case Type::kName: |
| 158 stream->writeText("/"); | 159 stream->writeText("/"); |
| 159 SkASSERT(is_valid_name(fStaticString)); | 160 SkASSERT(is_valid_name(fStaticString)); |
| 160 stream->writeText(fStaticString); | 161 stream->writeText(fStaticString); |
| 161 return; | 162 return; |
| 162 case Type::kString: | 163 case Type::kString: |
| 163 SkASSERT(fStaticString); | 164 SkASSERT(fStaticString); |
| 164 write_string(stream, format_string(fStaticString)); | 165 write_string(stream, format_string(fStaticString)); |
| 165 return; | 166 return; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 void SkPDFAtom::emitObject(SkWStream* stream, | 275 void SkPDFAtom::emitObject(SkWStream* stream, |
| 275 const SkPDFObjNumMap& objNumMap, | 276 const SkPDFObjNumMap& objNumMap, |
| 276 const SkPDFSubstituteMap& substitutes) { | 277 const SkPDFSubstituteMap& substitutes) { |
| 277 fValue.emitObject(stream, objNumMap, substitutes); | 278 fValue.emitObject(stream, objNumMap, substitutes); |
| 278 } | 279 } |
| 279 void SkPDFAtom::addResources(SkPDFObjNumMap* map, | 280 void SkPDFAtom::addResources(SkPDFObjNumMap* map, |
| 280 const SkPDFSubstituteMap& substitutes) const { | 281 const SkPDFSubstituteMap& substitutes) const { |
| 281 fValue.addResources(map, substitutes); | 282 fValue.addResources(map, substitutes); |
| 282 } | 283 } |
| 283 #endif // 0 | 284 #endif // 0 |
| 284 //////////////////////////////////////////////////////////////////////////////// | |
| 285 | |
| 286 // static | |
| 287 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { | |
| 288 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and | |
| 289 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31). | |
| 290 // When using floats that are outside the whole value range, we can use | |
| 291 // integers instead. | |
| 292 | |
| 293 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS) | |
| 294 if (value > 32767 || value < -32767) { | |
| 295 stream->writeDecAsText(SkScalarRoundToInt(value)); | |
| 296 return; | |
| 297 } | |
| 298 | |
| 299 char buffer[SkStrAppendScalar_MaxSize]; | |
| 300 char* end = SkStrAppendFixed(buffer, SkScalarToFixed(value)); | |
| 301 stream->write(buffer, end - buffer); | |
| 302 return; | |
| 303 #endif // !SK_ALLOW_LARGE_PDF_SCALARS | |
| 304 | |
| 305 #if defined(SK_ALLOW_LARGE_PDF_SCALARS) | |
| 306 // Floats have 24bits of significance, so anything outside that range is | |
| 307 // no more precise than an int. (Plus PDF doesn't support scientific | |
| 308 // notation, so this clamps to SK_Max/MinS32). | |
| 309 if (value > (1 << 24) || value < -(1 << 24)) { | |
| 310 stream->writeDecAsText(value); | |
| 311 return; | |
| 312 } | |
| 313 // Continue to enforce the PDF limits for small floats. | |
| 314 if (value < 1.0f/65536 && value > -1.0f/65536) { | |
| 315 stream->writeDecAsText(0); | |
| 316 return; | |
| 317 } | |
| 318 // SkStrAppendFloat might still use scientific notation, so use snprintf | |
| 319 // directly.. | |
| 320 static const int kFloat_MaxSize = 19; | |
| 321 char buffer[kFloat_MaxSize]; | |
| 322 int len = SNPRINTF(buffer, kFloat_MaxSize, "%#.8f", value); | |
| 323 // %f always prints trailing 0s, so strip them. | |
| 324 for (; buffer[len - 1] == '0' && len > 0; len--) { | |
| 325 buffer[len - 1] = '\0'; | |
| 326 } | |
| 327 if (buffer[len - 1] == '.') { | |
| 328 buffer[len - 1] = '\0'; | |
| 329 } | |
| 330 stream->writeText(buffer); | |
| 331 return; | |
| 332 #endif // SK_ALLOW_LARGE_PDF_SCALARS | |
| 333 } | |
| 334 | 285 |
| 335 //////////////////////////////////////////////////////////////////////////////// | 286 //////////////////////////////////////////////////////////////////////////////// |
| 336 | 287 |
| 337 // static | |
| 338 | |
| 339 SkString SkPDFString::FormatString(const char* cin, size_t len) { | |
| 340 SkASSERT(len <= kMaxLen); | |
| 341 | |
| 342 // 7-bit clean is a heuristic to decide what string format to use; | |
| 343 // a 7-bit clean string should require little escaping. | |
| 344 bool sevenBitClean = true; | |
| 345 size_t characterCount = 2 + len; | |
| 346 for (size_t i = 0; i < len; i++) { | |
| 347 if (cin[i] > '~' || cin[i] < ' ') { | |
| 348 sevenBitClean = false; | |
| 349 break; | |
| 350 } | |
| 351 if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { | |
| 352 ++characterCount; | |
| 353 } | |
| 354 } | |
| 355 SkString result; | |
| 356 if (sevenBitClean) { | |
| 357 result.resize(characterCount); | |
| 358 char* str = result.writable_str(); | |
| 359 *str++ = '('; | |
| 360 for (size_t i = 0; i < len; i++) { | |
| 361 if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { | |
| 362 *str++ = '\\'; | |
| 363 } | |
| 364 *str++ = cin[i]; | |
| 365 } | |
| 366 *str++ = ')'; | |
| 367 } else { | |
| 368 result.resize(2 * len + 2); | |
| 369 char* str = result.writable_str(); | |
| 370 *str++ = '<'; | |
| 371 for (size_t i = 0; i < len; i++) { | |
| 372 uint8_t c = static_cast<uint8_t>(cin[i]); | |
| 373 static const char gHex[] = "0123456789ABCDEF"; | |
| 374 *str++ = gHex[(c >> 4) & 0xF]; | |
| 375 *str++ = gHex[(c ) & 0xF]; | |
| 376 } | |
| 377 *str++ = '>'; | |
| 378 } | |
| 379 return result; | |
| 380 } | |
| 381 | |
| 382 //////////////////////////////////////////////////////////////////////////////// | |
| 383 | |
| 384 SkPDFArray::SkPDFArray() {} | 288 SkPDFArray::SkPDFArray() {} |
| 385 SkPDFArray::~SkPDFArray() { | 289 SkPDFArray::~SkPDFArray() { |
| 386 for (SkPDFUnion& value : fValues) { | 290 for (SkPDFUnion& value : fValues) { |
| 387 value.~SkPDFUnion(); | 291 value.~SkPDFUnion(); |
| 388 } | 292 } |
| 389 fValues.reset(); | 293 fValues.reset(); |
| 390 } | 294 } |
| 391 | 295 |
| 392 int SkPDFArray::size() const { return fValues.count(); } | 296 int SkPDFArray::size() const { return fValues.count(); } |
| 393 | 297 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 fObjects.push(obj); | 480 fObjects.push(obj); |
| 577 return true; | 481 return true; |
| 578 } | 482 } |
| 579 | 483 |
| 580 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { | 484 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { |
| 581 int32_t* objectNumberFound = fObjectNumbers.find(obj); | 485 int32_t* objectNumberFound = fObjectNumbers.find(obj); |
| 582 SkASSERT(objectNumberFound); | 486 SkASSERT(objectNumberFound); |
| 583 return *objectNumberFound; | 487 return *objectNumberFound; |
| 584 } | 488 } |
| 585 | 489 |
| OLD | NEW |