Home | History | Annotate | Download | only in pdf
      1 
      2 /*
      3  * Copyright 2010 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkData.h"
     11 #include "SkFlate.h"
     12 #include "SkPDFCatalog.h"
     13 #include "SkPDFStream.h"
     14 #include "SkStream.h"
     15 
     16 static bool skip_compression(SkPDFCatalog* catalog) {
     17     return SkToBool(catalog->getDocumentFlags() &
     18                     SkPDFDocument::kNoCompression_Flags);
     19 }
     20 
     21 SkPDFStream::SkPDFStream(SkStream* stream)
     22     : fState(kUnused_State),
     23       fData(stream) {
     24     SkSafeRef(stream);
     25 }
     26 
     27 SkPDFStream::SkPDFStream(SkData* data) : fState(kUnused_State) {
     28     SkMemoryStream* stream = new SkMemoryStream;
     29     stream->setData(data);
     30     fData.reset(stream);  // Transfer ownership.
     31 }
     32 
     33 SkPDFStream::SkPDFStream(const SkPDFStream& pdfStream)
     34         : SkPDFDict(),
     35           fState(kUnused_State),
     36           fData(pdfStream.fData.get()) {
     37     fData.get()->ref();
     38     bool removeLength = true;
     39     // Don't uncompress an already compressed stream, but we could.
     40     if (pdfStream.fState == kCompressed_State) {
     41         fState = kCompressed_State;
     42         removeLength = false;
     43     }
     44     SkPDFDict::Iter dict(pdfStream);
     45     SkPDFName* key;
     46     SkPDFObject* value;
     47     SkPDFName lengthName("Length");
     48     for (key = dict.next(&value); key != NULL; key = dict.next(&value)) {
     49         if (removeLength && *key == lengthName) {
     50             continue;
     51         }
     52         this->insert(key, value);
     53     }
     54 }
     55 
     56 SkPDFStream::~SkPDFStream() {}
     57 
     58 void SkPDFStream::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
     59                              bool indirect) {
     60     if (indirect) {
     61         return emitIndirectObject(stream, catalog);
     62     }
     63     if (!this->populate(catalog)) {
     64         return fSubstitute->emitObject(stream, catalog, indirect);
     65     }
     66 
     67     this->INHERITED::emitObject(stream, catalog, false);
     68     stream->writeText(" stream\n");
     69     stream->write(fData->getMemoryBase(), fData->getLength());
     70     stream->writeText("\nendstream");
     71 }
     72 
     73 size_t SkPDFStream::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
     74     if (indirect) {
     75         return getIndirectOutputSize(catalog);
     76     }
     77     if (!this->populate(catalog)) {
     78         return fSubstitute->getOutputSize(catalog, indirect);
     79     }
     80 
     81     return this->INHERITED::getOutputSize(catalog, false) +
     82         strlen(" stream\n\nendstream") + fData->getLength();
     83 }
     84 
     85 SkPDFStream::SkPDFStream() : fState(kUnused_State) {}
     86 
     87 void SkPDFStream::setData(SkStream* stream) {
     88     fData.reset(stream);
     89     SkSafeRef(stream);
     90 }
     91 
     92 bool SkPDFStream::populate(SkPDFCatalog* catalog) {
     93     if (fState == kUnused_State) {
     94         if (!skip_compression(catalog) && SkFlate::HaveFlate()) {
     95             SkDynamicMemoryWStream compressedData;
     96 
     97             SkAssertResult(SkFlate::Deflate(fData.get(), &compressedData));
     98             if (compressedData.getOffset() < fData->getLength()) {
     99                 SkMemoryStream* stream = new SkMemoryStream;
    100                 stream->setData(compressedData.copyToData())->unref();
    101                 fData.reset(stream);  // Transfer ownership.
    102                 insertName("Filter", "FlateDecode");
    103             }
    104             fState = kCompressed_State;
    105         } else {
    106             fState = kNoCompression_State;
    107         }
    108         insertInt("Length", fData->getLength());
    109     } else if (fState == kNoCompression_State && !skip_compression(catalog) &&
    110                SkFlate::HaveFlate()) {
    111         if (!fSubstitute.get()) {
    112             fSubstitute.reset(new SkPDFStream(*this));
    113             catalog->setSubstitute(this, fSubstitute.get());
    114         }
    115         return false;
    116     }
    117     return true;
    118 }
    119