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 1971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2033 const SkPaint& paint) { | 2035 const SkPaint& paint) { |
2034 SkMatrix matrix = origMatrix; | 2036 SkMatrix matrix = origMatrix; |
2035 SkRegion perspectiveBounds; | 2037 SkRegion perspectiveBounds; |
2036 const SkRegion* clipRegion = &origClipRegion; | 2038 const SkRegion* clipRegion = &origClipRegion; |
2037 SkBitmap perspectiveBitmap; | 2039 SkBitmap perspectiveBitmap; |
2038 const SkBitmap* bitmap = &origBitmap; | 2040 const SkBitmap* bitmap = &origBitmap; |
2039 SkBitmap tmpSubsetBitmap; | 2041 SkBitmap tmpSubsetBitmap; |
2040 | 2042 |
2041 // Rasterize the bitmap using perspective in a new bitmap. | 2043 // Rasterize the bitmap using perspective in a new bitmap. |
2042 if (origMatrix.hasPerspective()) { | 2044 if (origMatrix.hasPerspective()) { |
2045 if (fRasterDpi == 0) { | |
2046 return; | |
2047 } | |
2043 SkBitmap* subsetBitmap; | 2048 SkBitmap* subsetBitmap; |
2044 if (srcRect) { | 2049 if (srcRect) { |
2045 if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) { | 2050 if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) { |
2046 return; | 2051 return; |
2047 } | 2052 } |
2048 subsetBitmap = &tmpSubsetBitmap; | 2053 subsetBitmap = &tmpSubsetBitmap; |
2049 } else { | 2054 } else { |
2050 subsetBitmap = &tmpSubsetBitmap; | 2055 subsetBitmap = &tmpSubsetBitmap; |
2051 *subsetBitmap = origBitmap; | 2056 *subsetBitmap = origBitmap; |
2052 } | 2057 } |
2053 srcRect = NULL; | 2058 srcRect = NULL; |
2054 | 2059 |
2055 // Transform the bitmap in the new space. | 2060 // Transform the bitmap in the new space. |
2056 SkPath perspectiveOutline; | 2061 SkPath perspectiveOutline; |
2057 perspectiveOutline.addRect( | 2062 perspectiveOutline.addRect( |
2058 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), | 2063 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), |
2059 SkIntToScalar(subsetBitmap->height()))); | 2064 SkIntToScalar(subsetBitmap->height()))); |
2060 perspectiveOutline.transform(origMatrix); | 2065 perspectiveOutline.transform(origMatrix); |
2061 | 2066 |
2062 // TODO(edisonn): perf - use current clip too. | 2067 // TODO(edisonn): perf - use current clip too. |
2063 // Retrieve the bounds of the new shape. | 2068 // Retrieve the bounds of the new shape. |
2064 SkRect bounds = perspectiveOutline.getBounds(); | 2069 SkRect bounds = perspectiveOutline.getBounds(); |
2070 float scaleX = sqrt(fRasterDpi / (float)DPI_FOR_RASTER_SCALE_ONE); | |
vandebo (ex-Chrome)
2013/10/31 19:26:43
I don't understand, why sqrt ?
edisonn
2013/10/31 19:49:31
For some reason I was thinking DPI is "dots per sq
| |
2071 float scaleY = scaleX; | |
2065 | 2072 |
2066 // TODO(edisonn): add DPI settings. Currently 1 pixel/point, which does | 2073 scaleX *= SkScalarToFloat(fInitialTransform.getScaleX()); |
2067 // not look great, but it is not producing large PDFs. | 2074 scaleY *= SkScalarToFloat(fInitialTransform.getScaleY()); |
2075 | |
2076 scaleX = fabs(scaleX); | |
2077 scaleY = fabs(scaleY); | |
2068 | 2078 |
2069 // TODO(edisonn): A better approach would be to use a bitmap shader | 2079 // TODO(edisonn): A better approach would be to use a bitmap shader |
2070 // (in clamp mode) and draw a rect over the entire bounding box. Then | 2080 // (in clamp mode) and draw a rect over the entire bounding box. Then |
2071 // intersect perspectiveOutline to the clip. That will avoid introducing | 2081 // intersect perspectiveOutline to the clip. That will avoid introducing |
2072 // alpha to the image while still giving good behavior at the edge of | 2082 // alpha to the image while still giving good behavior at the edge of |
2073 // the image. Avoiding alpha will reduce the pdf size and generation | 2083 // the image. Avoiding alpha will reduce the pdf size and generation |
2074 // CPU time some. | 2084 // CPU time some. |
2075 | 2085 |
2076 perspectiveBitmap.setConfig(SkBitmap::kARGB_8888_Config, | 2086 perspectiveBitmap.setConfig( |
2077 SkScalarCeilToInt(bounds.width()), | 2087 SkBitmap::kARGB_8888_Config, |
2078 SkScalarCeilToInt(bounds.height())); | 2088 SkScalarCeilToInt(scaleX * bounds.width()), |
vandebo (ex-Chrome)
2013/10/31 19:26:43
This makes the image bigger
edisonn
2013/10/31 19:49:31
correct, when bitmap is put in perspective mode, i
| |
2089 SkScalarCeilToInt(scaleY * bounds.height())); | |
2079 perspectiveBitmap.allocPixels(); | 2090 perspectiveBitmap.allocPixels(); |
2080 perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); | 2091 perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); |
2081 | 2092 |
2082 SkBitmapDevice device(perspectiveBitmap); | 2093 SkBitmapDevice device(perspectiveBitmap); |
2083 SkCanvas canvas(&device); | 2094 SkCanvas canvas(&device); |
2084 | 2095 |
2085 SkScalar deltaX = bounds.left(); | 2096 SkScalar deltaX = bounds.left(); |
2086 SkScalar deltaY = bounds.top(); | 2097 SkScalar deltaY = bounds.top(); |
2087 | 2098 |
2088 SkMatrix offsetMatrix = origMatrix; | 2099 SkMatrix offsetMatrix = origMatrix; |
2089 offsetMatrix.postTranslate(-deltaX, -deltaY); | 2100 offsetMatrix.postTranslate(-deltaX, -deltaY); |
2101 offsetMatrix.postScale(scaleX, scaleY); | |
vandebo (ex-Chrome)
2013/10/31 19:26:43
Then this draws it bigger. Should this be 1/scale
edisonn
2013/10/31 19:49:31
The gms just work, I guess the code is correct.
vandebo (ex-Chrome)
2013/10/31 23:20:36
After much effort, I understand. Above makes the
| |
2090 | 2102 |
2091 // Translate the draw in the new canvas, so we perfectly fit the | 2103 // Translate the draw in the new canvas, so we perfectly fit the |
2092 // shape in the bitmap. | 2104 // shape in the bitmap. |
2093 canvas.setMatrix(offsetMatrix); | 2105 canvas.setMatrix(offsetMatrix); |
2094 | 2106 |
2095 canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0)); | 2107 canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0)); |
2096 | 2108 |
2097 // Make sure the final bits are in the bitmap. | 2109 // Make sure the final bits are in the bitmap. |
2098 canvas.flush(); | 2110 canvas.flush(); |
2099 | 2111 |
2100 // In the new space, we use the identity matrix translated. | 2112 // In the new space, we use the identity matrix translated |
2101 matrix.setTranslate(deltaX, deltaY); | 2113 // and scaled to reflect DPI. |
2114 matrix.setScale(1 / scaleX, 1 / scaleY); | |
2115 matrix.postTranslate(deltaX, deltaY); | |
2102 perspectiveBounds.setRect( | 2116 perspectiveBounds.setRect( |
2103 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), | 2117 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), |
2104 SkScalarFloorToInt(bounds.y()), | 2118 SkScalarFloorToInt(bounds.y()), |
2105 SkScalarCeilToInt(bounds.width()), | 2119 SkScalarCeilToInt(bounds.width()), |
2106 SkScalarCeilToInt(bounds.height()))); | 2120 SkScalarCeilToInt(bounds.height()))); |
2107 clipRegion = &perspectiveBounds; | 2121 clipRegion = &perspectiveBounds; |
2108 srcRect = NULL; | 2122 srcRect = NULL; |
2109 bitmap = &perspectiveBitmap; | 2123 bitmap = &perspectiveBitmap; |
2110 } | 2124 } |
2111 | 2125 |
(...skipping 26 matching lines...) Expand all Loading... | |
2138 } | 2152 } |
2139 | 2153 |
2140 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, | 2154 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, |
2141 SkCanvas::Config8888) { | 2155 SkCanvas::Config8888) { |
2142 return false; | 2156 return false; |
2143 } | 2157 } |
2144 | 2158 |
2145 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { | 2159 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { |
2146 return false; | 2160 return false; |
2147 } | 2161 } |
OLD | NEW |