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 |