| Index: src/pdf/SkPDFBitmap.cpp
|
| diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp
|
| index de43221630e5ed85e9db28bdf8738c3957c54ada..8fafe95e164fe6857d5973ca94f3b689c585352f 100644
|
| --- a/src/pdf/SkPDFBitmap.cpp
|
| +++ b/src/pdf/SkPDFBitmap.cpp
|
| @@ -8,11 +8,10 @@
|
| #include "SkColorPriv.h"
|
| #include "SkData.h"
|
| #include "SkDeflate.h"
|
| -#include "SkImageGenerator.h"
|
| +#include "SkImage_Base.h"
|
| #include "SkJpegInfo.h"
|
| #include "SkPDFBitmap.h"
|
| #include "SkPDFCanon.h"
|
| -#include "SkPixelRef.h"
|
| #include "SkStream.h"
|
| #include "SkUnPreMultiply.h"
|
|
|
| @@ -245,34 +244,41 @@ namespace {
|
| // This SkPDFObject only outputs the alpha layer of the given bitmap.
|
| class PDFAlphaBitmap : public SkPDFObject {
|
| public:
|
| - PDFAlphaBitmap(const SkBitmap& bm) : fBitmap(bm) {}
|
| + PDFAlphaBitmap(const SkImage* image) : fImage(SkRef(image)) {}
|
| ~PDFAlphaBitmap() {}
|
| void emitObject(SkWStream*,
|
| const SkPDFObjNumMap&,
|
| const SkPDFSubstituteMap&) const override;
|
|
|
| private:
|
| - const SkBitmap fBitmap;
|
| + SkAutoTUnref<const SkImage> fImage;
|
| };
|
|
|
| void PDFAlphaBitmap::emitObject(SkWStream* stream,
|
| const SkPDFObjNumMap& objNumMap,
|
| const SkPDFSubstituteMap& substitutes) const {
|
| - SkAutoLockPixels autoLockPixels(fBitmap);
|
| - SkASSERT(fBitmap.colorType() != kIndex_8_SkColorType ||
|
| - fBitmap.getColorTable());
|
| + // Should we lock as a SkPixMap, not a SkBitmap?
|
| + SkBitmap bitmap;
|
| + SkISize size = fImage->dimensions();
|
| + if (!as_IB(fImage.get())->getROPixels(&bitmap) ||
|
| + bitmap.dimensions() != size) {
|
| + bitmap.reset(); // bitmap_alpha_to_a8 will fill with zeroes.
|
| + }
|
| + SkAutoLockPixels autoLockPixels(bitmap);
|
| + SkASSERT(bitmap.colorType() != kIndex_8_SkColorType ||
|
| + bitmap.getColorTable());
|
|
|
| // Write to a temporary buffer to get the compressed length.
|
| SkDynamicMemoryWStream buffer;
|
| SkDeflateWStream deflateWStream(&buffer);
|
| - bitmap_alpha_to_a8(fBitmap, &deflateWStream);
|
| + bitmap_alpha_to_a8(bitmap, &deflateWStream);
|
| deflateWStream.finalize(); // call before detachAsStream().
|
| SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream());
|
|
|
| SkPDFDict pdfDict("XObject");
|
| pdfDict.insertName("Subtype", "Image");
|
| - pdfDict.insertInt("Width", fBitmap.width());
|
| - pdfDict.insertInt("Height", fBitmap.height());
|
| + pdfDict.insertInt("Width", size.width());
|
| + pdfDict.insertInt("Height", size.height());
|
| pdfDict.insertName("ColorSpace", "DeviceGray");
|
| pdfDict.insertInt("BitsPerComponent", 8);
|
| pdfDict.insertName("Filter", "FlateDecode");
|
| @@ -288,16 +294,19 @@ void PDFAlphaBitmap::emitObject(SkWStream* stream,
|
| ////////////////////////////////////////////////////////////////////////////////
|
|
|
| namespace {
|
| -class PDFDefaultBitmap : public SkPDFBitmap {
|
| +class PDFDefaultBitmap : public SkPDFObject {
|
| public:
|
| - const SkAutoTUnref<SkPDFObject> fSMask;
|
| void emitObject(SkWStream*,
|
| const SkPDFObjNumMap&,
|
| const SkPDFSubstituteMap&) const override;
|
| void addResources(SkPDFObjNumMap*,
|
| const SkPDFSubstituteMap&) const override;
|
| - PDFDefaultBitmap(const SkBitmap& bm, SkPDFObject* smask)
|
| - : SkPDFBitmap(bm), fSMask(smask) {}
|
| + PDFDefaultBitmap(const SkImage* image, SkPDFObject* smask)
|
| + : fImage(SkRef(image)), fSMask(smask) {}
|
| +
|
| +private:
|
| + SkAutoTUnref<const SkImage> fImage;
|
| + const SkAutoTUnref<SkPDFObject> fSMask;
|
| };
|
| } // namespace
|
|
|
| @@ -346,26 +355,33 @@ static SkPDFArray* make_indexed_color_space(const SkColorTable* table) {
|
| void PDFDefaultBitmap::emitObject(SkWStream* stream,
|
| const SkPDFObjNumMap& objNumMap,
|
| const SkPDFSubstituteMap& substitutes) const {
|
| - SkAutoLockPixels autoLockPixels(fBitmap);
|
| - SkASSERT(fBitmap.colorType() != kIndex_8_SkColorType ||
|
| - fBitmap.getColorTable());
|
| + SkBitmap bitmap; // Should we lock as a SkPixMap, not a SkBitmap?
|
| + SkISize size = fImage->dimensions();
|
| + if (!as_IB(fImage.get())->getROPixels(&bitmap) ||
|
| + bitmap.dimensions() != size) {
|
| + bitmap.reset(); // bitmap_to_pdf_pixels will fill with zeroes.
|
| + }
|
| + SkAutoLockPixels autoLockPixels(bitmap); // TODO(halcanry): test
|
| + // with malformed images?
|
| + SkASSERT(bitmap.colorType() != kIndex_8_SkColorType ||
|
| + bitmap.getColorTable());
|
|
|
| // Write to a temporary buffer to get the compressed length.
|
| SkDynamicMemoryWStream buffer;
|
| SkDeflateWStream deflateWStream(&buffer);
|
| - bitmap_to_pdf_pixels(fBitmap, &deflateWStream);
|
| + bitmap_to_pdf_pixels(bitmap, &deflateWStream);
|
| deflateWStream.finalize(); // call before detachAsStream().
|
| SkAutoTDelete<SkStreamAsset> asset(buffer.detachAsStream());
|
|
|
| SkPDFDict pdfDict("XObject");
|
| pdfDict.insertName("Subtype", "Image");
|
| - pdfDict.insertInt("Width", fBitmap.width());
|
| - pdfDict.insertInt("Height", fBitmap.height());
|
| - if (fBitmap.colorType() == kIndex_8_SkColorType) {
|
| - SkASSERT(1 == pdf_color_component_count(fBitmap.colorType()));
|
| + pdfDict.insertInt("Width", bitmap.width());
|
| + pdfDict.insertInt("Height", bitmap.height());
|
| + if (bitmap.colorType() == kIndex_8_SkColorType) {
|
| + SkASSERT(1 == pdf_color_component_count(bitmap.colorType()));
|
| pdfDict.insertObject("ColorSpace",
|
| - make_indexed_color_space(fBitmap.getColorTable()));
|
| - } else if (1 == pdf_color_component_count(fBitmap.colorType())) {
|
| + make_indexed_color_space(bitmap.getColorTable()));
|
| + } else if (1 == pdf_color_component_count(bitmap.colorType())) {
|
| pdfDict.insertName("ColorSpace", "DeviceGray");
|
| } else {
|
| pdfDict.insertName("ColorSpace", "DeviceRGB");
|
| @@ -385,26 +401,19 @@ void PDFDefaultBitmap::emitObject(SkWStream* stream,
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
|
|
| -static const SkBitmap& immutable_bitmap(const SkBitmap& bm, SkBitmap* copy) {
|
| - if (bm.isImmutable()) {
|
| - return bm;
|
| - }
|
| - bm.copyTo(copy);
|
| - copy->setImmutable();
|
| - return *copy;
|
| -}
|
| -
|
| namespace {
|
| /**
|
| - * This PDFObject assumes that its constructor was handed YUV JFIF
|
| - * Jpeg-encoded data that can be directly embedded into a PDF.
|
| + * This PDFObject assumes that its constructor was handed YUV or
|
| + * Grayscale JFIF Jpeg-encoded data that can be directly embedded
|
| + * into a PDF.
|
| */
|
| -class PDFJpegBitmap : public SkPDFBitmap {
|
| +class PDFJpegBitmap : public SkPDFObject {
|
| public:
|
| + SkISize fSize;
|
| SkAutoTUnref<SkData> fData;
|
| bool fIsYUV;
|
| - PDFJpegBitmap(const SkBitmap& bm, SkData* data, bool isYUV)
|
| - : SkPDFBitmap(bm), fData(SkRef(data)), fIsYUV(isYUV) {}
|
| + PDFJpegBitmap(SkISize size, SkData* data, bool isYUV)
|
| + : fSize(size), fData(SkRef(data)), fIsYUV(isYUV) {}
|
| void emitObject(SkWStream*,
|
| const SkPDFObjNumMap&,
|
| const SkPDFSubstituteMap&) const override;
|
| @@ -415,8 +424,8 @@ void PDFJpegBitmap::emitObject(SkWStream* stream,
|
| const SkPDFSubstituteMap& substituteMap) const {
|
| SkPDFDict pdfDict("XObject");
|
| pdfDict.insertName("Subtype", "Image");
|
| - pdfDict.insertInt("Width", fBitmap.width());
|
| - pdfDict.insertInt("Height", fBitmap.height());
|
| + pdfDict.insertInt("Width", fSize.width());
|
| + pdfDict.insertInt("Height", fSize.height());
|
| if (fIsYUV) {
|
| pdfDict.insertName("ColorSpace", "DeviceRGB");
|
| } else {
|
| @@ -435,39 +444,17 @@ void PDFJpegBitmap::emitObject(SkWStream* stream,
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
|
|
| -SkPDFBitmap* SkPDFBitmap::Create(SkPDFCanon* canon, const SkBitmap& bitmap) {
|
| - SkASSERT(canon);
|
| - if (!SkColorTypeIsValid(bitmap.colorType()) ||
|
| - kUnknown_SkColorType == bitmap.colorType()) {
|
| - return nullptr;
|
| - }
|
| - SkBitmap copy;
|
| - const SkBitmap& bm = immutable_bitmap(bitmap, ©);
|
| - if (bm.drawsNothing()) {
|
| - return nullptr;
|
| - }
|
| - if (SkPDFBitmap* canonBitmap = canon->findBitmap(bm)) {
|
| - return SkRef(canonBitmap);
|
| - }
|
| -
|
| - if (bm.pixelRef() && bm.pixelRefOrigin().isZero() &&
|
| - bm.dimensions() == bm.pixelRef()->info().dimensions()) {
|
| - // Requires the bitmap to be backed by lazy pixels.
|
| - SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
|
| - SkJFIFInfo info;
|
| - if (data && SkIsJFIF(data, &info)) {
|
| - bool yuv = info.fType == SkJFIFInfo::kYCbCr;
|
| - SkPDFBitmap* pdfBitmap = new PDFJpegBitmap(bm, data, yuv);
|
| - canon->addBitmap(pdfBitmap);
|
| - return pdfBitmap;
|
| +SkPDFObject* SkPDFCreateBitmapObject(const SkImage* image) {
|
| + SkAutoTUnref<SkData> data(image->refEncoded());
|
| + SkJFIFInfo info;
|
| + if (data && SkIsJFIF(data, &info)) {
|
| + bool yuv = info.fType == SkJFIFInfo::kYCbCr;
|
| + if (info.fSize == image->dimensions()) { // Sanity check.
|
| + // hold on to data, not image.
|
| + return new PDFJpegBitmap(info.fSize, data, yuv);
|
| }
|
| }
|
| -
|
| - SkPDFObject* smask = nullptr;
|
| - if (!bm.isOpaque() && !SkBitmap::ComputeIsOpaque(bm)) {
|
| - smask = new PDFAlphaBitmap(bm);
|
| - }
|
| - SkPDFBitmap* pdfBitmap = new PDFDefaultBitmap(bm, smask);
|
| - canon->addBitmap(pdfBitmap);
|
| - return pdfBitmap;
|
| + SkPDFObject* smask =
|
| + image->isOpaque() ? nullptr : new PDFAlphaBitmap(image);
|
| + return new PDFDefaultBitmap(image, smask);
|
| }
|
|
|