LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/pdf - SkPDFTypes.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 344 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 79 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "SkData.h"
       9             : #include "SkDeflate.h"
      10             : #include "SkMakeUnique.h"
      11             : #include "SkPDFTypes.h"
      12             : #include "SkPDFUtils.h"
      13             : #include "SkStream.h"
      14             : #include "SkStreamPriv.h"
      15             : 
      16             : ////////////////////////////////////////////////////////////////////////////////
      17             : 
      18           0 : SkString* pun(char* x) { return reinterpret_cast<SkString*>(x); }
      19           0 : const SkString* pun(const char* x) {
      20           0 :     return reinterpret_cast<const SkString*>(x);
      21             : }
      22             : 
      23           0 : SkPDFUnion::SkPDFUnion(Type t) : fType(t) {}
      24             : 
      25           0 : SkPDFUnion::~SkPDFUnion() {
      26           0 :     switch (fType) {
      27             :         case Type::kNameSkS:
      28             :         case Type::kStringSkS:
      29           0 :             pun(fSkString)->~SkString();
      30           0 :             return;
      31             :         case Type::kObjRef:
      32             :         case Type::kObject:
      33           0 :             SkASSERT(fObject);
      34           0 :             fObject->unref();
      35           0 :             return;
      36             :         default:
      37           0 :             return;
      38             :     }
      39           0 : }
      40             : 
      41           0 : SkPDFUnion& SkPDFUnion::operator=(SkPDFUnion&& other) {
      42           0 :     if (this != &other) {
      43           0 :         this->~SkPDFUnion();
      44           0 :         new (this) SkPDFUnion(std::move(other));
      45             :     }
      46           0 :     return *this;
      47             : }
      48             : 
      49           0 : SkPDFUnion::SkPDFUnion(SkPDFUnion&& other) {
      50           0 :     SkASSERT(this != &other);
      51           0 :     memcpy(this, &other, sizeof(*this));
      52           0 :     other.fType = Type::kDestroyed;
      53           0 : }
      54             : 
      55             : #if 0
      56             : SkPDFUnion SkPDFUnion::copy() const {
      57             :     SkPDFUnion u(fType);
      58             :     memcpy(&u, this, sizeof(u));
      59             :     switch (fType) {
      60             :         case Type::kNameSkS:
      61             :         case Type::kStringSkS:
      62             :             new (pun(u.fSkString)) SkString(*pun(fSkString));
      63             :             return u;
      64             :         case Type::kObjRef:
      65             :         case Type::kObject:
      66             :             SkRef(u.fObject);
      67             :             return u;
      68             :         default:
      69             :             return u;
      70             :     }
      71             : }
      72             : SkPDFUnion& SkPDFUnion::operator=(const SkPDFUnion& other) {
      73             :     return *this = other.copy();
      74             : }
      75             : SkPDFUnion::SkPDFUnion(const SkPDFUnion& other) {
      76             :     *this = other.copy();
      77             : }
      78             : #endif
      79             : 
      80           0 : bool SkPDFUnion::isName() const {
      81           0 :     return Type::kName == fType || Type::kNameSkS == fType;
      82             : }
      83             : 
      84             : #ifdef SK_DEBUG
      85             : // Most names need no escaping.  Such names are handled as static
      86             : // const strings.
      87           0 : bool is_valid_name(const char* n) {
      88             :     static const char kControlChars[] = "/%()<>[]{}";
      89           0 :     while (*n) {
      90           0 :         if (*n < '!' || *n > '~' || strchr(kControlChars, *n)) {
      91           0 :             return false;
      92             :         }
      93           0 :         ++n;
      94             :     }
      95           0 :     return true;
      96             : }
      97             : #endif  // SK_DEBUG
      98             : 
      99             : // Given an arbitrary string, write it as a valid name (not including
     100             : // leading slash).
     101           0 : static void write_name_escaped(SkWStream* o, const char* name) {
     102             :     static const char kToEscape[] = "#/%()<>[]{}";
     103             :     static const char kHex[] = "0123456789ABCDEF";
     104           0 :     for (const uint8_t* n = reinterpret_cast<const uint8_t*>(name); *n; ++n) {
     105           0 :         if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) {
     106           0 :             char buffer[3] = {'#', '\0', '\0'};
     107           0 :             buffer[1] = kHex[(*n >> 4) & 0xF];
     108           0 :             buffer[2] = kHex[*n & 0xF];
     109           0 :             o->write(buffer, sizeof(buffer));
     110             :         } else {
     111           0 :             o->write(n, 1);
     112             :         }
     113             :     }
     114           0 : }
     115             : 
     116           0 : void SkPDFUnion::emitObject(SkWStream* stream,
     117             :                             const SkPDFObjNumMap& objNumMap) const {
     118           0 :     switch (fType) {
     119             :         case Type::kInt:
     120           0 :             stream->writeDecAsText(fIntValue);
     121           0 :             return;
     122             :         case Type::kColorComponent:
     123           0 :             SkPDFUtils::AppendColorComponent(SkToU8(fIntValue), stream);
     124           0 :             return;
     125             :         case Type::kBool:
     126           0 :             stream->writeText(fBoolValue ? "true" : "false");
     127           0 :             return;
     128             :         case Type::kScalar:
     129           0 :             SkPDFUtils::AppendScalar(fScalarValue, stream);
     130           0 :             return;
     131             :         case Type::kName:
     132           0 :             stream->writeText("/");
     133           0 :             SkASSERT(is_valid_name(fStaticString));
     134           0 :             stream->writeText(fStaticString);
     135           0 :             return;
     136             :         case Type::kString:
     137           0 :             SkASSERT(fStaticString);
     138           0 :             SkPDFUtils::WriteString(stream, fStaticString,
     139           0 :                                     strlen(fStaticString));
     140           0 :             return;
     141             :         case Type::kNameSkS:
     142           0 :             stream->writeText("/");
     143           0 :             write_name_escaped(stream, pun(fSkString)->c_str());
     144           0 :             return;
     145             :         case Type::kStringSkS:
     146           0 :             SkPDFUtils::WriteString(stream, pun(fSkString)->c_str(),
     147           0 :                                     pun(fSkString)->size());
     148           0 :             return;
     149             :         case Type::kObjRef:
     150           0 :             stream->writeDecAsText(objNumMap.getObjectNumber(fObject));
     151           0 :             stream->writeText(" 0 R");  // Generation number is always 0.
     152           0 :             return;
     153             :         case Type::kObject:
     154           0 :             fObject->emitObject(stream, objNumMap);
     155           0 :             return;
     156             :         default:
     157           0 :             SkDEBUGFAIL("SkPDFUnion::emitObject with bad type");
     158             :     }
     159             : }
     160             : 
     161           0 : void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap) const {
     162           0 :     switch (fType) {
     163             :         case Type::kInt:
     164             :         case Type::kColorComponent:
     165             :         case Type::kBool:
     166             :         case Type::kScalar:
     167             :         case Type::kName:
     168             :         case Type::kString:
     169             :         case Type::kNameSkS:
     170             :         case Type::kStringSkS:
     171           0 :             return;  // These have no resources.
     172             :         case Type::kObjRef:
     173           0 :             objNumMap->addObjectRecursively(fObject);
     174           0 :             return;
     175             :         case Type::kObject:
     176           0 :             fObject->addResources(objNumMap);
     177           0 :             return;
     178             :         default:
     179           0 :             SkDEBUGFAIL("SkPDFUnion::addResources with bad type");
     180             :     }
     181             : }
     182             : 
     183           0 : SkPDFUnion SkPDFUnion::Int(int32_t value) {
     184           0 :     SkPDFUnion u(Type::kInt);
     185           0 :     u.fIntValue = value;
     186           0 :     return u;
     187             : }
     188             : 
     189           0 : SkPDFUnion SkPDFUnion::ColorComponent(uint8_t value) {
     190           0 :     SkPDFUnion u(Type::kColorComponent);
     191           0 :     u.fIntValue = value;
     192           0 :     return u;
     193             : }
     194             : 
     195           0 : SkPDFUnion SkPDFUnion::Bool(bool value) {
     196           0 :     SkPDFUnion u(Type::kBool);
     197           0 :     u.fBoolValue = value;
     198           0 :     return u;
     199             : }
     200             : 
     201           0 : SkPDFUnion SkPDFUnion::Scalar(SkScalar value) {
     202           0 :     SkPDFUnion u(Type::kScalar);
     203           0 :     u.fScalarValue = value;
     204           0 :     return u;
     205             : }
     206             : 
     207           0 : SkPDFUnion SkPDFUnion::Name(const char* value) {
     208           0 :     SkPDFUnion u(Type::kName);
     209           0 :     SkASSERT(value);
     210           0 :     SkASSERT(is_valid_name(value));
     211           0 :     u.fStaticString = value;
     212           0 :     return u;
     213             : }
     214             : 
     215           0 : SkPDFUnion SkPDFUnion::String(const char* value) {
     216           0 :     SkPDFUnion u(Type::kString);
     217           0 :     SkASSERT(value);
     218           0 :     u.fStaticString = value;
     219           0 :     return u;
     220             : }
     221             : 
     222           0 : SkPDFUnion SkPDFUnion::Name(const SkString& s) {
     223           0 :     SkPDFUnion u(Type::kNameSkS);
     224           0 :     new (pun(u.fSkString)) SkString(s);
     225           0 :     return u;
     226             : }
     227             : 
     228           0 : SkPDFUnion SkPDFUnion::String(const SkString& s) {
     229           0 :     SkPDFUnion u(Type::kStringSkS);
     230           0 :     new (pun(u.fSkString)) SkString(s);
     231           0 :     return u;
     232             : }
     233             : 
     234           0 : SkPDFUnion SkPDFUnion::ObjRef(sk_sp<SkPDFObject> objSp) {
     235           0 :     SkPDFUnion u(Type::kObjRef);
     236           0 :     SkASSERT(objSp.get());
     237           0 :     u.fObject = objSp.release();  // take ownership into union{}
     238           0 :     return u;
     239             : }
     240             : 
     241           0 : SkPDFUnion SkPDFUnion::Object(sk_sp<SkPDFObject> objSp) {
     242           0 :     SkPDFUnion u(Type::kObject);
     243           0 :     SkASSERT(objSp.get());
     244           0 :     u.fObject = objSp.release();  // take ownership into union{}
     245           0 :     return u;
     246             : }
     247             : 
     248             : ////////////////////////////////////////////////////////////////////////////////
     249             : 
     250             : #if 0  // Enable if needed.
     251             : void SkPDFAtom::emitObject(SkWStream* stream,
     252             :                            const SkPDFObjNumMap& objNumMap) const {
     253             :     fValue.emitObject(stream, objNumMap);
     254             : }
     255             : void SkPDFAtom::addResources(SkPDFObjNumMap* map) const {
     256             :     fValue.addResources(map);
     257             : }
     258             : #endif  // 0
     259             : 
     260             : ////////////////////////////////////////////////////////////////////////////////
     261             : 
     262           0 : SkPDFArray::SkPDFArray() { SkDEBUGCODE(fDumped = false;) }
     263             : 
     264           0 : SkPDFArray::~SkPDFArray() { this->drop(); }
     265             : 
     266           0 : void SkPDFArray::drop() {
     267           0 :     fValues.reset();
     268           0 :     SkDEBUGCODE(fDumped = true;)
     269           0 : }
     270             : 
     271           0 : int SkPDFArray::size() const { return fValues.count(); }
     272             : 
     273           0 : void SkPDFArray::reserve(int length) {
     274             :     // TODO(halcanary): implement SkTArray<T>::reserve() or change the
     275             :     // contstructor of SkPDFArray to take reserve size.
     276           0 : }
     277             : 
     278           0 : void SkPDFArray::emitObject(SkWStream* stream,
     279             :                             const SkPDFObjNumMap& objNumMap) const {
     280           0 :     SkASSERT(!fDumped);
     281           0 :     stream->writeText("[");
     282           0 :     for (int i = 0; i < fValues.count(); i++) {
     283           0 :         fValues[i].emitObject(stream, objNumMap);
     284           0 :         if (i + 1 < fValues.count()) {
     285           0 :             stream->writeText(" ");
     286             :         }
     287             :     }
     288           0 :     stream->writeText("]");
     289           0 : }
     290             : 
     291           0 : void SkPDFArray::addResources(SkPDFObjNumMap* catalog) const {
     292           0 :     SkASSERT(!fDumped);
     293           0 :     for (const SkPDFUnion& value : fValues) {
     294           0 :         value.addResources(catalog);
     295             :     }
     296           0 : }
     297             : 
     298           0 : void SkPDFArray::append(SkPDFUnion&& value) {
     299           0 :     fValues.emplace_back(std::move(value));
     300           0 : }
     301             : 
     302           0 : void SkPDFArray::appendInt(int32_t value) {
     303           0 :     this->append(SkPDFUnion::Int(value));
     304           0 : }
     305             : 
     306           0 : void SkPDFArray::appendColorComponent(uint8_t value) {
     307           0 :     this->append(SkPDFUnion::ColorComponent(value));
     308           0 : }
     309             : 
     310           0 : void SkPDFArray::appendBool(bool value) {
     311           0 :     this->append(SkPDFUnion::Bool(value));
     312           0 : }
     313             : 
     314           0 : void SkPDFArray::appendScalar(SkScalar value) {
     315           0 :     this->append(SkPDFUnion::Scalar(value));
     316           0 : }
     317             : 
     318           0 : void SkPDFArray::appendName(const char name[]) {
     319           0 :     this->append(SkPDFUnion::Name(SkString(name)));
     320           0 : }
     321             : 
     322           0 : void SkPDFArray::appendName(const SkString& name) {
     323           0 :     this->append(SkPDFUnion::Name(name));
     324           0 : }
     325             : 
     326           0 : void SkPDFArray::appendString(const SkString& value) {
     327           0 :     this->append(SkPDFUnion::String(value));
     328           0 : }
     329             : 
     330           0 : void SkPDFArray::appendString(const char value[]) {
     331           0 :     this->append(SkPDFUnion::String(value));
     332           0 : }
     333             : 
     334           0 : void SkPDFArray::appendObject(sk_sp<SkPDFObject> objSp) {
     335           0 :     this->append(SkPDFUnion::Object(std::move(objSp)));
     336           0 : }
     337             : 
     338           0 : void SkPDFArray::appendObjRef(sk_sp<SkPDFObject> objSp) {
     339           0 :     this->append(SkPDFUnion::ObjRef(std::move(objSp)));
     340           0 : }
     341             : 
     342             : ///////////////////////////////////////////////////////////////////////////////
     343             : 
     344           0 : SkPDFDict::~SkPDFDict() { this->drop(); }
     345             : 
     346           0 : void SkPDFDict::drop() {
     347           0 :     fRecords.reset();
     348           0 :     SkDEBUGCODE(fDumped = true;)
     349           0 : }
     350             : 
     351           0 : SkPDFDict::SkPDFDict(const char type[]) {
     352           0 :     SkDEBUGCODE(fDumped = false;)
     353           0 :     if (type) {
     354           0 :         this->insertName("Type", type);
     355             :     }
     356           0 : }
     357             : 
     358           0 : void SkPDFDict::emitObject(SkWStream* stream,
     359             :                            const SkPDFObjNumMap& objNumMap) const {
     360           0 :     stream->writeText("<<");
     361           0 :     this->emitAll(stream, objNumMap);
     362           0 :     stream->writeText(">>");
     363           0 : }
     364             : 
     365           0 : void SkPDFDict::emitAll(SkWStream* stream,
     366             :                         const SkPDFObjNumMap& objNumMap) const {
     367           0 :     SkASSERT(!fDumped);
     368           0 :     for (int i = 0; i < fRecords.count(); i++) {
     369           0 :         fRecords[i].fKey.emitObject(stream, objNumMap);
     370           0 :         stream->writeText(" ");
     371           0 :         fRecords[i].fValue.emitObject(stream, objNumMap);
     372           0 :         if (i + 1 < fRecords.count()) {
     373           0 :             stream->writeText("\n");
     374             :         }
     375             :     }
     376           0 : }
     377             : 
     378           0 : void SkPDFDict::addResources(SkPDFObjNumMap* catalog) const {
     379           0 :     SkASSERT(!fDumped);
     380           0 :     for (int i = 0; i < fRecords.count(); i++) {
     381           0 :         fRecords[i].fKey.addResources(catalog);
     382           0 :         fRecords[i].fValue.addResources(catalog);
     383             :     }
     384           0 : }
     385             : 
     386           0 : SkPDFDict::Record::Record(SkPDFUnion&& k, SkPDFUnion&& v)
     387           0 :     : fKey(std::move(k)), fValue(std::move(v)) {}
     388             : 
     389           0 : int SkPDFDict::size() const { return fRecords.count(); }
     390             : 
     391           0 : void SkPDFDict::insertObjRef(const char key[], sk_sp<SkPDFObject> objSp) {
     392           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(std::move(objSp)));
     393           0 : }
     394             : 
     395           0 : void SkPDFDict::insertObjRef(const SkString& key, sk_sp<SkPDFObject> objSp) {
     396           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(std::move(objSp)));
     397           0 : }
     398             : 
     399           0 : void SkPDFDict::insertObject(const char key[], sk_sp<SkPDFObject> objSp) {
     400           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Object(std::move(objSp)));
     401           0 : }
     402           0 : void SkPDFDict::insertObject(const SkString& key, sk_sp<SkPDFObject> objSp) {
     403           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Object(std::move(objSp)));
     404           0 : }
     405             : 
     406           0 : void SkPDFDict::insertBool(const char key[], bool value) {
     407           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Bool(value));
     408           0 : }
     409             : 
     410           0 : void SkPDFDict::insertInt(const char key[], int32_t value) {
     411           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Int(value));
     412           0 : }
     413             : 
     414           0 : void SkPDFDict::insertInt(const char key[], size_t value) {
     415           0 :     this->insertInt(key, SkToS32(value));
     416           0 : }
     417             : 
     418           0 : void SkPDFDict::insertScalar(const char key[], SkScalar value) {
     419           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Scalar(value));
     420           0 : }
     421             : 
     422           0 : void SkPDFDict::insertName(const char key[], const char name[]) {
     423           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
     424           0 : }
     425             : 
     426           0 : void SkPDFDict::insertName(const char key[], const SkString& name) {
     427           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::Name(name));
     428           0 : }
     429             : 
     430           0 : void SkPDFDict::insertString(const char key[], const char value[]) {
     431           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::String(value));
     432           0 : }
     433             : 
     434           0 : void SkPDFDict::insertString(const char key[], const SkString& value) {
     435           0 :     fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::String(value));
     436           0 : }
     437             : 
     438             : ////////////////////////////////////////////////////////////////////////////////
     439             : 
     440           0 : SkPDFSharedStream::SkPDFSharedStream(std::unique_ptr<SkStreamAsset> data)
     441           0 :     : fAsset(std::move(data)) {
     442           0 :     SkASSERT(fAsset);
     443           0 : }
     444             : 
     445           0 : SkPDFSharedStream::~SkPDFSharedStream() { this->drop(); }
     446             : 
     447           0 : void SkPDFSharedStream::drop() {
     448           0 :     fAsset = nullptr;;
     449           0 :     fDict.drop();
     450           0 : }
     451             : 
     452             : #ifdef SK_PDF_LESS_COMPRESSION
     453             : void SkPDFSharedStream::emitObject(
     454             :         SkWStream* stream,
     455             :         const SkPDFObjNumMap& objNumMap) const {
     456             :     SkASSERT(fAsset);
     457             :     std::unique_ptr<SkStreamAsset> dup(fAsset->duplicate());
     458             :     SkASSERT(dup && dup->hasLength());
     459             :     size_t length = dup->getLength();
     460             :     stream->writeText("<<");
     461             :     fDict.emitAll(stream, objNumMap);
     462             :     stream->writeText("\n");
     463             :     SkPDFUnion::Name("Length").emitObject(stream, objNumMap);
     464             :     stream->writeText(" ");
     465             :     SkPDFUnion::Int(length).emitObject(stream, objNumMap);
     466             :     stream->writeText("\n>>stream\n");
     467             :     SkStreamCopy(stream, dup.get());
     468             :     stream->writeText("\nendstream");
     469             : }
     470             : #else
     471           0 : void SkPDFSharedStream::emitObject(
     472             :         SkWStream* stream,
     473             :         const SkPDFObjNumMap& objNumMap) const {
     474           0 :     SkASSERT(fAsset);
     475           0 :     SkDynamicMemoryWStream buffer;
     476           0 :     SkDeflateWStream deflateWStream(&buffer);
     477             :     // Since emitObject is const, this function doesn't change the dictionary.
     478           0 :     std::unique_ptr<SkStreamAsset> dup(fAsset->duplicate());  // Cheap copy
     479           0 :     SkASSERT(dup);
     480           0 :     SkStreamCopy(&deflateWStream, dup.get());
     481           0 :     deflateWStream.finalize();
     482           0 :     size_t length = buffer.bytesWritten();
     483           0 :     stream->writeText("<<");
     484           0 :     fDict.emitAll(stream, objNumMap);
     485           0 :     stream->writeText("\n");
     486           0 :     SkPDFUnion::Name("Length").emitObject(stream, objNumMap);
     487           0 :     stream->writeText(" ");
     488           0 :     SkPDFUnion::Int(length).emitObject(stream, objNumMap);
     489           0 :     stream->writeText("\n");
     490           0 :     SkPDFUnion::Name("Filter").emitObject(stream, objNumMap);
     491           0 :     stream->writeText(" ");
     492           0 :     SkPDFUnion::Name("FlateDecode").emitObject(stream, objNumMap);
     493           0 :     stream->writeText(">>");
     494           0 :     stream->writeText(" stream\n");
     495           0 :     buffer.writeToStream(stream);
     496           0 :     stream->writeText("\nendstream");
     497           0 : }
     498             : #endif
     499             : 
     500           0 : void SkPDFSharedStream::addResources(
     501             :         SkPDFObjNumMap* catalog) const {
     502           0 :     SkASSERT(fAsset);
     503           0 :     fDict.addResources(catalog);
     504           0 : }
     505             : 
     506             : 
     507             : ////////////////////////////////////////////////////////////////////////////////
     508             : 
     509           0 : SkPDFStream:: SkPDFStream(sk_sp<SkData> data) {
     510           0 :     this->setData(skstd::make_unique<SkMemoryStream>(std::move(data)));
     511           0 : }
     512             : 
     513           0 : SkPDFStream::SkPDFStream(std::unique_ptr<SkStreamAsset> stream) {
     514           0 :     this->setData(std::move(stream));
     515           0 : }
     516             : 
     517           0 : SkPDFStream::SkPDFStream() {}
     518             : 
     519           0 : SkPDFStream::~SkPDFStream() {}
     520             : 
     521           0 : void SkPDFStream::addResources(SkPDFObjNumMap* catalog) const {
     522           0 :     SkASSERT(fCompressedData);
     523           0 :     fDict.addResources(catalog);
     524           0 : }
     525             : 
     526           0 : void SkPDFStream::drop() {
     527           0 :     fCompressedData.reset(nullptr);
     528           0 :     fDict.drop();
     529           0 : }
     530             : 
     531           0 : void SkPDFStream::emitObject(SkWStream* stream,
     532             :                              const SkPDFObjNumMap& objNumMap) const {
     533           0 :     SkASSERT(fCompressedData);
     534           0 :     fDict.emitObject(stream, objNumMap);
     535             :     // duplicate (a cheap operation) preserves const on fCompressedData.
     536           0 :     std::unique_ptr<SkStreamAsset> dup(fCompressedData->duplicate());
     537           0 :     SkASSERT(dup);
     538           0 :     SkASSERT(dup->hasLength());
     539           0 :     stream->writeText(" stream\n");
     540           0 :     stream->writeStream(dup.get(), dup->getLength());
     541           0 :     stream->writeText("\nendstream");
     542           0 : }
     543             : 
     544           0 : void SkPDFStream::setData(std::unique_ptr<SkStreamAsset> stream) {
     545           0 :     SkASSERT(!fCompressedData);  // Only call this function once.
     546           0 :     SkASSERT(stream);
     547             :     // Code assumes that the stream starts at the beginning.
     548             : 
     549             :     #ifdef SK_PDF_LESS_COMPRESSION
     550             :     fCompressedData = std::move(stream);
     551             :     SkASSERT(fCompressedData && fCompressedData->hasLength());
     552             :     fDict.insertInt("Length", fCompressedData->getLength());
     553             :     #else
     554             : 
     555           0 :     SkASSERT(stream->hasLength());
     556           0 :     SkDynamicMemoryWStream compressedData;
     557           0 :     SkDeflateWStream deflateWStream(&compressedData);
     558           0 :     if (stream->getLength() > 0) {
     559           0 :         SkStreamCopy(&deflateWStream, stream.get());
     560             :     }
     561           0 :     deflateWStream.finalize();
     562           0 :     size_t compressedLength = compressedData.bytesWritten();
     563           0 :     size_t originalLength = stream->getLength();
     564             : 
     565           0 :     if (originalLength <= compressedLength + strlen("/Filter_/FlateDecode_")) {
     566           0 :         SkAssertResult(stream->rewind());
     567           0 :         fCompressedData = std::move(stream);
     568           0 :         fDict.insertInt("Length", originalLength);
     569           0 :         return;
     570             :     }
     571           0 :     fCompressedData = compressedData.detachAsStream();
     572           0 :     fDict.insertName("Filter", "FlateDecode");
     573           0 :     fDict.insertInt("Length", compressedLength);
     574             :     #endif
     575             : }
     576             : 
     577             : ////////////////////////////////////////////////////////////////////////////////
     578             : 
     579           0 : bool SkPDFObjNumMap::addObject(SkPDFObject* obj) {
     580           0 :     if (fObjectNumbers.find(obj)) {
     581           0 :         return false;
     582             :     }
     583           0 :     fObjectNumbers.set(obj, fObjectNumbers.count() + 1);
     584           0 :     fObjects.emplace_back(sk_ref_sp(obj));
     585           0 :     return true;
     586             : }
     587             : 
     588           0 : void SkPDFObjNumMap::addObjectRecursively(SkPDFObject* obj) {
     589           0 :     if (obj && this->addObject(obj)) {
     590           0 :         obj->addResources(this);
     591             :     }
     592           0 : }
     593             : 
     594           0 : int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const {
     595           0 :     int32_t* objectNumberFound = fObjectNumbers.find(obj);
     596           0 :     SkASSERT(objectNumberFound);
     597           0 :     return *objectNumberFound;
     598             : }
     599             : 
     600             : #ifdef SK_PDF_IMAGE_STATS
     601             : SkAtomic<int> gDrawImageCalls(0);
     602             : SkAtomic<int> gJpegImageObjects(0);
     603             : SkAtomic<int> gRegularImageObjects(0);
     604             : 
     605             : void SkPDFImageDumpStats() {
     606             :     SkDebugf("\ntotal PDF drawImage/drawBitmap calls: %d\n"
     607             :              "total PDF jpeg images: %d\n"
     608             :              "total PDF regular images: %d\n",
     609             :              gDrawImageCalls.load(),
     610             :              gJpegImageObjects.load(),
     611             :              gRegularImageObjects.load());
     612             : }
     613             : #endif // SK_PDF_IMAGE_STATS

Generated by: LCOV version 1.13