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