Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/pdf/SkPDFDevice.cpp

Issue 1372783003: SkPDF: Implement drawImage*() properly (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "SkColor.h" 11 #include "SkColor.h"
12 #include "SkColorFilter.h" 12 #include "SkColorFilter.h"
13 #include "SkClipStack.h" 13 #include "SkClipStack.h"
14 #include "SkData.h" 14 #include "SkData.h"
15 #include "SkDraw.h" 15 #include "SkDraw.h"
16 #include "SkGlyphCache.h" 16 #include "SkGlyphCache.h"
17 #include "SkPaint.h" 17 #include "SkPaint.h"
18 #include "SkPath.h" 18 #include "SkPath.h"
19 #include "SkPathOps.h" 19 #include "SkPathOps.h"
20 #include "SkPDFBitmap.h" 20 #include "SkPDFBitmap.h"
21 #include "SkPDFCanon.h"
21 #include "SkPDFFont.h" 22 #include "SkPDFFont.h"
22 #include "SkPDFFormXObject.h" 23 #include "SkPDFFormXObject.h"
23 #include "SkPDFGraphicState.h" 24 #include "SkPDFGraphicState.h"
24 #include "SkPDFResourceDict.h" 25 #include "SkPDFResourceDict.h"
25 #include "SkPDFShader.h" 26 #include "SkPDFShader.h"
26 #include "SkPDFStream.h" 27 #include "SkPDFStream.h"
27 #include "SkPDFTypes.h" 28 #include "SkPDFTypes.h"
28 #include "SkPDFUtils.h" 29 #include "SkPDFUtils.h"
29 #include "SkRasterClip.h" 30 #include "SkRasterClip.h"
30 #include "SkRect.h" 31 #include "SkRect.h"
(...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); 1034 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
1034 if (!content.entry()) { 1035 if (!content.entry()) {
1035 return; 1036 return;
1036 } 1037 }
1037 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(), 1038 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(),
1038 &content.entry()->fContent); 1039 &content.entry()->fContent);
1039 SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(), 1040 SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
1040 &content.entry()->fContent); 1041 &content.entry()->fContent);
1041 } 1042 }
1042 1043
1043 void SkPDFDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, 1044 void SkPDFDevice::drawBitmapRect(const SkDraw& draw,
1044 const SkRect* src, const SkRect& dst, 1045 const SkBitmap& bitmap,
1045 const SkPaint& srcPaint, SkCanvas::SrcRectConst raint constraint) { 1046 const SkRect* src,
1047 const SkRect& dst,
1048 const SkPaint& srcPaint,
1049 SkCanvas::SrcRectConstraint constraint) {
1050 const SkImage* image = fCanon->bitmapToImage(bitmap);
1051 if (!image) {
1052 return;
1053 }
1054 // ownership of this image is retained by the canon.
1055 this->drawImageRect(draw, image, src, dst, srcPaint, constraint);
1056 }
1057
1058 void SkPDFDevice::drawBitmap(const SkDraw& d,
1059 const SkBitmap& bitmap,
1060 const SkMatrix& matrix,
1061 const SkPaint& srcPaint) {
1046 SkPaint paint = srcPaint; 1062 SkPaint paint = srcPaint;
1047 if (bitmap.isOpaque()) { 1063 if (bitmap.isOpaque()) {
1048 replace_srcmode_on_opaque_paint(&paint); 1064 replace_srcmode_on_opaque_paint(&paint);
1049 } 1065 }
1050 1066
1067 if (d.fClip->isEmpty()) {
1068 return;
1069 }
1070
1071 SkMatrix transform = matrix;
1072 transform.postConcat(*d.fMatrix);
1073 const SkImage* image = fCanon->bitmapToImage(bitmap);
1074 if (!image) {
1075 return;
1076 }
1077 this->internalDrawImage(transform, d.fClipStack, *d.fClip, image, nullptr,
1078 paint);
1079 }
1080
1081 void SkPDFDevice::drawSprite(const SkDraw& d,
1082 const SkBitmap& bitmap,
1083 int x,
1084 int y,
1085 const SkPaint& srcPaint) {
1086 SkPaint paint = srcPaint;
1087 if (bitmap.isOpaque()) {
1088 replace_srcmode_on_opaque_paint(&paint);
1089 }
1090
1091 if (d.fClip->isEmpty()) {
1092 return;
1093 }
1094
1095 SkMatrix matrix;
1096 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
1097 const SkImage* image = fCanon->bitmapToImage(bitmap);
1098 if (!image) {
1099 return;
1100 }
1101 this->internalDrawImage(matrix, d.fClipStack, *d.fClip, image, nullptr,
1102 paint);
1103 }
1104
1105 void SkPDFDevice::drawImage(const SkDraw& draw,
1106 const SkImage* image,
1107 SkScalar x,
1108 SkScalar y,
1109 const SkPaint& srcPaint) {
1110 SkPaint paint = srcPaint;
1111 if (!image) {
1112 return;
1113 }
1114 if (image->isOpaque()) {
1115 replace_srcmode_on_opaque_paint(&paint);
1116 }
1117 if (draw.fClip->isEmpty()) {
1118 return;
1119 }
1120 SkMatrix transform = SkMatrix::MakeTrans(x, y);
1121 transform.postConcat(*draw.fMatrix);
1122 this->internalDrawImage(transform, draw.fClipStack, *draw.fClip, image,
1123 nullptr, paint);
1124 }
1125
1126 void SkPDFDevice::drawImageRect(const SkDraw& draw,
1127 const SkImage* image,
1128 const SkRect* src,
1129 const SkRect& dst,
1130 const SkPaint& srcPaint,
1131 SkCanvas::SrcRectConstraint constraint) {
1132 if (!image) {
1133 return;
1134 }
1135 if (draw.fClip->isEmpty()) {
1136 return;
1137 }
1138 SkPaint paint = srcPaint;
1139 if (image->isOpaque()) {
1140 replace_srcmode_on_opaque_paint(&paint);
1141 }
1051 // TODO: this code path must be updated to respect the flags parameter 1142 // TODO: this code path must be updated to respect the flags parameter
1052 SkMatrix matrix; 1143 SkMatrix matrix;
1053 SkRect bitmapBounds, tmpSrc, tmpDst; 1144 SkRect tmpSrc, tmpDst;
1054 SkBitmap tmpBitmap; 1145 SkRect imageBounds = SkRect::Make(image->bounds());
1055
1056 bitmapBounds.isetWH(bitmap.width(), bitmap.height());
1057 1146
1058 // Compute matrix from the two rectangles 1147 // Compute matrix from the two rectangles
1059 if (src) { 1148 if (src) {
1060 tmpSrc = *src; 1149 tmpSrc = *src;
1061 } else { 1150 } else {
1062 tmpSrc = bitmapBounds; 1151 tmpSrc = imageBounds;
1063 } 1152 }
1064 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 1153 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
1065 1154
1066 const SkBitmap* bitmapPtr = &bitmap; 1155 // FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
1067 1156
1068 // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if 1157 // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
1069 // needed (if the src was clipped). No check needed if src==null. 1158 // needed (if the src was clipped). No check needed if src==null.
1159 SkAutoTUnref<const SkImage> autoImageUnref;
1070 if (src) { 1160 if (src) {
1071 if (!bitmapBounds.contains(*src)) { 1161 if (!imageBounds.contains(*src)) {
1072 if (!tmpSrc.intersect(bitmapBounds)) { 1162 if (!tmpSrc.intersect(imageBounds)) {
1073 return; // nothing to draw 1163 return; // nothing to draw
1074 } 1164 }
1075 // recompute dst, based on the smaller tmpSrc 1165 // recompute dst, based on the smaller tmpSrc
1076 matrix.mapRect(&tmpDst, tmpSrc); 1166 matrix.mapRect(&tmpDst, tmpSrc);
1077 } 1167 }
1078 1168
1079 // since we may need to clamp to the borders of the src rect within 1169 // since we may need to clamp to the borders of the src rect within
1080 // the bitmap, we extract a subset. 1170 // the bitmap, we extract a subset.
1081 // TODO: make sure this is handled in drawBitmap and remove from here. 1171 // TODO: make sure this is handled in drawBitmap and remove from here.
1082 SkIRect srcIR; 1172 SkIRect srcIR;
1083 tmpSrc.roundOut(&srcIR); 1173 tmpSrc.roundOut(&srcIR);
1084 if (!bitmap.extractSubset(&tmpBitmap, srcIR)) { 1174
1175 autoImageUnref.reset(image->newSubset(srcIR));
1176 if (!autoImageUnref) {
1085 return; 1177 return;
1086 } 1178 }
1087 bitmapPtr = &tmpBitmap; 1179 image = autoImageUnref;
1088
1089 // Since we did an extract, we need to adjust the matrix accordingly 1180 // Since we did an extract, we need to adjust the matrix accordingly
1090 SkScalar dx = 0, dy = 0; 1181 SkScalar dx = 0, dy = 0;
1091 if (srcIR.fLeft > 0) { 1182 if (srcIR.fLeft > 0) {
1092 dx = SkIntToScalar(srcIR.fLeft); 1183 dx = SkIntToScalar(srcIR.fLeft);
1093 } 1184 }
1094 if (srcIR.fTop > 0) { 1185 if (srcIR.fTop > 0) {
1095 dy = SkIntToScalar(srcIR.fTop); 1186 dy = SkIntToScalar(srcIR.fTop);
1096 } 1187 }
1097 if (dx || dy) { 1188 if (dx || dy) {
1098 matrix.preTranslate(dx, dy); 1189 matrix.preTranslate(dx, dy);
1099 } 1190 }
1100 } 1191 }
1101 this->drawBitmap(draw, *bitmapPtr, matrix, paint); 1192 this->internalDrawImage(matrix, draw.fClipStack, *draw.fClip, image,
1102 } 1193 nullptr, paint);
1103
1104 void SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap,
1105 const SkMatrix& matrix, const SkPaint& srcPaint) {
1106 SkPaint paint = srcPaint;
1107 if (bitmap.isOpaque()) {
1108 replace_srcmode_on_opaque_paint(&paint);
1109 }
1110
1111 if (d.fClip->isEmpty()) {
1112 return;
1113 }
1114
1115 SkMatrix transform = matrix;
1116 transform.postConcat(*d.fMatrix);
1117 this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, nullptr,
1118 paint);
1119 }
1120
1121 void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap,
1122 int x, int y, const SkPaint& srcPaint) {
1123 SkPaint paint = srcPaint;
1124 if (bitmap.isOpaque()) {
1125 replace_srcmode_on_opaque_paint(&paint);
1126 }
1127
1128 if (d.fClip->isEmpty()) {
1129 return;
1130 }
1131
1132 SkMatrix matrix;
1133 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
1134 this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, nullptr,
1135 paint);
1136 } 1194 }
1137 1195
1138 // Create a PDF string. Maximum length (in bytes) is 65,535. 1196 // Create a PDF string. Maximum length (in bytes) is 65,535.
1139 // @param input A string value. 1197 // @param input A string value.
1140 // @param len The length of the input array. 1198 // @param len The length of the input array.
1141 // @param wideChars True iff the upper byte in each uint16_t is 1199 // @param wideChars True iff the upper byte in each uint16_t is
1142 // significant and should be encoded and not 1200 // significant and should be encoded and not
1143 // discarded. If true, the upper byte is encoded 1201 // discarded. If true, the upper byte is encoded
1144 // first. Otherwise, we assert the upper byte is 1202 // first. Otherwise, we assert the upper byte is
1145 // zero. 1203 // zero.
(...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after
2063 SkPDFFont::GetFontResource(fCanon, typeface, glyphID)); 2121 SkPDFFont::GetFontResource(fCanon, typeface, glyphID));
2064 int resourceIndex = fFontResources.find(newFont.get()); 2122 int resourceIndex = fFontResources.find(newFont.get());
2065 if (resourceIndex < 0) { 2123 if (resourceIndex < 0) {
2066 resourceIndex = fFontResources.count(); 2124 resourceIndex = fFontResources.count();
2067 fFontResources.push(newFont.get()); 2125 fFontResources.push(newFont.get());
2068 newFont.get()->ref(); 2126 newFont.get()->ref();
2069 } 2127 }
2070 return resourceIndex; 2128 return resourceIndex;
2071 } 2129 }
2072 2130
2073 void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, 2131 static SkSize rect_to_size(const SkRect& r) {
2074 const SkClipStack* clipStack, 2132 return SkSize::Make(r.width(), r.height());
2075 const SkRegion& origClipRegion, 2133 }
2076 const SkBitmap& origBitmap, 2134
2077 const SkIRect* srcRect, 2135 static const SkImage* color_filter(const SkImage* image,
2078 const SkPaint& paint) { 2136 SkColorFilter* colorFilter) {
2137 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(
2138 SkImageInfo::MakeN32Premul(image->dimensions())));
2139 if (!surface) {
2140 return image;
2141 }
2142 SkCanvas* canvas = surface->getCanvas();
2143 canvas->clear(SK_ColorTRANSPARENT);
2144 SkPaint paint;
2145 paint.setColorFilter(colorFilter);
2146 canvas->drawImage(image, 0, 0, &paint);
2147 canvas->flush();
2148 return surface->newImageSnapshot();
2149 }
2150
2151 ////////////////////////////////////////////////////////////////////////////////
2152 void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix,
2153 const SkClipStack* clipStack,
2154 const SkRegion& origClipRegion,
2155 const SkImage* image,
2156 const SkIRect* srcRect,
2157 const SkPaint& paint) {
2158 SkASSERT(image);
2079 SkMatrix matrix = origMatrix; 2159 SkMatrix matrix = origMatrix;
2080 SkRegion perspectiveBounds; 2160 SkRegion perspectiveBounds;
2081 const SkRegion* clipRegion = &origClipRegion; 2161 const SkRegion* clipRegion = &origClipRegion;
2082 SkBitmap perspectiveBitmap; 2162 SkAutoTUnref<const SkImage> autoImageUnref;
2083 const SkBitmap* bitmap = &origBitmap;
2084 SkBitmap tmpSubsetBitmap;
2085 2163
2164 if (srcRect) {
2165 autoImageUnref.reset(image->newSubset(*srcRect));
2166 if (!autoImageUnref) {
2167 return;
2168 }
2169 image = autoImageUnref;
2170 }
2086 // Rasterize the bitmap using perspective in a new bitmap. 2171 // Rasterize the bitmap using perspective in a new bitmap.
2087 if (origMatrix.hasPerspective()) { 2172 if (origMatrix.hasPerspective()) {
2088 if (fRasterDpi == 0) { 2173 if (fRasterDpi == 0) {
2089 return; 2174 return;
2090 } 2175 }
2091 SkBitmap* subsetBitmap;
2092 if (srcRect) {
2093 if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) {
2094 return;
2095 }
2096 subsetBitmap = &tmpSubsetBitmap;
2097 } else {
2098 subsetBitmap = &tmpSubsetBitmap;
2099 *subsetBitmap = origBitmap;
2100 }
2101 srcRect = nullptr;
2102
2103 // Transform the bitmap in the new space, without taking into 2176 // Transform the bitmap in the new space, without taking into
2104 // account the initial transform. 2177 // account the initial transform.
2105 SkPath perspectiveOutline; 2178 SkPath perspectiveOutline;
2106 perspectiveOutline.addRect( 2179 SkRect imageBounds = SkRect::Make(image->bounds());
2107 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), 2180 perspectiveOutline.addRect(imageBounds);
2108 SkIntToScalar(subsetBitmap->height())));
2109 perspectiveOutline.transform(origMatrix); 2181 perspectiveOutline.transform(origMatrix);
2110 2182
2111 // TODO(edisonn): perf - use current clip too. 2183 // TODO(edisonn): perf - use current clip too.
2112 // Retrieve the bounds of the new shape. 2184 // Retrieve the bounds of the new shape.
2113 SkRect bounds = perspectiveOutline.getBounds(); 2185 SkRect bounds = perspectiveOutline.getBounds();
2114 2186
2115 // Transform the bitmap in the new space, taking into 2187 // Transform the bitmap in the new space, taking into
2116 // account the initial transform. 2188 // account the initial transform.
2117 SkMatrix total = origMatrix; 2189 SkMatrix total = origMatrix;
2118 total.postConcat(fInitialTransform); 2190 total.postConcat(fInitialTransform);
2119 total.postScale(SkIntToScalar(fRasterDpi) / 2191 SkScalar dpiScale = SkIntToScalar(fRasterDpi) /
2120 SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE), 2192 SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE);
2121 SkIntToScalar(fRasterDpi) / 2193 total.postScale(dpiScale, dpiScale);
2122 SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE)); 2194
2123 SkPath physicalPerspectiveOutline; 2195 SkPath physicalPerspectiveOutline;
2124 physicalPerspectiveOutline.addRect( 2196 physicalPerspectiveOutline.addRect(imageBounds);
2125 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()),
2126 SkIntToScalar(subsetBitmap->height())));
2127 physicalPerspectiveOutline.transform(total); 2197 physicalPerspectiveOutline.transform(total);
2128 2198
2129 SkScalar scaleX = physicalPerspectiveOutline.getBounds().width() / 2199 SkRect physicalPerspectiveBounds =
2130 bounds.width(); 2200 physicalPerspectiveOutline.getBounds();
2131 SkScalar scaleY = physicalPerspectiveOutline.getBounds().height() / 2201 SkScalar scaleX = physicalPerspectiveBounds.width() / bounds.width();
2132 bounds.height(); 2202 SkScalar scaleY = physicalPerspectiveBounds.height() / bounds.height();
2133 2203
2134 // TODO(edisonn): A better approach would be to use a bitmap shader 2204 // TODO(edisonn): A better approach would be to use a bitmap shader
2135 // (in clamp mode) and draw a rect over the entire bounding box. Then 2205 // (in clamp mode) and draw a rect over the entire bounding box. Then
2136 // intersect perspectiveOutline to the clip. That will avoid introducing 2206 // intersect perspectiveOutline to the clip. That will avoid introducing
2137 // alpha to the image while still giving good behavior at the edge of 2207 // alpha to the image while still giving good behavior at the edge of
2138 // the image. Avoiding alpha will reduce the pdf size and generation 2208 // the image. Avoiding alpha will reduce the pdf size and generation
2139 // CPU time some. 2209 // CPU time some.
2140 2210
2141 const int w = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().w idth()); 2211 SkISize wh = rect_to_size(physicalPerspectiveBounds).toCeil();
2142 const int h = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().h eight()); 2212
2143 if (!perspectiveBitmap.tryAllocN32Pixels(w, h)) { 2213 SkAutoTUnref<SkSurface> surface(
2214 SkSurface::NewRaster(SkImageInfo::MakeN32Premul(wh)));
2215 if (!surface) {
2144 return; 2216 return;
2145 } 2217 }
2146 perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); 2218 SkCanvas* canvas = surface->getCanvas();
2147 2219 canvas->clear(SK_ColorTRANSPARENT);
2148 SkCanvas canvas(perspectiveBitmap);
2149 2220
2150 SkScalar deltaX = bounds.left(); 2221 SkScalar deltaX = bounds.left();
2151 SkScalar deltaY = bounds.top(); 2222 SkScalar deltaY = bounds.top();
2152 2223
2153 SkMatrix offsetMatrix = origMatrix; 2224 SkMatrix offsetMatrix = origMatrix;
2154 offsetMatrix.postTranslate(-deltaX, -deltaY); 2225 offsetMatrix.postTranslate(-deltaX, -deltaY);
2155 offsetMatrix.postScale(scaleX, scaleY); 2226 offsetMatrix.postScale(scaleX, scaleY);
2156 2227
2157 // Translate the draw in the new canvas, so we perfectly fit the 2228 // Translate the draw in the new canvas, so we perfectly fit the
2158 // shape in the bitmap. 2229 // shape in the bitmap.
2159 canvas.setMatrix(offsetMatrix); 2230 canvas->setMatrix(offsetMatrix);
2160 2231 canvas->drawImage(image, 0, 0, nullptr);
2161 canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0));
2162
2163 // Make sure the final bits are in the bitmap. 2232 // Make sure the final bits are in the bitmap.
2164 canvas.flush(); 2233 canvas->flush();
2165 2234
2166 // In the new space, we use the identity matrix translated 2235 // In the new space, we use the identity matrix translated
2167 // and scaled to reflect DPI. 2236 // and scaled to reflect DPI.
2168 matrix.setScale(1 / scaleX, 1 / scaleY); 2237 matrix.setScale(1 / scaleX, 1 / scaleY);
2169 matrix.postTranslate(deltaX, deltaY); 2238 matrix.postTranslate(deltaX, deltaY);
2170 2239
2171 perspectiveBounds.setRect( 2240 perspectiveBounds.setRect(bounds.roundOut());
2172 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()),
2173 SkScalarFloorToInt(bounds.y()),
2174 SkScalarCeilToInt(bounds.width()),
2175 SkScalarCeilToInt(bounds.height())));
2176 clipRegion = &perspectiveBounds; 2241 clipRegion = &perspectiveBounds;
2177 srcRect = nullptr; 2242 srcRect = nullptr;
2178 bitmap = &perspectiveBitmap; 2243
2244 autoImageUnref.reset(surface->newImageSnapshot());
2245 image = autoImageUnref;
2179 } 2246 }
2180 2247
2181 SkMatrix scaled; 2248 SkMatrix scaled;
2182 // Adjust for origin flip. 2249 // Adjust for origin flip.
2183 scaled.setScale(SK_Scalar1, -SK_Scalar1); 2250 scaled.setScale(SK_Scalar1, -SK_Scalar1);
2184 scaled.postTranslate(0, SK_Scalar1); 2251 scaled.postTranslate(0, SK_Scalar1);
2185 // Scale the image up from 1x1 to WxH. 2252 // Scale the image up from 1x1 to WxH.
2186 SkIRect subset = bitmap->bounds(); 2253 SkIRect subset = image->bounds();
2187 scaled.postScale(SkIntToScalar(subset.width()), 2254 scaled.postScale(SkIntToScalar(image->width()),
2188 SkIntToScalar(subset.height())); 2255 SkIntToScalar(image->height()));
2189 scaled.postConcat(matrix); 2256 scaled.postConcat(matrix);
2190 ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint); 2257 ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint);
2191 if (!content.entry() || (srcRect && !subset.intersect(*srcRect))) { 2258 if (!content.entry() || (srcRect && !subset.intersect(*srcRect))) {
2192 return; 2259 return;
2193 } 2260 }
2194 if (content.needShape()) { 2261 if (content.needShape()) {
2195 SkPath shape; 2262 SkPath shape;
2196 shape.addRect(SkRect::MakeWH(SkIntToScalar(subset.width()), 2263 shape.addRect(SkRect::Make(subset));
2197 SkIntToScalar(subset.height())));
2198 shape.transform(matrix); 2264 shape.transform(matrix);
2199 content.setShape(shape); 2265 content.setShape(shape);
2200 } 2266 }
2201 if (!content.needSource()) { 2267 if (!content.needSource()) {
2202 return; 2268 return;
2203 } 2269 }
2204 2270
2205 SkBitmap subsetBitmap;
2206 if (!bitmap->extractSubset(&subsetBitmap, subset)) {
2207 return;
2208 }
2209 if (SkColorFilter* colorFilter = paint.getColorFilter()) { 2271 if (SkColorFilter* colorFilter = paint.getColorFilter()) {
2210 // TODO(http://skbug.com/4378): implement colorfilter on other 2272 // TODO(http://skbug.com/4378): implement colorfilter on other
2211 // draw calls. This code here works for all drawBitmap*() 2273 // draw calls. This code here works for all
2212 // calls amd ImageFilters (which rasterize a layer on this 2274 // drawBitmap*()/drawImage*() calls amd ImageFilters (which
2213 // backend). Fortuanely, this seems to be how Chromium 2275 // rasterize a layer on this backend). Fortuanely, this seems
2214 // impements most color-filters. 2276 // to be how Chromium impements most color-filters.
2215 SkBitmap tmp; 2277 autoImageUnref.reset(color_filter(image, colorFilter));
2216 if (subsetBitmap.copyTo(&tmp, kN32_SkColorType)) { 2278 image = autoImageUnref;
2217 SkAutoLockPixels autoLockPixelsTmp(tmp); 2279 // TODO(halcanary): de-dupe this by caching filtered images.
2218 for (int y = 0; y < tmp.height(); ++y) { 2280 // (maybe in the resource cache?)
2219 SkPMColor* pixels = tmp.getAddr32(0, y); 2281 }
2220 colorFilter->filterSpan(pixels, tmp.width(), pixels); 2282 SkAutoTUnref<SkPDFObject> pdfimage(fCanon->findPDFBitmap(image));
2221 } 2283 if (!pdfimage) {
2222 tmp.setImmutable(); 2284 pdfimage.reset(SkPDFCreateBitmapObject(image));
2223 subsetBitmap = tmp; 2285 if (!pdfimage) {
2286 return;
2224 } 2287 }
2288 fCanon->addPDFBitmap(image->uniqueID(), pdfimage);
2225 } 2289 }
2226 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap)); 2290 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()),
2227 if (!image) {
2228 return;
2229 }
2230
2231 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
2232 &content.entry()->fContent); 2291 &content.entry()->fContent);
2233 } 2292 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698