1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 28459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc. 48459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 78459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org */ 88459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 108a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com#include "SkData.h" 11a09ef977b6799f01cd3fd64725fb3069da8be4bcvandebo@chromium.org#include "SkFlate.h" 128459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org#include "SkPDFCatalog.h" 138459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org#include "SkPDFStream.h" 148459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org#include "SkStream.h" 1567ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary#include "SkStreamPriv.h" 168459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org 17421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgstatic bool skip_compression(SkPDFCatalog* catalog) { 18238be8c7e5de5a83517440a3db7f7965b47fb010vandebo@chromium.org return SkToBool(catalog->getDocumentFlags() & 198c020612bad088d1a26dd663f0a806deeef8029bedisonn@google.com SkPDFDocument::kFavorSpeedOverSize_Flags); 20421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org} 211cfa2c458626abe952a63b1a9397d8e496a134d6vandebo@chromium.org 2226e1449d85805c61e4caff1f68e4f57498359649vandebo@chromium.orgSkPDFStream::SkPDFStream(SkStream* stream) : fState(kUnused_State) { 2367ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary this->setData(stream); 248459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org} 258459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org 26421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFStream::SkPDFStream(SkData* data) : fState(kUnused_State) { 2767ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary this->setData(data); 28421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org} 29421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 30421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFStream::SkPDFStream(const SkPDFStream& pdfStream) 31421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org : SkPDFDict(), 3226e1449d85805c61e4caff1f68e4f57498359649vandebo@chromium.org fState(kUnused_State) { 33e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary this->setData(pdfStream.fDataStream.get()); 34421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org bool removeLength = true; 35421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org // Don't uncompress an already compressed stream, but we could. 36421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (pdfStream.fState == kCompressed_State) { 37421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fState = kCompressed_State; 38421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org removeLength = false; 39421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 401f8ed022226c9f960b9fc95af9297d5111a07eadhalcanary this->mergeFrom(pdfStream); 411f8ed022226c9f960b9fc95af9297d5111a07eadhalcanary if (removeLength) { 421f8ed022226c9f960b9fc95af9297d5111a07eadhalcanary this->remove("Length"); 43421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 448459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org} 458459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org 46421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFStream::~SkPDFStream() {} 47421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 488459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.orgvoid SkPDFStream::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 498459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org bool indirect) { 50421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (indirect) { 518459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org return emitIndirectObject(stream, catalog); 52421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 5367ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary SkAutoMutexAcquire lock(fMutex); // multiple threads could be calling emit 54421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (!this->populate(catalog)) { 55421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org return fSubstitute->emitObject(stream, catalog, indirect); 56421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 578459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org 58d90c141feb10c80581c16dbb57fcc97719a0c002vandebo@chromium.org this->INHERITED::emitObject(stream, catalog, false); 598459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org stream->writeText(" stream\n"); 60e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary stream->writeStream(fDataStream.get(), fDataStream->getLength()); 61e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary SkAssertResult(fDataStream->rewind()); 629b49dc0db8254e3dcdc2de4a1e0add4f8a7ac5a8vandebo@chromium.org stream->writeText("\nendstream"); 638459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org} 648459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org 658459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.orgsize_t SkPDFStream::getOutputSize(SkPDFCatalog* catalog, bool indirect) { 66421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (indirect) { 678459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org return getIndirectOutputSize(catalog); 68421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 6967ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary SkAutoMutexAcquire lock(fMutex); // multiple threads could be calling emit 70421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (!this->populate(catalog)) { 71421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org return fSubstitute->getOutputSize(catalog, indirect); 72421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 738459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org 74d90c141feb10c80581c16dbb57fcc97719a0c002vandebo@chromium.org return this->INHERITED::getOutputSize(catalog, false) + 7567ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary strlen(" stream\n\nendstream") + this->dataSize(); 76421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org} 77421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 78421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgSkPDFStream::SkPDFStream() : fState(kUnused_State) {} 79421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 80d8d976e7d2d302d4efb53f143034f153adc5565ccommit-bot@chromium.orgvoid SkPDFStream::setData(SkData* data) { 81e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary fMemoryStream.setData(data); 82e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary if (&fMemoryStream != fDataStream.get()) { 83e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary fDataStream.reset(SkRef(&fMemoryStream)); 84e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary } 85d8d976e7d2d302d4efb53f143034f153adc5565ccommit-bot@chromium.org} 86d8d976e7d2d302d4efb53f143034f153adc5565ccommit-bot@chromium.org 87421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgvoid SkPDFStream::setData(SkStream* stream) { 8826e1449d85805c61e4caff1f68e4f57498359649vandebo@chromium.org // Code assumes that the stream starts at the beginning and is rewindable. 89e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary if (&fMemoryStream == fDataStream.get()) { 90e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary SkASSERT(&fMemoryStream != stream); 91e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary fMemoryStream.setData(NULL); 92e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary } 93e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary SkASSERT(0 == fMemoryStream.getLength()); 9426e1449d85805c61e4caff1f68e4f57498359649vandebo@chromium.org if (stream) { 95e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary // SkStreamRewindableFromSkStream will try stream->duplicate(). 96e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary fDataStream.reset(SkStreamRewindableFromSkStream(stream)); 97e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary SkASSERT(fDataStream.get()); 9867ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary } else { 99e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary fDataStream.reset(SkRef(&fMemoryStream)); 10026e1449d85805c61e4caff1f68e4f57498359649vandebo@chromium.org } 10167ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary} 10267ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary 10367ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanarysize_t SkPDFStream::dataSize() const { 104e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary SkASSERT(fDataStream->hasLength()); 105e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary return fDataStream->getLength(); 106421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org} 107421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 108421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.orgbool SkPDFStream::populate(SkPDFCatalog* catalog) { 109421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (fState == kUnused_State) { 110421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (!skip_compression(catalog) && SkFlate::HaveFlate()) { 111421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkDynamicMemoryWStream compressedData; 112421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org 113e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary SkAssertResult( 114e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary SkFlate::Deflate(fDataStream.get(), &compressedData)); 115e322482f4d82bc704e40b8c89843f2ea5b6ddc04halcanary SkAssertResult(fDataStream->rewind()); 11667ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary if (compressedData.getOffset() < this->dataSize()) { 117f459c85457c6f470af3fe096fef2524d5443401ahalcanary SkAutoTUnref<SkStream> compressed( 118f459c85457c6f470af3fe096fef2524d5443401ahalcanary compressedData.detachAsStream()); 119f459c85457c6f470af3fe096fef2524d5443401ahalcanary this->setData(compressed.get()); 120421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org insertName("Filter", "FlateDecode"); 121421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 122421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fState = kCompressed_State; 123421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } else { 124421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org fState = kNoCompression_State; 125421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 12667ec1f8eecfb48bc0a6ba04c0057f103c1c9696fhalcanary insertInt("Length", this->dataSize()); 127421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } else if (fState == kNoCompression_State && !skip_compression(catalog) && 128421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org SkFlate::HaveFlate()) { 129421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org if (!fSubstitute.get()) { 130d96d17b9c113ac694138224249ff2ce643e961ddvandebo@chromium.org fSubstitute.reset(new SkPDFStream(*this)); 131421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org catalog->setSubstitute(this, fSubstitute.get()); 132421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 133421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org return false; 134421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org } 135421d6443fbd3a913dfa32b6492c4a2969bc6314bvandebo@chromium.org return true; 1368459d4e5e32608ec6da3f2b81731aaeb7b038843vandebo@chromium.org} 137