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 "SkAnnotationKeys.h" | 10 #include "SkAnnotationKeys.h" |
(...skipping 1042 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1053 if (bitmap.isOpaque()) { | 1053 if (bitmap.isOpaque()) { |
1054 replace_srcmode_on_opaque_paint(&paint); | 1054 replace_srcmode_on_opaque_paint(&paint); |
1055 } | 1055 } |
1056 | 1056 |
1057 if (d.fClip->isEmpty()) { | 1057 if (d.fClip->isEmpty()) { |
1058 return; | 1058 return; |
1059 } | 1059 } |
1060 | 1060 |
1061 SkMatrix transform = matrix; | 1061 SkMatrix transform = matrix; |
1062 transform.postConcat(*d.fMatrix); | 1062 transform.postConcat(*d.fMatrix); |
1063 const SkImage* image = fDocument->canon()->bitmapToImage(bitmap); | 1063 SkImageBitmap imageBitmap(bitmap); |
1064 if (!image) { | 1064 this->internalDrawImage( |
1065 return; | 1065 transform, d.fClipStack, *d.fClip, imageBitmap, paint); |
1066 } | |
1067 this->internalDrawImage(transform, d.fClipStack, *d.fClip, image, nullptr, | |
1068 paint); | |
1069 } | 1066 } |
1070 | 1067 |
1071 void SkPDFDevice::drawSprite(const SkDraw& d, | 1068 void SkPDFDevice::drawSprite(const SkDraw& d, |
1072 const SkBitmap& bitmap, | 1069 const SkBitmap& bitmap, |
1073 int x, | 1070 int x, |
1074 int y, | 1071 int y, |
1075 const SkPaint& srcPaint) { | 1072 const SkPaint& srcPaint) { |
1076 SkPaint paint = srcPaint; | 1073 SkPaint paint = srcPaint; |
1077 if (bitmap.isOpaque()) { | 1074 if (bitmap.isOpaque()) { |
1078 replace_srcmode_on_opaque_paint(&paint); | 1075 replace_srcmode_on_opaque_paint(&paint); |
1079 } | 1076 } |
1080 | 1077 |
1081 if (d.fClip->isEmpty()) { | 1078 if (d.fClip->isEmpty()) { |
1082 return; | 1079 return; |
1083 } | 1080 } |
1084 | 1081 |
1085 SkMatrix matrix; | 1082 SkMatrix matrix; |
1086 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); | 1083 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); |
1087 const SkImage* image = fDocument->canon()->bitmapToImage(bitmap); | 1084 SkImageBitmap imageBitmap(bitmap); |
1088 if (!image) { | 1085 this->internalDrawImage( |
1089 return; | 1086 matrix, d.fClipStack, *d.fClip, imageBitmap, paint); |
1090 } | |
1091 this->internalDrawImage(matrix, d.fClipStack, *d.fClip, image, nullptr, | |
1092 paint); | |
1093 } | 1087 } |
1094 | 1088 |
1095 void SkPDFDevice::drawImage(const SkDraw& draw, | 1089 void SkPDFDevice::drawImage(const SkDraw& draw, |
1096 const SkImage* image, | 1090 const SkImage* image, |
1097 SkScalar x, | 1091 SkScalar x, |
1098 SkScalar y, | 1092 SkScalar y, |
1099 const SkPaint& srcPaint) { | 1093 const SkPaint& srcPaint) { |
1100 SkPaint paint = srcPaint; | 1094 SkPaint paint = srcPaint; |
1101 if (!image) { | 1095 if (!image) { |
1102 return; | 1096 return; |
1103 } | 1097 } |
1104 if (image->isOpaque()) { | 1098 if (image->isOpaque()) { |
1105 replace_srcmode_on_opaque_paint(&paint); | 1099 replace_srcmode_on_opaque_paint(&paint); |
1106 } | 1100 } |
1107 if (draw.fClip->isEmpty()) { | 1101 if (draw.fClip->isEmpty()) { |
1108 return; | 1102 return; |
1109 } | 1103 } |
1110 SkMatrix transform = SkMatrix::MakeTrans(x, y); | 1104 SkMatrix transform = SkMatrix::MakeTrans(x, y); |
1111 transform.postConcat(*draw.fMatrix); | 1105 transform.postConcat(*draw.fMatrix); |
1112 this->internalDrawImage(transform, draw.fClipStack, *draw.fClip, image, | 1106 SkImageBitmap imageBitmap(const_cast<SkImage*>(image)); |
1113 nullptr, paint); | 1107 this->internalDrawImage( |
| 1108 transform, draw.fClipStack, *draw.fClip, imageBitmap, paint); |
1114 } | 1109 } |
1115 | 1110 |
1116 void SkPDFDevice::drawImageRect(const SkDraw& draw, | 1111 void SkPDFDevice::drawImageRect(const SkDraw& draw, |
1117 const SkImage* image, | 1112 const SkImage* image, |
1118 const SkRect* src, | 1113 const SkRect* src, |
1119 const SkRect& dst, | 1114 const SkRect& dst, |
1120 const SkPaint& srcPaint, | 1115 const SkPaint& srcPaint, |
1121 SkCanvas::SrcRectConstraint constraint) { | 1116 SkCanvas::SrcRectConstraint constraint) { |
1122 SkASSERT(false); | 1117 SkASSERT(false); |
1123 } | 1118 } |
(...skipping 983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2107 fFontResources.push(newFont.get()); | 2102 fFontResources.push(newFont.get()); |
2108 newFont.get()->ref(); | 2103 newFont.get()->ref(); |
2109 } | 2104 } |
2110 return resourceIndex; | 2105 return resourceIndex; |
2111 } | 2106 } |
2112 | 2107 |
2113 static SkSize rect_to_size(const SkRect& r) { | 2108 static SkSize rect_to_size(const SkRect& r) { |
2114 return SkSize::Make(r.width(), r.height()); | 2109 return SkSize::Make(r.width(), r.height()); |
2115 } | 2110 } |
2116 | 2111 |
2117 static const SkImage* color_filter(const SkImage* image, SkColorFilter* colorFil
ter) { | 2112 static sk_sp<SkImage> color_filter(const SkImageBitmap& imageBitmap, |
| 2113 SkColorFilter* colorFilter) { |
2118 sk_sp<SkSurface> surface(SkSurface::NewRaster( | 2114 sk_sp<SkSurface> surface(SkSurface::NewRaster( |
2119 SkImageInfo::MakeN32Premul(image->dimensions()))); | 2115 SkImageInfo::MakeN32Premul(imageBitmap.dimensions()))); |
2120 if (!surface) { | 2116 SkASSERT(surface); |
2121 return image; | |
2122 } | |
2123 SkCanvas* canvas = surface->getCanvas(); | 2117 SkCanvas* canvas = surface->getCanvas(); |
2124 canvas->clear(SK_ColorTRANSPARENT); | 2118 canvas->clear(SK_ColorTRANSPARENT); |
2125 SkPaint paint; | 2119 SkPaint paint; |
2126 paint.setColorFilter(sk_ref_sp(colorFilter)); | 2120 paint.setColorFilter(sk_ref_sp(colorFilter)); |
2127 canvas->drawImage(image, 0, 0, &paint); | 2121 imageBitmap.draw(canvas, &paint); |
2128 canvas->flush(); | 2122 canvas->flush(); |
2129 return surface->makeImageSnapshot().release(); | 2123 return surface->makeImageSnapshot(); |
2130 } | 2124 } |
2131 | 2125 |
2132 //////////////////////////////////////////////////////////////////////////////// | 2126 //////////////////////////////////////////////////////////////////////////////// |
2133 void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix, | 2127 void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix, |
2134 const SkClipStack* clipStack, | 2128 const SkClipStack* clipStack, |
2135 const SkRegion& origClipRegion, | 2129 const SkRegion& origClipRegion, |
2136 const SkImage* image, | 2130 SkImageBitmap imageBitmap, |
2137 const SkIRect* srcRect, | |
2138 const SkPaint& paint) { | 2131 const SkPaint& paint) { |
2139 SkASSERT(image); | 2132 if (imageBitmap.dimensions().isZero()) { |
| 2133 return; |
| 2134 } |
2140 #ifdef SK_PDF_IMAGE_STATS | 2135 #ifdef SK_PDF_IMAGE_STATS |
2141 gDrawImageCalls.fetch_add(1); | 2136 gDrawImageCalls.fetch_add(1); |
2142 #endif | 2137 #endif |
2143 SkMatrix matrix = origMatrix; | 2138 SkMatrix matrix = origMatrix; |
2144 SkRegion perspectiveBounds; | 2139 SkRegion perspectiveBounds; |
2145 const SkRegion* clipRegion = &origClipRegion; | 2140 const SkRegion* clipRegion = &origClipRegion; |
2146 sk_sp<const SkImage> autoImageUnref; | 2141 sk_sp<SkImage> autoImageUnref; |
2147 | 2142 |
2148 if (srcRect) { | |
2149 autoImageUnref = image->makeSubset(*srcRect); | |
2150 if (!autoImageUnref) { | |
2151 return; | |
2152 } | |
2153 image = autoImageUnref.get(); | |
2154 } | |
2155 // Rasterize the bitmap using perspective in a new bitmap. | 2143 // Rasterize the bitmap using perspective in a new bitmap. |
2156 if (origMatrix.hasPerspective()) { | 2144 if (origMatrix.hasPerspective()) { |
2157 if (fRasterDpi == 0) { | 2145 if (fRasterDpi == 0) { |
2158 return; | 2146 return; |
2159 } | 2147 } |
2160 // Transform the bitmap in the new space, without taking into | 2148 // Transform the bitmap in the new space, without taking into |
2161 // account the initial transform. | 2149 // account the initial transform. |
2162 SkPath perspectiveOutline; | 2150 SkPath perspectiveOutline; |
2163 SkRect imageBounds = SkRect::Make(image->bounds()); | 2151 SkRect imageBounds = SkRect::Make(imageBitmap.bounds()); |
2164 perspectiveOutline.addRect(imageBounds); | 2152 perspectiveOutline.addRect(imageBounds); |
2165 perspectiveOutline.transform(origMatrix); | 2153 perspectiveOutline.transform(origMatrix); |
2166 | 2154 |
2167 // TODO(edisonn): perf - use current clip too. | 2155 // TODO(edisonn): perf - use current clip too. |
2168 // Retrieve the bounds of the new shape. | 2156 // Retrieve the bounds of the new shape. |
2169 SkRect bounds = perspectiveOutline.getBounds(); | 2157 SkRect bounds = perspectiveOutline.getBounds(); |
2170 | 2158 |
2171 // Transform the bitmap in the new space, taking into | 2159 // Transform the bitmap in the new space, taking into |
2172 // account the initial transform. | 2160 // account the initial transform. |
2173 SkMatrix total = origMatrix; | 2161 SkMatrix total = origMatrix; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2205 SkScalar deltaX = bounds.left(); | 2193 SkScalar deltaX = bounds.left(); |
2206 SkScalar deltaY = bounds.top(); | 2194 SkScalar deltaY = bounds.top(); |
2207 | 2195 |
2208 SkMatrix offsetMatrix = origMatrix; | 2196 SkMatrix offsetMatrix = origMatrix; |
2209 offsetMatrix.postTranslate(-deltaX, -deltaY); | 2197 offsetMatrix.postTranslate(-deltaX, -deltaY); |
2210 offsetMatrix.postScale(scaleX, scaleY); | 2198 offsetMatrix.postScale(scaleX, scaleY); |
2211 | 2199 |
2212 // Translate the draw in the new canvas, so we perfectly fit the | 2200 // Translate the draw in the new canvas, so we perfectly fit the |
2213 // shape in the bitmap. | 2201 // shape in the bitmap. |
2214 canvas->setMatrix(offsetMatrix); | 2202 canvas->setMatrix(offsetMatrix); |
2215 canvas->drawImage(image, 0, 0, nullptr); | 2203 imageBitmap.draw(canvas, nullptr); |
2216 // Make sure the final bits are in the bitmap. | 2204 // Make sure the final bits are in the bitmap. |
2217 canvas->flush(); | 2205 canvas->flush(); |
2218 | 2206 |
2219 // In the new space, we use the identity matrix translated | 2207 // In the new space, we use the identity matrix translated |
2220 // and scaled to reflect DPI. | 2208 // and scaled to reflect DPI. |
2221 matrix.setScale(1 / scaleX, 1 / scaleY); | 2209 matrix.setScale(1 / scaleX, 1 / scaleY); |
2222 matrix.postTranslate(deltaX, deltaY); | 2210 matrix.postTranslate(deltaX, deltaY); |
2223 | 2211 |
2224 perspectiveBounds.setRect(bounds.roundOut()); | 2212 perspectiveBounds.setRect(bounds.roundOut()); |
2225 clipRegion = &perspectiveBounds; | 2213 clipRegion = &perspectiveBounds; |
2226 srcRect = nullptr; | |
2227 | 2214 |
2228 autoImageUnref.reset(surface->makeImageSnapshot().release()); | 2215 autoImageUnref = surface->makeImageSnapshot(); |
2229 image = autoImageUnref.get(); | 2216 imageBitmap = SkImageBitmap(autoImageUnref.get()); |
2230 } | 2217 } |
2231 | 2218 |
2232 SkMatrix scaled; | 2219 SkMatrix scaled; |
2233 // Adjust for origin flip. | 2220 // Adjust for origin flip. |
2234 scaled.setScale(SK_Scalar1, -SK_Scalar1); | 2221 scaled.setScale(SK_Scalar1, -SK_Scalar1); |
2235 scaled.postTranslate(0, SK_Scalar1); | 2222 scaled.postTranslate(0, SK_Scalar1); |
2236 // Scale the image up from 1x1 to WxH. | 2223 // Scale the image up from 1x1 to WxH. |
2237 SkIRect subset = image->bounds(); | 2224 SkIRect subset = imageBitmap.bounds(); |
2238 scaled.postScale(SkIntToScalar(image->width()), | 2225 scaled.postScale(SkIntToScalar(imageBitmap.dimensions().width()), |
2239 SkIntToScalar(image->height())); | 2226 SkIntToScalar(imageBitmap.dimensions().height())); |
2240 scaled.postConcat(matrix); | 2227 scaled.postConcat(matrix); |
2241 ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint); | 2228 ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint); |
2242 if (!content.entry() || (srcRect && !subset.intersect(*srcRect))) { | 2229 if (!content.entry()) { |
2243 return; | 2230 return; |
2244 } | 2231 } |
2245 if (content.needShape()) { | 2232 if (content.needShape()) { |
2246 SkPath shape; | 2233 SkPath shape; |
2247 shape.addRect(SkRect::Make(subset)); | 2234 shape.addRect(SkRect::Make(subset)); |
2248 shape.transform(matrix); | 2235 shape.transform(matrix); |
2249 content.setShape(shape); | 2236 content.setShape(shape); |
2250 } | 2237 } |
2251 if (!content.needSource()) { | 2238 if (!content.needSource()) { |
2252 return; | 2239 return; |
2253 } | 2240 } |
2254 | 2241 |
2255 if (SkColorFilter* colorFilter = paint.getColorFilter()) { | 2242 if (SkColorFilter* colorFilter = paint.getColorFilter()) { |
2256 // TODO(https://bug.skia.org/4378): implement colorfilter on other | 2243 // TODO(https://bug.skia.org/4378): implement colorfilter on other |
2257 // draw calls. This code here works for all | 2244 // draw calls. This code here works for all |
2258 // drawBitmap*()/drawImage*() calls amd ImageFilters (which | 2245 // drawBitmap*()/drawImage*() calls amd ImageFilters (which |
2259 // rasterize a layer on this backend). Fortuanely, this seems | 2246 // rasterize a layer on this backend). Fortuanely, this seems |
2260 // to be how Chromium impements most color-filters. | 2247 // to be how Chromium impements most color-filters. |
2261 autoImageUnref.reset(color_filter(image, colorFilter)); | 2248 autoImageUnref = color_filter(imageBitmap, colorFilter); |
2262 image = autoImageUnref.get(); | 2249 imageBitmap = SkImageBitmap(autoImageUnref.get()); |
2263 // TODO(halcanary): de-dupe this by caching filtered images. | 2250 // TODO(halcanary): de-dupe this by caching filtered images. |
2264 // (maybe in the resource cache?) | 2251 // (maybe in the resource cache?) |
2265 } | 2252 } |
2266 sk_sp<SkPDFObject> pdfimage(SkSafeRef(fDocument->canon()->findPDFBitmap(imag
e))); | 2253 |
| 2254 SkBitmapKey key = imageBitmap.getKey(); |
| 2255 sk_sp<SkPDFObject> pdfimage = fDocument->canon()->findPDFBitmap(key); |
2267 if (!pdfimage) { | 2256 if (!pdfimage) { |
2268 pdfimage.reset(SkPDFCreateBitmapObject( | 2257 auto img = imageBitmap.makeImage(); |
2269 image, fDocument->canon()->getPixelSerializer()))
; | 2258 if (!img) { |
| 2259 return; |
| 2260 } |
| 2261 pdfimage = SkPDFCreateBitmapObject( |
| 2262 std::move(img), fDocument->canon()->getPixelSerializer()); |
2270 if (!pdfimage) { | 2263 if (!pdfimage) { |
2271 return; | 2264 return; |
2272 } | 2265 } |
2273 #if SK_PDF_SERIALIZE_IMAGES_EARLY // TODO(halcanary): enable. | 2266 fDocument->serialize(pdfimage); // serialize images early. |
2274 sk_sp<SkData> encodedImage(image->refEncodedData()); | 2267 fDocument->canon()->addPDFBitmap(key, pdfimage); |
2275 if (!encodedImage) { | |
2276 fDocument->serialize(pdfimage); | |
2277 } | |
2278 #endif | |
2279 fDocument->canon()->addPDFBitmap(image->uniqueID(), pdfimage.get()); | |
2280 } | 2268 } |
| 2269 // TODO(halcanary): addXObjectResource() should take a sk_sp<SkPDFObject> |
2281 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), | 2270 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), |
2282 &content.entry()->fContent); | 2271 &content.entry()->fContent); |
2283 } | 2272 } |
OLD | NEW |