OLD | NEW |
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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 int upperBounds; | 42 int upperBounds; |
43 | 43 |
44 bool operator==(const TypefaceFallbackData& b) const { | 44 bool operator==(const TypefaceFallbackData& b) const { |
45 return typeface == b.typeface && | 45 return typeface == b.typeface && |
46 lowerBounds == b.lowerBounds && | 46 lowerBounds == b.lowerBounds && |
47 upperBounds == b.upperBounds; | 47 upperBounds == b.upperBounds; |
48 } | 48 } |
49 }; | 49 }; |
50 #endif | 50 #endif |
51 | 51 |
| 52 #define DPI_FOR_RASTER_SCALE_ONE 72 |
| 53 |
52 // Utility functions | 54 // Utility functions |
53 | 55 |
54 static void emit_pdf_color(SkColor color, SkWStream* result) { | 56 static void emit_pdf_color(SkColor color, SkWStream* result) { |
55 SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere. | 57 SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere. |
56 SkScalar colorMax = SkIntToScalar(0xFF); | 58 SkScalar colorMax = SkIntToScalar(0xFF); |
57 SkPDFScalar::Append( | 59 SkPDFScalar::Append( |
58 SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result); | 60 SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result); |
59 result->writeText(" "); | 61 result->writeText(" "); |
60 SkPDFScalar::Append( | 62 SkPDFScalar::Append( |
61 SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result); | 63 SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result); |
(...skipping 2094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2156 const SkPaint& paint) { | 2158 const SkPaint& paint) { |
2157 SkMatrix matrix = origMatrix; | 2159 SkMatrix matrix = origMatrix; |
2158 SkRegion perspectiveBounds; | 2160 SkRegion perspectiveBounds; |
2159 const SkRegion* clipRegion = &origClipRegion; | 2161 const SkRegion* clipRegion = &origClipRegion; |
2160 SkBitmap perspectiveBitmap; | 2162 SkBitmap perspectiveBitmap; |
2161 const SkBitmap* bitmap = &origBitmap; | 2163 const SkBitmap* bitmap = &origBitmap; |
2162 SkBitmap tmpSubsetBitmap; | 2164 SkBitmap tmpSubsetBitmap; |
2163 | 2165 |
2164 // Rasterize the bitmap using perspective in a new bitmap. | 2166 // Rasterize the bitmap using perspective in a new bitmap. |
2165 if (origMatrix.hasPerspective()) { | 2167 if (origMatrix.hasPerspective()) { |
| 2168 if (fRasterDpi == 0) { |
| 2169 return; |
| 2170 } |
2166 SkBitmap* subsetBitmap; | 2171 SkBitmap* subsetBitmap; |
2167 if (srcRect) { | 2172 if (srcRect) { |
2168 if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) { | 2173 if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) { |
2169 return; | 2174 return; |
2170 } | 2175 } |
2171 subsetBitmap = &tmpSubsetBitmap; | 2176 subsetBitmap = &tmpSubsetBitmap; |
2172 } else { | 2177 } else { |
2173 subsetBitmap = &tmpSubsetBitmap; | 2178 subsetBitmap = &tmpSubsetBitmap; |
2174 *subsetBitmap = origBitmap; | 2179 *subsetBitmap = origBitmap; |
2175 } | 2180 } |
2176 srcRect = NULL; | 2181 srcRect = NULL; |
2177 | 2182 |
2178 // Transform the bitmap in the new space. | 2183 // Transform the bitmap in the new space. |
2179 SkPath perspectiveOutline; | 2184 SkPath perspectiveOutline; |
2180 perspectiveOutline.addRect( | 2185 perspectiveOutline.addRect( |
2181 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), | 2186 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), |
2182 SkIntToScalar(subsetBitmap->height()))); | 2187 SkIntToScalar(subsetBitmap->height()))); |
2183 perspectiveOutline.transform(origMatrix); | 2188 perspectiveOutline.transform(origMatrix); |
2184 | 2189 |
2185 // TODO(edisonn): perf - use current clip too. | 2190 // TODO(edisonn): perf - use current clip too. |
2186 // Retrieve the bounds of the new shape. | 2191 // Retrieve the bounds of the new shape. |
2187 SkRect bounds = perspectiveOutline.getBounds(); | 2192 SkRect bounds = perspectiveOutline.getBounds(); |
2188 | 2193 SkScalar scaleX = SkIntToScalar(fRasterDpi) / |
2189 // TODO(edisonn): add DPI settings. Currently 1 pixel/point, which does | 2194 SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE); |
2190 // not look great, but it is not producing large PDFs. | 2195 SkScalar scaleY = scaleX; |
| 2196 scaleX *= fInitialTransform.getScaleX(); |
| 2197 scaleY *= fInitialTransform.getScaleY(); |
2191 | 2198 |
2192 // TODO(edisonn): A better approach would be to use a bitmap shader | 2199 // TODO(edisonn): A better approach would be to use a bitmap shader |
2193 // (in clamp mode) and draw a rect over the entire bounding box. Then | 2200 // (in clamp mode) and draw a rect over the entire bounding box. Then |
2194 // intersect perspectiveOutline to the clip. That will avoid introducing | 2201 // intersect perspectiveOutline to the clip. That will avoid introducing |
2195 // alpha to the image while still giving good behavior at the edge of | 2202 // alpha to the image while still giving good behavior at the edge of |
2196 // the image. Avoiding alpha will reduce the pdf size and generation | 2203 // the image. Avoiding alpha will reduce the pdf size and generation |
2197 // CPU time some. | 2204 // CPU time some. |
2198 | 2205 |
2199 perspectiveBitmap.setConfig(SkBitmap::kARGB_8888_Config, | 2206 perspectiveBitmap.setConfig( |
2200 SkScalarCeilToInt(bounds.width()), | 2207 SkBitmap::kARGB_8888_Config, |
2201 SkScalarCeilToInt(bounds.height())); | 2208 SkScalarCeilToInt(SkScalarAbs(scaleX) * bounds.width()), |
| 2209 SkScalarCeilToInt(SkScalarAbs(scaleY) * bounds.height())); |
2202 perspectiveBitmap.allocPixels(); | 2210 perspectiveBitmap.allocPixels(); |
2203 perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); | 2211 perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); |
2204 | 2212 |
2205 SkBitmapDevice device(perspectiveBitmap); | 2213 SkBitmapDevice device(perspectiveBitmap); |
2206 SkCanvas canvas(&device); | 2214 SkCanvas canvas(&device); |
2207 | 2215 |
2208 SkScalar deltaX = bounds.left(); | 2216 SkScalar deltaX = bounds.left(); |
2209 SkScalar deltaY = bounds.top(); | 2217 SkScalar deltaY = bounds.top(); |
2210 | 2218 |
2211 SkMatrix offsetMatrix = origMatrix; | 2219 SkMatrix offsetMatrix = origMatrix; |
2212 offsetMatrix.postTranslate(-deltaX, -deltaY); | 2220 offsetMatrix.postTranslate(-deltaX, -deltaY); |
| 2221 offsetMatrix.postScale(scaleX, scaleY); |
2213 | 2222 |
2214 // Translate the draw in the new canvas, so we perfectly fit the | 2223 // Translate the draw in the new canvas, so we perfectly fit the |
2215 // shape in the bitmap. | 2224 // shape in the bitmap. |
2216 canvas.setMatrix(offsetMatrix); | 2225 canvas.setMatrix(offsetMatrix); |
2217 | 2226 |
2218 canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0)); | 2227 canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0)); |
2219 | 2228 |
2220 // Make sure the final bits are in the bitmap. | 2229 // Make sure the final bits are in the bitmap. |
2221 canvas.flush(); | 2230 canvas.flush(); |
2222 | 2231 |
2223 // In the new space, we use the identity matrix translated. | 2232 // In the new space, we use the identity matrix translated |
2224 matrix.setTranslate(deltaX, deltaY); | 2233 // and scaled to reflect DPI. |
| 2234 scaleX /= fInitialTransform.getScaleX(); |
| 2235 scaleY /= fInitialTransform.getScaleY(); |
| 2236 matrix.setScale(1 / scaleX, 1 / scaleY); |
| 2237 matrix.postTranslate(deltaX, deltaY); |
| 2238 |
2225 perspectiveBounds.setRect( | 2239 perspectiveBounds.setRect( |
2226 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), | 2240 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), |
2227 SkScalarFloorToInt(bounds.y()), | 2241 SkScalarFloorToInt(bounds.y()), |
2228 SkScalarCeilToInt(bounds.width()), | 2242 SkScalarCeilToInt(bounds.width()), |
2229 SkScalarCeilToInt(bounds.height()))); | 2243 SkScalarCeilToInt(bounds.height()))); |
2230 clipRegion = &perspectiveBounds; | 2244 clipRegion = &perspectiveBounds; |
2231 srcRect = NULL; | 2245 srcRect = NULL; |
2232 bitmap = &perspectiveBitmap; | 2246 bitmap = &perspectiveBitmap; |
2233 } | 2247 } |
2234 | 2248 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2267 } | 2281 } |
2268 | 2282 |
2269 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, | 2283 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, |
2270 SkCanvas::Config8888) { | 2284 SkCanvas::Config8888) { |
2271 return false; | 2285 return false; |
2272 } | 2286 } |
2273 | 2287 |
2274 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { | 2288 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { |
2275 return false; | 2289 return false; |
2276 } | 2290 } |
OLD | NEW |