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 2010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2021 SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface, glyphID
)); | 2021 SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface, glyphID
)); |
2022 int resourceIndex = fFontResources.find(newFont.get()); | 2022 int resourceIndex = fFontResources.find(newFont.get()); |
2023 if (resourceIndex < 0) { | 2023 if (resourceIndex < 0) { |
2024 resourceIndex = fFontResources.count(); | 2024 resourceIndex = fFontResources.count(); |
2025 fFontResources.push(newFont.get()); | 2025 fFontResources.push(newFont.get()); |
2026 newFont.get()->ref(); | 2026 newFont.get()->ref(); |
2027 } | 2027 } |
2028 return resourceIndex; | 2028 return resourceIndex; |
2029 } | 2029 } |
2030 | 2030 |
2031 void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix, | 2031 void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, |
2032 const SkClipStack* clipStack, | 2032 const SkClipStack* clipStack, |
2033 const SkRegion& clipRegion, | 2033 const SkRegion& origClipRegion, |
2034 const SkBitmap& bitmap, | 2034 const SkBitmap& origBitmap, |
2035 const SkIRect* srcRect, | 2035 const SkIRect* srcRect, |
2036 const SkPaint& paint) { | 2036 const SkPaint& paint) { |
2037 // TODO(edisonn): Perspective matrix support implemented here | 2037 SkMatrix matrix = origMatrix; |
| 2038 SkRegion perspectiveBounds; |
| 2039 const SkRegion* clipRegion = &origClipRegion; |
| 2040 SkBitmap perspectiveBitmap; |
| 2041 const SkBitmap* bitmap = &origBitmap; |
| 2042 SkBitmap tmpSubsetBitmap; |
| 2043 |
| 2044 // Rasterize the bitmap using perspective in a new bitmap. |
| 2045 if (origMatrix.hasPerspective()) { |
| 2046 SkBitmap* subsetBitmap; |
| 2047 if (srcRect) { |
| 2048 if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) { |
| 2049 return; |
| 2050 } |
| 2051 subsetBitmap = &tmpSubsetBitmap; |
| 2052 } else { |
| 2053 subsetBitmap = &tmpSubsetBitmap; |
| 2054 *subsetBitmap = origBitmap; |
| 2055 } |
| 2056 srcRect = NULL; |
| 2057 |
| 2058 // Transform the bitmap in the new space. |
| 2059 SkPath perspectiveOutline; |
| 2060 perspectiveOutline.addRect( |
| 2061 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), |
| 2062 SkIntToScalar(subsetBitmap->height()))); |
| 2063 perspectiveOutline.transform(origMatrix); |
| 2064 |
| 2065 // TODO(edisonn): perf - use current clip too. |
| 2066 // Retrieve the bounds of the new shape. |
| 2067 SkRect bounds = perspectiveOutline.getBounds(); |
| 2068 |
| 2069 // TODO(edisonn): add DPI settings. Currently 1 pixel/point, which does |
| 2070 // not look great, but it is not producing large PDFs. |
| 2071 |
| 2072 // TODO(edisonn): A better approach would be to use a bitmap shader |
| 2073 // (in clamp mode) and draw a rect over the entire bounding box. Then |
| 2074 // intersect perspectiveOutline to the clip. That will avoid introducing |
| 2075 // alpha to the image while still giving good behavior at the edge of |
| 2076 // the image. Avoiding alpha will reduce the pdf size and generation |
| 2077 // CPU time some. |
| 2078 |
| 2079 perspectiveBitmap.setConfig(SkBitmap::kARGB_8888_Config, |
| 2080 SkScalarCeilToInt(bounds.width()), |
| 2081 SkScalarCeilToInt(bounds.height())); |
| 2082 perspectiveBitmap.allocPixels(); |
| 2083 perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); |
| 2084 |
| 2085 SkBitmapDevice device(perspectiveBitmap); |
| 2086 SkCanvas canvas(&device); |
| 2087 |
| 2088 SkScalar deltaX = bounds.left(); |
| 2089 SkScalar deltaY = bounds.top(); |
| 2090 |
| 2091 SkMatrix offsetMatrix = origMatrix; |
| 2092 offsetMatrix.postTranslate(-deltaX, -deltaY); |
| 2093 |
| 2094 // Translate the draw in the new canvas, so we perfectly fit the |
| 2095 // shape in the bitmap. |
| 2096 canvas.setMatrix(offsetMatrix); |
| 2097 |
| 2098 canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0)); |
| 2099 |
| 2100 // Make sure the final bits are in the bitmap. |
| 2101 canvas.flush(); |
| 2102 |
| 2103 // In the new space, we use the identity matrix translated. |
| 2104 matrix.setTranslate(deltaX, deltaY); |
| 2105 perspectiveBounds.setRect( |
| 2106 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), |
| 2107 SkScalarFloorToInt(bounds.y()), |
| 2108 SkScalarCeilToInt(bounds.width()), |
| 2109 SkScalarCeilToInt(bounds.height()))); |
| 2110 clipRegion = &perspectiveBounds; |
| 2111 srcRect = NULL; |
| 2112 bitmap = &perspectiveBitmap; |
| 2113 } |
| 2114 |
2038 SkMatrix scaled; | 2115 SkMatrix scaled; |
2039 // Adjust for origin flip. | 2116 // Adjust for origin flip. |
2040 scaled.setScale(SK_Scalar1, -SK_Scalar1); | 2117 scaled.setScale(SK_Scalar1, -SK_Scalar1); |
2041 scaled.postTranslate(0, SK_Scalar1); | 2118 scaled.postTranslate(0, SK_Scalar1); |
2042 // Scale the image up from 1x1 to WxH. | 2119 // Scale the image up from 1x1 to WxH. |
2043 SkIRect subset = SkIRect::MakeWH(bitmap.width(), bitmap.height()); | 2120 SkIRect subset = SkIRect::MakeWH(bitmap->width(), bitmap->height()); |
2044 scaled.postScale(SkIntToScalar(subset.width()), | 2121 scaled.postScale(SkIntToScalar(subset.width()), |
2045 SkIntToScalar(subset.height())); | 2122 SkIntToScalar(subset.height())); |
2046 scaled.postConcat(matrix); | 2123 scaled.postConcat(matrix); |
2047 ScopedContentEntry content(this, clipStack, clipRegion, scaled, paint); | 2124 ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint); |
2048 if (!content.entry()) { | 2125 if (!content.entry()) { |
2049 return; | 2126 return; |
2050 } | 2127 } |
2051 | 2128 |
2052 if (srcRect && !subset.intersect(*srcRect)) { | 2129 if (srcRect && !subset.intersect(*srcRect)) { |
2053 return; | 2130 return; |
2054 } | 2131 } |
2055 | 2132 |
2056 SkPDFImage* image = SkPDFImage::CreateImage(bitmap, subset, fEncoder); | 2133 SkPDFImage* image = SkPDFImage::CreateImage(*bitmap, subset, fEncoder); |
2057 if (!image) { | 2134 if (!image) { |
2058 return; | 2135 return; |
2059 } | 2136 } |
2060 | 2137 |
2061 fXObjectResources.push(image); // Transfer reference. | 2138 fXObjectResources.push(image); // Transfer reference. |
2062 SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1, | 2139 SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1, |
2063 &content.entry()->fContent); | 2140 &content.entry()->fContent); |
2064 } | 2141 } |
2065 | 2142 |
2066 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, | 2143 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, |
2067 SkCanvas::Config8888) { | 2144 SkCanvas::Config8888) { |
2068 return false; | 2145 return false; |
2069 } | 2146 } |
2070 | 2147 |
2071 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { | 2148 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { |
2072 return false; | 2149 return false; |
2073 } | 2150 } |
OLD | NEW |