blob: 837de7a9698565a97a5bca2183d7ab48ea3e0360 [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"
halcanary67ec1f82014-06-27 11:36:20 -070015#include "SkStreamPriv.h"
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000016
vandebo@chromium.org421d6442011-07-20 17:39:01 +000017static bool skip_compression(SkPDFCatalog* catalog) {
vandebo@chromium.org238be8c2012-07-13 20:06:02 +000018 return SkToBool(catalog->getDocumentFlags() &
edisonn@google.com8c020612013-03-12 19:53:16 +000019 SkPDFDocument::kFavorSpeedOverSize_Flags);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000020}
vandebo@chromium.org1cfa2c42011-01-31 19:35:43 +000021
vandebo@chromium.org26e14492013-08-26 22:52:09 +000022SkPDFStream::SkPDFStream(SkStream* stream) : fState(kUnused_State) {
halcanary67ec1f82014-06-27 11:36:20 -070023 this->setData(stream);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000024}
25
26SkPDFStream::SkPDFStream(SkData* data) : fState(kUnused_State) {
halcanary67ec1f82014-06-27 11:36:20 -070027 this->setData(data);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000028}
29
30SkPDFStream::SkPDFStream(const SkPDFStream& pdfStream)
31 : SkPDFDict(),
vandebo@chromium.org26e14492013-08-26 22:52:09 +000032 fState(kUnused_State) {
halcanarye3224822014-07-14 09:12:12 -070033 this->setData(pdfStream.fDataStream.get());
vandebo@chromium.org421d6442011-07-20 17:39:01 +000034 bool removeLength = true;
35 // Don't uncompress an already compressed stream, but we could.
36 if (pdfStream.fState == kCompressed_State) {
37 fState = kCompressed_State;
38 removeLength = false;
vandebo@chromium.orga09ef972010-12-01 22:17:20 +000039 }
halcanary1f8ed022014-06-27 10:37:27 -070040 this->mergeFrom(pdfStream);
41 if (removeLength) {
42 this->remove("Length");
vandebo@chromium.org421d6442011-07-20 17:39:01 +000043 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000044}
45
vandebo@chromium.org421d6442011-07-20 17:39:01 +000046SkPDFStream::~SkPDFStream() {}
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000047
halcanary4fc48af2015-01-12 10:07:50 -080048void SkPDFStream::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
halcanary67ec1f82014-06-27 11:36:20 -070049 SkAutoMutexAcquire lock(fMutex); // multiple threads could be calling emit
vandebo@chromium.org421d6442011-07-20 17:39:01 +000050 if (!this->populate(catalog)) {
halcanary4fc48af2015-01-12 10:07:50 -080051 return fSubstitute->emitObject(stream, catalog);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000052 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000053
halcanary4fc48af2015-01-12 10:07:50 -080054 this->INHERITED::emitObject(stream, catalog);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000055 stream->writeText(" stream\n");
halcanarye3224822014-07-14 09:12:12 -070056 stream->writeStream(fDataStream.get(), fDataStream->getLength());
57 SkAssertResult(fDataStream->rewind());
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000058 stream->writeText("\nendstream");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000059}
60
vandebo@chromium.org421d6442011-07-20 17:39:01 +000061SkPDFStream::SkPDFStream() : fState(kUnused_State) {}
62
commit-bot@chromium.orgd8d976e2013-07-08 23:17:57 +000063void SkPDFStream::setData(SkData* data) {
halcanarye3224822014-07-14 09:12:12 -070064 fMemoryStream.setData(data);
65 if (&fMemoryStream != fDataStream.get()) {
66 fDataStream.reset(SkRef(&fMemoryStream));
67 }
commit-bot@chromium.orgd8d976e2013-07-08 23:17:57 +000068}
69
vandebo@chromium.org421d6442011-07-20 17:39:01 +000070void SkPDFStream::setData(SkStream* stream) {
vandebo@chromium.org26e14492013-08-26 22:52:09 +000071 // Code assumes that the stream starts at the beginning and is rewindable.
halcanarye3224822014-07-14 09:12:12 -070072 if (&fMemoryStream == fDataStream.get()) {
73 SkASSERT(&fMemoryStream != stream);
74 fMemoryStream.setData(NULL);
75 }
76 SkASSERT(0 == fMemoryStream.getLength());
vandebo@chromium.org26e14492013-08-26 22:52:09 +000077 if (stream) {
halcanarye3224822014-07-14 09:12:12 -070078 // SkStreamRewindableFromSkStream will try stream->duplicate().
79 fDataStream.reset(SkStreamRewindableFromSkStream(stream));
80 SkASSERT(fDataStream.get());
halcanary67ec1f82014-06-27 11:36:20 -070081 } else {
halcanarye3224822014-07-14 09:12:12 -070082 fDataStream.reset(SkRef(&fMemoryStream));
vandebo@chromium.org26e14492013-08-26 22:52:09 +000083 }
halcanary67ec1f82014-06-27 11:36:20 -070084}
85
86size_t SkPDFStream::dataSize() const {
halcanarye3224822014-07-14 09:12:12 -070087 SkASSERT(fDataStream->hasLength());
88 return fDataStream->getLength();
vandebo@chromium.org421d6442011-07-20 17:39:01 +000089}
90
91bool SkPDFStream::populate(SkPDFCatalog* catalog) {
92 if (fState == kUnused_State) {
93 if (!skip_compression(catalog) && SkFlate::HaveFlate()) {
94 SkDynamicMemoryWStream compressedData;
95
halcanarye3224822014-07-14 09:12:12 -070096 SkAssertResult(
97 SkFlate::Deflate(fDataStream.get(), &compressedData));
98 SkAssertResult(fDataStream->rewind());
halcanary67ec1f82014-06-27 11:36:20 -070099 if (compressedData.getOffset() < this->dataSize()) {
halcanaryf459c852014-07-14 12:59:59 -0700100 SkAutoTUnref<SkStream> compressed(
101 compressedData.detachAsStream());
102 this->setData(compressed.get());
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000103 insertName("Filter", "FlateDecode");
104 }
105 fState = kCompressed_State;
106 } else {
107 fState = kNoCompression_State;
108 }
halcanary67ec1f82014-06-27 11:36:20 -0700109 insertInt("Length", this->dataSize());
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}