diff options
author | 2013-11-11 20:55:15 +0000 | |
---|---|---|
committer | 2013-11-11 20:55:15 +0000 | |
commit | 73a7ea3ae0d37ee28f90d6b38c49fda052638253 (patch) | |
tree | f8e006e6a64f9eb9dbf0acace91fdf13e608445f | |
parent | d830d13c27437b4677a4a1abfa866d98dc2d2ab9 (diff) |
Implement DPI for perspective bitmaps in PDF - we save the bitmap at the resolution requested.
R=reed@google.com, vandebo@chromium.org
Review URL: https://codereview.chromium.org/54913004
git-svn-id: http://skia.googlecode.com/svn/trunk@12230 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | gm/gmmain.cpp | 12 | ||||
-rw-r--r-- | include/pdf/SkPDFDevice.h | 11 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 45 |
3 files changed, 53 insertions, 15 deletions
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp index d1ab966abc..86a346da66 100644 --- a/gm/gmmain.cpp +++ b/gm/gmmain.cpp @@ -198,6 +198,7 @@ static PipeFlagComboData gPipeWritingFlagCombos[] = { }; static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap); +DECLARE_int32(pdfRasterDpi); const static ErrorCombination kDefaultIgnorableErrorTypes = ErrorCombination() .plus(kMissingExpectations_ErrorType) @@ -636,7 +637,10 @@ public: SkMatrix initialTransform = gm->getInitialTransform(); if (FLAGS_useDocumentInsteadOfDevice) { SkISize pageISize = gm->getISize(); - SkAutoTUnref<SkDocument> pdfDoc(SkDocument::CreatePDF(&pdf, NULL, encode_to_dct_data)); + SkAutoTUnref<SkDocument> pdfDoc( + SkDocument::CreatePDF(&pdf, NULL, + encode_to_dct_data, + SkIntToScalar(FLAGS_pdfRasterDpi))); if (!pdfDoc.get()) { return false; @@ -667,6 +671,7 @@ public: dev = new SkPDFDevice(pageSize, contentSize, initialTransform); } dev->setDCTEncoder(encode_to_dct_data); + dev->setRasterDpi(SkIntToScalar(FLAGS_pdfRasterDpi)); SkAutoUnref aur(dev); SkCanvas c(dev); invokeGM(gm, &c, true, false); @@ -1475,7 +1480,10 @@ DEFINE_int32(pdfJpegQuality, -1, "Encodes images in JPEG at quality level N, " // then we can write something reabable like --rotate centerx centery 90 DEFINE_bool(forcePerspectiveMatrix, false, "Force a perspective matrix."); DEFINE_bool(useDocumentInsteadOfDevice, false, "Use SkDocument::CreateFoo instead of SkFooDevice."); - +DEFINE_int32(pdfRasterDpi, 72, "Scale at which at which the non suported " + "features in PDF are rasterized. Must be be in range 0-10000. " + "Default is 72. N = 0 will disable rasterizing features like " + "text shadows or perspective bitmaps."); static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap) { // Filter output of warnings that JPEG is not available for the image. if (bitmap.width() >= 65500 || bitmap.height() >= 65500) return NULL; diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h index 8e1f41823f..51d046de60 100644 --- a/include/pdf/SkPDFDevice.h +++ b/include/pdf/SkPDFDevice.h @@ -194,11 +194,6 @@ public: return *(fFontGlyphUsage.get()); } -protected: - virtual bool onReadPixels(const SkBitmap& bitmap, int x, int y, - SkCanvas::Config8888) SK_OVERRIDE; - - virtual bool allowImageFilter(SkImageFilter*) SK_OVERRIDE; /** * rasterDpi - the DPI at which features without native PDF support @@ -214,6 +209,12 @@ protected: fRasterDpi = rasterDpi; } +protected: + virtual bool onReadPixels(const SkBitmap& bitmap, int x, int y, + SkCanvas::Config8888) SK_OVERRIDE; + + virtual bool allowImageFilter(SkImageFilter*) SK_OVERRIDE; + private: // TODO(vandebo): push most of SkPDFDevice's state into a core object in // order to get the right access levels without using friend. diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index de71253d92..ff7dd2cd92 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -50,6 +50,8 @@ struct TypefaceFallbackData { }; #endif +#define DPI_FOR_RASTER_SCALE_ONE 72 + // Utility functions static void emit_pdf_color(SkColor color, SkWStream* result) { @@ -2171,6 +2173,9 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, // Rasterize the bitmap using perspective in a new bitmap. if (origMatrix.hasPerspective()) { + if (fRasterDpi == 0) { + return; + } SkBitmap* subsetBitmap; if (srcRect) { if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) { @@ -2183,7 +2188,8 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, } srcRect = NULL; - // Transform the bitmap in the new space. + // Transform the bitmap in the new space, without taking into + // account the initial transform. SkPath perspectiveOutline; perspectiveOutline.addRect( SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), @@ -2194,8 +2200,24 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, // Retrieve the bounds of the new shape. SkRect bounds = perspectiveOutline.getBounds(); - // TODO(edisonn): add DPI settings. Currently 1 pixel/point, which does - // not look great, but it is not producing large PDFs. + // Transform the bitmap in the new space, taking into + // account the initial transform. + SkMatrix total = origMatrix; + total.postConcat(fInitialTransform); + total.postScale(SkIntToScalar(fRasterDpi) / + SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE), + SkIntToScalar(fRasterDpi) / + SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE)); + SkPath physicalPerspectiveOutline; + physicalPerspectiveOutline.addRect( + SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), + SkIntToScalar(subsetBitmap->height()))); + physicalPerspectiveOutline.transform(total); + + SkScalar scaleX = physicalPerspectiveOutline.getBounds().width() / + bounds.width(); + SkScalar scaleY = physicalPerspectiveOutline.getBounds().height() / + bounds.height(); // TODO(edisonn): A better approach would be to use a bitmap shader // (in clamp mode) and draw a rect over the entire bounding box. Then @@ -2204,9 +2226,12 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, // the image. Avoiding alpha will reduce the pdf size and generation // CPU time some. - perspectiveBitmap.setConfig(SkBitmap::kARGB_8888_Config, - SkScalarCeilToInt(bounds.width()), - SkScalarCeilToInt(bounds.height())); + perspectiveBitmap.setConfig( + SkBitmap::kARGB_8888_Config, + SkScalarCeilToInt( + physicalPerspectiveOutline.getBounds().width()), + SkScalarCeilToInt( + physicalPerspectiveOutline.getBounds().height())); perspectiveBitmap.allocPixels(); perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); @@ -2218,6 +2243,7 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, SkMatrix offsetMatrix = origMatrix; offsetMatrix.postTranslate(-deltaX, -deltaY); + offsetMatrix.postScale(scaleX, scaleY); // Translate the draw in the new canvas, so we perfectly fit the // shape in the bitmap. @@ -2228,8 +2254,11 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, // Make sure the final bits are in the bitmap. canvas.flush(); - // In the new space, we use the identity matrix translated. - matrix.setTranslate(deltaX, deltaY); + // In the new space, we use the identity matrix translated + // and scaled to reflect DPI. + matrix.setScale(1 / scaleX, 1 / scaleY); + matrix.postTranslate(deltaX, deltaY); + perspectiveBounds.setRect( SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), SkScalarFloorToInt(bounds.y()), |