blob: a6b2ec8b8e3112a019944603d007b097c55f8d43 [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.org421d6442011-07-20 17:39:01 +000021SkPDFStream::SkPDFStream(SkStream* stream)
22 : fState(kUnused_State),
23 fData(stream) {
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +000024 SkSafeRef(stream);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000025}
26
27SkPDFStream::SkPDFStream(SkData* data) : fState(kUnused_State) {
28 SkMemoryStream* stream = new SkMemoryStream;
29 stream->setData(data);
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +000030 fData.reset(stream); // Transfer ownership.
vandebo@chromium.org421d6442011-07-20 17:39:01 +000031}
32
33SkPDFStream::SkPDFStream(const SkPDFStream& pdfStream)
34 : SkPDFDict(),
35 fState(kUnused_State),
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +000036 fData(pdfStream.fData.get()) {
37 fData.get()->ref();
vandebo@chromium.org421d6442011-07-20 17:39:01 +000038 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;
vandebo@chromium.orga09ef972010-12-01 22:17:20 +000043 }
vandebo@chromium.org421d6442011-07-20 17:39:01 +000044 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 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000054}
55
vandebo@chromium.org421d6442011-07-20 17:39:01 +000056SkPDFStream::~SkPDFStream() {}
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000057
58void SkPDFStream::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
59 bool indirect) {
vandebo@chromium.org421d6442011-07-20 17:39:01 +000060 if (indirect) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000061 return emitIndirectObject(stream, catalog);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000062 }
63 if (!this->populate(catalog)) {
64 return fSubstitute->emitObject(stream, catalog, indirect);
65 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000066
vandebo@chromium.orgd90c1412011-02-24 21:50:04 +000067 this->INHERITED::emitObject(stream, catalog, false);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000068 stream->writeText(" stream\n");
vandebo@chromium.org421d6442011-07-20 17:39:01 +000069 stream->write(fData->getMemoryBase(), fData->getLength());
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000070 stream->writeText("\nendstream");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000071}
72
73size_t SkPDFStream::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
vandebo@chromium.org421d6442011-07-20 17:39:01 +000074 if (indirect) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000075 return getIndirectOutputSize(catalog);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000076 }
77 if (!this->populate(catalog)) {
78 return fSubstitute->getOutputSize(catalog, indirect);
79 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000080
vandebo@chromium.orgd90c1412011-02-24 21:50:04 +000081 return this->INHERITED::getOutputSize(catalog, false) +
vandebo@chromium.org421d6442011-07-20 17:39:01 +000082 strlen(" stream\n\nendstream") + fData->getLength();
83}
84
85SkPDFStream::SkPDFStream() : fState(kUnused_State) {}
86
87void SkPDFStream::setData(SkStream* stream) {
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +000088 fData.reset(stream);
89 SkSafeRef(stream);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000090}
91
92bool 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;
vandebo@chromium.org610f7162012-03-14 18:34:15 +0000100 stream->setData(compressedData.copyToData())->unref();
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000101 fData.reset(stream); // Transfer ownership.
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000102 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()) {
vandebo@chromium.orgd96d17b2013-01-04 19:31:24 +0000112 fSubstitute.reset(new SkPDFStream(*this));
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000113 catalog->setSubstitute(this, fSubstitute.get());
114 }
115 return false;
116 }
117 return true;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000118}