blob: e663cce1710bb3490ca4812d9fb57d3b8434c9c6 [file] [log] [blame]
robertphillips@google.com53238bc2013-08-30 13:12:10 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkBitmapDevice.h"
9#include "SkConfig8888.h"
10#include "SkDraw.h"
reede51c3562016-07-19 14:33:20 -070011#include "SkImageFilter.h"
senorblanco900c3672016-04-27 11:31:23 -070012#include "SkImageFilterCache.h"
mtkleincd495412015-11-05 09:46:23 -080013#include "SkMallocPixelRef.h"
bungemand3ebb482015-08-05 13:57:49 -070014#include "SkMatrix.h"
15#include "SkPaint.h"
16#include "SkPath.h"
reed884e97c2015-05-26 11:31:54 -070017#include "SkPixelRef.h"
bungemand3ebb482015-08-05 13:57:49 -070018#include "SkPixmap.h"
reede51c3562016-07-19 14:33:20 -070019#include "SkRasterClip.h"
robertphillips@google.com53238bc2013-08-30 13:12:10 +000020#include "SkShader.h"
reede51c3562016-07-19 14:33:20 -070021#include "SkSpecialImage.h"
reed@google.com76f10a32014-02-05 15:32:21 +000022#include "SkSurface.h"
bungemand3ebb482015-08-05 13:57:49 -070023#include "SkXfermode.h"
24
25class SkColorTable;
robertphillips@google.com53238bc2013-08-30 13:12:10 +000026
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000027static bool valid_for_bitmap_device(const SkImageInfo& info,
28 SkAlphaType* newAlphaType) {
29 if (info.width() < 0 || info.height() < 0) {
30 return false;
31 }
32
33 // TODO: can we stop supporting kUnknown in SkBitmkapDevice?
34 if (kUnknown_SkColorType == info.colorType()) {
35 if (newAlphaType) {
reed44977482015-02-27 10:23:00 -080036 *newAlphaType = kUnknown_SkAlphaType;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000037 }
38 return true;
39 }
skia.committer@gmail.com969588f2014-02-16 03:01:56 +000040
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000041 switch (info.alphaType()) {
42 case kPremul_SkAlphaType:
43 case kOpaque_SkAlphaType:
44 break;
45 default:
46 return false;
47 }
48
49 SkAlphaType canonicalAlphaType = info.alphaType();
50
51 switch (info.colorType()) {
52 case kAlpha_8_SkColorType:
53 break;
54 case kRGB_565_SkColorType:
55 canonicalAlphaType = kOpaque_SkAlphaType;
56 break;
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +000057 case kN32_SkColorType:
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000058 break;
reeda34be682016-02-15 07:48:35 -080059 case kRGBA_F16_SkColorType:
60 break;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000061 default:
62 return false;
63 }
64
65 if (newAlphaType) {
66 *newAlphaType = canonicalAlphaType;
67 }
68 return true;
69}
70
robertphillips9a53fd72015-06-22 09:46:59 -070071SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
reed589a39e2016-08-20 07:59:19 -070072 : INHERITED(bitmap.info(), SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType))
reed2c9e2002016-07-25 08:05:22 -070073 , fBitmap(bitmap)
74{
halcanary96fcdcc2015-08-27 07:41:13 -070075 SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
reed2c9e2002016-07-25 08:05:22 -070076 fBitmap.lockPixels();
robertphillips@google.com53238bc2013-08-30 13:12:10 +000077}
78
robertphillips9a53fd72015-06-22 09:46:59 -070079SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& info) {
80 return Create(info, SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType));
81}
82
robertphillipsfcf78292015-06-19 11:49:52 -070083SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkSurfaceProps& surfaceProps)
reed589a39e2016-08-20 07:59:19 -070084 : INHERITED(bitmap.info(), surfaceProps)
reed2c9e2002016-07-25 08:05:22 -070085 , fBitmap(bitmap)
86{
halcanary96fcdcc2015-08-27 07:41:13 -070087 SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
reed2c9e2002016-07-25 08:05:22 -070088 fBitmap.lockPixels();
robertphillips@google.com53238bc2013-08-30 13:12:10 +000089}
90
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000091SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
robertphillips9a53fd72015-06-22 09:46:59 -070092 const SkSurfaceProps& surfaceProps) {
reede5ea5002014-09-03 11:54:58 -070093 SkAlphaType newAT = origInfo.alphaType();
94 if (!valid_for_bitmap_device(origInfo, &newAT)) {
halcanary96fcdcc2015-08-27 07:41:13 -070095 return nullptr;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000096 }
robertphillips@google.com53238bc2013-08-30 13:12:10 +000097
reede5ea5002014-09-03 11:54:58 -070098 const SkImageInfo info = origInfo.makeAlphaType(newAT);
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000099 SkBitmap bitmap;
100
101 if (kUnknown_SkColorType == info.colorType()) {
commit-bot@chromium.orga3264e52014-05-30 13:26:10 +0000102 if (!bitmap.setInfo(info)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700103 return nullptr;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000104 }
lsalzman04d975a2016-01-08 11:20:14 -0800105 } else if (info.isOpaque()) {
mtkleincd495412015-11-05 09:46:23 -0800106 // If this bitmap is opaque, we don't have any sensible default color,
107 // so we just return uninitialized pixels.
reed84825042014-09-02 12:50:45 -0700108 if (!bitmap.tryAllocPixels(info)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700109 return nullptr;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000110 }
mtkleincd495412015-11-05 09:46:23 -0800111 } else {
112 // This bitmap has transparency, so we'll zero the pixels (to transparent).
113 // We use a ZeroedPRFactory as a faster alloc-then-eraseColor(SK_ColorTRANSPARENT).
114 SkMallocPixelRef::ZeroedPRFactory factory;
115 if (!bitmap.tryAllocPixels(info, &factory, nullptr/*color table*/)) {
116 return nullptr;
commit-bot@chromium.org15a14052014-02-16 00:59:25 +0000117 }
118 }
119
halcanary385fe4d2015-08-26 13:07:48 -0700120 return new SkBitmapDevice(bitmap, surfaceProps);
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000121}
122
mtkleinfeaadee2015-04-08 11:25:48 -0700123void SkBitmapDevice::setNewSize(const SkISize& size) {
124 SkASSERT(!fBitmap.pixelRef());
125 fBitmap.setInfo(fBitmap.info().makeWH(size.fWidth, size.fHeight));
reed589a39e2016-08-20 07:59:19 -0700126 this->privateResize(fBitmap.info().width(), fBitmap.info().height());
mtkleinfeaadee2015-04-08 11:25:48 -0700127}
128
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000129void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
130 SkASSERT(bm.width() == fBitmap.width());
131 SkASSERT(bm.height() == fBitmap.height());
132 fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config)
133 fBitmap.lockPixels();
reed589a39e2016-08-20 07:59:19 -0700134 this->privateResize(fBitmap.info().width(), fBitmap.info().height());
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000135}
136
reed76033be2015-03-14 10:54:31 -0700137SkBaseDevice* SkBitmapDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
robertphillips9a53fd72015-06-22 09:46:59 -0700138 const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry);
139 return SkBitmapDevice::Create(cinfo.fInfo, surfaceProps);
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000140}
141
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000142const SkBitmap& SkBitmapDevice::onAccessBitmap() {
143 return fBitmap;
144}
145
reed884e97c2015-05-26 11:31:54 -0700146bool SkBitmapDevice::onAccessPixels(SkPixmap* pmap) {
reedb560b5c2016-07-24 12:30:34 -0700147 if (this->onPeekPixels(pmap)) {
reed6e764852015-06-05 14:11:32 -0700148 fBitmap.notifyPixelsChanged();
149 return true;
150 }
151 return false;
reed9572a102015-05-26 19:22:17 -0700152}
153
154bool SkBitmapDevice::onPeekPixels(SkPixmap* pmap) {
reed884e97c2015-05-26 11:31:54 -0700155 const SkImageInfo info = fBitmap.info();
156 if (fBitmap.getPixels() && (kUnknown_SkColorType != info.colorType())) {
halcanary96fcdcc2015-08-27 07:41:13 -0700157 SkColorTable* ctable = nullptr;
reed884e97c2015-05-26 11:31:54 -0700158 pmap->reset(fBitmap.info(), fBitmap.getPixels(), fBitmap.rowBytes(), ctable);
159 return true;
reed@google.com9c135db2014-03-12 18:28:35 +0000160 }
reed884e97c2015-05-26 11:31:54 -0700161 return false;
reed@google.com9c135db2014-03-12 18:28:35 +0000162}
163
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000164bool SkBitmapDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels,
165 size_t srcRowBytes, int x, int y) {
reed@google.com0d30c512014-03-14 14:02:58 +0000166 // since we don't stop creating un-pixeled devices yet, check for no pixels here
halcanary96fcdcc2015-08-27 07:41:13 -0700167 if (nullptr == fBitmap.getPixels()) {
reed@google.com0d30c512014-03-14 14:02:58 +0000168 return false;
169 }
170
reede5ea5002014-09-03 11:54:58 -0700171 const SkImageInfo dstInfo = fBitmap.info().makeWH(srcInfo.width(), srcInfo.height());
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000172
173 void* dstPixels = fBitmap.getAddr(x, y);
174 size_t dstRowBytes = fBitmap.rowBytes();
175
reedb184f7f2014-07-13 04:32:32 -0700176 if (SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes)) {
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000177 fBitmap.notifyPixelsChanged();
178 return true;
179 }
180 return false;
181}
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000182
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000183bool SkBitmapDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
184 int x, int y) {
reedb184f7f2014-07-13 04:32:32 -0700185 return fBitmap.readPixels(dstInfo, dstPixels, dstRowBytes, x, y);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000186}
187
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000188///////////////////////////////////////////////////////////////////////////////
189
190void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
191 draw.drawPaint(paint);
192}
193
194void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
195 const SkPoint pts[], const SkPaint& paint) {
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000196 draw.drawPoints(mode, count, pts, paint);
197}
198
199void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) {
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000200 draw.drawRect(r, paint);
201}
202
203void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000204 SkPath path;
205 path.addOval(oval);
206 // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
207 // required to override drawOval.
halcanary96fcdcc2015-08-27 07:41:13 -0700208 this->drawPath(draw, path, paint, nullptr, true);
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000209}
210
211void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) {
robertphillips@google.com50a76002013-11-12 01:16:56 +0000212#ifdef SK_IGNORE_BLURRED_RRECT_OPT
213 SkPath path;
214
215 path.addRRect(rrect);
216 // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
217 // required to override drawRRect.
halcanary96fcdcc2015-08-27 07:41:13 -0700218 this->drawPath(draw, path, paint, nullptr, true);
robertphillips@google.com50a76002013-11-12 01:16:56 +0000219#else
scroggo@google.coma8e33a92013-11-08 18:02:53 +0000220 draw.drawRRect(rrect, paint);
robertphillips@google.com50a76002013-11-12 01:16:56 +0000221#endif
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000222}
223
224void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path,
225 const SkPaint& paint, const SkMatrix* prePathMatrix,
226 bool pathIsMutable) {
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000227 draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
228}
229
230void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
231 const SkMatrix& matrix, const SkPaint& paint) {
ericrk983294f2016-04-18 09:14:00 -0700232 LogDrawScaleFactor(SkMatrix::Concat(*draw.fMatrix, matrix), paint.getFilterQuality());
halcanary96fcdcc2015-08-27 07:41:13 -0700233 draw.drawBitmap(bitmap, matrix, nullptr, paint);
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000234}
235
fmalitaab83da72016-08-26 13:04:14 -0700236static inline bool CanApplyDstMatrixAsCTM(const SkMatrix& m, const SkPaint& paint) {
237 if (!paint.getMaskFilter()) {
238 return true;
239 }
240
241 // Some mask filters parameters (sigma) depend on the CTM/scale.
242 return m.getType() <= SkMatrix::kTranslate_Mask;
243}
244
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000245void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
246 const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700247 const SkPaint& paint, SkCanvas::SrcRectConstraint constraint) {
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000248 SkMatrix matrix;
249 SkRect bitmapBounds, tmpSrc, tmpDst;
250 SkBitmap tmpBitmap;
251
252 bitmapBounds.isetWH(bitmap.width(), bitmap.height());
253
254 // Compute matrix from the two rectangles
255 if (src) {
256 tmpSrc = *src;
257 } else {
258 tmpSrc = bitmapBounds;
259 }
260 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
261
ericrk983294f2016-04-18 09:14:00 -0700262 LogDrawScaleFactor(SkMatrix::Concat(*draw.fMatrix, matrix), paint.getFilterQuality());
263
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000264 const SkRect* dstPtr = &dst;
265 const SkBitmap* bitmapPtr = &bitmap;
266
267 // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
268 // needed (if the src was clipped). No check needed if src==null.
269 if (src) {
270 if (!bitmapBounds.contains(*src)) {
271 if (!tmpSrc.intersect(bitmapBounds)) {
272 return; // nothing to draw
273 }
274 // recompute dst, based on the smaller tmpSrc
275 matrix.mapRect(&tmpDst, tmpSrc);
276 dstPtr = &tmpDst;
277 }
reed27efa232016-07-25 19:10:10 -0700278 }
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000279
reed27efa232016-07-25 19:10:10 -0700280 if (src && !src->contains(bitmapBounds) &&
281 SkCanvas::kFast_SrcRectConstraint == constraint &&
282 paint.getFilterQuality() != kNone_SkFilterQuality) {
283 // src is smaller than the bounds of the bitmap, and we are filtering, so we don't know
284 // how much more of the bitmap we need, so we can't use extractSubset or drawBitmap,
285 // but we must use a shader w/ dst bounds (which can access all of the bitmap needed).
286 goto USE_SHADER;
287 }
288
289 if (src) {
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000290 // since we may need to clamp to the borders of the src rect within
291 // the bitmap, we extract a subset.
reedb07a94f2014-11-19 05:03:18 -0800292 const SkIRect srcIR = tmpSrc.roundOut();
bsalomon19fe41e2016-08-23 14:02:54 -0700293 if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
294 return;
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000295 }
296 bitmapPtr = &tmpBitmap;
297
298 // Since we did an extract, we need to adjust the matrix accordingly
299 SkScalar dx = 0, dy = 0;
300 if (srcIR.fLeft > 0) {
301 dx = SkIntToScalar(srcIR.fLeft);
302 }
303 if (srcIR.fTop > 0) {
304 dy = SkIntToScalar(srcIR.fTop);
305 }
306 if (dx || dy) {
307 matrix.preTranslate(dx, dy);
308 }
309
310 SkRect extractedBitmapBounds;
311 extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height());
312 if (extractedBitmapBounds == tmpSrc) {
313 // no fractional part in src, we can just call drawBitmap
314 goto USE_DRAWBITMAP;
315 }
316 } else {
317 USE_DRAWBITMAP:
318 // We can go faster by just calling drawBitmap, which will concat the
319 // matrix with the CTM, and try to call drawSprite if it can. If not,
320 // it will make a shader and call drawRect, as we do below.
fmalitaab83da72016-08-26 13:04:14 -0700321 if (CanApplyDstMatrixAsCTM(matrix, paint)) {
322 draw.drawBitmap(*bitmapPtr, matrix, dstPtr, paint);
323 return;
324 }
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000325 }
326
reed27efa232016-07-25 19:10:10 -0700327 USE_SHADER:
reedf77c47b2016-08-05 10:15:00 -0700328
329 // Since the shader need only live for our stack-frame, pass in a custom allocator. This
330 // can save malloc calls, and signals to SkMakeBitmapShader to not try to copy the bitmap
331 // if its mutable, since that precaution is not needed (give the short lifetime of the shader).
332 SkTBlitterAllocator allocator;
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000333 // construct a shader, so we can call drawRect with the dst
reedf77c47b2016-08-05 10:15:00 -0700334 auto s = SkMakeBitmapShader(*bitmapPtr, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
reed1ec04d92016-08-05 12:07:41 -0700335 &matrix, kNever_SkCopyPixelsMode, &allocator);
reed8a21c9f2016-03-08 18:50:00 -0800336 if (!s) {
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000337 return;
338 }
reedf77c47b2016-08-05 10:15:00 -0700339 // we deliberately add a ref, since the allocator wants to be the last owner
340 s.get()->ref();
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000341
342 SkPaint paintWithShader(paint);
343 paintWithShader.setStyle(SkPaint::kFill_Style);
reedf77c47b2016-08-05 10:15:00 -0700344 paintWithShader.setShader(s);
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000345
346 // Call ourself, in case the subclass wanted to share this setup code
347 // but handle the drawRect code themselves.
348 this->drawRect(draw, *dstPtr, paintWithShader);
349}
350
351void SkBitmapDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
352 int x, int y, const SkPaint& paint) {
353 draw.drawSprite(bitmap, x, y, paint);
354}
355
356void SkBitmapDevice::drawText(const SkDraw& draw, const void* text, size_t len,
357 SkScalar x, SkScalar y, const SkPaint& paint) {
358 draw.drawText((const char*)text, len, x, y, paint);
359}
360
361void SkBitmapDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
fmalita05c4a432014-09-29 06:29:53 -0700362 const SkScalar xpos[], int scalarsPerPos,
363 const SkPoint& offset, const SkPaint& paint) {
364 draw.drawPosText((const char*)text, len, xpos, scalarsPerPos, offset, paint);
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000365}
366
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000367void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
368 int vertexCount,
369 const SkPoint verts[], const SkPoint textures[],
370 const SkColor colors[], SkXfermode* xmode,
371 const uint16_t indices[], int indexCount,
372 const SkPaint& paint) {
373 draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
374 indices, indexCount, paint);
375}
376
377void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
378 int x, int y, const SkPaint& paint) {
reedcf5c8462016-07-20 12:28:40 -0700379 SkASSERT(!paint.getImageFilter());
reed9572a102015-05-26 19:22:17 -0700380 draw.drawSprite(static_cast<SkBitmapDevice*>(device)->fBitmap, x, y, paint);
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000381}
382
reede51c3562016-07-19 14:33:20 -0700383///////////////////////////////////////////////////////////////////////////////
384
385void SkBitmapDevice::drawSpecial(const SkDraw& draw, SkSpecialImage* srcImg, int x, int y,
386 const SkPaint& paint) {
387 SkASSERT(!srcImg->isTextureBacked());
388
389 SkBitmap resultBM;
390
391 SkImageFilter* filter = paint.getImageFilter();
392 if (filter) {
393 SkIPoint offset = SkIPoint::Make(0, 0);
394 SkMatrix matrix = *draw.fMatrix;
395 matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
396 const SkIRect clipBounds = draw.fRC->getBounds().makeOffset(-x, -y);
397 SkAutoTUnref<SkImageFilterCache> cache(this->getImageFilterCache());
brianosman2a75e5d2016-09-22 07:15:37 -0700398 SkImageFilter::OutputProperties outputProperties(fBitmap.colorSpace());
399 SkImageFilter::Context ctx(matrix, clipBounds, cache.get(), outputProperties);
liyuqian2add0ff2016-10-20 11:04:39 -0700400
reede51c3562016-07-19 14:33:20 -0700401 sk_sp<SkSpecialImage> resultImg(filter->filterImage(srcImg, ctx, &offset));
402 if (resultImg) {
403 SkPaint tmpUnfiltered(paint);
404 tmpUnfiltered.setImageFilter(nullptr);
405 if (resultImg->getROPixels(&resultBM)) {
406 this->drawSprite(draw, resultBM, x + offset.x(), y + offset.y(), tmpUnfiltered);
407 }
408 }
409 } else {
410 if (srcImg->getROPixels(&resultBM)) {
411 this->drawSprite(draw, resultBM, x, y, paint);
412 }
413 }
414}
415
416sk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkBitmap& bitmap) {
417 return SkSpecialImage::MakeFromRaster(bitmap.bounds(), bitmap);
418}
419
420sk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkImage* image) {
421 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(image->width(), image->height()),
422 image->makeNonTextureImage());
423}
424
425sk_sp<SkSpecialImage> SkBitmapDevice::snapSpecial() {
426 return this->makeSpecial(fBitmap);
427}
428
429///////////////////////////////////////////////////////////////////////////////
430
reede8f30622016-03-23 18:59:25 -0700431sk_sp<SkSurface> SkBitmapDevice::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
432 return SkSurface::MakeRaster(info, &props);
reed@google.com76f10a32014-02-05 15:32:21 +0000433}
434
senorblanco900c3672016-04-27 11:31:23 -0700435SkImageFilterCache* SkBitmapDevice::getImageFilterCache() {
436 SkImageFilterCache* cache = SkImageFilterCache::Get();
senorblanco55b6d8b2014-07-30 11:26:46 -0700437 cache->ref();
438 return cache;
439}
440
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000441///////////////////////////////////////////////////////////////////////////////
442
reedb2db8982014-11-13 12:41:02 -0800443bool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const {
commit-bot@chromium.orgcba73782014-05-29 15:57:47 +0000444 if (kN32_SkColorType != fBitmap.colorType() ||
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000445 paint.getRasterizer() ||
446 paint.getPathEffect() ||
447 paint.isFakeBoldText() ||
448 paint.getStyle() != SkPaint::kFill_Style ||
reed374772b2016-10-05 17:33:02 -0700449 !paint.isSrcOver())
reedb2db8982014-11-13 12:41:02 -0800450 {
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000451 return true;
452 }
robertphillips@google.com53238bc2013-08-30 13:12:10 +0000453 return false;
454}