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

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: 2015-09-29 (Tuesday) 14:09:03 EDT 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
tomhudson 2015/09/30 16:10:30 Not ready to land?
hal.canary 2015/10/01 01:24:55 Done.
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 matrix.postConcat(*draw.fMatrix);
1102 } 1193 this->internalDrawImage(matrix, draw.fClipStack, *draw.fClip, image,
1103 1194 nullptr, paint);
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 } 1195 }
1137 1196
1138 // Create a PDF string. Maximum length (in bytes) is 65,535. 1197 // Create a PDF string. Maximum length (in bytes) is 65,535.
1139 // @param input A string value. 1198 // @param input A string value.
1140 // @param len The length of the input array. 1199 // @param len The length of the input array.
1141 // @param wideChars True iff the upper byte in each uint16_t is 1200 // @param wideChars True iff the upper byte in each uint16_t is
1142 // significant and should be encoded and not 1201 // significant and should be encoded and not
1143 // discarded. If true, the upper byte is encoded 1202 // discarded. If true, the upper byte is encoded
1144 // first. Otherwise, we assert the upper byte is 1203 // first. Otherwise, we assert the upper byte is
1145 // zero. 1204 // zero.
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1428 mediaBox->appendInt(0); 1487 mediaBox->appendInt(0);
1429 mediaBox->appendInt(0); 1488 mediaBox->appendInt(0);
1430 mediaBox->appendInt(fPageSize.fWidth); 1489 mediaBox->appendInt(fPageSize.fWidth);
1431 mediaBox->appendInt(fPageSize.fHeight); 1490 mediaBox->appendInt(fPageSize.fHeight);
1432 return mediaBox.detach(); 1491 return mediaBox.detach();
1433 } 1492 }
1434 1493
1435 SkStreamAsset* SkPDFDevice::content() const { 1494 SkStreamAsset* SkPDFDevice::content() const {
1436 SkDynamicMemoryWStream buffer; 1495 SkDynamicMemoryWStream buffer;
1437 this->writeContent(&buffer); 1496 this->writeContent(&buffer);
1438 return buffer.detachAsStream(); 1497 return buffer.bytesWritten() > 0
1498 ? buffer.detachAsStream()
1499 : new SkMemoryStream;
1439 } 1500 }
1440 1501
1441 void SkPDFDevice::copyContentEntriesToData(ContentEntry* entry, 1502 void SkPDFDevice::copyContentEntriesToData(ContentEntry* entry,
1442 SkWStream* data) const { 1503 SkWStream* data) const {
1443 // TODO(ctguil): For margins, I'm not sure fExistingClipStack/Region is the 1504 // TODO(ctguil): For margins, I'm not sure fExistingClipStack/Region is the
1444 // right thing to pass here. 1505 // right thing to pass here.
1445 GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, data); 1506 GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, data);
1446 while (entry != nullptr) { 1507 while (entry != nullptr) {
1447 SkPoint translation; 1508 SkPoint translation;
1448 translation.iset(this->getOrigin()); 1509 translation.iset(this->getOrigin());
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
2063 SkPDFFont::GetFontResource(fCanon, typeface, glyphID)); 2124 SkPDFFont::GetFontResource(fCanon, typeface, glyphID));
2064 int resourceIndex = fFontResources.find(newFont.get()); 2125 int resourceIndex = fFontResources.find(newFont.get());
2065 if (resourceIndex < 0) { 2126 if (resourceIndex < 0) {
2066 resourceIndex = fFontResources.count(); 2127 resourceIndex = fFontResources.count();
2067 fFontResources.push(newFont.get()); 2128 fFontResources.push(newFont.get());
2068 newFont.get()->ref(); 2129 newFont.get()->ref();
2069 } 2130 }
2070 return resourceIndex; 2131 return resourceIndex;
2071 } 2132 }
2072 2133
2073 void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, 2134 static SkSize rect_to_size(const SkRect& r) {
2074 const SkClipStack* clipStack, 2135 return SkSize::Make(r.width(), r.height());
2075 const SkRegion& origClipRegion, 2136 }
2076 const SkBitmap& origBitmap, 2137
2077 const SkIRect* srcRect, 2138 static const SkImage* color_filter(const SkImage* image,
2078 const SkPaint& paint) { 2139 SkColorFilter* colorFilter) {
2140 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(
2141 SkImageInfo::MakeN32Premul(image->dimensions())));
2142 if (!surface) {
2143 return image;
2144 }
2145 SkCanvas* canvas = surface->getCanvas();
2146 canvas->clear(SK_ColorTRANSPARENT);
2147 SkPaint paint;
2148 paint.setColorFilter(colorFilter);
2149 canvas->drawImage(image, 0, 0, &paint);
2150 canvas->flush();
2151 return surface->newImageSnapshot();
2152 }
2153
2154 ////////////////////////////////////////////////////////////////////////////////
2155 void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix,
2156 const SkClipStack* clipStack,
2157 const SkRegion& origClipRegion,
2158 const SkImage* image,
2159 const SkIRect* srcRect,
2160 const SkPaint& paint) {
2161 SkASSERT(image);
2162 #ifdef SK_PDF_IMAGE_STATS
2163 gDrawImageCalls.fetch_add(1);
2164 #endif
2079 SkMatrix matrix = origMatrix; 2165 SkMatrix matrix = origMatrix;
2080 SkRegion perspectiveBounds; 2166 SkRegion perspectiveBounds;
2081 const SkRegion* clipRegion = &origClipRegion; 2167 const SkRegion* clipRegion = &origClipRegion;
2082 SkBitmap perspectiveBitmap; 2168 SkAutoTUnref<const SkImage> autoImageUnref;
2083 const SkBitmap* bitmap = &origBitmap;
2084 SkBitmap tmpSubsetBitmap;
2085 2169
2170 if (srcRect) {
2171 autoImageUnref.reset(image->newSubset(*srcRect));
2172 if (!autoImageUnref) {
2173 return;
2174 }
2175 image = autoImageUnref;
2176 }
2086 // Rasterize the bitmap using perspective in a new bitmap. 2177 // Rasterize the bitmap using perspective in a new bitmap.
2087 if (origMatrix.hasPerspective()) { 2178 if (origMatrix.hasPerspective()) {
2088 if (fRasterDpi == 0) { 2179 if (fRasterDpi == 0) {
2089 return; 2180 return;
2090 } 2181 }
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 2182 // Transform the bitmap in the new space, without taking into
2104 // account the initial transform. 2183 // account the initial transform.
2105 SkPath perspectiveOutline; 2184 SkPath perspectiveOutline;
2106 perspectiveOutline.addRect( 2185 SkRect imageBounds = SkRect::Make(image->bounds());
2107 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), 2186 perspectiveOutline.addRect(imageBounds);
2108 SkIntToScalar(subsetBitmap->height())));
2109 perspectiveOutline.transform(origMatrix); 2187 perspectiveOutline.transform(origMatrix);
2110 2188
2111 // TODO(edisonn): perf - use current clip too. 2189 // TODO(edisonn): perf - use current clip too.
2112 // Retrieve the bounds of the new shape. 2190 // Retrieve the bounds of the new shape.
2113 SkRect bounds = perspectiveOutline.getBounds(); 2191 SkRect bounds = perspectiveOutline.getBounds();
2114 2192
2115 // Transform the bitmap in the new space, taking into 2193 // Transform the bitmap in the new space, taking into
2116 // account the initial transform. 2194 // account the initial transform.
2117 SkMatrix total = origMatrix; 2195 SkMatrix total = origMatrix;
2118 total.postConcat(fInitialTransform); 2196 total.postConcat(fInitialTransform);
2119 total.postScale(SkIntToScalar(fRasterDpi) / 2197 SkScalar dpiScale = SkIntToScalar(fRasterDpi) /
2120 SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE), 2198 SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE);
2121 SkIntToScalar(fRasterDpi) / 2199 total.postScale(dpiScale, dpiScale);
2122 SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE)); 2200
2123 SkPath physicalPerspectiveOutline; 2201 SkPath physicalPerspectiveOutline;
2124 physicalPerspectiveOutline.addRect( 2202 physicalPerspectiveOutline.addRect(imageBounds);
2125 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()),
2126 SkIntToScalar(subsetBitmap->height())));
2127 physicalPerspectiveOutline.transform(total); 2203 physicalPerspectiveOutline.transform(total);
2128 2204
2129 SkScalar scaleX = physicalPerspectiveOutline.getBounds().width() / 2205 SkRect physicalPerspectiveBounds =
2130 bounds.width(); 2206 physicalPerspectiveOutline.getBounds();
2131 SkScalar scaleY = physicalPerspectiveOutline.getBounds().height() / 2207 SkScalar scaleX = physicalPerspectiveBounds.width() / bounds.width();
2132 bounds.height(); 2208 SkScalar scaleY = physicalPerspectiveBounds.height() / bounds.height();
2133 2209
2134 // TODO(edisonn): A better approach would be to use a bitmap shader 2210 // 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 2211 // (in clamp mode) and draw a rect over the entire bounding box. Then
2136 // intersect perspectiveOutline to the clip. That will avoid introducing 2212 // intersect perspectiveOutline to the clip. That will avoid introducing
2137 // alpha to the image while still giving good behavior at the edge of 2213 // 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 2214 // the image. Avoiding alpha will reduce the pdf size and generation
2139 // CPU time some. 2215 // CPU time some.
2140 2216
2141 const int w = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().w idth()); 2217 SkISize wh = rect_to_size(physicalPerspectiveBounds).toCeil();
2142 const int h = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().h eight()); 2218
2143 if (!perspectiveBitmap.tryAllocN32Pixels(w, h)) { 2219 SkAutoTUnref<SkSurface> surface(
2220 SkSurface::NewRaster(SkImageInfo::MakeN32Premul(wh)));
2221 if (!surface) {
2144 return; 2222 return;
2145 } 2223 }
2146 perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT); 2224 SkCanvas* canvas = surface->getCanvas();
2147 2225 canvas->clear(SK_ColorTRANSPARENT);
2148 SkCanvas canvas(perspectiveBitmap);
2149 2226
2150 SkScalar deltaX = bounds.left(); 2227 SkScalar deltaX = bounds.left();
2151 SkScalar deltaY = bounds.top(); 2228 SkScalar deltaY = bounds.top();
2152 2229
2153 SkMatrix offsetMatrix = origMatrix; 2230 SkMatrix offsetMatrix = origMatrix;
2154 offsetMatrix.postTranslate(-deltaX, -deltaY); 2231 offsetMatrix.postTranslate(-deltaX, -deltaY);
2155 offsetMatrix.postScale(scaleX, scaleY); 2232 offsetMatrix.postScale(scaleX, scaleY);
2156 2233
2157 // Translate the draw in the new canvas, so we perfectly fit the 2234 // Translate the draw in the new canvas, so we perfectly fit the
2158 // shape in the bitmap. 2235 // shape in the bitmap.
2159 canvas.setMatrix(offsetMatrix); 2236 canvas->setMatrix(offsetMatrix);
2160 2237 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. 2238 // Make sure the final bits are in the bitmap.
2164 canvas.flush(); 2239 canvas->flush();
2165 2240
2166 // In the new space, we use the identity matrix translated 2241 // In the new space, we use the identity matrix translated
2167 // and scaled to reflect DPI. 2242 // and scaled to reflect DPI.
2168 matrix.setScale(1 / scaleX, 1 / scaleY); 2243 matrix.setScale(1 / scaleX, 1 / scaleY);
2169 matrix.postTranslate(deltaX, deltaY); 2244 matrix.postTranslate(deltaX, deltaY);
2170 2245
2171 perspectiveBounds.setRect( 2246 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; 2247 clipRegion = &perspectiveBounds;
2177 srcRect = nullptr; 2248 srcRect = nullptr;
2178 bitmap = &perspectiveBitmap; 2249
2250 autoImageUnref.reset(surface->newImageSnapshot());
2251 image = autoImageUnref;
2179 } 2252 }
2180 2253
2181 SkMatrix scaled; 2254 SkMatrix scaled;
2182 // Adjust for origin flip. 2255 // Adjust for origin flip.
2183 scaled.setScale(SK_Scalar1, -SK_Scalar1); 2256 scaled.setScale(SK_Scalar1, -SK_Scalar1);
2184 scaled.postTranslate(0, SK_Scalar1); 2257 scaled.postTranslate(0, SK_Scalar1);
2185 // Scale the image up from 1x1 to WxH. 2258 // Scale the image up from 1x1 to WxH.
2186 SkIRect subset = bitmap->bounds(); 2259 SkIRect subset = image->bounds();
2187 scaled.postScale(SkIntToScalar(subset.width()), 2260 scaled.postScale(SkIntToScalar(image->width()),
2188 SkIntToScalar(subset.height())); 2261 SkIntToScalar(image->height()));
2189 scaled.postConcat(matrix); 2262 scaled.postConcat(matrix);
2190 ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint); 2263 ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint);
2191 if (!content.entry() || (srcRect && !subset.intersect(*srcRect))) { 2264 if (!content.entry() || (srcRect && !subset.intersect(*srcRect))) {
2192 return; 2265 return;
2193 } 2266 }
2194 if (content.needShape()) { 2267 if (content.needShape()) {
2195 SkPath shape; 2268 SkPath shape;
2196 shape.addRect(SkRect::MakeWH(SkIntToScalar(subset.width()), 2269 shape.addRect(SkRect::Make(subset));
2197 SkIntToScalar(subset.height())));
2198 shape.transform(matrix); 2270 shape.transform(matrix);
2199 content.setShape(shape); 2271 content.setShape(shape);
2200 } 2272 }
2201 if (!content.needSource()) { 2273 if (!content.needSource()) {
2202 return; 2274 return;
2203 } 2275 }
2204 2276
2205 SkBitmap subsetBitmap;
2206 if (!bitmap->extractSubset(&subsetBitmap, subset)) {
2207 return;
2208 }
2209 if (SkColorFilter* colorFilter = paint.getColorFilter()) { 2277 if (SkColorFilter* colorFilter = paint.getColorFilter()) {
2210 // TODO(http://skbug.com/4378): implement colorfilter on other 2278 // TODO(http://skbug.com/4378): implement colorfilter on other
2211 // draw calls. This code here works for all drawBitmap*() 2279 // draw calls. This code here works for all
2212 // calls amd ImageFilters (which rasterize a layer on this 2280 // drawBitmap*()/drawImage*() calls amd ImageFilters (which
2213 // backend). Fortuanely, this seems to be how Chromium 2281 // rasterize a layer on this backend). Fortuanely, this seems
2214 // impements most color-filters. 2282 // to be how Chromium impements most color-filters.
2215 SkBitmap tmp; 2283 autoImageUnref.reset(color_filter(image, colorFilter));
2216 if (subsetBitmap.copyTo(&tmp, kN32_SkColorType)) { 2284 image = autoImageUnref;
2217 SkAutoLockPixels autoLockPixelsTmp(tmp); 2285 // TODO(halcanary): de-dupe this by caching filtered images.
2218 for (int y = 0; y < tmp.height(); ++y) { 2286 // (maybe in the resource cache?)
2219 SkPMColor* pixels = tmp.getAddr32(0, y); 2287 }
2220 colorFilter->filterSpan(pixels, tmp.width(), pixels); 2288 SkAutoTUnref<SkPDFObject> pdfimage(fCanon->findPDFBitmap(image));
2221 } 2289 if (!pdfimage) {
2222 tmp.setImmutable(); 2290 pdfimage.reset(SkPDFCreateBitmapObject(image));
2223 subsetBitmap = tmp; 2291 if (!pdfimage) {
2292 return;
2224 } 2293 }
2294 fCanon->addPDFBitmap(image->uniqueID(), pdfimage);
2225 } 2295 }
2226 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap)); 2296 SkPDFUtils::DrawFormXObject(this->addXObjectResource(SkRef(pdfimage.get())),
2227 if (!image) {
2228 return;
2229 }
2230
2231 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
2232 &content.entry()->fContent); 2297 &content.entry()->fContent);
2233 } 2298 }
OLDNEW
« src/pdf/SkPDFBitmap.cpp ('K') | « src/pdf/SkPDFDevice.h ('k') | src/pdf/SkPDFTypes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698