SkPDF: PDFStream has-a not is-a PDFDict
Motivation: SkPDFStream and SkPDFSharedStream now work the same. Also: - move SkPDFStream into SkPDFTypes (it's a fundamental PDF type). - minor refactor of SkPDFSharedStream - SkPDFSharedStream takes unique_ptr to represent ownership BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2190883003 Review-Url: https://codereview.chromium.org/2190883003
This commit is contained in:
parent
d05a875273
commit
fa25106f02
@ -137,8 +137,9 @@ protected:
|
||||
SkASSERT(fAsset);
|
||||
if (!fAsset) { return; }
|
||||
while (loops-- > 0) {
|
||||
sk_sp<SkPDFObject> object(
|
||||
new SkPDFSharedStream(fAsset->duplicate()));
|
||||
sk_sp<SkPDFObject> object =
|
||||
sk_make_sp<SkPDFSharedStream>(
|
||||
std::unique_ptr<SkStreamAsset>(fAsset->duplicate()));
|
||||
test_pdf_object_serialization(object);
|
||||
}
|
||||
}
|
||||
|
@ -39,8 +39,6 @@
|
||||
'<(skia_src_path)/pdf/SkPDFResourceDict.h',
|
||||
'<(skia_src_path)/pdf/SkPDFShader.cpp',
|
||||
'<(skia_src_path)/pdf/SkPDFShader.h',
|
||||
'<(skia_src_path)/pdf/SkPDFStream.cpp',
|
||||
'<(skia_src_path)/pdf/SkPDFStream.h',
|
||||
'<(skia_src_path)/pdf/SkPDFTypes.cpp',
|
||||
'<(skia_src_path)/pdf/SkPDFTypes.h',
|
||||
'<(skia_src_path)/pdf/SkPDFUtils.cpp',
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "SkPDFGraphicState.h"
|
||||
#include "SkPDFResourceDict.h"
|
||||
#include "SkPDFShader.h"
|
||||
#include "SkPDFStream.h"
|
||||
#include "SkPDFTypes.h"
|
||||
#include "SkPDFUtils.h"
|
||||
#include "SkRasterClip.h"
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "SkPDFCanvas.h"
|
||||
#include "SkPDFDevice.h"
|
||||
#include "SkPDFDocument.h"
|
||||
#include "SkPDFStream.h"
|
||||
#include "SkPDFUtils.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
@ -321,7 +320,7 @@ static sk_sp<SkData> SkSrgbIcm() {
|
||||
|
||||
static sk_sp<SkPDFStream> make_srgb_color_profile() {
|
||||
sk_sp<SkPDFStream> stream = sk_make_sp<SkPDFStream>(SkSrgbIcm());
|
||||
stream->insertInt("N", 3);
|
||||
stream->dict()->insertInt("N", 3);
|
||||
sk_sp<SkPDFArray> array = sk_make_sp<SkPDFArray>();
|
||||
array->appendScalar(0.0f);
|
||||
array->appendScalar(1.0f);
|
||||
@ -329,7 +328,7 @@ static sk_sp<SkPDFStream> make_srgb_color_profile() {
|
||||
array->appendScalar(1.0f);
|
||||
array->appendScalar(0.0f);
|
||||
array->appendScalar(1.0f);
|
||||
stream->insertObject("Range", std::move(array));
|
||||
stream->dict()->insertObject("Range", std::move(array));
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "SkPDFDevice.h"
|
||||
#include "SkPDFFont.h"
|
||||
#include "SkPDFFontImpl.h"
|
||||
#include "SkPDFStream.h"
|
||||
#include "SkPDFUtils.h"
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkScalar.h"
|
||||
@ -1006,7 +1005,7 @@ static sk_sp<SkPDFObject> get_subset_font_stream(
|
||||
subsetFont, subsetFontSize,
|
||||
[](const void* p, void*) { delete[] (unsigned char*)p; },
|
||||
nullptr));
|
||||
subsetStream->insertInt("Length1", subsetFontSize);
|
||||
subsetStream->dict()->insertInt("Length1", subsetFontSize);
|
||||
return subsetStream;
|
||||
}
|
||||
#endif // SK_SFNTLY_SUBSETTER
|
||||
@ -1048,7 +1047,7 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth,
|
||||
fontAsset.reset(this->typeface()->openStream(&ttcIndex));
|
||||
}
|
||||
#endif // SK_SFNTLY_SUBSETTER
|
||||
auto fontStream = sk_make_sp<SkPDFSharedStream>(fontAsset.release());
|
||||
auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset));
|
||||
fontStream->dict()->insertInt("Length1", fontSize);
|
||||
descriptor->insertObjRef("FontFile2", std::move(fontStream));
|
||||
break;
|
||||
@ -1062,8 +1061,7 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth,
|
||||
if (!fontData || 0 == fontData->getLength()) {
|
||||
return false;
|
||||
}
|
||||
sk_sp<SkPDFSharedStream> fontStream(
|
||||
new SkPDFSharedStream(fontData.release()));
|
||||
auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData));
|
||||
if (getType() == SkAdvancedTypefaceMetrics::kCFF_Font) {
|
||||
fontStream->dict()->insertName("Subtype", "Type1C");
|
||||
} else {
|
||||
@ -1200,9 +1198,9 @@ bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) {
|
||||
}
|
||||
SkASSERT(this->canEmbed());
|
||||
auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData));
|
||||
fontStream->insertInt("Length1", header);
|
||||
fontStream->insertInt("Length2", data);
|
||||
fontStream->insertInt("Length3", trailer);
|
||||
fontStream->dict()->insertInt("Length1", header);
|
||||
fontStream->dict()->insertInt("Length2", data);
|
||||
fontStream->dict()->insertInt("Length3", trailer);
|
||||
descriptor->insertObjRef("FontFile", std::move(fontStream));
|
||||
|
||||
this->insertObjRef("FontDescriptor", std::move(descriptor));
|
||||
|
@ -15,14 +15,14 @@ sk_sp<SkPDFObject> SkPDFMakeFormXObject(std::unique_ptr<SkStreamAsset> content,
|
||||
const SkMatrix& inverseTransform,
|
||||
const char* colorSpace) {
|
||||
auto form = sk_make_sp<SkPDFStream>(std::move(content));
|
||||
form->insertName("Type", "XObject");
|
||||
form->insertName("Subtype", "Form");
|
||||
form->dict()->insertName("Type", "XObject");
|
||||
form->dict()->insertName("Subtype", "Form");
|
||||
if (!inverseTransform.isIdentity()) {
|
||||
form->insertObject("Matrix",
|
||||
SkPDFUtils::MatrixToArray(inverseTransform));
|
||||
sk_sp<SkPDFObject> mat(SkPDFUtils::MatrixToArray(inverseTransform));
|
||||
form->dict()->insertObject("Matrix", std::move(mat));
|
||||
}
|
||||
form->insertObject("Resources", std::move(resourceDict));
|
||||
form->insertObject("BBox", std::move(mediaBox));
|
||||
form->dict()->insertObject("Resources", std::move(resourceDict));
|
||||
form->dict()->insertObject("BBox", std::move(mediaBox));
|
||||
|
||||
// Right now FormXObject is only used for saveLayer, which implies
|
||||
// isolated blending. Do this conditionally if that changes.
|
||||
@ -34,6 +34,6 @@ sk_sp<SkPDFObject> SkPDFMakeFormXObject(std::unique_ptr<SkStreamAsset> content,
|
||||
group->insertName("CS", colorSpace);
|
||||
}
|
||||
group->insertBool("I", true); // Isolated.
|
||||
form->insertObject("Group", std::move(group));
|
||||
form->dict()->insertObject("Group", std::move(group));
|
||||
return form;
|
||||
}
|
||||
|
@ -9,8 +9,8 @@
|
||||
#ifndef SkPDFFormXObject_DEFINED
|
||||
#define SkPDFFormXObject_DEFINED
|
||||
|
||||
#include "SkPDFStream.h"
|
||||
#include "SkPDFDevice.h"
|
||||
#include "SkPDFTypes.h"
|
||||
|
||||
/** A form XObject is a self contained description of a graphics
|
||||
object. A form XObject is a page object with slightly different
|
||||
|
@ -137,9 +137,9 @@ sk_sp<SkPDFStream> SkPDFGraphicState::MakeInvertFunction() {
|
||||
// Do not copy the trailing '\0' into the SkData.
|
||||
auto invertFunction = sk_make_sp<SkPDFStream>(
|
||||
SkData::MakeWithoutCopy(psInvert, strlen(psInvert)));
|
||||
invertFunction->insertInt("FunctionType", 4);
|
||||
invertFunction->insertObject("Domain", domainAndRange);
|
||||
invertFunction->insertObject("Range", std::move(domainAndRange));
|
||||
invertFunction->dict()->insertInt("FunctionType", 4);
|
||||
invertFunction->dict()->insertObject("Domain", domainAndRange);
|
||||
invertFunction->dict()->insertObject("Range", std::move(domainAndRange));
|
||||
return invertFunction;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#ifndef SkPDFGraphicState_DEFINED
|
||||
#define SkPDFGraphicState_DEFINED
|
||||
|
||||
#include "SkPDFStream.h"
|
||||
#include "SkPDFTypes.h"
|
||||
#include "SkChecksum.h"
|
||||
|
||||
class SkPaint;
|
||||
|
@ -743,8 +743,9 @@ SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create(
|
||||
create_pattern_fill_content(0, bbox));
|
||||
alphaFunctionShader->setData(std::move(colorStream));
|
||||
|
||||
populate_tiling_pattern_dict(alphaFunctionShader, bbox, resourceDict.get(),
|
||||
SkMatrix::I());
|
||||
populate_tiling_pattern_dict(
|
||||
alphaFunctionShader->dict(), bbox, resourceDict.get(),
|
||||
SkMatrix::I());
|
||||
doc->canon()->addAlphaShader(alphaFunctionShader);
|
||||
return alphaFunctionShader;
|
||||
}
|
||||
@ -804,9 +805,9 @@ static sk_sp<SkPDFStream> make_ps_function(
|
||||
SkPDFArray* domain,
|
||||
sk_sp<SkPDFObject> range) {
|
||||
auto result = sk_make_sp<SkPDFStream>(std::move(psCode));
|
||||
result->insertInt("FunctionType", 4);
|
||||
result->insertObject("Domain", sk_ref_sp(domain));
|
||||
result->insertObject("Range", std::move(range));
|
||||
result->dict()->insertInt("FunctionType", 4);
|
||||
result->dict()->insertObject("Domain", sk_ref_sp(domain));
|
||||
result->dict()->insertObject("Range", std::move(range));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1213,7 +1214,7 @@ SkPDFImageShader* SkPDFImageShader::Create(
|
||||
imageShader->setData(patternDevice->content());
|
||||
|
||||
auto resourceDict = patternDevice->makeResourceDict();
|
||||
populate_tiling_pattern_dict(imageShader, patternBBox,
|
||||
populate_tiling_pattern_dict(imageShader->dict(), patternBBox,
|
||||
resourceDict.get(), finalMatrix);
|
||||
|
||||
imageShader->fShaderState->fImage.unlockPixels();
|
||||
|
@ -9,7 +9,6 @@
|
||||
#ifndef SkPDFShader_DEFINED
|
||||
#define SkPDFShader_DEFINED
|
||||
|
||||
#include "SkPDFStream.h"
|
||||
#include "SkPDFTypes.h"
|
||||
|
||||
class SkPDFCanon;
|
||||
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#include "SkData.h"
|
||||
#include "SkDeflate.h"
|
||||
#include "SkPDFStream.h"
|
||||
#include "SkStreamPriv.h"
|
||||
|
||||
SkPDFStream::~SkPDFStream() {}
|
||||
|
||||
void SkPDFStream::drop() {
|
||||
fCompressedData.reset(nullptr);
|
||||
this->SkPDFDict::drop();
|
||||
}
|
||||
|
||||
void SkPDFStream::emitObject(SkWStream* stream,
|
||||
const SkPDFObjNumMap& objNumMap,
|
||||
const SkPDFSubstituteMap& substitutes) const {
|
||||
SkASSERT(fCompressedData);
|
||||
this->INHERITED::emitObject(stream, objNumMap, substitutes);
|
||||
// duplicate (a cheap operation) preserves const on fCompressedData.
|
||||
std::unique_ptr<SkStreamAsset> dup(fCompressedData->duplicate());
|
||||
SkASSERT(dup);
|
||||
SkASSERT(dup->hasLength());
|
||||
stream->writeText(" stream\n");
|
||||
stream->writeStream(dup.get(), dup->getLength());
|
||||
stream->writeText("\nendstream");
|
||||
}
|
||||
|
||||
void SkPDFStream::setData(std::unique_ptr<SkStreamAsset> stream) {
|
||||
SkASSERT(!fCompressedData); // Only call this function once.
|
||||
SkASSERT(stream);
|
||||
// Code assumes that the stream starts at the beginning.
|
||||
|
||||
#ifdef SK_PDF_LESS_COMPRESSION
|
||||
fCompressedData = std::move(stream);
|
||||
SkASSERT(fCompressedData && fCompressedData->hasLength());
|
||||
this->insertInt("Length", fCompressedData->getLength());
|
||||
#else
|
||||
|
||||
SkASSERT(stream->hasLength());
|
||||
SkDynamicMemoryWStream compressedData;
|
||||
SkDeflateWStream deflateWStream(&compressedData);
|
||||
SkStreamCopy(&deflateWStream, stream.get());
|
||||
deflateWStream.finalize();
|
||||
size_t compressedLength = compressedData.bytesWritten();
|
||||
size_t originalLength = stream->getLength();
|
||||
|
||||
if (originalLength <= compressedLength + strlen("/Filter_/FlateDecode_")) {
|
||||
SkAssertResult(stream->rewind());
|
||||
fCompressedData = std::move(stream);
|
||||
this->insertInt("Length", originalLength);
|
||||
return;
|
||||
}
|
||||
fCompressedData.reset(compressedData.detachAsStream());
|
||||
this->insertName("Filter", "FlateDecode");
|
||||
this->insertInt("Length", compressedLength);
|
||||
#endif
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SkPDFStream_DEFINED
|
||||
#define SkPDFStream_DEFINED
|
||||
|
||||
#include "SkPDFTypes.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
/** \class SkPDFStream
|
||||
|
||||
A stream object in a PDF. Note, all streams must be indirect objects (via
|
||||
SkObjRef).
|
||||
*/
|
||||
class SkPDFStream : public SkPDFDict {
|
||||
|
||||
public:
|
||||
/** Create a PDF stream. A Length entry is automatically added to the
|
||||
* stream dictionary.
|
||||
* @param data The data part of the stream. */
|
||||
explicit SkPDFStream(sk_sp<SkData> data) {
|
||||
this->setData(std::unique_ptr<SkStreamAsset>(
|
||||
new SkMemoryStream(std::move(data))));
|
||||
}
|
||||
|
||||
/** Create a PDF stream. A Length entry is automatically added to the
|
||||
* stream dictionary.
|
||||
* @param stream The data part of the stream.
|
||||
*/
|
||||
explicit SkPDFStream(std::unique_ptr<SkStreamAsset> stream) {
|
||||
this->setData(std::move(stream));
|
||||
}
|
||||
|
||||
virtual ~SkPDFStream();
|
||||
|
||||
// The SkPDFObject interface.
|
||||
void emitObject(SkWStream* stream,
|
||||
const SkPDFObjNumMap& objNumMap,
|
||||
const SkPDFSubstituteMap& substitutes) const override;
|
||||
void drop() override;
|
||||
|
||||
protected:
|
||||
/* Create a PDF stream with no data. The setData method must be called to
|
||||
* set the data.
|
||||
*/
|
||||
SkPDFStream() {}
|
||||
|
||||
/** Only call this function once. */
|
||||
void setData(std::unique_ptr<SkStreamAsset> stream);
|
||||
|
||||
private:
|
||||
std::unique_ptr<SkStreamAsset> fCompressedData;
|
||||
|
||||
typedef SkPDFDict INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
@ -5,6 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkData.h"
|
||||
#include "SkDeflate.h"
|
||||
#include "SkPDFTypes.h"
|
||||
#include "SkPDFUtils.h"
|
||||
@ -456,18 +457,16 @@ void SkPDFDict::insertString(const char key[], const SkString& value) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkPDFSharedStream::SkPDFSharedStream(SkStreamAsset* data)
|
||||
: fAsset(data), fDict(new SkPDFDict) {
|
||||
SkDEBUGCODE(fDumped = false;)
|
||||
SkASSERT(data);
|
||||
SkPDFSharedStream::SkPDFSharedStream(std::unique_ptr<SkStreamAsset> data)
|
||||
: fAsset(std::move(data)) {
|
||||
SkASSERT(fAsset);
|
||||
}
|
||||
|
||||
SkPDFSharedStream::~SkPDFSharedStream() { this->drop(); }
|
||||
|
||||
void SkPDFSharedStream::drop() {
|
||||
fAsset.reset();
|
||||
fDict.reset(nullptr);
|
||||
SkDEBUGCODE(fDumped = true;)
|
||||
fAsset = nullptr;;
|
||||
fDict.drop();
|
||||
}
|
||||
|
||||
#ifdef SK_PDF_LESS_COMPRESSION
|
||||
@ -475,12 +474,12 @@ void SkPDFSharedStream::emitObject(
|
||||
SkWStream* stream,
|
||||
const SkPDFObjNumMap& objNumMap,
|
||||
const SkPDFSubstituteMap& substitutes) const {
|
||||
SkASSERT(!fDumped);
|
||||
SkASSERT(fAsset);
|
||||
std::unique_ptr<SkStreamAsset> dup(fAsset->duplicate());
|
||||
SkASSERT(dup && dup->hasLength());
|
||||
size_t length = dup->getLength();
|
||||
stream->writeText("<<");
|
||||
fDict->emitAll(stream, objNumMap, substitutes);
|
||||
fDict.emitAll(stream, objNumMap, substitutes);
|
||||
stream->writeText("\n");
|
||||
SkPDFUnion::Name("Length").emitObject(
|
||||
stream, objNumMap, substitutes);
|
||||
@ -496,7 +495,7 @@ void SkPDFSharedStream::emitObject(
|
||||
SkWStream* stream,
|
||||
const SkPDFObjNumMap& objNumMap,
|
||||
const SkPDFSubstituteMap& substitutes) const {
|
||||
SkASSERT(!fDumped);
|
||||
SkASSERT(fAsset);
|
||||
SkDynamicMemoryWStream buffer;
|
||||
SkDeflateWStream deflateWStream(&buffer);
|
||||
// Since emitObject is const, this function doesn't change the dictionary.
|
||||
@ -506,7 +505,7 @@ void SkPDFSharedStream::emitObject(
|
||||
deflateWStream.finalize();
|
||||
size_t length = buffer.bytesWritten();
|
||||
stream->writeText("<<");
|
||||
fDict->emitAll(stream, objNumMap, substitutes);
|
||||
fDict.emitAll(stream, objNumMap, substitutes);
|
||||
stream->writeText("\n");
|
||||
SkPDFUnion::Name("Length").emitObject(stream, objNumMap, substitutes);
|
||||
stream->writeText(" ");
|
||||
@ -524,8 +523,80 @@ void SkPDFSharedStream::emitObject(
|
||||
|
||||
void SkPDFSharedStream::addResources(
|
||||
SkPDFObjNumMap* catalog, const SkPDFSubstituteMap& substitutes) const {
|
||||
SkASSERT(!fDumped);
|
||||
fDict->addResources(catalog, substitutes);
|
||||
SkASSERT(fAsset);
|
||||
fDict.addResources(catalog, substitutes);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkPDFStream:: SkPDFStream(sk_sp<SkData> data) {
|
||||
this->setData(std::unique_ptr<SkStreamAsset>(
|
||||
new SkMemoryStream(std::move(data))));
|
||||
}
|
||||
|
||||
SkPDFStream::SkPDFStream(std::unique_ptr<SkStreamAsset> stream) {
|
||||
this->setData(std::move(stream));
|
||||
}
|
||||
|
||||
SkPDFStream::SkPDFStream() {}
|
||||
|
||||
SkPDFStream::~SkPDFStream() {}
|
||||
|
||||
void SkPDFStream::addResources(
|
||||
SkPDFObjNumMap* catalog, const SkPDFSubstituteMap& substitutes) const {
|
||||
SkASSERT(fCompressedData);
|
||||
fDict.addResources(catalog, substitutes);
|
||||
}
|
||||
|
||||
void SkPDFStream::drop() {
|
||||
fCompressedData.reset(nullptr);
|
||||
fDict.drop();
|
||||
}
|
||||
|
||||
void SkPDFStream::emitObject(SkWStream* stream,
|
||||
const SkPDFObjNumMap& objNumMap,
|
||||
const SkPDFSubstituteMap& substitutes) const {
|
||||
SkASSERT(fCompressedData);
|
||||
fDict.emitObject(stream, objNumMap, substitutes);
|
||||
// duplicate (a cheap operation) preserves const on fCompressedData.
|
||||
std::unique_ptr<SkStreamAsset> dup(fCompressedData->duplicate());
|
||||
SkASSERT(dup);
|
||||
SkASSERT(dup->hasLength());
|
||||
stream->writeText(" stream\n");
|
||||
stream->writeStream(dup.get(), dup->getLength());
|
||||
stream->writeText("\nendstream");
|
||||
}
|
||||
|
||||
void SkPDFStream::setData(std::unique_ptr<SkStreamAsset> stream) {
|
||||
SkASSERT(!fCompressedData); // Only call this function once.
|
||||
SkASSERT(stream);
|
||||
// Code assumes that the stream starts at the beginning.
|
||||
|
||||
#ifdef SK_PDF_LESS_COMPRESSION
|
||||
fCompressedData = std::move(stream);
|
||||
SkASSERT(fCompressedData && fCompressedData->hasLength());
|
||||
fDict.insertInt("Length", fCompressedData->getLength());
|
||||
#else
|
||||
|
||||
SkASSERT(stream->hasLength());
|
||||
SkDynamicMemoryWStream compressedData;
|
||||
SkDeflateWStream deflateWStream(&compressedData);
|
||||
SkStreamCopy(&deflateWStream, stream.get());
|
||||
deflateWStream.finalize();
|
||||
size_t compressedLength = compressedData.bytesWritten();
|
||||
size_t originalLength = stream->getLength();
|
||||
|
||||
if (originalLength <= compressedLength + strlen("/Filter_/FlateDecode_")) {
|
||||
SkAssertResult(stream->rewind());
|
||||
fCompressedData = std::move(stream);
|
||||
fDict.insertInt("Length", originalLength);
|
||||
return;
|
||||
}
|
||||
fCompressedData.reset(compressedData.detachAsStream());
|
||||
fDict.insertName("Filter", "FlateDecode");
|
||||
fDict.insertInt("Length", compressedLength);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "SkTHash.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
class SkData;
|
||||
class SkPDFObjNumMap;
|
||||
class SkPDFObject;
|
||||
class SkPDFSubstituteMap;
|
||||
@ -307,10 +308,9 @@ private:
|
||||
*/
|
||||
class SkPDFSharedStream final : public SkPDFObject {
|
||||
public:
|
||||
// Takes ownership of asset.
|
||||
SkPDFSharedStream(SkStreamAsset* data);
|
||||
SkPDFSharedStream(std::unique_ptr<SkStreamAsset> data);
|
||||
~SkPDFSharedStream();
|
||||
SkPDFDict* dict() { return fDict.get(); }
|
||||
SkPDFDict* dict() { return &fDict; }
|
||||
void emitObject(SkWStream*,
|
||||
const SkPDFObjNumMap&,
|
||||
const SkPDFSubstituteMap&) const override;
|
||||
@ -320,11 +320,52 @@ public:
|
||||
|
||||
private:
|
||||
std::unique_ptr<SkStreamAsset> fAsset;
|
||||
sk_sp<SkPDFDict> fDict;
|
||||
SkDEBUGCODE(bool fDumped;)
|
||||
SkPDFDict fDict;
|
||||
typedef SkPDFObject INHERITED;
|
||||
};
|
||||
|
||||
/** \class SkPDFStream
|
||||
|
||||
This class takes an asset and assumes that it is the only owner of
|
||||
the asset's data. It immediately compresses the asset to save
|
||||
memory.
|
||||
*/
|
||||
|
||||
class SkPDFStream : public SkPDFObject {
|
||||
|
||||
public:
|
||||
/** Create a PDF stream. A Length entry is automatically added to the
|
||||
* stream dictionary.
|
||||
* @param data The data part of the stream.
|
||||
* @param stream The data part of the stream. */
|
||||
explicit SkPDFStream(sk_sp<SkData> data);
|
||||
explicit SkPDFStream(std::unique_ptr<SkStreamAsset> stream);
|
||||
virtual ~SkPDFStream();
|
||||
|
||||
SkPDFDict* dict() { return &fDict; }
|
||||
|
||||
// The SkPDFObject interface.
|
||||
void emitObject(SkWStream* stream,
|
||||
const SkPDFObjNumMap& objNumMap,
|
||||
const SkPDFSubstituteMap& substitutes) const override;
|
||||
void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const final;
|
||||
void drop() override;
|
||||
|
||||
protected:
|
||||
/* Create a PDF stream with no data. The setData method must be called to
|
||||
* set the data. */
|
||||
SkPDFStream();
|
||||
|
||||
/** Only call this function once. */
|
||||
void setData(std::unique_ptr<SkStreamAsset> stream);
|
||||
|
||||
private:
|
||||
std::unique_ptr<SkStreamAsset> fCompressedData;
|
||||
SkPDFDict fDict;
|
||||
|
||||
typedef SkPDFDict INHERITED;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** \class SkPDFObjNumMap
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "SkPDFCanon.h"
|
||||
#include "SkPDFDevice.h"
|
||||
#include "SkPDFFont.h"
|
||||
#include "SkPDFStream.h"
|
||||
#include "SkPDFTypes.h"
|
||||
#include "SkPDFUtils.h"
|
||||
#include "SkReadBuffer.h"
|
||||
@ -89,7 +88,7 @@ static void TestPDFStream(skiatest::Reporter* reporter) {
|
||||
assert_emit_eq(reporter,
|
||||
*stream,
|
||||
"<</Length 12>> stream\nTest\nFoo\tBar\nendstream");
|
||||
stream->insertInt("Attribute", 42);
|
||||
stream->dict()->insertInt("Attribute", 42);
|
||||
assert_emit_eq(reporter,
|
||||
*stream,
|
||||
"<</Length 12\n/Attribute 42>> stream\n"
|
||||
|
Loading…
Reference in New Issue
Block a user