1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkPDFTypes.h" 9 10 #include "SkData.h" 11 #include "SkDeflate.h" 12 #include "SkExecutor.h" 13 #include "SkMakeUnique.h" 14 #include "SkPDFDocumentPriv.h" 15 #include "SkPDFUnion.h" 16 #include "SkPDFUtils.h" 17 #include "SkStream.h" 18 #include "SkStreamPriv.h" 19 #include "SkTo.h" 20 21 #include <new> 22 23 //////////////////////////////////////////////////////////////////////////////// 24 25 SkPDFUnion::SkPDFUnion(Type t) : fType(t) {} 26 SkPDFUnion::SkPDFUnion(Type t, int32_t v) : fIntValue (v), fType(t) {} 27 SkPDFUnion::SkPDFUnion(Type t, bool v) : fBoolValue (v), fType(t) {} 28 SkPDFUnion::SkPDFUnion(Type t, SkScalar v) : fScalarValue (v), fType(t) {} 29 SkPDFUnion::SkPDFUnion(Type t, SkString v) : fType(t) { fSkString.init(std::move(v)); } 30 31 SkPDFUnion::~SkPDFUnion() { 32 switch (fType) { 33 case Type::kNameSkS: 34 case Type::kStringSkS: 35 fSkString.destroy(); 36 return; 37 case Type::kObject: 38 SkASSERT(fObject); 39 delete fObject; 40 return; 41 default: 42 return; 43 } 44 } 45 46 SkPDFUnion& SkPDFUnion::operator=(SkPDFUnion&& other) { 47 if (this != &other) { 48 this->~SkPDFUnion(); 49 new (this) SkPDFUnion(std::move(other)); 50 } 51 return *this; 52 } 53 54 SkPDFUnion::SkPDFUnion(SkPDFUnion&& other) { 55 SkASSERT(this != &other); 56 memcpy(this, &other, sizeof(*this)); 57 other.fType = Type::kDestroyed; 58 } 59 60 #if 0 61 SkPDFUnion SkPDFUnion::copy() const { 62 SkPDFUnion u(fType); 63 memcpy(&u, this, sizeof(u)); 64 switch (fType) { 65 case Type::kNameSkS: 66 case Type::kStringSkS: 67 u.fSkString.init(fSkString.get()); 68 return u; 69 case Type::kObject: 70 SkRef(u.fObject); 71 return u; 72 default: 73 return u; 74 } 75 } 76 SkPDFUnion& SkPDFUnion::operator=(const SkPDFUnion& other) { 77 return *this = other.copy(); 78 } 79 SkPDFUnion::SkPDFUnion(const SkPDFUnion& other) { 80 *this = other.copy(); 81 } 82 #endif 83 84 bool SkPDFUnion::isName() const { 85 return Type::kName == fType || Type::kNameSkS == fType; 86 } 87 88 #ifdef SK_DEBUG 89 // Most names need no escaping. Such names are handled as static 90 // const strings. 91 bool is_valid_name(const char* n) { 92 static const char kControlChars[] = "/%()<>[]{}"; 93 while (*n) { 94 if (*n < '!' || *n > '~' || strchr(kControlChars, *n)) { 95 return false; 96 } 97 ++n; 98 } 99 return true; 100 } 101 #endif // SK_DEBUG 102 103 // Given an arbitrary string, write it as a valid name (not including 104 // leading slash). 105 static void write_name_escaped(SkWStream* o, const char* name) { 106 static const char kToEscape[] = "#/%()<>[]{}"; 107 for (const uint8_t* n = reinterpret_cast<const uint8_t*>(name); *n; ++n) { 108 uint8_t v = *n; 109 if (v < '!' || v > '~' || strchr(kToEscape, v)) { 110 char buffer[3] = {'#', 111 SkHexadecimalDigits::gUpper[v >> 4], 112 SkHexadecimalDigits::gUpper[v & 0xF]}; 113 o->write(buffer, sizeof(buffer)); 114 } else { 115 o->write(n, 1); 116 } 117 } 118 } 119 120 static void write_string(SkWStream* wStream, const char* cin, size_t len) { 121 SkDEBUGCODE(static const size_t kMaxLen = 65535;) 122 SkASSERT(len <= kMaxLen); 123 124 size_t extraCharacterCount = 0; 125 for (size_t i = 0; i < len; i++) { 126 if (cin[i] > '~' || cin[i] < ' ') { 127 extraCharacterCount += 3; 128 } else if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { 129 ++extraCharacterCount; 130 } 131 } 132 if (extraCharacterCount <= len) { 133 wStream->writeText("("); 134 for (size_t i = 0; i < len; i++) { 135 if (cin[i] > '~' || cin[i] < ' ') { 136 uint8_t c = static_cast<uint8_t>(cin[i]); 137 uint8_t octal[4] = { '\\', 138 (uint8_t)('0' | ( c >> 6 )), 139 (uint8_t)('0' | ((c >> 3) & 0x07)), 140 (uint8_t)('0' | ( c & 0x07)) }; 141 wStream->write(octal, 4); 142 } else { 143 if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { 144 wStream->writeText("\\"); 145 } 146 wStream->write(&cin[i], 1); 147 } 148 } 149 wStream->writeText(")"); 150 } else { 151 wStream->writeText("<"); 152 for (size_t i = 0; i < len; i++) { 153 uint8_t c = static_cast<uint8_t>(cin[i]); 154 char hexValue[2] = { SkHexadecimalDigits::gUpper[c >> 4], 155 SkHexadecimalDigits::gUpper[c & 0xF] }; 156 wStream->write(hexValue, 2); 157 } 158 wStream->writeText(">"); 159 } 160 } 161 162 void SkPDFWriteString(SkWStream* wStream, const char* cin, size_t len) { 163 write_string(wStream, cin, len); 164 } 165 166 void SkPDFUnion::emitObject(SkWStream* stream) const { 167 switch (fType) { 168 case Type::kInt: 169 stream->writeDecAsText(fIntValue); 170 return; 171 case Type::kColorComponent: 172 SkPDFUtils::AppendColorComponent(SkToU8(fIntValue), stream); 173 return; 174 case Type::kColorComponentF: 175 SkPDFUtils::AppendColorComponentF(fScalarValue, stream); 176 return; 177 case Type::kBool: 178 stream->writeText(fBoolValue ? "true" : "false"); 179 return; 180 case Type::kScalar: 181 SkPDFUtils::AppendScalar(fScalarValue, stream); 182 return; 183 case Type::kName: 184 stream->writeText("/"); 185 SkASSERT(is_valid_name(fStaticString)); 186 stream->writeText(fStaticString); 187 return; 188 case Type::kString: 189 SkASSERT(fStaticString); 190 write_string(stream, fStaticString, strlen(fStaticString)); 191 return; 192 case Type::kNameSkS: 193 stream->writeText("/"); 194 write_name_escaped(stream, fSkString.get().c_str()); 195 return; 196 case Type::kStringSkS: 197 write_string(stream, fSkString.get().c_str(), fSkString.get().size()); 198 return; 199 case Type::kObject: 200 fObject->emitObject(stream); 201 return; 202 case Type::kRef: 203 SkASSERT(fIntValue >= 0); 204 stream->writeDecAsText(fIntValue); 205 stream->writeText(" 0 R"); // Generation number is always 0. 206 return; 207 default: 208 SkDEBUGFAIL("SkPDFUnion::emitObject with bad type"); 209 } 210 } 211 212 SkPDFUnion SkPDFUnion::Int(int32_t value) { return SkPDFUnion(Type::kInt, value); } 213 214 SkPDFUnion SkPDFUnion::ColorComponent(uint8_t value) { 215 return SkPDFUnion(Type::kColorComponent, (int32_t)value); 216 } 217 218 SkPDFUnion SkPDFUnion::ColorComponentF(float value) { 219 return SkPDFUnion(Type::kColorComponentF, (SkScalar)value); 220 } 221 222 SkPDFUnion SkPDFUnion::Bool(bool value) { 223 return SkPDFUnion(Type::kBool, value); 224 } 225 226 SkPDFUnion SkPDFUnion::Scalar(SkScalar value) { 227 return SkPDFUnion(Type::kScalar, value); 228 } 229 230 SkPDFUnion SkPDFUnion::Name(const char* value) { 231 SkPDFUnion u(Type::kName); 232 SkASSERT(value); 233 SkASSERT(is_valid_name(value)); 234 u.fStaticString = value; 235 return u; 236 } 237 238 SkPDFUnion SkPDFUnion::String(const char* value) { 239 SkPDFUnion u(Type::kString); 240 SkASSERT(value); 241 u.fStaticString = value; 242 return u; 243 } 244 245 SkPDFUnion SkPDFUnion::Name(SkString s) { return SkPDFUnion(Type::kNameSkS, std::move(s)); } 246 247 SkPDFUnion SkPDFUnion::String(SkString s) { return SkPDFUnion(Type::kStringSkS, std::move(s)); } 248 249 SkPDFUnion SkPDFUnion::Object(std::unique_ptr<SkPDFObject> objSp) { 250 SkPDFUnion u(Type::kObject); 251 SkASSERT(objSp.get()); 252 u.fObject = objSp.release(); // take ownership into union{} 253 return u; 254 } 255 256 SkPDFUnion SkPDFUnion::Ref(SkPDFIndirectReference ref) { 257 return SkASSERT(ref.fValue > 0), SkPDFUnion(Type::kRef, (int32_t)ref.fValue); 258 } 259 260 //////////////////////////////////////////////////////////////////////////////// 261 262 #if 0 // Enable if needed. 263 void SkPDFAtom::emitObject(SkWStream* stream) const { 264 fValue.emitObject(stream); 265 } 266 #endif // 0 267 268 //////////////////////////////////////////////////////////////////////////////// 269 270 SkPDFArray::SkPDFArray() {} 271 272 SkPDFArray::~SkPDFArray() {} 273 274 size_t SkPDFArray::size() const { return fValues.size(); } 275 276 void SkPDFArray::reserve(int length) { 277 fValues.reserve(length); 278 } 279 280 void SkPDFArray::emitObject(SkWStream* stream) const { 281 stream->writeText("["); 282 for (size_t i = 0; i < fValues.size(); i++) { 283 fValues[i].emitObject(stream); 284 if (i + 1 < fValues.size()) { 285 stream->writeText(" "); 286 } 287 } 288 stream->writeText("]"); 289 } 290 291 void SkPDFArray::append(SkPDFUnion&& value) { 292 fValues.emplace_back(std::move(value)); 293 } 294 295 void SkPDFArray::appendInt(int32_t value) { 296 this->append(SkPDFUnion::Int(value)); 297 } 298 299 void SkPDFArray::appendColorComponent(uint8_t value) { 300 this->append(SkPDFUnion::ColorComponent(value)); 301 } 302 303 void SkPDFArray::appendBool(bool value) { 304 this->append(SkPDFUnion::Bool(value)); 305 } 306 307 void SkPDFArray::appendScalar(SkScalar value) { 308 this->append(SkPDFUnion::Scalar(value)); 309 } 310 311 void SkPDFArray::appendName(const char name[]) { 312 this->append(SkPDFUnion::Name(SkString(name))); 313 } 314 315 void SkPDFArray::appendName(SkString name) { 316 this->append(SkPDFUnion::Name(std::move(name))); 317 } 318 319 void SkPDFArray::appendString(SkString value) { 320 this->append(SkPDFUnion::String(std::move(value))); 321 } 322 323 void SkPDFArray::appendString(const char value[]) { 324 this->append(SkPDFUnion::String(value)); 325 } 326 327 void SkPDFArray::appendObject(std::unique_ptr<SkPDFObject>&& objSp) { 328 this->append(SkPDFUnion::Object(std::move(objSp))); 329 } 330 331 void SkPDFArray::appendRef(SkPDFIndirectReference ref) { 332 this->append(SkPDFUnion::Ref(ref)); 333 } 334 335 /////////////////////////////////////////////////////////////////////////////// 336 337 SkPDFDict::~SkPDFDict() {} 338 339 SkPDFDict::SkPDFDict(const char type[]) { 340 if (type) { 341 this->insertName("Type", type); 342 } 343 } 344 345 void SkPDFDict::emitObject(SkWStream* stream) const { 346 stream->writeText("<<"); 347 for (size_t i = 0; i < fRecords.size(); ++i) { 348 const std::pair<SkPDFUnion, SkPDFUnion>& record = fRecords[i]; 349 record.first.emitObject(stream); 350 stream->writeText(" "); 351 record.second.emitObject(stream); 352 if (i + 1 < fRecords.size()) { 353 stream->writeText("\n"); 354 } 355 } 356 stream->writeText(">>"); 357 } 358 359 size_t SkPDFDict::size() const { return fRecords.size(); } 360 361 void SkPDFDict::reserve(int n) { 362 fRecords.reserve(n); 363 } 364 365 void SkPDFDict::insertRef(const char key[], SkPDFIndirectReference ref) { 366 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Ref(ref)); 367 } 368 369 void SkPDFDict::insertRef(SkString key, SkPDFIndirectReference ref) { 370 fRecords.emplace_back(SkPDFUnion::Name(std::move(key)), SkPDFUnion::Ref(ref)); 371 } 372 373 void SkPDFDict::insertObject(const char key[], std::unique_ptr<SkPDFObject>&& objSp) { 374 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Object(std::move(objSp))); 375 } 376 void SkPDFDict::insertObject(SkString key, std::unique_ptr<SkPDFObject>&& objSp) { 377 fRecords.emplace_back(SkPDFUnion::Name(std::move(key)), 378 SkPDFUnion::Object(std::move(objSp))); 379 } 380 381 void SkPDFDict::insertBool(const char key[], bool value) { 382 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Bool(value)); 383 } 384 385 void SkPDFDict::insertInt(const char key[], int32_t value) { 386 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Int(value)); 387 } 388 389 void SkPDFDict::insertInt(const char key[], size_t value) { 390 this->insertInt(key, SkToS32(value)); 391 } 392 393 void SkPDFDict::insertColorComponentF(const char key[], SkScalar value) { 394 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::ColorComponentF(value)); 395 } 396 397 void SkPDFDict::insertScalar(const char key[], SkScalar value) { 398 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Scalar(value)); 399 } 400 401 void SkPDFDict::insertName(const char key[], const char name[]) { 402 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Name(name)); 403 } 404 405 void SkPDFDict::insertName(const char key[], SkString name) { 406 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Name(std::move(name))); 407 } 408 409 void SkPDFDict::insertString(const char key[], const char value[]) { 410 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::String(value)); 411 } 412 413 void SkPDFDict::insertString(const char key[], SkString value) { 414 fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::String(std::move(value))); 415 } 416 417 //////////////////////////////////////////////////////////////////////////////// 418 419 420 421 static void serialize_stream(SkPDFDict* origDict, 422 SkStreamAsset* stream, 423 bool deflate, 424 SkPDFDocument* doc, 425 SkPDFIndirectReference ref) { 426 // Code assumes that the stream starts at the beginning. 427 SkASSERT(stream && stream->hasLength()); 428 429 std::unique_ptr<SkStreamAsset> tmp; 430 SkPDFDict tmpDict; 431 SkPDFDict& dict = origDict ? *origDict : tmpDict; 432 static const size_t kMinimumSavings = strlen("/Filter_/FlateDecode_"); 433 if (deflate && stream->getLength() > kMinimumSavings) { 434 SkDynamicMemoryWStream compressedData; 435 SkDeflateWStream deflateWStream(&compressedData); 436 SkStreamCopy(&deflateWStream, stream); 437 deflateWStream.finalize(); 438 #ifdef SK_PDF_BASE85_BINARY 439 { 440 SkPDFUtils::Base85Encode(compressedData.detachAsStream(), &compressedData); 441 tmp = compressedData.detachAsStream(); 442 stream = tmp.get(); 443 auto filters = SkPDFMakeArray(); 444 filters->appendName("ASCII85Decode"); 445 filters->appendName("FlateDecode"); 446 dict.insertObject("Filter", std::move(filters)); 447 } 448 #else 449 if (stream->getLength() > compressedData.bytesWritten() + kMinimumSavings) { 450 tmp = compressedData.detachAsStream(); 451 stream = tmp.get(); 452 dict.insertName("Filter", "FlateDecode"); 453 } else { 454 SkAssertResult(stream->rewind()); 455 } 456 #endif 457 458 } 459 dict.insertInt("Length", stream->getLength()); 460 doc->emitStream(dict, 461 [stream](SkWStream* dst) { dst->writeStream(stream, stream->getLength()); }, 462 ref); 463 } 464 465 SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr<SkPDFDict> dict, 466 std::unique_ptr<SkStreamAsset> content, 467 SkPDFDocument* doc, 468 bool deflate) { 469 SkPDFIndirectReference ref = doc->reserveRef(); 470 if (SkExecutor* executor = doc->executor()) { 471 SkPDFDict* dictPtr = dict.release(); 472 SkStreamAsset* contentPtr = content.release(); 473 // Pass ownership of both pointers into a std::function, which should 474 // only be executed once. 475 doc->incrementJobCount(); 476 executor->add([dictPtr, contentPtr, deflate, doc, ref]() { 477 serialize_stream(dictPtr, contentPtr, deflate, doc, ref); 478 delete dictPtr; 479 delete contentPtr; 480 doc->signalJobComplete(); 481 }); 482 return ref; 483 } 484 serialize_stream(dict.get(), content.get(), deflate, doc, ref); 485 return ref; 486 } 487