Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Unified Diff: src/pdf/SkPDFDevice.cpp

Issue 27236007: Implement perspective for bitmaps in pdf. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: nits and properly use SkScalarCeil Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pdf/SkPDFDevice.cpp
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 43117a2b2fc4d5760d692cb50970070721d71b0c..e90edb1408fa790592e2f0766305eb923e72d3b6 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -2028,23 +2028,100 @@ int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
return resourceIndex;
}
-void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix,
+void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
const SkClipStack* clipStack,
- const SkRegion& clipRegion,
- const SkBitmap& bitmap,
+ const SkRegion& origClipRegion,
+ const SkBitmap& origBitmap,
const SkIRect* srcRect,
const SkPaint& paint) {
- // TODO(edisonn): Perspective matrix support implemented here
+ SkMatrix matrix = origMatrix;
+ SkRegion perspectiveBounds;
+ const SkRegion* clipRegion = &origClipRegion;
+ SkBitmap perspectiveBitmap;
+ const SkBitmap* bitmap = &origBitmap;
+ SkBitmap tmpSubsetBitmap;
+
+ // Rasterize the bitmap using perspective in a new bitmap.
+ if (origMatrix.hasPerspective()) {
+ SkBitmap* subsetBitmap;
+ if (srcRect) {
+ if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) {
+ return;
+ }
+ subsetBitmap = &tmpSubsetBitmap;
+ } else {
+ subsetBitmap = &tmpSubsetBitmap;
+ *subsetBitmap = origBitmap;
+ }
+ srcRect = NULL;
+
+ // Transform the bitmap in the new space.
+ SkPath perspectiveOutline;
+ perspectiveOutline.addRect(
+ SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()),
+ SkIntToScalar(subsetBitmap->height())));
+ perspectiveOutline.transform(origMatrix);
+
+ // TODO(edisonn): perf - use current clip too.
+ // 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.
+
+ // 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
+ // intersect perspectiveOutline to the clip. That will avoid introducing
+ // alpha to the image while still giving good behavior at the edge of
+ // 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.allocPixels();
+ perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT);
+
+ SkBitmapDevice device(perspectiveBitmap);
+ SkCanvas canvas(&device);
+
+ SkScalar deltaX = bounds.left();
+ SkScalar deltaY = bounds.top();
+
+ SkMatrix offsetMatrix = origMatrix;
+ offsetMatrix.postTranslate(-deltaX, -deltaY);
+
+ // Translate the draw in the new canvas, so we perfectly fit the
+ // shape in the bitmap.
+ canvas.setMatrix(offsetMatrix);
+
+ canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0));
+
+ // 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);
+ perspectiveBounds.setRect(
+ SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()),
+ SkScalarFloorToInt(bounds.y()),
+ SkScalarCeilToInt(bounds.width()),
+ SkScalarCeilToInt(bounds.height())));
+ clipRegion = &perspectiveBounds;
+ srcRect = NULL;
+ bitmap = &perspectiveBitmap;
+ }
+
SkMatrix scaled;
// Adjust for origin flip.
scaled.setScale(SK_Scalar1, -SK_Scalar1);
scaled.postTranslate(0, SK_Scalar1);
// Scale the image up from 1x1 to WxH.
- SkIRect subset = SkIRect::MakeWH(bitmap.width(), bitmap.height());
+ SkIRect subset = SkIRect::MakeWH(bitmap->width(), bitmap->height());
scaled.postScale(SkIntToScalar(subset.width()),
SkIntToScalar(subset.height()));
scaled.postConcat(matrix);
- ScopedContentEntry content(this, clipStack, clipRegion, scaled, paint);
+ ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint);
if (!content.entry()) {
return;
}
@@ -2053,7 +2130,7 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix,
return;
}
- SkPDFImage* image = SkPDFImage::CreateImage(bitmap, subset, fEncoder);
+ SkPDFImage* image = SkPDFImage::CreateImage(*bitmap, subset, fEncoder);
if (!image) {
return;
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698