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); |
} |