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