• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
skip_compression(SkPDFCatalog * catalog)16 static bool skip_compression(SkPDFCatalog* catalog) {
17     return SkToBool(catalog->getDocumentFlags() &
18                     SkPDFDocument::kFavorSpeedOverSize_Flags);
19 }
20 
SkPDFStream(SkStream * stream)21 SkPDFStream::SkPDFStream(SkStream* stream) : fState(kUnused_State) {
22     setData(stream);
23 }
24 
SkPDFStream(SkData * data)25 SkPDFStream::SkPDFStream(SkData* data) : fState(kUnused_State) {
26     setData(data);
27 }
28 
SkPDFStream(const SkPDFStream & pdfStream)29 SkPDFStream::SkPDFStream(const SkPDFStream& pdfStream)
30         : SkPDFDict(),
31           fState(kUnused_State) {
32     setData(pdfStream.fData.get());
33     bool removeLength = true;
34     // Don't uncompress an already compressed stream, but we could.
35     if (pdfStream.fState == kCompressed_State) {
36         fState = kCompressed_State;
37         removeLength = false;
38     }
39     SkPDFDict::Iter dict(pdfStream);
40     SkPDFName* key;
41     SkPDFObject* value;
42     SkPDFName lengthName("Length");
43     for (key = dict.next(&value); key != NULL; key = dict.next(&value)) {
44         if (removeLength && *key == lengthName) {
45             continue;
46         }
47         this->insert(key, value);
48     }
49 }
50 
~SkPDFStream()51 SkPDFStream::~SkPDFStream() {}
52 
emitObject(SkWStream * stream,SkPDFCatalog * catalog,bool indirect)53 void SkPDFStream::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
54                              bool indirect) {
55     if (indirect) {
56         return emitIndirectObject(stream, catalog);
57     }
58     if (!this->populate(catalog)) {
59         return fSubstitute->emitObject(stream, catalog, indirect);
60     }
61 
62     this->INHERITED::emitObject(stream, catalog, false);
63     stream->writeText(" stream\n");
64     stream->writeStream(fData.get(), fData->getLength());
65     fData->rewind();
66     stream->writeText("\nendstream");
67 }
68 
getOutputSize(SkPDFCatalog * catalog,bool indirect)69 size_t SkPDFStream::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
70     if (indirect) {
71         return getIndirectOutputSize(catalog);
72     }
73     if (!this->populate(catalog)) {
74         return fSubstitute->getOutputSize(catalog, indirect);
75     }
76 
77     return this->INHERITED::getOutputSize(catalog, false) +
78         strlen(" stream\n\nendstream") + fData->getLength();
79 }
80 
SkPDFStream()81 SkPDFStream::SkPDFStream() : fState(kUnused_State) {}
82 
setData(SkData * data)83 void SkPDFStream::setData(SkData* data) {
84     SkMemoryStream* stream = new SkMemoryStream;
85     stream->setData(data);
86     fData.reset(stream);  // Transfer ownership.
87 }
88 
setData(SkStream * stream)89 void SkPDFStream::setData(SkStream* stream) {
90     // Code assumes that the stream starts at the beginning and is rewindable.
91     if (stream) {
92         SkASSERT(stream->getPosition() == 0);
93         SkASSERT(stream->rewind());
94     }
95     fData.reset(stream);
96     SkSafeRef(stream);
97 }
98 
populate(SkPDFCatalog * catalog)99 bool SkPDFStream::populate(SkPDFCatalog* catalog) {
100     if (fState == kUnused_State) {
101         if (!skip_compression(catalog) && SkFlate::HaveFlate()) {
102             SkDynamicMemoryWStream compressedData;
103 
104             SkAssertResult(SkFlate::Deflate(fData.get(), &compressedData));
105             if (compressedData.getOffset() < fData->getLength()) {
106                 SkMemoryStream* stream = new SkMemoryStream;
107                 stream->setData(compressedData.copyToData())->unref();
108                 fData.reset(stream);  // Transfer ownership.
109                 insertName("Filter", "FlateDecode");
110             }
111             fState = kCompressed_State;
112         } else {
113             fState = kNoCompression_State;
114         }
115         insertInt("Length", fData->getLength());
116     } else if (fState == kNoCompression_State && !skip_compression(catalog) &&
117                SkFlate::HaveFlate()) {
118         if (!fSubstitute.get()) {
119             fSubstitute.reset(new SkPDFStream(*this));
120             catalog->setSubstitute(this, fSubstitute.get());
121         }
122         return false;
123     }
124     return true;
125 }
126