| 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 | 9 |
| 10 #include "SkPDFCatalog.h" | |
| 11 #include "SkPDFTypes.h" | 10 #include "SkPDFTypes.h" |
| 12 #include "SkStream.h" | 11 #include "SkStream.h" |
| 13 | 12 |
| 14 #ifdef SK_BUILD_FOR_WIN | 13 #ifdef SK_BUILD_FOR_WIN |
| 15 #define SNPRINTF _snprintf | 14 #define SNPRINTF _snprintf |
| 16 #else | 15 #else |
| 17 #define SNPRINTF snprintf | 16 #define SNPRINTF snprintf |
| 18 #endif | 17 #endif |
| 19 | 18 |
| 20 //////////////////////////////////////////////////////////////////////////////// | 19 //////////////////////////////////////////////////////////////////////////////// |
| 21 | 20 |
| 22 SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) { | 21 SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) { |
| 23 SkSafeRef(obj); | 22 SkSafeRef(obj); |
| 24 } | 23 } |
| 25 | 24 |
| 26 SkPDFObjRef::~SkPDFObjRef() {} | 25 SkPDFObjRef::~SkPDFObjRef() {} |
| 27 | 26 |
| 28 void SkPDFObjRef::emitObject(SkWStream* stream, SkPDFCatalog* catalog) { | 27 void SkPDFObjRef::emitObject(SkWStream* stream, |
| 29 SkPDFObject* obj = catalog->getSubstituteObject(fObj); | 28 const SkPDFObjNumMap& objNumMap, |
| 30 stream->writeDecAsText(catalog->getObjectNumber(obj)); | 29 const SkPDFSubstituteMap& substitutes) { |
| 30 SkPDFObject* obj = substitutes.getSubstitute(fObj); |
| 31 stream->writeDecAsText(objNumMap.getObjectNumber(obj)); |
| 31 stream->writeText(" 0 R"); // Generation number is always 0. | 32 stream->writeText(" 0 R"); // Generation number is always 0. |
| 32 } | 33 } |
| 33 | 34 |
| 34 void SkPDFObjRef::addResources(SkPDFCatalog* catalog) const { | 35 void SkPDFObjRef::addResources(SkPDFObjNumMap* catalog, |
| 35 SkPDFObject* obj = catalog->getSubstituteObject(fObj); | 36 const SkPDFSubstituteMap& substitutes) const { |
| 37 SkPDFObject* obj = substitutes.getSubstitute(fObj); |
| 36 SkASSERT(obj); | 38 SkASSERT(obj); |
| 37 if (catalog->addObject(obj)) { | 39 if (catalog->addObject(obj)) { |
| 38 obj->addResources(catalog); | 40 obj->addResources(catalog, substitutes); |
| 39 } | 41 } |
| 40 } | 42 } |
| 41 | 43 |
| 42 //////////////////////////////////////////////////////////////////////////////// | 44 //////////////////////////////////////////////////////////////////////////////// |
| 43 | 45 |
| 44 SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {} | 46 SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {} |
| 45 SkPDFInt::~SkPDFInt() {} | 47 SkPDFInt::~SkPDFInt() {} |
| 46 | 48 |
| 47 void SkPDFInt::emitObject(SkWStream* stream, SkPDFCatalog* catalog) { | 49 void SkPDFInt::emitObject(SkWStream* stream, |
| 50 const SkPDFObjNumMap&, |
| 51 const SkPDFSubstituteMap&) { |
| 48 stream->writeDecAsText(fValue); | 52 stream->writeDecAsText(fValue); |
| 49 } | 53 } |
| 50 | 54 |
| 51 //////////////////////////////////////////////////////////////////////////////// | 55 //////////////////////////////////////////////////////////////////////////////// |
| 52 | 56 |
| 53 SkPDFBool::SkPDFBool(bool value) : fValue(value) {} | 57 SkPDFBool::SkPDFBool(bool value) : fValue(value) {} |
| 54 SkPDFBool::~SkPDFBool() {} | 58 SkPDFBool::~SkPDFBool() {} |
| 55 | 59 |
| 56 void SkPDFBool::emitObject(SkWStream* stream, SkPDFCatalog* catalog) { | 60 void SkPDFBool::emitObject(SkWStream* stream, |
| 57 if (fValue) { | 61 const SkPDFObjNumMap&, |
| 58 stream->writeText("true"); | 62 const SkPDFSubstituteMap&) { |
| 59 } else { | 63 stream->writeText(fValue ? "true" : "false"); |
| 60 stream->writeText("false"); | |
| 61 } | |
| 62 } | 64 } |
| 63 | 65 |
| 64 //////////////////////////////////////////////////////////////////////////////// | 66 //////////////////////////////////////////////////////////////////////////////// |
| 65 | 67 |
| 66 SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {} | 68 SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {} |
| 67 SkPDFScalar::~SkPDFScalar() {} | 69 SkPDFScalar::~SkPDFScalar() {} |
| 68 | 70 |
| 69 void SkPDFScalar::emitObject(SkWStream* stream, SkPDFCatalog* catalog) { | 71 void SkPDFScalar::emitObject(SkWStream* stream, |
| 70 Append(fValue, stream); | 72 const SkPDFObjNumMap&, |
| 73 const SkPDFSubstituteMap&) { |
| 74 SkPDFScalar::Append(fValue, stream); |
| 71 } | 75 } |
| 72 | 76 |
| 73 // static | 77 // static |
| 74 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { | 78 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { |
| 75 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and | 79 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and |
| 76 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31). | 80 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31). |
| 77 // When using floats that are outside the whole value range, we can use | 81 // When using floats that are outside the whole value range, we can use |
| 78 // integers instead. | 82 // integers instead. |
| 79 | 83 |
| 80 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS) | 84 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS) |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 SkPDFString::SkPDFString(const SkString& value) | 132 SkPDFString::SkPDFString(const SkString& value) |
| 129 : fValue(FormatString(value.c_str(), value.size())) { | 133 : fValue(FormatString(value.c_str(), value.size())) { |
| 130 } | 134 } |
| 131 | 135 |
| 132 SkPDFString::SkPDFString(const uint16_t* value, size_t len, bool wideChars) | 136 SkPDFString::SkPDFString(const uint16_t* value, size_t len, bool wideChars) |
| 133 : fValue(FormatString(value, len, wideChars)) { | 137 : fValue(FormatString(value, len, wideChars)) { |
| 134 } | 138 } |
| 135 | 139 |
| 136 SkPDFString::~SkPDFString() {} | 140 SkPDFString::~SkPDFString() {} |
| 137 | 141 |
| 138 void SkPDFString::emitObject(SkWStream* stream, SkPDFCatalog* catalog) { | 142 void SkPDFString::emitObject(SkWStream* stream, |
| 143 const SkPDFObjNumMap&, |
| 144 const SkPDFSubstituteMap&) { |
| 139 stream->write(fValue.c_str(), fValue.size()); | 145 stream->write(fValue.c_str(), fValue.size()); |
| 140 } | 146 } |
| 141 | 147 |
| 142 // static | 148 // static |
| 143 SkString SkPDFString::FormatString(const char* input, size_t len) { | 149 SkString SkPDFString::FormatString(const char* input, size_t len) { |
| 144 return DoFormatString(input, len, false, false); | 150 return DoFormatString(input, len, false, false); |
| 145 } | 151 } |
| 146 | 152 |
| 147 SkString SkPDFString::FormatString(const uint16_t* input, size_t len, | 153 SkString SkPDFString::FormatString(const uint16_t* input, size_t len, |
| 148 bool wideChars) { | 154 bool wideChars) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 //////////////////////////////////////////////////////////////////////////////// | 213 //////////////////////////////////////////////////////////////////////////////// |
| 208 | 214 |
| 209 SkPDFName::SkPDFName(const char name[]) : fValue(FormatName(SkString(name))) {} | 215 SkPDFName::SkPDFName(const char name[]) : fValue(FormatName(SkString(name))) {} |
| 210 SkPDFName::SkPDFName(const SkString& name) : fValue(FormatName(name)) {} | 216 SkPDFName::SkPDFName(const SkString& name) : fValue(FormatName(name)) {} |
| 211 SkPDFName::~SkPDFName() {} | 217 SkPDFName::~SkPDFName() {} |
| 212 | 218 |
| 213 bool SkPDFName::operator==(const SkPDFName& b) const { | 219 bool SkPDFName::operator==(const SkPDFName& b) const { |
| 214 return fValue == b.fValue; | 220 return fValue == b.fValue; |
| 215 } | 221 } |
| 216 | 222 |
| 217 void SkPDFName::emitObject(SkWStream* stream, SkPDFCatalog* catalog) { | 223 void SkPDFName::emitObject(SkWStream* stream, |
| 224 const SkPDFObjNumMap&, |
| 225 const SkPDFSubstituteMap&) { |
| 218 stream->write(fValue.c_str(), fValue.size()); | 226 stream->write(fValue.c_str(), fValue.size()); |
| 219 } | 227 } |
| 220 | 228 |
| 221 // static | 229 // static |
| 222 SkString SkPDFName::FormatName(const SkString& input) { | 230 SkString SkPDFName::FormatName(const SkString& input) { |
| 223 SkASSERT(input.size() <= kMaxLen); | 231 SkASSERT(input.size() <= kMaxLen); |
| 224 // TODO(vandebo) If more escaping is needed, improve the linear scan. | 232 // TODO(vandebo) If more escaping is needed, improve the linear scan. |
| 225 static const char escaped[] = "#/%()<>[]{}"; | 233 static const char escaped[] = "#/%()<>[]{}"; |
| 226 | 234 |
| 227 SkString result("/"); | 235 SkString result("/"); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 238 return result; | 246 return result; |
| 239 } | 247 } |
| 240 | 248 |
| 241 //////////////////////////////////////////////////////////////////////////////// | 249 //////////////////////////////////////////////////////////////////////////////// |
| 242 | 250 |
| 243 SkPDFArray::SkPDFArray() {} | 251 SkPDFArray::SkPDFArray() {} |
| 244 SkPDFArray::~SkPDFArray() { | 252 SkPDFArray::~SkPDFArray() { |
| 245 fValue.unrefAll(); | 253 fValue.unrefAll(); |
| 246 } | 254 } |
| 247 | 255 |
| 248 void SkPDFArray::emitObject(SkWStream* stream, SkPDFCatalog* catalog) { | 256 void SkPDFArray::emitObject(SkWStream* stream, |
| 257 const SkPDFObjNumMap& objNumMap, |
| 258 const SkPDFSubstituteMap& substitutes) { |
| 249 stream->writeText("["); | 259 stream->writeText("["); |
| 250 for (int i = 0; i < fValue.count(); i++) { | 260 for (int i = 0; i < fValue.count(); i++) { |
| 251 catalog->getSubstituteObject(fValue[i])->emitObject(stream, catalog); | 261 SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]); |
| 262 fValue[i]->emitObject(stream, objNumMap, substitutes); |
| 252 if (i + 1 < fValue.count()) { | 263 if (i + 1 < fValue.count()) { |
| 253 stream->writeText(" "); | 264 stream->writeText(" "); |
| 254 } | 265 } |
| 255 } | 266 } |
| 256 stream->writeText("]"); | 267 stream->writeText("]"); |
| 257 } | 268 } |
| 258 | 269 |
| 259 void SkPDFArray::addResources(SkPDFCatalog* catalog) const { | 270 void SkPDFArray::addResources(SkPDFObjNumMap* catalog, |
| 271 const SkPDFSubstituteMap& substitutes) const { |
| 260 for (int i = 0; i < fValue.count(); i++) { | 272 for (int i = 0; i < fValue.count(); i++) { |
| 261 catalog->getSubstituteObject(fValue[i])->addResources(catalog); | 273 SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]); |
| 274 fValue[i]->addResources(catalog, substitutes); |
| 262 } | 275 } |
| 263 } | 276 } |
| 264 | 277 |
| 265 void SkPDFArray::reserve(int length) { | 278 void SkPDFArray::reserve(int length) { |
| 266 SkASSERT(length <= kMaxLen); | 279 SkASSERT(length <= kMaxLen); |
| 267 fValue.setReserve(length); | 280 fValue.setReserve(length); |
| 268 } | 281 } |
| 269 | 282 |
| 270 SkPDFObject* SkPDFArray::setAt(int offset, SkPDFObject* value) { | 283 SkPDFObject* SkPDFArray::setAt(int offset, SkPDFObject* value) { |
| 271 SkASSERT(offset < fValue.count()); | 284 SkASSERT(offset < fValue.count()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 } | 319 } |
| 307 | 320 |
| 308 SkPDFDict::~SkPDFDict() { | 321 SkPDFDict::~SkPDFDict() { |
| 309 clear(); | 322 clear(); |
| 310 } | 323 } |
| 311 | 324 |
| 312 int SkPDFDict::size() const { | 325 int SkPDFDict::size() const { |
| 313 return fValue.count(); | 326 return fValue.count(); |
| 314 } | 327 } |
| 315 | 328 |
| 316 void SkPDFDict::emitObject(SkWStream* stream, SkPDFCatalog* catalog) { | 329 void SkPDFDict::emitObject(SkWStream* stream, |
| 330 const SkPDFObjNumMap& objNumMap, |
| 331 const SkPDFSubstituteMap& substitutes) { |
| 317 stream->writeText("<<"); | 332 stream->writeText("<<"); |
| 318 for (int i = 0; i < fValue.count(); i++) { | 333 for (int i = 0; i < fValue.count(); i++) { |
| 319 SkASSERT(fValue[i].key); | 334 SkASSERT(fValue[i].key); |
| 320 SkASSERT(fValue[i].value); | 335 SkASSERT(fValue[i].value); |
| 321 fValue[i].key->emitObject(stream, catalog); | 336 SkASSERT(substitutes.getSubstitute(fValue[i].key) == fValue[i].key); |
| 337 SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value); |
| 338 fValue[i].key->emitObject(stream, objNumMap, substitutes); |
| 322 stream->writeText(" "); | 339 stream->writeText(" "); |
| 323 catalog->getSubstituteObject(fValue[i].value) | 340 fValue[i].value->emitObject(stream, objNumMap, substitutes); |
| 324 ->emitObject(stream, catalog); | 341 if (i + 1 < fValue.count()) { |
| 325 stream->writeText("\n"); | 342 stream->writeText("\n"); |
| 343 } |
| 326 } | 344 } |
| 327 stream->writeText(">>"); | 345 stream->writeText(">>"); |
| 328 } | 346 } |
| 329 | 347 |
| 330 void SkPDFDict::addResources(SkPDFCatalog* catalog) const { | 348 void SkPDFDict::addResources(SkPDFObjNumMap* catalog, |
| 349 const SkPDFSubstituteMap& substitutes) const { |
| 331 for (int i = 0; i < fValue.count(); i++) { | 350 for (int i = 0; i < fValue.count(); i++) { |
| 332 SkASSERT(fValue[i].key); | 351 SkASSERT(fValue[i].key); |
| 333 SkASSERT(fValue[i].value); | 352 SkASSERT(fValue[i].value); |
| 334 fValue[i].key->addResources(catalog); | 353 fValue[i].key->addResources(catalog, substitutes); |
| 335 catalog->getSubstituteObject(fValue[i].value)->addResources(catalog); | 354 SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value); |
| 355 fValue[i].value->addResources(catalog, substitutes); |
| 336 } | 356 } |
| 337 } | 357 } |
| 338 | 358 |
| 339 SkPDFObject* SkPDFDict::append(SkPDFName* key, SkPDFObject* value) { | 359 SkPDFObject* SkPDFDict::append(SkPDFName* key, SkPDFObject* value) { |
| 340 SkASSERT(key); | 360 SkASSERT(key); |
| 341 SkASSERT(value); | 361 SkASSERT(value); |
| 342 *(fValue.append()) = Rec(key, value); | 362 *(fValue.append()) = Rec(key, value); |
| 343 return value; | 363 return value; |
| 344 } | 364 } |
| 345 | 365 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 } | 407 } |
| 388 } | 408 } |
| 389 } | 409 } |
| 390 | 410 |
| 391 void SkPDFDict::mergeFrom(const SkPDFDict& other) { | 411 void SkPDFDict::mergeFrom(const SkPDFDict& other) { |
| 392 for (int i = 0; i < other.fValue.count(); i++) { | 412 for (int i = 0; i < other.fValue.count(); i++) { |
| 393 *(fValue.append()) = | 413 *(fValue.append()) = |
| 394 Rec(SkRef(other.fValue[i].key), SkRef(other.fValue[i].value)); | 414 Rec(SkRef(other.fValue[i].key), SkRef(other.fValue[i].value)); |
| 395 } | 415 } |
| 396 } | 416 } |
| 417 |
| 418 //////////////////////////////////////////////////////////////////////////////// |
| 419 |
| 420 SkPDFSubstituteMap::~SkPDFSubstituteMap() { |
| 421 fSubstituteMap.foreach( |
| 422 [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); }); |
| 423 } |
| 424 |
| 425 void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original, |
| 426 SkPDFObject* substitute) { |
| 427 SkASSERT(original != substitute); |
| 428 SkASSERT(!fSubstituteMap.find(original)); |
| 429 fSubstituteMap.set(original, SkRef(substitute)); |
| 430 } |
| 431 |
| 432 SkPDFObject* SkPDFSubstituteMap::getSubstitute(SkPDFObject* object) const { |
| 433 SkPDFObject** found = fSubstituteMap.find(object); |
| 434 return found ? *found : object; |
| 435 } |
| 436 |
| 437 //////////////////////////////////////////////////////////////////////////////// |
| 438 |
| 439 bool SkPDFObjNumMap::addObject(SkPDFObject* obj) { |
| 440 if (fObjectNumbers.find(obj)) { |
| 441 return false; |
| 442 } |
| 443 fObjectNumbers.set(obj, fObjectNumbers.count() + 1); |
| 444 fObjects.push(obj); |
| 445 return true; |
| 446 } |
| 447 |
| 448 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { |
| 449 int32_t* objectNumberFound = fObjectNumbers.find(obj); |
| 450 SkASSERT(objectNumberFound); |
| 451 return *objectNumberFound; |
| 452 } |
| 453 |
| OLD | NEW |