Use SkPicture::ExtractBitmap callback in pdf too, there is no need for a specialized function pointer for pdf only only to pass a rectangle, when we can use subseted bitmaps.
R=scroggo@google.com, reed@google.com, vandebo@chromium.org, bsalomon@google.com Author: edisonn@google.com Review URL: https://codereview.chromium.org/25054002 git-svn-id: http://skia.googlecode.com/svn/trunk@11591 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
f7f5b7c506
commit
608ea6508a
@ -193,7 +193,7 @@ static PipeFlagComboData gPipeWritingFlagCombos[] = {
|
|||||||
| SkGPipeWriter::kSharedAddressSpace_Flag }
|
| SkGPipeWriter::kSharedAddressSpace_Flag }
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool encode_to_dct_stream(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect);
|
static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap);
|
||||||
|
|
||||||
const static ErrorCombination kDefaultIgnorableErrorTypes = ErrorCombination()
|
const static ErrorCombination kDefaultIgnorableErrorTypes = ErrorCombination()
|
||||||
.plus(kMissingExpectations_ErrorType)
|
.plus(kMissingExpectations_ErrorType)
|
||||||
@ -633,7 +633,7 @@ public:
|
|||||||
SkScalarRoundToInt(content.height()));
|
SkScalarRoundToInt(content.height()));
|
||||||
dev = new SkPDFDevice(pageSize, contentSize, initialTransform);
|
dev = new SkPDFDevice(pageSize, contentSize, initialTransform);
|
||||||
}
|
}
|
||||||
dev->setDCTEncoder(encode_to_dct_stream);
|
dev->setDCTEncoder(encode_to_dct_data);
|
||||||
SkAutoUnref aur(dev);
|
SkAutoUnref aur(dev);
|
||||||
|
|
||||||
SkCanvas c(dev);
|
SkCanvas c(dev);
|
||||||
@ -1422,7 +1422,6 @@ DEFINE_string2(writePicturePath, p, "", "Write .skp files into this directory.")
|
|||||||
DEFINE_int32(pdfJpegQuality, -1, "Encodes images in JPEG at quality level N, "
|
DEFINE_int32(pdfJpegQuality, -1, "Encodes images in JPEG at quality level N, "
|
||||||
"which can be in range 0-100). N = -1 will disable JPEG compression. "
|
"which can be in range 0-100). N = -1 will disable JPEG compression. "
|
||||||
"Default is N = 100, maximum quality.");
|
"Default is N = 100, maximum quality.");
|
||||||
|
|
||||||
// TODO(edisonn): pass a matrix instead of forcePerspectiveMatrix
|
// TODO(edisonn): pass a matrix instead of forcePerspectiveMatrix
|
||||||
// Either the 9 numbers defining the matrix
|
// Either the 9 numbers defining the matrix
|
||||||
// or probably more readable would be to replace it with a set of a few predicates
|
// or probably more readable would be to replace it with a set of a few predicates
|
||||||
@ -1431,32 +1430,33 @@ DEFINE_int32(pdfJpegQuality, -1, "Encodes images in JPEG at quality level N, "
|
|||||||
// then we can write something reabable like --rotate centerx centery 90
|
// then we can write something reabable like --rotate centerx centery 90
|
||||||
DEFINE_bool(forcePerspectiveMatrix, false, "Force a perspective matrix.");
|
DEFINE_bool(forcePerspectiveMatrix, false, "Force a perspective matrix.");
|
||||||
|
|
||||||
static bool encode_to_dct_stream(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect) {
|
static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap) {
|
||||||
// Filter output of warnings that JPEG is not available for the image.
|
// Filter output of warnings that JPEG is not available for the image.
|
||||||
if (bitmap.width() >= 65500 || bitmap.height() >= 65500) return false;
|
if (bitmap.width() >= 65500 || bitmap.height() >= 65500) return NULL;
|
||||||
if (FLAGS_pdfJpegQuality == -1) return false;
|
if (FLAGS_pdfJpegQuality == -1) return NULL;
|
||||||
|
|
||||||
SkIRect bitmapBounds;
|
|
||||||
SkBitmap subset;
|
|
||||||
const SkBitmap* bitmapToUse = &bitmap;
|
|
||||||
bitmap.getBounds(&bitmapBounds);
|
|
||||||
if (rect != bitmapBounds) {
|
|
||||||
SkAssertResult(bitmap.extractSubset(&subset, rect));
|
|
||||||
bitmapToUse = ⊂
|
|
||||||
}
|
|
||||||
|
|
||||||
|
SkBitmap bm = bitmap;
|
||||||
#if defined(SK_BUILD_FOR_MAC)
|
#if defined(SK_BUILD_FOR_MAC)
|
||||||
// Workaround bug #1043 where bitmaps with referenced pixels cause
|
// Workaround bug #1043 where bitmaps with referenced pixels cause
|
||||||
// CGImageDestinationFinalize to crash
|
// CGImageDestinationFinalize to crash
|
||||||
SkBitmap copy;
|
SkBitmap copy;
|
||||||
bitmapToUse->deepCopyTo(©, bitmapToUse->config());
|
bitmap.deepCopyTo(©, bitmap.config());
|
||||||
bitmapToUse = ©
|
bm = copy;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return SkImageEncoder::EncodeStream(stream,
|
SkPixelRef* pr = bm.pixelRef();
|
||||||
*bitmapToUse,
|
if (pr != NULL) {
|
||||||
SkImageEncoder::kJPEG_Type,
|
SkData* data = pr->refEncodedData();
|
||||||
FLAGS_pdfJpegQuality);
|
if (data != NULL) {
|
||||||
|
*pixelRefOffset = bm.pixelRefOffset();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*pixelRefOffset = 0;
|
||||||
|
return SkImageEncoder::EncodeData(bm,
|
||||||
|
SkImageEncoder::kJPEG_Type,
|
||||||
|
FLAGS_pdfJpegQuality);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int findConfig(const char config[]) {
|
static int findConfig(const char config[]) {
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "SkCanvas.h"
|
#include "SkCanvas.h"
|
||||||
#include "SkPaint.h"
|
#include "SkPaint.h"
|
||||||
#include "SkPath.h"
|
#include "SkPath.h"
|
||||||
|
#include "SkPicture.h"
|
||||||
#include "SkRect.h"
|
#include "SkRect.h"
|
||||||
#include "SkRefCnt.h"
|
#include "SkRefCnt.h"
|
||||||
#include "SkStream.h"
|
#include "SkStream.h"
|
||||||
@ -38,8 +39,6 @@ struct ContentEntry;
|
|||||||
struct GraphicStateEntry;
|
struct GraphicStateEntry;
|
||||||
struct NamedDestination;
|
struct NamedDestination;
|
||||||
|
|
||||||
typedef bool (*EncodeToDCTStream)(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect);
|
|
||||||
|
|
||||||
/** \class SkPDFDevice
|
/** \class SkPDFDevice
|
||||||
|
|
||||||
The drawing context for the PDF backend.
|
The drawing context for the PDF backend.
|
||||||
@ -140,7 +139,7 @@ public:
|
|||||||
* encoding and decoding might not be worth the space savings,
|
* encoding and decoding might not be worth the space savings,
|
||||||
* if any at all.
|
* if any at all.
|
||||||
*/
|
*/
|
||||||
void setDCTEncoder(EncodeToDCTStream encoder) {
|
void setDCTEncoder(SkPicture::EncodeBitmap encoder) {
|
||||||
fEncoder = encoder;
|
fEncoder = encoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +231,7 @@ private:
|
|||||||
// Glyph ids used for each font on this device.
|
// Glyph ids used for each font on this device.
|
||||||
SkAutoTDelete<SkPDFGlyphSetMap> fFontGlyphUsage;
|
SkAutoTDelete<SkPDFGlyphSetMap> fFontGlyphUsage;
|
||||||
|
|
||||||
EncodeToDCTStream fEncoder;
|
SkPicture::EncodeBitmap fEncoder;
|
||||||
|
|
||||||
SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack,
|
SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack,
|
||||||
const SkRegion& existingClipRegion);
|
const SkRegion& existingClipRegion);
|
||||||
|
@ -339,7 +339,7 @@ static SkPDFArray* make_indexed_color_space(SkColorTable* table) {
|
|||||||
// static
|
// static
|
||||||
SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap,
|
SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap,
|
||||||
const SkIRect& srcRect,
|
const SkIRect& srcRect,
|
||||||
EncodeToDCTStream encoder) {
|
SkPicture::EncodeBitmap encoder) {
|
||||||
if (bitmap.getConfig() == SkBitmap::kNo_Config) {
|
if (bitmap.getConfig() == SkBitmap::kNo_Config) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -390,7 +390,7 @@ SkPDFImage::SkPDFImage(SkStream* stream,
|
|||||||
const SkBitmap& bitmap,
|
const SkBitmap& bitmap,
|
||||||
bool isAlpha,
|
bool isAlpha,
|
||||||
const SkIRect& srcRect,
|
const SkIRect& srcRect,
|
||||||
EncodeToDCTStream encoder)
|
SkPicture::EncodeBitmap encoder)
|
||||||
: fIsAlpha(isAlpha),
|
: fIsAlpha(isAlpha),
|
||||||
fSrcRect(srcRect),
|
fSrcRect(srcRect),
|
||||||
fEncoder(encoder) {
|
fEncoder(encoder) {
|
||||||
@ -482,19 +482,28 @@ bool SkPDFImage::populate(SkPDFCatalog* catalog) {
|
|||||||
// Initializing image data for the first time.
|
// Initializing image data for the first time.
|
||||||
SkDynamicMemoryWStream dctCompressedWStream;
|
SkDynamicMemoryWStream dctCompressedWStream;
|
||||||
if (!skip_compression(catalog) && fEncoder &&
|
if (!skip_compression(catalog) && fEncoder &&
|
||||||
get_uncompressed_size(fBitmap, fSrcRect) > 1 &&
|
get_uncompressed_size(fBitmap, fSrcRect) > 1) {
|
||||||
fEncoder(&dctCompressedWStream, fBitmap, fSrcRect) &&
|
SkBitmap subset;
|
||||||
dctCompressedWStream.getOffset() <
|
// Extract subset
|
||||||
get_uncompressed_size(fBitmap, fSrcRect)) {
|
if (!fBitmap.extractSubset(&subset, fSrcRect)) {
|
||||||
SkAutoTUnref<SkData> data(dctCompressedWStream.copyToData());
|
// TODO(edisonn) It fails only for kA1_Config, if that is a
|
||||||
SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
|
// major concern we will fix it later, so far it is NYI.
|
||||||
setData(stream.get());
|
return false;
|
||||||
|
}
|
||||||
|
size_t pixelRefOffset = 0;
|
||||||
|
SkAutoTUnref<SkData> data(fEncoder(&pixelRefOffset, subset));
|
||||||
|
if (data.get() && data->size() < get_uncompressed_size(fBitmap,
|
||||||
|
fSrcRect)) {
|
||||||
|
SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream,
|
||||||
|
(data)));
|
||||||
|
setData(stream.get());
|
||||||
|
|
||||||
insertName("Filter", "DCTDecode");
|
insertName("Filter", "DCTDecode");
|
||||||
insertInt("ColorTransform", kNoColorTransform);
|
insertInt("ColorTransform", kNoColorTransform);
|
||||||
insertInt("Length", getData()->getLength());
|
insertInt("Length", getData()->getLength());
|
||||||
setState(kCompressed_State);
|
setState(kCompressed_State);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Fallback method
|
// Fallback method
|
||||||
if (!fStreamValid) {
|
if (!fStreamValid) {
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#ifndef SkPDFImage_DEFINED
|
#ifndef SkPDFImage_DEFINED
|
||||||
#define SkPDFImage_DEFINED
|
#define SkPDFImage_DEFINED
|
||||||
|
|
||||||
|
#include "SkPicture.h"
|
||||||
#include "SkPDFDevice.h"
|
#include "SkPDFDevice.h"
|
||||||
#include "SkPDFStream.h"
|
#include "SkPDFStream.h"
|
||||||
#include "SkPDFTypes.h"
|
#include "SkPDFTypes.h"
|
||||||
@ -38,7 +39,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
static SkPDFImage* CreateImage(const SkBitmap& bitmap,
|
static SkPDFImage* CreateImage(const SkBitmap& bitmap,
|
||||||
const SkIRect& srcRect,
|
const SkIRect& srcRect,
|
||||||
EncodeToDCTStream encoder);
|
SkPicture::EncodeBitmap encoder);
|
||||||
|
|
||||||
virtual ~SkPDFImage();
|
virtual ~SkPDFImage();
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ private:
|
|||||||
SkBitmap fBitmap;
|
SkBitmap fBitmap;
|
||||||
bool fIsAlpha;
|
bool fIsAlpha;
|
||||||
SkIRect fSrcRect;
|
SkIRect fSrcRect;
|
||||||
EncodeToDCTStream fEncoder;
|
SkPicture::EncodeBitmap fEncoder;
|
||||||
bool fStreamValid;
|
bool fStreamValid;
|
||||||
|
|
||||||
SkTDArray<SkPDFObject*> fResources;
|
SkTDArray<SkPDFObject*> fResources;
|
||||||
@ -80,7 +81,7 @@ private:
|
|||||||
* May be NULL.
|
* May be NULL.
|
||||||
*/
|
*/
|
||||||
SkPDFImage(SkStream* stream, const SkBitmap& bitmap, bool isAlpha,
|
SkPDFImage(SkStream* stream, const SkBitmap& bitmap, bool isAlpha,
|
||||||
const SkIRect& srcRect, EncodeToDCTStream encoder);
|
const SkIRect& srcRect, SkPicture::EncodeBitmap encoder);
|
||||||
|
|
||||||
/** Copy constructor, used to generate substitutes.
|
/** Copy constructor, used to generate substitutes.
|
||||||
* @param image The SkPDFImage to copy.
|
* @param image The SkPDFImage to copy.
|
||||||
|
@ -39,9 +39,11 @@ private:
|
|||||||
SkTDArray<SkPDFObject*> fResources;
|
SkTDArray<SkPDFObject*> fResources;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool encode_to_dct_stream(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect) {
|
#define DUMMY_TEXT "DCT compessed stream."
|
||||||
stream->writeText("DCT compessed stream.");
|
|
||||||
return true;
|
static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap) {
|
||||||
|
*pixelRefOffset = 0;
|
||||||
|
return SkData::NewWithProc(DUMMY_TEXT, sizeof(DUMMY_TEXT) - 1, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset,
|
static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset,
|
||||||
@ -253,7 +255,7 @@ static void TestImage(skiatest::Reporter* reporter, const SkBitmap& bitmap,
|
|||||||
SkAutoTUnref<SkPDFDevice> dev(new SkPDFDevice(pageSize, pageSize, SkMatrix::I()));
|
SkAutoTUnref<SkPDFDevice> dev(new SkPDFDevice(pageSize, pageSize, SkMatrix::I()));
|
||||||
|
|
||||||
if (useDCTEncoder) {
|
if (useDCTEncoder) {
|
||||||
dev->setDCTEncoder(encode_to_dct_stream);
|
dev->setDCTEncoder(encode_to_dct_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkCanvas c(dev);
|
SkCanvas c(dev);
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
virtual void render() = 0;
|
virtual void render() = 0;
|
||||||
virtual void end();
|
virtual void end();
|
||||||
|
|
||||||
PdfRenderer(EncodeToDCTStream encoder)
|
PdfRenderer(SkPicture::EncodeBitmap encoder)
|
||||||
: fPicture(NULL)
|
: fPicture(NULL)
|
||||||
, fPDFDevice(NULL)
|
, fPDFDevice(NULL)
|
||||||
, fEncoder(encoder)
|
, fEncoder(encoder)
|
||||||
@ -48,7 +48,7 @@ protected:
|
|||||||
SkAutoTUnref<SkCanvas> fCanvas;
|
SkAutoTUnref<SkCanvas> fCanvas;
|
||||||
SkPicture* fPicture;
|
SkPicture* fPicture;
|
||||||
SkPDFDevice* fPDFDevice;
|
SkPDFDevice* fPDFDevice;
|
||||||
EncodeToDCTStream fEncoder;
|
SkPicture::EncodeBitmap fEncoder;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef SkRefCnt INHERITED;
|
typedef SkRefCnt INHERITED;
|
||||||
@ -56,7 +56,7 @@ private:
|
|||||||
|
|
||||||
class SimplePdfRenderer : public PdfRenderer {
|
class SimplePdfRenderer : public PdfRenderer {
|
||||||
public:
|
public:
|
||||||
SimplePdfRenderer(EncodeToDCTStream encoder)
|
SimplePdfRenderer(SkPicture::EncodeBitmap encoder)
|
||||||
: PdfRenderer(encoder) {}
|
: PdfRenderer(encoder) {}
|
||||||
virtual void render() SK_OVERRIDE;
|
virtual void render() SK_OVERRIDE;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "SkImageEncoder.h"
|
#include "SkImageEncoder.h"
|
||||||
#include "SkOSFile.h"
|
#include "SkOSFile.h"
|
||||||
#include "SkPicture.h"
|
#include "SkPicture.h"
|
||||||
|
#include "SkPixelRef.h"
|
||||||
#include "SkStream.h"
|
#include "SkStream.h"
|
||||||
#include "SkTArray.h"
|
#include "SkTArray.h"
|
||||||
#include "PdfRenderer.h"
|
#include "PdfRenderer.h"
|
||||||
@ -81,30 +82,33 @@ static bool replace_filename_extension(SkString* path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int gJpegQuality = 100;
|
int gJpegQuality = 100;
|
||||||
static bool encode_to_dct_stream(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect) {
|
static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap) {
|
||||||
if (gJpegQuality == -1) return false;
|
if (gJpegQuality == -1) {
|
||||||
|
return NULL;
|
||||||
SkIRect bitmapBounds;
|
}
|
||||||
SkBitmap subset;
|
|
||||||
const SkBitmap* bitmapToUse = &bitmap;
|
|
||||||
bitmap.getBounds(&bitmapBounds);
|
|
||||||
if (rect != bitmapBounds) {
|
|
||||||
SkAssertResult(bitmap.extractSubset(&subset, rect));
|
|
||||||
bitmapToUse = ⊂
|
|
||||||
}
|
|
||||||
|
|
||||||
|
SkBitmap bm = bitmap;
|
||||||
#if defined(SK_BUILD_FOR_MAC)
|
#if defined(SK_BUILD_FOR_MAC)
|
||||||
// Workaround bug #1043 where bitmaps with referenced pixels cause
|
// Workaround bug #1043 where bitmaps with referenced pixels cause
|
||||||
// CGImageDestinationFinalize to crash
|
// CGImageDestinationFinalize to crash
|
||||||
SkBitmap copy;
|
SkBitmap copy;
|
||||||
bitmapToUse->deepCopyTo(©, bitmapToUse->config());
|
bitmap.deepCopyTo(©, bitmap.config());
|
||||||
bitmapToUse = ©
|
bm = copy;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return SkImageEncoder::EncodeStream(stream,
|
SkPixelRef* pr = bm.pixelRef();
|
||||||
*bitmapToUse,
|
if (pr != NULL) {
|
||||||
SkImageEncoder::kJPEG_Type,
|
SkData* data = pr->refEncodedData();
|
||||||
gJpegQuality);
|
if (data != NULL) {
|
||||||
|
*pixelRefOffset = bm.pixelRefOffset();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*pixelRefOffset = 0;
|
||||||
|
return SkImageEncoder::EncodeData(bm,
|
||||||
|
SkImageEncoder::kJPEG_Type,
|
||||||
|
gJpegQuality);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Builds the output filename. path = dir/name, and it replaces expected
|
/** Builds the output filename. path = dir/name, and it replaces expected
|
||||||
@ -264,7 +268,7 @@ int tool_main_core(int argc, char** argv) {
|
|||||||
SkTArray<SkString> inputs;
|
SkTArray<SkString> inputs;
|
||||||
|
|
||||||
SkAutoTUnref<sk_tools::PdfRenderer>
|
SkAutoTUnref<sk_tools::PdfRenderer>
|
||||||
renderer(SkNEW_ARGS(sk_tools::SimplePdfRenderer, (encode_to_dct_stream)));
|
renderer(SkNEW_ARGS(sk_tools::SimplePdfRenderer, (encode_to_dct_data)));
|
||||||
SkASSERT(renderer.get());
|
SkASSERT(renderer.get());
|
||||||
|
|
||||||
SkString outputDir;
|
SkString outputDir;
|
||||||
|
Loading…
Reference in New Issue
Block a user