blob: 0ff7b49ff087e021f8e62d8149bfc54176998549 [file] [log] [blame]
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00001/*
vandebo@chromium.orgd90c1412011-02-24 21:50:04 +00002 * Copyright (C) 2010 Google Inc.
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +00003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
reed@google.com8a85d0c2011-06-24 19:12:12 +000017#include "SkData.h"
vandebo@chromium.orga09ef972010-12-01 22:17:20 +000018#include "SkFlate.h"
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000019#include "SkPDFCatalog.h"
20#include "SkPDFStream.h"
21#include "SkStream.h"
22
vandebo@chromium.org421d6442011-07-20 17:39:01 +000023static bool skip_compression(SkPDFCatalog* catalog) {
24 return catalog->getDocumentFlags() & SkPDFDocument::kNoCompression_Flag;
25}
vandebo@chromium.org1cfa2c42011-01-31 19:35:43 +000026
vandebo@chromium.org421d6442011-07-20 17:39:01 +000027SkPDFStream::SkPDFStream(SkStream* stream)
28 : fState(kUnused_State),
29 fData(stream) {
30}
31
32SkPDFStream::SkPDFStream(SkData* data) : fState(kUnused_State) {
33 SkMemoryStream* stream = new SkMemoryStream;
34 stream->setData(data);
35 fData = stream;
36 fData->unref(); // SkRefPtr and new both took a reference.
37}
38
39SkPDFStream::SkPDFStream(const SkPDFStream& pdfStream)
40 : SkPDFDict(),
41 fState(kUnused_State),
42 fData(pdfStream.fData) {
43 bool removeLength = true;
44 // Don't uncompress an already compressed stream, but we could.
45 if (pdfStream.fState == kCompressed_State) {
46 fState = kCompressed_State;
47 removeLength = false;
vandebo@chromium.orga09ef972010-12-01 22:17:20 +000048 }
vandebo@chromium.org421d6442011-07-20 17:39:01 +000049 SkPDFDict::Iter dict(pdfStream);
50 SkPDFName* key;
51 SkPDFObject* value;
52 SkPDFName lengthName("Length");
53 for (key = dict.next(&value); key != NULL; key = dict.next(&value)) {
54 if (removeLength && *key == lengthName) {
55 continue;
56 }
57 this->insert(key, value);
58 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000059}
60
vandebo@chromium.org421d6442011-07-20 17:39:01 +000061SkPDFStream::~SkPDFStream() {}
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000062
63void SkPDFStream::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
64 bool indirect) {
vandebo@chromium.org421d6442011-07-20 17:39:01 +000065 if (indirect) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000066 return emitIndirectObject(stream, catalog);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000067 }
68 if (!this->populate(catalog)) {
69 return fSubstitute->emitObject(stream, catalog, indirect);
70 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000071
vandebo@chromium.orgd90c1412011-02-24 21:50:04 +000072 this->INHERITED::emitObject(stream, catalog, false);
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000073 stream->writeText(" stream\n");
vandebo@chromium.org421d6442011-07-20 17:39:01 +000074 stream->write(fData->getMemoryBase(), fData->getLength());
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000075 stream->writeText("\nendstream");
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000076}
77
78size_t SkPDFStream::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
vandebo@chromium.org421d6442011-07-20 17:39:01 +000079 if (indirect) {
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000080 return getIndirectOutputSize(catalog);
vandebo@chromium.org421d6442011-07-20 17:39:01 +000081 }
82 if (!this->populate(catalog)) {
83 return fSubstitute->getOutputSize(catalog, indirect);
84 }
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +000085
vandebo@chromium.orgd90c1412011-02-24 21:50:04 +000086 return this->INHERITED::getOutputSize(catalog, false) +
vandebo@chromium.org421d6442011-07-20 17:39:01 +000087 strlen(" stream\n\nendstream") + fData->getLength();
88}
89
90SkPDFStream::SkPDFStream() : fState(kUnused_State) {}
91
92void SkPDFStream::setData(SkStream* stream) {
93 fData = stream;
94}
95
96bool SkPDFStream::populate(SkPDFCatalog* catalog) {
97 if (fState == kUnused_State) {
98 if (!skip_compression(catalog) && SkFlate::HaveFlate()) {
99 SkDynamicMemoryWStream compressedData;
100
101 SkAssertResult(SkFlate::Deflate(fData.get(), &compressedData));
102 if (compressedData.getOffset() < fData->getLength()) {
103 SkMemoryStream* stream = new SkMemoryStream;
104 stream->setData(compressedData.copyToData());
105 fData = stream;
106 fData->unref(); // SkRefPtr and new both took a reference.
107 insertName("Filter", "FlateDecode");
108 }
109 fState = kCompressed_State;
110 } else {
111 fState = kNoCompression_State;
112 }
113 insertInt("Length", fData->getLength());
114 } else if (fState == kNoCompression_State && !skip_compression(catalog) &&
115 SkFlate::HaveFlate()) {
116 if (!fSubstitute.get()) {
117 fSubstitute = new SkPDFStream(*this);
118 fSubstitute->unref(); // SkRefPtr and new both took a reference.
119 catalog->setSubstitute(this, fSubstitute.get());
120 }
121 return false;
122 }
123 return true;
vandebo@chromium.org8459d4e2010-09-24 22:25:30 +0000124}