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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkPDFDevice.h" 8 #include "SkPDFDevice.h"
9 9
10 #include "SkAnnotation.h" 10 #include "SkAnnotation.h"
(...skipping 2010 matching lines...) Expand 10 before | Expand all | Expand 10 after
2021 SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface, glyphID )); 2021 SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface, glyphID ));
2022 int resourceIndex = fFontResources.find(newFont.get()); 2022 int resourceIndex = fFontResources.find(newFont.get());
2023 if (resourceIndex < 0) { 2023 if (resourceIndex < 0) {
2024 resourceIndex = fFontResources.count(); 2024 resourceIndex = fFontResources.count();
2025 fFontResources.push(newFont.get()); 2025 fFontResources.push(newFont.get());
2026 newFont.get()->ref(); 2026 newFont.get()->ref();
2027 } 2027 }
2028 return resourceIndex; 2028 return resourceIndex;
2029 } 2029 }
2030 2030
2031 void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix, 2031 void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
2032 const SkClipStack* clipStack, 2032 const SkClipStack* clipStack,
2033 const SkRegion& clipRegion, 2033 const SkRegion& origClipRegion,
2034 const SkBitmap& bitmap, 2034 const SkBitmap& origBitmap,
2035 const SkIRect* srcRect, 2035 const SkIRect* srcRect,
2036 const SkPaint& paint) { 2036 const SkPaint& paint) {
2037 // TODO(edisonn): Perspective matrix support implemented here 2037 SkMatrix matrix = origMatrix;
2038 SkRegion perspectiveBounds;
2039 const SkRegion* clipRegion = &origClipRegion;
2040 SkBitmap perspectiveBitmap;
2041 const SkBitmap* bitmap = &origBitmap;
2042 SkBitmap tmpSubsetBitmap;
2043
2044 // Rasterize the bitmap using perspective in a new bitmap.
2045 if (origMatrix.hasPerspective()) {
2046 SkBitmap* subsetBitmap;
2047 if (srcRect) {
2048 if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) {
2049 return;
2050 }
2051 subsetBitmap = &tmpSubsetBitmap;
2052 } else {
2053 subsetBitmap = &tmpSubsetBitmap;
2054 *subsetBitmap = origBitmap;
2055 }
2056 srcRect = NULL;
2057
2058 // Transform the bitmap in the new space.
2059 SkPath perspectiveOutline;
2060 perspectiveOutline.addRect(
2061 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()),
2062 SkIntToScalar(subsetBitmap->height())));
2063 perspectiveOutline.transform(origMatrix);
2064
2065 // TODO(edisonn): perf - use current clip too.
2066 // Retrieve the bounds of the new shape.
2067 SkRect bounds = perspectiveOutline.getBounds();
2068
2069 // TODO(edisonn): add DPI settings. Currently 1 pixel/point, which does
2070 // not look great, but it is not producing large PDFs.
2071
2072 // TODO(edisonn): A better approach would be to use a bitmap shader
2073 // (in clamp mode) and draw a rect over the entire bounding box. Then
2074 // intersect perspectiveOutline to the clip. That will avoid introducing
2075 // alpha to the image while still giving good behavior at the edge of
2076 // the image. Avoiding alpha will reduce the pdf size and generation
2077 // CPU time some.
2078
2079 perspectiveBitmap.setConfig(SkBitmap::kARGB_8888_Config,
2080 SkScalarCeilToInt(bounds.width()),
2081 SkScalarCeilToInt(bounds.height()));
2082 perspectiveBitmap.allocPixels();
2083 perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT);
2084
2085 SkBitmapDevice device(perspectiveBitmap);
2086 SkCanvas canvas(&device);
2087
2088 SkScalar deltaX = bounds.left();
2089 SkScalar deltaY = bounds.top();
2090
2091 SkMatrix offsetMatrix = origMatrix;
2092 offsetMatrix.postTranslate(-deltaX, -deltaY);
2093
2094 // Translate the draw in the new canvas, so we perfectly fit the
2095 // shape in the bitmap.
2096 canvas.setMatrix(offsetMatrix);
2097
2098 canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0));
2099
2100 // Make sure the final bits are in the bitmap.
2101 canvas.flush();
2102
2103 // In the new space, we use the identity matrix translated.
2104 matrix.setTranslate(deltaX, deltaY);
2105 perspectiveBounds.setRect(
2106 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()),
2107 SkScalarFloorToInt(bounds.y()),
2108 SkScalarCeilToInt(bounds.width()),
2109 SkScalarCeilToInt(bounds.height())));
2110 clipRegion = &perspectiveBounds;
2111 srcRect = NULL;
2112 bitmap = &perspectiveBitmap;
2113 }
2114
2038 SkMatrix scaled; 2115 SkMatrix scaled;
2039 // Adjust for origin flip. 2116 // Adjust for origin flip.
2040 scaled.setScale(SK_Scalar1, -SK_Scalar1); 2117 scaled.setScale(SK_Scalar1, -SK_Scalar1);
2041 scaled.postTranslate(0, SK_Scalar1); 2118 scaled.postTranslate(0, SK_Scalar1);
2042 // Scale the image up from 1x1 to WxH. 2119 // Scale the image up from 1x1 to WxH.
2043 SkIRect subset = SkIRect::MakeWH(bitmap.width(), bitmap.height()); 2120 SkIRect subset = SkIRect::MakeWH(bitmap->width(), bitmap->height());
2044 scaled.postScale(SkIntToScalar(subset.width()), 2121 scaled.postScale(SkIntToScalar(subset.width()),
2045 SkIntToScalar(subset.height())); 2122 SkIntToScalar(subset.height()));
2046 scaled.postConcat(matrix); 2123 scaled.postConcat(matrix);
2047 ScopedContentEntry content(this, clipStack, clipRegion, scaled, paint); 2124 ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint);
2048 if (!content.entry()) { 2125 if (!content.entry()) {
2049 return; 2126 return;
2050 } 2127 }
2051 2128
2052 if (srcRect && !subset.intersect(*srcRect)) { 2129 if (srcRect && !subset.intersect(*srcRect)) {
2053 return; 2130 return;
2054 } 2131 }
2055 2132
2056 SkPDFImage* image = SkPDFImage::CreateImage(bitmap, subset, fEncoder); 2133 SkPDFImage* image = SkPDFImage::CreateImage(*bitmap, subset, fEncoder);
2057 if (!image) { 2134 if (!image) {
2058 return; 2135 return;
2059 } 2136 }
2060 2137
2061 fXObjectResources.push(image); // Transfer reference. 2138 fXObjectResources.push(image); // Transfer reference.
2062 SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1, 2139 SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1,
2063 &content.entry()->fContent); 2140 &content.entry()->fContent);
2064 } 2141 }
2065 2142
2066 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, 2143 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y,
2067 SkCanvas::Config8888) { 2144 SkCanvas::Config8888) {
2068 return false; 2145 return false;
2069 } 2146 }
2070 2147
2071 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { 2148 bool SkPDFDevice::allowImageFilter(SkImageFilter*) {
2072 return false; 2149 return false;
2073 } 2150 }
OLDNEW
« 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