blob: 815ef481ee2135abab110171975687f6d8a6d28a [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 Google Inc.
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@google.com8a85d0c2011-06-24 19:12:12 +000010#include "SkData.h"
vandebo@chromium.orga09ef972010-12-01 22:17:20 +000011#include "SkFlate.h"
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000012#include "SkPDFCatalog.h"
13#include "SkPDFStream.h"
14#include "SkStream.h"
15
vandebo@chromium.org421d6442011-07-20 17:39:01 +000016static bool skip_compression(SkPDFCatalog* catalog) {
vandebo@chromium.org238be8c2012-07-13 20:06:02 +000017 return SkToBool(catalog->getDocumentFlags() &
edisonn@google.com8c020612013-03-12 19:53:16 +000018 SkPDFDocument::kFavorSpeedOverSize_Flags);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000019}
vandebo@chromium.org1cfa2c42011-01-31 19:35:43 +000020
vandebo@chromium.org26e14492013-08-26 22:52:09 +000021SkPDFStream::SkPDFStream(SkStream* stream) : fState(kUnused_State) {
rmistrye1c55862014-06-26 14:31:06 -070022 setData(stream);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000023}
24
25SkPDFStream::SkPDFStream(SkData* data) : fState(kUnused_State) {
rmistrye1c55862014-06-26 14:31:06 -070026 setData(data);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000027}
28
29SkPDFStream::SkPDFStream(const SkPDFStream& pdfStream)
30 : SkPDFDict(),
vandebo@chromium.org26e14492013-08-26 22:52:09 +000031 fState(kUnused_State) {
rmistrye1c55862014-06-26 14:31:06 -070032 setData(pdfStream.fData.get());
vandebo@chromium.org421d6442011-07-20 17:39:01 +000033 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;
vandebo@chromium.orga09ef972010-12-01 22:17:20 +000038 }
halcanary1f8ed022014-06-27 10:37:27 -070039 this->mergeFrom(pdfStream);
40 if (removeLength) {
41 this->remove("Length");
vandebo@chromium.org421d6442011-07-20 17:39:01 +000042 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000043}
44
vandebo@chromium.org421d6442011-07-20 17:39:01 +000045SkPDFStream::~SkPDFStream() {}
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000046
47void SkPDFStream::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
48 bool indirect) {
vandebo@chromium.org421d6442011-07-20 17:39:01 +000049 if (indirect) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000050 return emitIndirectObject(stream, catalog);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000051 }
52 if (!this->populate(catalog)) {
53 return fSubstitute->emitObject(stream, catalog, indirect);
54 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000055
vandebo@chromium.orgd90c1412011-02-24 21:50:04 +000056 this->INHERITED::emitObject(stream, catalog, false);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000057 stream->writeText(" stream\n");
rmistrye1c55862014-06-26 14:31:06 -070058 stream->writeStream(fData.get(), fData->getLength());
59 fData->rewind();
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000060 stream->writeText("\nendstream");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000061}
62
63size_t SkPDFStream::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
vandebo@chromium.org421d6442011-07-20 17:39:01 +000064 if (indirect) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000065 return getIndirectOutputSize(catalog);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000066 }
67 if (!this->populate(catalog)) {
68 return fSubstitute->getOutputSize(catalog, indirect);
69 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000070
vandebo@chromium.orgd90c1412011-02-24 21:50:04 +000071 return this->INHERITED::getOutputSize(catalog, false) +
rmistrye1c55862014-06-26 14:31:06 -070072 strlen(" stream\n\nendstream") + fData->getLength();
vandebo@chromium.org421d6442011-07-20 17:39:01 +000073}
74
75SkPDFStream::SkPDFStream() : fState(kUnused_State) {}
76
commit-bot@chromium.orgd8d976e2013-07-08 23:17:57 +000077void SkPDFStream::setData(SkData* data) {
rmistrye1c55862014-06-26 14:31:06 -070078 SkMemoryStream* stream = new SkMemoryStream;
79 stream->setData(data);
80 fData.reset(stream); // Transfer ownership.
commit-bot@chromium.orgd8d976e2013-07-08 23:17:57 +000081}
82
vandebo@chromium.org421d6442011-07-20 17:39:01 +000083void SkPDFStream::setData(SkStream* stream) {
vandebo@chromium.org26e14492013-08-26 22:52:09 +000084 // Code assumes that the stream starts at the beginning and is rewindable.
85 if (stream) {
86 SkASSERT(stream->getPosition() == 0);
87 SkASSERT(stream->rewind());
88 }
rmistrye1c55862014-06-26 14:31:06 -070089 fData.reset(stream);
90 SkSafeRef(stream);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000091}
92
93bool SkPDFStream::populate(SkPDFCatalog* catalog) {
94 if (fState == kUnused_State) {
95 if (!skip_compression(catalog) && SkFlate::HaveFlate()) {
96 SkDynamicMemoryWStream compressedData;
97
98 SkAssertResult(SkFlate::Deflate(fData.get(), &compressedData));
rmistrye1c55862014-06-26 14:31:06 -070099 if (compressedData.getOffset() < fData->getLength()) {
100 SkMemoryStream* stream = new SkMemoryStream;
101 stream->setData(compressedData.copyToData())->unref();
102 fData.reset(stream); // Transfer ownership.
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000103 insertName("Filter", "FlateDecode");
104 }
105 fState = kCompressed_State;
106 } else {
107 fState = kNoCompression_State;
108 }
rmistrye1c55862014-06-26 14:31:06 -0700109 insertInt("Length", fData->getLength());
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000110 } else if (fState == kNoCompression_State && !skip_compression(catalog) &&
111 SkFlate::HaveFlate()) {
112 if (!fSubstitute.get()) {
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000113 fSubstitute.reset(new SkPDFStream(*this));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000114 catalog->setSubstitute(this, fSubstitute.get());
115 }
116 return false;
117 }
118 return true;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000119}