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