diff options
author | halcanary <halcanary@google.com> | 2015-12-10 08:59:43 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-10 08:59:43 -0800 |
commit | 712fdf7603c62820b21174da9b0a2071c174936b (patch) | |
tree | 52f88b6e297f2bce7b940adb9cfe052178076758 | |
parent | a06e6ab3fafb8c8712bc296f72c3f8b88856f1fe (diff) |
SkDocument::setDCTEncoder() for old versions of webkit
Review URL: https://codereview.chromium.org/1505763003
-rw-r--r-- | include/core/SkDocument.h | 19 | ||||
-rw-r--r-- | src/doc/SkDocument_PDF.cpp | 19 | ||||
-rw-r--r-- | src/pdf/SkPDFBitmap.cpp | 18 | ||||
-rw-r--r-- | src/pdf/SkPDFBitmap.h | 2 | ||||
-rw-r--r-- | src/pdf/SkPDFCanon.h | 3 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 3 | ||||
-rw-r--r-- | tests/PDFDocumentTest.cpp | 44 |
7 files changed, 101 insertions, 7 deletions
diff --git a/include/core/SkDocument.h b/include/core/SkDocument.h index 316d15a253..6ee96b9ce3 100644 --- a/include/core/SkDocument.h +++ b/include/core/SkDocument.h @@ -16,6 +16,7 @@ #include "SkTime.h" class SkCanvas; +class SkPixelSerializer; class SkWStream; /** SK_ScalarDefaultDPI is 72 DPI. @@ -58,6 +59,24 @@ public: SkScalar dpi = SK_ScalarDefaultRasterDPI); /** + * @param jpegEncoder For PDF documents, if a jpegEncoder is set, + * use it to encode SkImages and SkBitmaps as [JFIF]JPEGs. + * This feature is deprecated and is only supplied for + * backwards compatability. + * + * The prefered method to create PDFs with JPEG images is + * to use SkImage::NewFromEncoded() and not jpegEncoder. + * Chromium uses NewFromEncoded. + * + * If the encoder is unset, or if jpegEncoder->onEncode() + * returns NULL, fall back on encoding images losslessly + * with Deflate. + */ + static SkDocument* CreatePDF(SkWStream*, + SkScalar dpi, + SkPixelSerializer* jpegEncoder); + + /** * Create a PDF-backed document, writing the results into a file. */ static SkDocument* CreatePDF(const char outputFilePath[], diff --git a/src/doc/SkDocument_PDF.cpp b/src/doc/SkDocument_PDF.cpp index ff7a038b6b..fb560ea1e3 100644 --- a/src/doc/SkDocument_PDF.cpp +++ b/src/doc/SkDocument_PDF.cpp @@ -322,9 +322,12 @@ class SkDocument_PDF : public SkDocument { public: SkDocument_PDF(SkWStream* stream, void (*doneProc)(SkWStream*, bool), - SkScalar rasterDpi) + SkScalar rasterDpi, + SkPixelSerializer* jpegEncoder) : SkDocument(stream, doneProc) - , fRasterDpi(rasterDpi) {} + , fRasterDpi(rasterDpi) { + fCanon.fPixelSerializer.reset(SkSafeRef(jpegEncoder)); + } virtual ~SkDocument_PDF() { // subclasses must call close() in their destructors @@ -386,7 +389,15 @@ private: /////////////////////////////////////////////////////////////////////////////// SkDocument* SkDocument::CreatePDF(SkWStream* stream, SkScalar dpi) { - return stream ? new SkDocument_PDF(stream, nullptr, dpi) : nullptr; + return stream ? new SkDocument_PDF(stream, nullptr, dpi, nullptr) : nullptr; +} + +SkDocument* SkDocument::CreatePDF(SkWStream* stream, + SkScalar dpi, + SkPixelSerializer* jpegEncoder) { + return stream + ? new SkDocument_PDF(stream, nullptr, dpi, jpegEncoder) + : nullptr; } SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { @@ -396,5 +407,5 @@ SkDocument* SkDocument::CreatePDF(const char path[], SkScalar dpi) { return nullptr; } auto delete_wstream = [](SkWStream* stream, bool) { delete stream; }; - return new SkDocument_PDF(stream, delete_wstream, dpi); + return new SkDocument_PDF(stream, delete_wstream, dpi, nullptr); } diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp index 0c53da6974..4e49db518d 100644 --- a/src/pdf/SkPDFBitmap.cpp +++ b/src/pdf/SkPDFBitmap.cpp @@ -468,7 +468,8 @@ void PDFJpegBitmap::emitObject(SkWStream* stream, //////////////////////////////////////////////////////////////////////////////// -SkPDFObject* SkPDFCreateBitmapObject(const SkImage* image) { +SkPDFObject* SkPDFCreateBitmapObject(const SkImage* image, + SkPixelSerializer* pixelSerializer) { SkAutoTUnref<SkData> data(image->refEncoded()); SkJFIFInfo info; if (data && SkIsJFIF(data, &info)) { @@ -481,6 +482,21 @@ SkPDFObject* SkPDFCreateBitmapObject(const SkImage* image) { return new PDFJpegBitmap(info.fSize, data, yuv); } } + + if (pixelSerializer) { + SkBitmap bm; + SkAutoPixmapUnlock apu; + if (as_IB(image)->getROPixels(&bm) && bm.requestLock(&apu)) { + data.reset(pixelSerializer->encode(apu.pixmap())); + if (data && SkIsJFIF(data, &info)) { + bool yuv = info.fType == SkJFIFInfo::kYCbCr; + if (info.fSize == image->dimensions()) { // Sanity check. + return new PDFJpegBitmap(info.fSize, data, yuv); + } + } + } + } + SkPDFObject* smask = image_compute_is_opaque(image) ? nullptr : new PDFAlphaBitmap(image); #ifdef SK_PDF_IMAGE_STATS diff --git a/src/pdf/SkPDFBitmap.h b/src/pdf/SkPDFBitmap.h index d931331431..b0254c1f55 100644 --- a/src/pdf/SkPDFBitmap.h +++ b/src/pdf/SkPDFBitmap.h @@ -16,6 +16,6 @@ class SkImage; * It is designed to use a minimal amout of memory, aside from refing * the image, and its emitObject() does not cache any data. */ -SkPDFObject* SkPDFCreateBitmapObject(const SkImage*); +SkPDFObject* SkPDFCreateBitmapObject(const SkImage*, SkPixelSerializer*); #endif // SkPDFBitmap_DEFINED diff --git a/src/pdf/SkPDFCanon.h b/src/pdf/SkPDFCanon.h index 3d2ba6a77d..9ecb3a02d9 100644 --- a/src/pdf/SkPDFCanon.h +++ b/src/pdf/SkPDFCanon.h @@ -10,6 +10,7 @@ #include "SkBitmap.h" #include "SkPDFGraphicState.h" #include "SkPDFShader.h" +#include "SkPixelSerializer.h" #include "SkTDArray.h" #include "SkTHash.h" @@ -80,6 +81,8 @@ public: SkTHashMap<uint32_t, bool> fCanEmbedTypeface; + SkAutoTUnref<SkPixelSerializer> fPixelSerializer; + private: struct FontRec { SkPDFFont* fFont; diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 1c5b4da070..012caf6d7d 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -2433,7 +2433,8 @@ void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix, } SkAutoTUnref<SkPDFObject> pdfimage(SkSafeRef(fCanon->findPDFBitmap(image))); if (!pdfimage) { - pdfimage.reset(SkPDFCreateBitmapObject(image)); + pdfimage.reset(SkPDFCreateBitmapObject( + image, fCanon->fPixelSerializer)); if (!pdfimage) { return; } diff --git a/tests/PDFDocumentTest.cpp b/tests/PDFDocumentTest.cpp index 04c3ede6aa..c3a5f0e041 100644 --- a/tests/PDFDocumentTest.cpp +++ b/tests/PDFDocumentTest.cpp @@ -6,10 +6,12 @@ */ #include "Test.h" +#include "Resources.h" #include "SkCanvas.h" #include "SkDocument.h" #include "SkOSFile.h" #include "SkStream.h" +#include "SkPixelSerializer.h" static void test_empty(skiatest::Reporter* reporter) { SkDynamicMemoryWStream stream; @@ -110,3 +112,45 @@ DEF_TEST(document_tests, reporter) { test_file(reporter); test_close(reporter); } + +namespace { +class JPEGSerializer final : public SkPixelSerializer { + bool onUseEncodedData(const void*, size_t) override { return true; } + SkData* onEncode(const SkPixmap& pixmap) override { + SkBitmap bm; + return bm.installPixels(pixmap.info(), + pixmap.writable_addr(), + pixmap.rowBytes(), + pixmap.ctable(), + nullptr, nullptr) + ? SkImageEncoder::EncodeData(bm, SkImageEncoder::kJPEG_Type, 85) + : nullptr; + } +}; +} // namespace + +size_t count_bytes(const SkBitmap& bm, bool useDCT) { + SkDynamicMemoryWStream stream; + SkAutoTUnref<SkDocument> doc; + if (useDCT) { + SkAutoTUnref<SkPixelSerializer> serializer(new JPEGSerializer); + doc.reset(SkDocument::CreatePDF( + &stream, SK_ScalarDefaultRasterDPI, serializer)); + } else { + doc.reset(SkDocument::CreatePDF(&stream)); + } + SkCanvas* canvas = doc->beginPage(64, 64); + canvas->drawBitmap(bm, 0, 0); + doc->endPage(); + doc->close(); + return stream.bytesWritten(); +} + +DEF_TEST(document_dct_encoder, r) { + REQUIRE_PDF_DOCUMENT(document_dct_encoder, r); + SkBitmap bm; + if (GetResourceAsBitmap("mandrill_64.png", &bm)) { + // Lossy encoding works better on photographs. + REPORTER_ASSERT(r, count_bytes(bm, true) < count_bytes(bm, false)); + } +} |