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