Chromium Code Reviews| 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, without taking into |
| 2184 // account the initial transform. | |
| 2179 SkPath perspectiveOutline; | 2185 SkPath perspectiveOutline; |
| 2180 perspectiveOutline.addRect( | 2186 perspectiveOutline.addRect( |
| 2181 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), | 2187 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), |
| 2182 SkIntToScalar(subsetBitmap->height()))); | 2188 SkIntToScalar(subsetBitmap->height()))); |
| 2183 perspectiveOutline.transform(origMatrix); | 2189 perspectiveOutline.transform(origMatrix); |
| 2184 | 2190 |
| 2185 // TODO(edisonn): perf - use current clip too. | 2191 // TODO(edisonn): perf - use current clip too. |
| 2186 // Retrieve the bounds of the new shape. | 2192 // Retrieve the bounds of the new shape. |
| 2187 SkRect bounds = perspectiveOutline.getBounds(); | 2193 SkRect bounds = perspectiveOutline.getBounds(); |
| 2188 | 2194 |
| 2189 // TODO(edisonn): add DPI settings. Currently 1 pixel/point, which does | 2195 // Transform the bitmap in the new space, taking into |
| 2190 // not look great, but it is not producing large PDFs. | 2196 // account the initial transform. |
| 2197 SkMatrix total = origMatrix; | |
| 2198 total.postConcat(fInitialTransform); | |
|
vandebo (ex-Chrome)
2013/11/07 22:44:00
Should this be preConcat? fInitialTransform is ap
edisonn
2013/11/11 17:26:56
I don't think so, gms fail and they don't output a
vandebo (ex-Chrome)
2013/11/11 17:52:19
Oops, I got Pre/Post mixed up in what they do.
| |
| 2199 SkMatrix scaleDpi; | |
| 2200 scaleDpi.setScale(SkIntToScalar(fRasterDpi) / | |
| 2201 SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE), | |
| 2202 SkIntToScalar(fRasterDpi) / | |
| 2203 SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE)); | |
| 2204 total.postConcat(scaleDpi); | |
|
vandebo (ex-Chrome)
2013/11/07 22:44:00
nit: scaleDPI isn't needed, just do postScale here
edisonn
2013/11/11 17:26:56
Done.
| |
| 2205 SkPath physicalPerspectiveOutline; | |
| 2206 physicalPerspectiveOutline.addRect( | |
| 2207 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), | |
| 2208 SkIntToScalar(subsetBitmap->height()))); | |
| 2209 physicalPerspectiveOutline.transform(total); | |
| 2210 | |
| 2211 SkScalar scaleX = physicalPerspectiveOutline.getBounds().width() / | |
| 2212 bounds.width(); | |
| 2213 SkScalar scaleY = physicalPerspectiveOutline.getBounds().height() / | |
| 2214 bounds.height(); | |
| 2191 | 2215 |
| 2192 // TODO(edisonn): A better approach would be to use a bitmap shader | 2216 // 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 | 2217 // (in clamp mode) and draw a rect over the entire bounding box. Then |
| 2194 // intersect perspectiveOutline to the clip. That will avoid introducing | 2218 // intersect perspectiveOutline to the clip. That will avoid introducing |
| 2195 // alpha to the image while still giving good behavior at the edge of | 2219 // 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 | 2220 // the image. Avoiding alpha will reduce the pdf size and generation |
| 2197 // CPU time some. | 2221 // CPU time some. |
| 2198 | 2222 |
| 2199 perspectiveBitmap.setConfig(SkBitmap::kARGB_8888_Config, | 2223 perspectiveBitmap.setConfig( |
| 2200 SkScalarCeilToInt(bounds.width()), | 2224 SkBitmap::kARGB_8888_Config, |
| 2201 SkScalarCeilToInt(bounds.height())); | 2225 SkScalarCeilToInt(scaleX * bounds.width()), |
|
vandebo (ex-Chrome)
2013/11/07 22:44:00
Just use physicalPerspectiveOutline.getBounds().w
edisonn
2013/11/11 17:26:56
Done.
| |
| 2226 SkScalarCeilToInt(scaleY * bounds.height())); | |
| 2202 perspectiveBitmap.allocPixels(); | 2227 perspectiveBitmap.allocPixels(); |
| 2203 perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); | 2228 perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); |
| 2204 | 2229 |
| 2205 SkBitmapDevice device(perspectiveBitmap); | 2230 SkBitmapDevice device(perspectiveBitmap); |
| 2206 SkCanvas canvas(&device); | 2231 SkCanvas canvas(&device); |
| 2207 | 2232 |
| 2208 SkScalar deltaX = bounds.left(); | 2233 SkScalar deltaX = bounds.left(); |
| 2209 SkScalar deltaY = bounds.top(); | 2234 SkScalar deltaY = bounds.top(); |
| 2210 | 2235 |
| 2211 SkMatrix offsetMatrix = origMatrix; | 2236 SkMatrix offsetMatrix = origMatrix; |
| 2212 offsetMatrix.postTranslate(-deltaX, -deltaY); | 2237 offsetMatrix.postTranslate(-deltaX, -deltaY); |
| 2238 offsetMatrix.postScale(scaleX, scaleY); | |
| 2213 | 2239 |
| 2214 // Translate the draw in the new canvas, so we perfectly fit the | 2240 // Translate the draw in the new canvas, so we perfectly fit the |
| 2215 // shape in the bitmap. | 2241 // shape in the bitmap. |
| 2216 canvas.setMatrix(offsetMatrix); | 2242 canvas.setMatrix(offsetMatrix); |
| 2217 | 2243 |
| 2218 canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0)); | 2244 canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0)); |
| 2219 | 2245 |
| 2220 // Make sure the final bits are in the bitmap. | 2246 // Make sure the final bits are in the bitmap. |
| 2221 canvas.flush(); | 2247 canvas.flush(); |
| 2222 | 2248 |
| 2223 // In the new space, we use the identity matrix translated. | 2249 // In the new space, we use the identity matrix translated |
| 2224 matrix.setTranslate(deltaX, deltaY); | 2250 // and scaled to reflect DPI. |
| 2251 matrix.setScale(1 / scaleX, 1 / scaleY); | |
| 2252 matrix.postTranslate(deltaX, deltaY); | |
|
vandebo (ex-Chrome)
2013/11/07 22:44:00
Not sure, should this be preTranslate ?
edisonn
2013/11/11 17:26:56
gms fail badly if I use preTranslate
| |
| 2253 | |
| 2225 perspectiveBounds.setRect( | 2254 perspectiveBounds.setRect( |
| 2226 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), | 2255 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), |
| 2227 SkScalarFloorToInt(bounds.y()), | 2256 SkScalarFloorToInt(bounds.y()), |
| 2228 SkScalarCeilToInt(bounds.width()), | 2257 SkScalarCeilToInt(bounds.width()), |
| 2229 SkScalarCeilToInt(bounds.height()))); | 2258 SkScalarCeilToInt(bounds.height()))); |
| 2230 clipRegion = &perspectiveBounds; | 2259 clipRegion = &perspectiveBounds; |
| 2231 srcRect = NULL; | 2260 srcRect = NULL; |
| 2232 bitmap = &perspectiveBitmap; | 2261 bitmap = &perspectiveBitmap; |
| 2233 } | 2262 } |
| 2234 | 2263 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2267 } | 2296 } |
| 2268 | 2297 |
| 2269 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, | 2298 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, |
| 2270 SkCanvas::Config8888) { | 2299 SkCanvas::Config8888) { |
| 2271 return false; | 2300 return false; |
| 2272 } | 2301 } |
| 2273 | 2302 |
| 2274 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { | 2303 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { |
| 2275 return false; | 2304 return false; |
| 2276 } | 2305 } |
| OLD | NEW |