PDF: why do we have flags no one uses (or can use)?
BUG=skia: Review URL: https://codereview.chromium.org/936403002
This commit is contained in:
parent
ce07afb8fa
commit
cabc08c429
@ -30,14 +30,6 @@ static size_t pixel_count(const SkBitmap& bm) {
|
||||
return SkToSizeT(bm.width()) * SkToSizeT(bm.height());
|
||||
}
|
||||
|
||||
static bool skip_compression(SkPDFDocument::Flags flag) {
|
||||
#ifndef SK_NO_FLATE
|
||||
return SkToBool(flag & SkPDFDocument::kFavorSpeedOverSize_Flags);
|
||||
#else
|
||||
return true;
|
||||
#endif // SK_NO_FLATE
|
||||
}
|
||||
|
||||
// write a single byte to a stream n times.
|
||||
static void fill_stream(SkWStream* out, char value, size_t n) {
|
||||
char buffer[4096];
|
||||
@ -164,14 +156,6 @@ private:
|
||||
void PDFAlphaBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
|
||||
SkAutoLockPixels autoLockPixels(fBitmap);
|
||||
|
||||
if (skip_compression(catalog->getDocumentFlags())) {
|
||||
this->emitDict(stream, catalog, pixel_count(fBitmap),
|
||||
/*deflate=*/false);
|
||||
pdf_stream_begin(stream);
|
||||
pmcolor_alpha_to_a8(fBitmap, stream);
|
||||
pdf_stream_end(stream);
|
||||
return;
|
||||
}
|
||||
#ifndef SK_NO_FLATE
|
||||
// Write to a temporary buffer to get the compressed length.
|
||||
SkDynamicMemoryWStream buffer;
|
||||
@ -184,6 +168,11 @@ void PDFAlphaBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
|
||||
pdf_stream_begin(stream);
|
||||
stream->writeStream(asset.get(), asset->getLength());
|
||||
pdf_stream_end(stream);
|
||||
#else
|
||||
this->emitDict(stream, catalog, pixel_count(fBitmap), /*deflate=*/false);
|
||||
pdf_stream_begin(stream);
|
||||
pmcolor_alpha_to_a8(fBitmap, stream);
|
||||
pdf_stream_end(stream);
|
||||
#endif // SK_NO_FLATE
|
||||
}
|
||||
|
||||
@ -217,14 +206,6 @@ void SkPDFBitmap::addResources(SkTSet<SkPDFObject*>* resourceSet,
|
||||
void SkPDFBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
|
||||
SkAutoLockPixels autoLockPixels(fBitmap);
|
||||
|
||||
if (skip_compression(catalog->getDocumentFlags())) {
|
||||
this->emitDict(stream, catalog, 3 * pixel_count(fBitmap),
|
||||
/*deflate=*/false);
|
||||
pdf_stream_begin(stream);
|
||||
pmcolor_to_rgb24(fBitmap, stream);
|
||||
pdf_stream_end(stream);
|
||||
return;
|
||||
}
|
||||
#ifndef SK_NO_FLATE
|
||||
// Write to a temporary buffer to get the compressed length.
|
||||
SkDynamicMemoryWStream buffer;
|
||||
@ -237,6 +218,12 @@ void SkPDFBitmap::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
|
||||
pdf_stream_begin(stream);
|
||||
stream->writeStream(asset.get(), asset->getLength());
|
||||
pdf_stream_end(stream);
|
||||
#else
|
||||
this->emitDict(stream, catalog, 3 * pixel_count(fBitmap), /*deflate=*/false);
|
||||
pdf_stream_begin(stream);
|
||||
pmcolor_to_rgb24(fBitmap, stream);
|
||||
pdf_stream_end(stream);
|
||||
return;
|
||||
#endif // SK_NO_FLATE
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,10 @@
|
||||
#include "SkStream.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
SkPDFCatalog::SkPDFCatalog(SkPDFDocument::Flags flags)
|
||||
: fFirstPageCount(0),
|
||||
fNextObjNum(1),
|
||||
fNextFirstPageObjNum(0),
|
||||
fDocumentFlags(flags) {
|
||||
}
|
||||
SkPDFCatalog::SkPDFCatalog()
|
||||
: fFirstPageCount(0)
|
||||
, fNextObjNum(1)
|
||||
, fNextFirstPageObjNum(0) {}
|
||||
|
||||
SkPDFCatalog::~SkPDFCatalog() {
|
||||
fSubstituteResourcesRemaining.safeUnrefAll();
|
||||
|
@ -26,7 +26,7 @@ class SkPDFCatalog {
|
||||
public:
|
||||
/** Create a PDF catalog.
|
||||
*/
|
||||
explicit SkPDFCatalog(SkPDFDocument::Flags flags);
|
||||
SkPDFCatalog();
|
||||
~SkPDFCatalog();
|
||||
|
||||
/** Add the passed object to the catalog. Refs obj.
|
||||
@ -48,10 +48,6 @@ public:
|
||||
*/
|
||||
int32_t getObjectNumber(SkPDFObject* obj);
|
||||
|
||||
/** Return the document flags in effect for this catalog/document.
|
||||
*/
|
||||
SkPDFDocument::Flags getDocumentFlags() const { return fDocumentFlags; }
|
||||
|
||||
/** Output the cross reference table for objects in the catalog.
|
||||
* Returns the total number of objects.
|
||||
* @param stream The writable output stream to send the output to.
|
||||
@ -106,8 +102,6 @@ private:
|
||||
// Next object number to assign on the first page.
|
||||
uint32_t fNextFirstPageObjNum;
|
||||
|
||||
SkPDFDocument::Flags fDocumentFlags;
|
||||
|
||||
int findObjectIndex(SkPDFObject* obj);
|
||||
|
||||
int assignObjNum(SkPDFObject* obj);
|
||||
|
@ -47,10 +47,10 @@ static void perform_font_subsetting(SkPDFCatalog* catalog,
|
||||
}
|
||||
}
|
||||
|
||||
SkPDFDocument::SkPDFDocument(Flags flags)
|
||||
SkPDFDocument::SkPDFDocument()
|
||||
: fXRefFileOffset(0),
|
||||
fTrailerDict(NULL) {
|
||||
fCatalog.reset(new SkPDFCatalog(flags));
|
||||
fCatalog.reset(SkNEW(SkPDFCatalog));
|
||||
fDocCatalog = SkNEW_ARGS(SkPDFDict, ("Catalog"));
|
||||
fCatalog->addObject(fDocCatalog, true);
|
||||
fFirstPageResources = NULL;
|
||||
|
@ -29,18 +29,7 @@ template <typename T> class SkTSet;
|
||||
*/
|
||||
class SkPDFDocument {
|
||||
public:
|
||||
enum Flags {
|
||||
kNoCompression_Flags = 0x01, //!< DEPRECATED.
|
||||
kFavorSpeedOverSize_Flags = 0x01, //!< Don't compress the stream, but
|
||||
// if it is already compressed return
|
||||
// the compressed stream.
|
||||
kNoLinks_Flags = 0x02, //!< do not honor link annotations.
|
||||
|
||||
kDraftMode_Flags = 0x01,
|
||||
};
|
||||
/** Create a PDF document.
|
||||
*/
|
||||
explicit SK_API SkPDFDocument(Flags flags = (Flags)0);
|
||||
SK_API SkPDFDocument();
|
||||
SK_API ~SkPDFDocument();
|
||||
|
||||
/** Output the PDF to the passed stream. It is an error to call this (it
|
||||
|
@ -22,11 +22,6 @@
|
||||
|
||||
static const int kNoColorTransform = 0;
|
||||
|
||||
static bool skip_compression(SkPDFCatalog* catalog) {
|
||||
return SkToBool(catalog->getDocumentFlags() &
|
||||
SkPDFDocument::kFavorSpeedOverSize_Flags);
|
||||
}
|
||||
|
||||
static size_t get_uncompressed_size(const SkBitmap& bitmap,
|
||||
const SkIRect& srcRect) {
|
||||
switch (bitmap.colorType()) {
|
||||
@ -603,8 +598,7 @@ SkPDFImage::SkPDFImage(SkPDFImage& pdfImage)
|
||||
bool SkPDFImage::populate(SkPDFCatalog* catalog) {
|
||||
if (getState() == kUnused_State) {
|
||||
// Initializing image data for the first time.
|
||||
if (!skip_compression(catalog) && fEncoder &&
|
||||
get_uncompressed_size(fBitmap, fSrcRect) > 1) {
|
||||
if (fEncoder && get_uncompressed_size(fBitmap, fSrcRect) > 1) {
|
||||
SkBitmap subset;
|
||||
// Extract subset
|
||||
if (!fBitmap.extractSubset(&subset, fSrcRect)) {
|
||||
@ -633,11 +627,9 @@ bool SkPDFImage::populate(SkPDFCatalog* catalog) {
|
||||
return INHERITED::populate(catalog);
|
||||
}
|
||||
#ifndef SK_NO_FLATE
|
||||
else if (getState() == kNoCompression_State && !skip_compression(catalog)) {
|
||||
else if (getState() == kNoCompression_State) {
|
||||
#else // SK_NO_FLATE
|
||||
else if (getState() == kNoCompression_State &&
|
||||
!skip_compression(catalog) &&
|
||||
fEncoder) {
|
||||
else if (getState() == kNoCompression_State && fEncoder) {
|
||||
#endif // SK_NO_FLATE
|
||||
// Compression has not been requested when the stream was first created,
|
||||
// but the new catalog wants it compressed.
|
||||
|
@ -27,12 +27,9 @@ void SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage,
|
||||
if (fContentStream.get() == NULL) {
|
||||
this->insert("Resources", fDevice->getResourceDict());
|
||||
SkSafeUnref(this->insert("MediaBox", fDevice->copyMediaBox()));
|
||||
if (!SkToBool(catalog->getDocumentFlags() &
|
||||
SkPDFDocument::kNoLinks_Flags)) {
|
||||
SkPDFArray* annots = fDevice->getAnnotations();
|
||||
if (annots && annots->size() > 0) {
|
||||
insert("Annots", annots);
|
||||
}
|
||||
SkPDFArray* annots = fDevice->getAnnotations();
|
||||
if (annots && annots->size() > 0) {
|
||||
insert("Annots", annots);
|
||||
}
|
||||
|
||||
SkAutoTUnref<SkData> content(fDevice->copyContentToData());
|
||||
|
@ -14,11 +14,6 @@
|
||||
#include "SkStream.h"
|
||||
#include "SkStreamPriv.h"
|
||||
|
||||
static bool skip_compression(SkPDFCatalog* catalog) {
|
||||
return SkToBool(catalog->getDocumentFlags() &
|
||||
SkPDFDocument::kFavorSpeedOverSize_Flags);
|
||||
}
|
||||
|
||||
SkPDFStream::SkPDFStream(SkStream* stream) : fState(kUnused_State) {
|
||||
this->setData(stream);
|
||||
}
|
||||
@ -94,25 +89,21 @@ bool SkPDFStream::populate(SkPDFCatalog* catalog) {
|
||||
|
||||
if (fState == kUnused_State) {
|
||||
fState = kNoCompression_State;
|
||||
if (!skip_compression(catalog)) {
|
||||
SkDynamicMemoryWStream compressedData;
|
||||
SkDynamicMemoryWStream compressedData;
|
||||
|
||||
SkAssertResult(
|
||||
SkFlate::Deflate(fDataStream.get(), &compressedData));
|
||||
SkAssertResult(fDataStream->rewind());
|
||||
if (compressedData.getOffset() < this->dataSize()) {
|
||||
SkAutoTDelete<SkStream> compressed(
|
||||
compressedData.detachAsStream());
|
||||
this->setData(compressed.get());
|
||||
insertName("Filter", "FlateDecode");
|
||||
}
|
||||
fState = kCompressed_State;
|
||||
} else {
|
||||
fState = kNoCompression_State;
|
||||
SkAssertResult(
|
||||
SkFlate::Deflate(fDataStream.get(), &compressedData));
|
||||
SkAssertResult(fDataStream->rewind());
|
||||
if (compressedData.getOffset() < this->dataSize()) {
|
||||
SkAutoTDelete<SkStream> compressed(
|
||||
compressedData.detachAsStream());
|
||||
this->setData(compressed.get());
|
||||
insertName("Filter", "FlateDecode");
|
||||
}
|
||||
fState = kCompressed_State;
|
||||
insertInt("Length", this->dataSize());
|
||||
}
|
||||
else if (fState == kNoCompression_State && !skip_compression(catalog)) {
|
||||
else if (fState == kNoCompression_State) {
|
||||
if (!fSubstitute.get()) {
|
||||
fSubstitute.reset(new SkPDFStream(*this));
|
||||
catalog->setSubstitute(this, fSubstitute.get());
|
||||
|
@ -39,11 +39,6 @@ DEF_TEST(Annotation_NoDraw, reporter) {
|
||||
REPORTER_ASSERT(reporter, 0 == *bm.getAddr32(0, 0));
|
||||
}
|
||||
|
||||
struct testCase {
|
||||
SkPDFDocument::Flags flags;
|
||||
bool expectAnnotations;
|
||||
};
|
||||
|
||||
DEF_TEST(Annotation_PdfLink, reporter) {
|
||||
SkISize size = SkISize::Make(612, 792);
|
||||
SkMatrix initialTransform;
|
||||
@ -56,20 +51,14 @@ DEF_TEST(Annotation_PdfLink, reporter) {
|
||||
SkAutoDataUnref data(SkData::NewWithCString("http://www.gooogle.com"));
|
||||
SkAnnotateRectWithURL(&canvas, r, data.get());
|
||||
|
||||
testCase tests[] = {{(SkPDFDocument::Flags)0, true},
|
||||
{SkPDFDocument::kNoLinks_Flags, false}};
|
||||
for (size_t testNum = 0; testNum < SK_ARRAY_COUNT(tests); testNum++) {
|
||||
SkPDFDocument doc(tests[testNum].flags);
|
||||
doc.appendPage(&device);
|
||||
SkDynamicMemoryWStream outStream;
|
||||
doc.emitPDF(&outStream);
|
||||
SkAutoDataUnref out(outStream.copyToData());
|
||||
const char* rawOutput = (const char*)out->data();
|
||||
SkPDFDocument doc;
|
||||
doc.appendPage(&device);
|
||||
SkDynamicMemoryWStream outStream;
|
||||
doc.emitPDF(&outStream);
|
||||
SkAutoDataUnref out(outStream.copyToData());
|
||||
const char* rawOutput = (const char*)out->data();
|
||||
|
||||
REPORTER_ASSERT(reporter,
|
||||
ContainsString(rawOutput, out->size(), "/Annots ")
|
||||
== tests[testNum].expectAnnotations);
|
||||
}
|
||||
REPORTER_ASSERT(reporter, ContainsString(rawOutput, out->size(), "/Annots "));
|
||||
}
|
||||
|
||||
DEF_TEST(Annotation_NamedDestination, reporter) {
|
||||
|
@ -75,12 +75,8 @@ static size_t get_output_size(SkPDFObject* object,
|
||||
|
||||
static void CheckObjectOutput(skiatest::Reporter* reporter, SkPDFObject* obj,
|
||||
const char* expectedData, size_t expectedSize,
|
||||
bool indirect, bool compression) {
|
||||
SkPDFDocument::Flags docFlags = (SkPDFDocument::Flags) 0;
|
||||
if (!compression) {
|
||||
docFlags = SkTBitOr(docFlags, SkPDFDocument::kFavorSpeedOverSize_Flags);
|
||||
}
|
||||
SkPDFCatalog catalog(docFlags);
|
||||
bool indirect) {
|
||||
SkPDFCatalog catalog;
|
||||
size_t directSize = get_output_size(obj, &catalog, false);
|
||||
REPORTER_ASSERT(reporter, directSize == expectedSize);
|
||||
|
||||
@ -118,7 +114,7 @@ static void SimpleCheckObjectOutput(skiatest::Reporter* reporter,
|
||||
SkPDFObject* obj,
|
||||
const char* expectedResult) {
|
||||
CheckObjectOutput(reporter, obj, expectedResult,
|
||||
strlen(expectedResult), true, false);
|
||||
strlen(expectedResult), true);
|
||||
}
|
||||
|
||||
static void TestPDFStream(skiatest::Reporter* reporter) {
|
||||
@ -148,32 +144,21 @@ static void TestPDFStream(skiatest::Reporter* reporter) {
|
||||
SkFlate::Deflate(streamData2.get(), &compressedByteStream);
|
||||
SkAutoDataUnref compressedData(compressedByteStream.copyToData());
|
||||
|
||||
// Check first without compression.
|
||||
SkDynamicMemoryWStream expectedResult1;
|
||||
expectedResult1.writeText("<</Length 167\n>> stream\n");
|
||||
expectedResult1.writeText(streamBytes2);
|
||||
expectedResult1.writeText("\nendstream");
|
||||
SkAutoDataUnref expectedResultData1(expectedResult1.copyToData());
|
||||
CheckObjectOutput(reporter, stream.get(),
|
||||
(const char*) expectedResultData1->data(),
|
||||
expectedResultData1->size(), true, false);
|
||||
|
||||
// Then again with compression.
|
||||
SkDynamicMemoryWStream expectedResult2;
|
||||
expectedResult2.writeText("<</Filter /FlateDecode\n/Length 116\n"
|
||||
SkDynamicMemoryWStream expected;
|
||||
expected.writeText("<</Filter /FlateDecode\n/Length 116\n"
|
||||
">> stream\n");
|
||||
expectedResult2.write(compressedData->data(), compressedData->size());
|
||||
expectedResult2.writeText("\nendstream");
|
||||
SkAutoDataUnref expectedResultData2(expectedResult2.copyToData());
|
||||
expected.write(compressedData->data(), compressedData->size());
|
||||
expected.writeText("\nendstream");
|
||||
SkAutoDataUnref expectedResultData2(expected.copyToData());
|
||||
CheckObjectOutput(reporter, stream.get(),
|
||||
(const char*) expectedResultData2->data(),
|
||||
expectedResultData2->size(), true, true);
|
||||
expectedResultData2->size(), true);
|
||||
}
|
||||
#endif // SK_NO_FLATE
|
||||
}
|
||||
|
||||
static void TestCatalog(skiatest::Reporter* reporter) {
|
||||
SkPDFCatalog catalog((SkPDFDocument::Flags)0);
|
||||
SkPDFCatalog catalog;
|
||||
SkAutoTUnref<SkPDFInt> int1(new SkPDFInt(1));
|
||||
SkAutoTUnref<SkPDFInt> int2(new SkPDFInt(2));
|
||||
SkAutoTUnref<SkPDFInt> int3(new SkPDFInt(3));
|
||||
@ -195,7 +180,7 @@ static void TestObjectRef(skiatest::Reporter* reporter) {
|
||||
SkAutoTUnref<SkPDFInt> int2(new SkPDFInt(2));
|
||||
SkAutoTUnref<SkPDFObjRef> int2ref(new SkPDFObjRef(int2.get()));
|
||||
|
||||
SkPDFCatalog catalog((SkPDFDocument::Flags)0);
|
||||
SkPDFCatalog catalog;
|
||||
catalog.addObject(int1.get(), false);
|
||||
catalog.addObject(int2.get(), false);
|
||||
REPORTER_ASSERT(reporter, catalog.getObjectNumber(int1.get()) == 1);
|
||||
@ -216,7 +201,7 @@ static void TestSubstitute(skiatest::Reporter* reporter) {
|
||||
proxy->insert("Value", new SkPDFInt(33))->unref();
|
||||
stub->insert("Value", new SkPDFInt(44))->unref();
|
||||
|
||||
SkPDFCatalog catalog((SkPDFDocument::Flags)0);
|
||||
SkPDFCatalog catalog;
|
||||
catalog.addObject(proxy.get(), false);
|
||||
catalog.setSubstitute(proxy.get(), stub.get());
|
||||
|
||||
@ -278,12 +263,12 @@ DEF_TEST(PDFPrimitives, reporter) {
|
||||
SkAutoTUnref<SkPDFName> name(new SkPDFName("Test name\twith#tab"));
|
||||
const char expectedResult[] = "/Test#20name#09with#23tab";
|
||||
CheckObjectOutput(reporter, name.get(), expectedResult,
|
||||
strlen(expectedResult), false, false);
|
||||
strlen(expectedResult), false);
|
||||
|
||||
SkAutoTUnref<SkPDFName> escapedName(new SkPDFName("A#/%()<>[]{}B"));
|
||||
const char escapedNameExpected[] = "/A#23#2F#25#28#29#3C#3E#5B#5D#7B#7DB";
|
||||
CheckObjectOutput(reporter, escapedName.get(), escapedNameExpected,
|
||||
strlen(escapedNameExpected), false, false);
|
||||
strlen(escapedNameExpected), false);
|
||||
|
||||
// Test that we correctly handle characters with the high-bit set.
|
||||
const unsigned char highBitCString[] = {0xDE, 0xAD, 'b', 'e', 0xEF, 0};
|
||||
@ -291,7 +276,7 @@ DEF_TEST(PDFPrimitives, reporter) {
|
||||
new SkPDFName((const char*)highBitCString));
|
||||
const char highBitExpectedResult[] = "/#DE#ADbe#EF";
|
||||
CheckObjectOutput(reporter, highBitName.get(), highBitExpectedResult,
|
||||
strlen(highBitExpectedResult), false, false);
|
||||
strlen(highBitExpectedResult), false);
|
||||
|
||||
SkAutoTUnref<SkPDFArray> array(new SkPDFArray);
|
||||
SimpleCheckObjectOutput(reporter, array.get(), "[]");
|
||||
|
Loading…
Reference in New Issue
Block a user