• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "SkDraw.h"
10 #include "SkImageFilter.h"
11 #include "SkImageFilterCache.h"
12 #include "SkMallocPixelRef.h"
13 #include "SkMatrix.h"
14 #include "SkPaint.h"
15 #include "SkPath.h"
16 #include "SkPixelRef.h"
17 #include "SkPixmap.h"
18 #include "SkRasterClip.h"
19 #include "SkRasterHandleAllocator.h"
20 #include "SkShader.h"
21 #include "SkSpecialImage.h"
22 #include "SkSurface.h"
23 #include "SkTLazy.h"
24 #include "SkVertices.h"
25 
26 class SkColorTable;
27 
valid_for_bitmap_device(const SkImageInfo & info,SkAlphaType * newAlphaType)28 static bool valid_for_bitmap_device(const SkImageInfo& info,
29                                     SkAlphaType* newAlphaType) {
30     if (info.width() < 0 || info.height() < 0) {
31         return false;
32     }
33 
34     // TODO: can we stop supporting kUnknown in SkBitmkapDevice?
35     if (kUnknown_SkColorType == info.colorType()) {
36         if (newAlphaType) {
37             *newAlphaType = kUnknown_SkAlphaType;
38         }
39         return true;
40     }
41 
42     SkAlphaType canonicalAlphaType = info.alphaType();
43 
44     switch (info.colorType()) {
45         case kAlpha_8_SkColorType:
46         case kARGB_4444_SkColorType:
47         case kRGBA_8888_SkColorType:
48         case kBGRA_8888_SkColorType:
49         case kRGBA_1010102_SkColorType:
50         case kRGBA_F16_SkColorType:
51             break;
52         case kGray_8_SkColorType:
53         case kRGB_565_SkColorType:
54         case kRGB_888x_SkColorType:
55         case kRGB_101010x_SkColorType:
56             canonicalAlphaType = kOpaque_SkAlphaType;
57             break;
58         default:
59             return false;
60     }
61 
62     if (newAlphaType) {
63         *newAlphaType = canonicalAlphaType;
64     }
65     return true;
66 }
67 
SkBitmapDevice(const SkBitmap & bitmap)68 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
69     : INHERITED(bitmap.info(), SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType))
70     , fBitmap(bitmap)
71     , fRCStack(bitmap.width(), bitmap.height())
72 {
73     SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
74 }
75 
Create(const SkImageInfo & info)76 SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& info) {
77     return Create(info, SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType));
78 }
79 
SkBitmapDevice(const SkBitmap & bitmap,const SkSurfaceProps & surfaceProps,SkRasterHandleAllocator::Handle hndl)80 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkSurfaceProps& surfaceProps,
81                                SkRasterHandleAllocator::Handle hndl)
82     : INHERITED(bitmap.info(), surfaceProps)
83     , fBitmap(bitmap)
84     , fRasterHandle(hndl)
85     , fRCStack(bitmap.width(), bitmap.height())
86 {
87     SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
88 }
89 
Create(const SkImageInfo & origInfo,const SkSurfaceProps & surfaceProps,SkRasterHandleAllocator * allocator)90 SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
91                                        const SkSurfaceProps& surfaceProps,
92                                        SkRasterHandleAllocator* allocator) {
93     SkAlphaType newAT = origInfo.alphaType();
94     if (!valid_for_bitmap_device(origInfo, &newAT)) {
95         return nullptr;
96     }
97 
98     SkRasterHandleAllocator::Handle hndl = nullptr;
99     const SkImageInfo info = origInfo.makeAlphaType(newAT);
100     SkBitmap bitmap;
101 
102     if (kUnknown_SkColorType == info.colorType()) {
103         if (!bitmap.setInfo(info)) {
104             return nullptr;
105         }
106     } else if (allocator) {
107         hndl = allocator->allocBitmap(info, &bitmap);
108         if (!hndl) {
109             return nullptr;
110         }
111     } else if (info.isOpaque()) {
112         // If this bitmap is opaque, we don't have any sensible default color,
113         // so we just return uninitialized pixels.
114         if (!bitmap.tryAllocPixels(info)) {
115             return nullptr;
116         }
117     } else {
118         // This bitmap has transparency, so we'll zero the pixels (to transparent).
119         // We use the flag as a faster alloc-then-eraseColor(SK_ColorTRANSPARENT).
120         if (!bitmap.tryAllocPixelsFlags(info, SkBitmap::kZeroPixels_AllocFlag)) {
121             return nullptr;
122         }
123     }
124 
125     return new SkBitmapDevice(bitmap, surfaceProps, hndl);
126 }
127 
replaceBitmapBackendForRasterSurface(const SkBitmap & bm)128 void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
129     SkASSERT(bm.width() == fBitmap.width());
130     SkASSERT(bm.height() == fBitmap.height());
131     fBitmap = bm;   // intent is to use bm's pixelRef (and rowbytes/config)
132     this->privateResize(fBitmap.info().width(), fBitmap.info().height());
133 }
134 
onCreateDevice(const CreateInfo & cinfo,const SkPaint *)135 SkBaseDevice* SkBitmapDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) {
136     const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry);
137     return SkBitmapDevice::Create(cinfo.fInfo, surfaceProps, cinfo.fAllocator);
138 }
139 
onAccessPixels(SkPixmap * pmap)140 bool SkBitmapDevice::onAccessPixels(SkPixmap* pmap) {
141     if (this->onPeekPixels(pmap)) {
142         fBitmap.notifyPixelsChanged();
143         return true;
144     }
145     return false;
146 }
147 
onPeekPixels(SkPixmap * pmap)148 bool SkBitmapDevice::onPeekPixels(SkPixmap* pmap) {
149     const SkImageInfo info = fBitmap.info();
150     if (fBitmap.getPixels() && (kUnknown_SkColorType != info.colorType())) {
151         pmap->reset(fBitmap.info(), fBitmap.getPixels(), fBitmap.rowBytes());
152         return true;
153     }
154     return false;
155 }
156 
onWritePixels(const SkPixmap & pm,int x,int y)157 bool SkBitmapDevice::onWritePixels(const SkPixmap& pm, int x, int y) {
158     // since we don't stop creating un-pixeled devices yet, check for no pixels here
159     if (nullptr == fBitmap.getPixels()) {
160         return false;
161     }
162 
163     if (fBitmap.writePixels(pm, x, y)) {
164         fBitmap.notifyPixelsChanged();
165         return true;
166     }
167     return false;
168 }
169 
onReadPixels(const SkPixmap & pm,int x,int y)170 bool SkBitmapDevice::onReadPixels(const SkPixmap& pm, int x, int y) {
171     return fBitmap.readPixels(pm, x, y);
172 }
173 
174 ///////////////////////////////////////////////////////////////////////////////
175 
176 class SkBitmapDevice::BDDraw : public SkDraw {
177 public:
BDDraw(SkBitmapDevice * dev)178     BDDraw(SkBitmapDevice* dev) {
179         // we need fDst to be set, and if we're actually drawing, to dirty the genID
180         if (!dev->accessPixels(&fDst)) {
181             // NoDrawDevice uses us (why?) so we have to catch this case w/ no pixels
182             fDst.reset(dev->imageInfo(), nullptr, 0);
183         }
184         fMatrix = &dev->ctm();
185         fRC = &dev->fRCStack.rc();
186     }
187 };
188 
drawPaint(const SkPaint & paint)189 void SkBitmapDevice::drawPaint(const SkPaint& paint) {
190     BDDraw(this).drawPaint(paint);
191 }
192 
drawPoints(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)193 void SkBitmapDevice::drawPoints(SkCanvas::PointMode mode, size_t count,
194                                 const SkPoint pts[], const SkPaint& paint) {
195     BDDraw(this).drawPoints(mode, count, pts, paint, nullptr);
196 }
197 
drawRect(const SkRect & r,const SkPaint & paint)198 void SkBitmapDevice::drawRect(const SkRect& r, const SkPaint& paint) {
199     BDDraw(this).drawRect(r, paint);
200 }
201 
drawOval(const SkRect & oval,const SkPaint & paint)202 void SkBitmapDevice::drawOval(const SkRect& oval, const SkPaint& paint) {
203     SkPath path;
204     path.addOval(oval);
205     // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
206     // required to override drawOval.
207     this->drawPath(path, paint, nullptr, true);
208 }
209 
drawRRect(const SkRRect & rrect,const SkPaint & paint)210 void SkBitmapDevice::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
211 #ifdef SK_IGNORE_BLURRED_RRECT_OPT
212     SkPath  path;
213 
214     path.addRRect(rrect);
215     // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
216     // required to override drawRRect.
217     this->drawPath(path, paint, nullptr, true);
218 #else
219     BDDraw(this).drawRRect(rrect, paint);
220 #endif
221 }
222 
drawPath(const SkPath & path,const SkPaint & paint,const SkMatrix * prePathMatrix,bool pathIsMutable)223 void SkBitmapDevice::drawPath(const SkPath& path,
224                               const SkPaint& paint, const SkMatrix* prePathMatrix,
225                               bool pathIsMutable) {
226     BDDraw(this).drawPath(path, paint, prePathMatrix, pathIsMutable);
227 }
228 
drawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint & paint)229 void SkBitmapDevice::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
230                                 const SkPaint& paint) {
231     SkMatrix matrix = SkMatrix::MakeTrans(x, y);
232     LogDrawScaleFactor(SkMatrix::Concat(this->ctm(), matrix), paint.getFilterQuality());
233     BDDraw(this).drawBitmap(bitmap, matrix, nullptr, paint);
234 }
235 
CanApplyDstMatrixAsCTM(const SkMatrix & m,const SkPaint & paint)236 static 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 
drawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint & paint,SkCanvas::SrcRectConstraint constraint)245 void SkBitmapDevice::drawBitmapRect(const SkBitmap& bitmap,
246                                     const SkRect* src, const SkRect& dst,
247                                     const SkPaint& paint, SkCanvas::SrcRectConstraint constraint) {
248     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 
262     LogDrawScaleFactor(SkMatrix::Concat(this->ctm(), matrix), paint.getFilterQuality());
263 
264     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         }
278     }
279 
280     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) {
290         // since we may need to clamp to the borders of the src rect within
291         // the bitmap, we extract a subset.
292         const SkIRect srcIR = tmpSrc.roundOut();
293         if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
294             return;
295         }
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 #ifdef SK_DRAWBITMAPRECT_FAST_OFFSET
311         SkRect extractedBitmapBounds = SkRect::MakeXYWH(dx, dy,
312                                                         SkIntToScalar(bitmapPtr->width()),
313                                                         SkIntToScalar(bitmapPtr->height()));
314 #else
315         SkRect extractedBitmapBounds;
316         extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height());
317 #endif
318         if (extractedBitmapBounds == tmpSrc) {
319             // no fractional part in src, we can just call drawBitmap
320             goto USE_DRAWBITMAP;
321         }
322     } else {
323         USE_DRAWBITMAP:
324         // We can go faster by just calling drawBitmap, which will concat the
325         // matrix with the CTM, and try to call drawSprite if it can. If not,
326         // it will make a shader and call drawRect, as we do below.
327         if (CanApplyDstMatrixAsCTM(matrix, paint)) {
328             BDDraw(this).drawBitmap(*bitmapPtr, matrix, dstPtr, paint);
329             return;
330         }
331     }
332 
333     USE_SHADER:
334 
335     // TODO(herb): Move this over to SkArenaAlloc when arena alloc has a facility to return sk_sps.
336     // Since the shader need only live for our stack-frame, pass in a custom allocator. This
337     // can save malloc calls, and signals to SkMakeBitmapShader to not try to copy the bitmap
338     // if its mutable, since that precaution is not needed (give the short lifetime of the shader).
339 
340     // construct a shader, so we can call drawRect with the dst
341     auto s = SkMakeBitmapShader(*bitmapPtr, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
342                                 &matrix, kNever_SkCopyPixelsMode);
343     if (!s) {
344         return;
345     }
346 
347     SkPaint paintWithShader(paint);
348     paintWithShader.setStyle(SkPaint::kFill_Style);
349     paintWithShader.setShader(s);
350 
351     // Call ourself, in case the subclass wanted to share this setup code
352     // but handle the drawRect code themselves.
353     this->drawRect(*dstPtr, paintWithShader);
354 }
355 
drawSprite(const SkBitmap & bitmap,int x,int y,const SkPaint & paint)356 void SkBitmapDevice::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& paint) {
357     BDDraw(this).drawSprite(bitmap, x, y, paint);
358 }
359 
drawText(const void * text,size_t len,SkScalar x,SkScalar y,const SkPaint & paint)360 void SkBitmapDevice::drawText(const void* text, size_t len,
361                               SkScalar x, SkScalar y, const SkPaint& paint) {
362     BDDraw(this).drawText((const char*)text, len, x, y, paint, &fSurfaceProps);
363 }
364 
drawPosText(const void * text,size_t len,const SkScalar xpos[],int scalarsPerPos,const SkPoint & offset,const SkPaint & paint)365 void SkBitmapDevice::drawPosText(const void* text, size_t len, const SkScalar xpos[],
366                                  int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) {
367     BDDraw(this).drawPosText((const char*)text, len, xpos, scalarsPerPos, offset, paint,
368                              &fSurfaceProps);
369 }
370 
drawVertices(const SkVertices * vertices,SkBlendMode bmode,const SkPaint & paint)371 void SkBitmapDevice::drawVertices(const SkVertices* vertices, SkBlendMode bmode,
372                                   const SkPaint& paint) {
373     BDDraw(this).drawVertices(vertices->mode(), vertices->vertexCount(), vertices->positions(),
374                               vertices->texCoords(), vertices->colors(), bmode,
375                               vertices->indices(), vertices->indexCount(), paint);
376 }
377 
drawDevice(SkBaseDevice * device,int x,int y,const SkPaint & origPaint)378 void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPaint& origPaint) {
379     SkASSERT(!origPaint.getImageFilter());
380 
381     // todo: can we unify with similar adjustment in SkGpuDevice?
382     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
383     if (paint->getMaskFilter()) {
384         paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm()));
385     }
386 
387     BDDraw(this).drawSprite(static_cast<SkBitmapDevice*>(device)->fBitmap, x, y, *paint);
388 }
389 
390 ///////////////////////////////////////////////////////////////////////////////
391 
392 namespace {
393 
394 class SkAutoDeviceClipRestore {
395 public:
SkAutoDeviceClipRestore(SkBaseDevice * device,const SkIRect & clip)396     SkAutoDeviceClipRestore(SkBaseDevice* device, const SkIRect& clip)
397         : fDevice(device)
398         , fPrevCTM(device->ctm()) {
399         fDevice->save();
400         fDevice->setCTM(SkMatrix::I());
401         fDevice->clipRect(SkRect::Make(clip), SkClipOp::kIntersect, false);
402         fDevice->setCTM(fPrevCTM);
403     }
404 
~SkAutoDeviceClipRestore()405     ~SkAutoDeviceClipRestore() {
406         fDevice->restore(fPrevCTM);
407     }
408 
409 private:
410     SkBaseDevice*  fDevice;
411     const SkMatrix fPrevCTM;
412 };
413 
414 }  // anonymous ns
415 
drawSpecial(SkSpecialImage * src,int x,int y,const SkPaint & origPaint,SkImage * clipImage,const SkMatrix & clipMatrix)416 void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPaint& origPaint,
417                                  SkImage* clipImage, const SkMatrix& clipMatrix) {
418     SkASSERT(!src->isTextureBacked());
419 
420     sk_sp<SkSpecialImage> filteredImage;
421     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
422 
423     if (SkImageFilter* filter = paint->getImageFilter()) {
424         SkIPoint offset = SkIPoint::Make(0, 0);
425         const SkMatrix matrix = SkMatrix::Concat(
426             SkMatrix::MakeTrans(SkIntToScalar(-x), SkIntToScalar(-y)), this->ctm());
427         const SkIRect clipBounds = fRCStack.rc().getBounds().makeOffset(-x, -y);
428         sk_sp<SkImageFilterCache> cache(this->getImageFilterCache());
429         SkImageFilter::OutputProperties outputProperties(fBitmap.colorSpace());
430         SkImageFilter::Context ctx(matrix, clipBounds, cache.get(), outputProperties);
431 
432         filteredImage = filter->filterImage(src, ctx, &offset);
433         if (!filteredImage) {
434             return;
435         }
436 
437         src = filteredImage.get();
438         paint.writable()->setImageFilter(nullptr);
439         x += offset.x();
440         y += offset.y();
441     }
442 
443     if (paint->getMaskFilter()) {
444         paint.writable()->setMaskFilter(paint->getMaskFilter()->makeWithLocalMatrix(this->ctm()));
445     }
446 
447     if (!clipImage) {
448         SkBitmap resultBM;
449         if (src->getROPixels(&resultBM)) {
450             this->drawSprite(resultBM, x, y, *paint);
451         }
452         return;
453     }
454 
455     // Clip image case.
456     sk_sp<SkImage> srcImage(src->asImage());
457     if (!srcImage) {
458         return;
459     }
460 
461     const SkMatrix totalMatrix = SkMatrix::Concat(this->ctm(), clipMatrix);
462     SkRect clipBounds;
463     totalMatrix.mapRect(&clipBounds, SkRect::Make(clipImage->bounds()));
464     const SkIRect srcBounds = srcImage->bounds().makeOffset(x, y);
465 
466     SkIRect maskBounds = fRCStack.rc().getBounds();
467     if (!maskBounds.intersect(clipBounds.roundOut()) || !maskBounds.intersect(srcBounds)) {
468         return;
469     }
470 
471     sk_sp<SkImage> mask;
472     SkMatrix maskMatrix, shaderMatrix;
473     SkTLazy<SkAutoDeviceClipRestore> autoClipRestore;
474 
475     SkMatrix totalInverse;
476     if (clipImage->isAlphaOnly() && totalMatrix.invert(&totalInverse)) {
477         // If the mask is already in A8 format, we can draw it directly
478         // (while compensating in the shader matrix).
479         mask = sk_ref_sp(clipImage);
480         maskMatrix = totalMatrix;
481         shaderMatrix = SkMatrix::Concat(totalInverse, SkMatrix::MakeTrans(x, y));
482 
483         // If the mask is not fully contained within the src layer, we must clip.
484         if (!srcBounds.contains(clipBounds)) {
485             autoClipRestore.init(this, srcBounds);
486         }
487 
488         maskBounds.offsetTo(0, 0);
489     } else {
490         // Otherwise, we convert the mask to A8 explicitly.
491         sk_sp<SkSurface> surf = SkSurface::MakeRaster(SkImageInfo::MakeA8(maskBounds.width(),
492                                                                           maskBounds.height()));
493         SkCanvas* canvas = surf->getCanvas();
494         canvas->translate(-maskBounds.x(), -maskBounds.y());
495         canvas->concat(totalMatrix);
496         canvas->drawImage(clipImage, 0, 0);
497 
498         mask = surf->makeImageSnapshot();
499         maskMatrix = SkMatrix::I();
500         shaderMatrix = SkMatrix::MakeTrans(x - maskBounds.x(), y - maskBounds.y());
501     }
502 
503     SkAutoDeviceCTMRestore adctmr(this, maskMatrix);
504     paint.writable()->setShader(srcImage->makeShader(&shaderMatrix));
505     this->drawImage(mask.get(), maskBounds.x(), maskBounds.y(), *paint);
506 }
507 
makeSpecial(const SkBitmap & bitmap)508 sk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkBitmap& bitmap) {
509     return SkSpecialImage::MakeFromRaster(bitmap.bounds(), bitmap);
510 }
511 
makeSpecial(const SkImage * image)512 sk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkImage* image) {
513     return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(image->width(), image->height()),
514                                          image->makeNonTextureImage(), fBitmap.colorSpace());
515 }
516 
snapSpecial()517 sk_sp<SkSpecialImage> SkBitmapDevice::snapSpecial() {
518     return this->makeSpecial(fBitmap);
519 }
520 
521 ///////////////////////////////////////////////////////////////////////////////
522 
makeSurface(const SkImageInfo & info,const SkSurfaceProps & props)523 sk_sp<SkSurface> SkBitmapDevice::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
524     return SkSurface::MakeRaster(info, &props);
525 }
526 
getImageFilterCache()527 SkImageFilterCache* SkBitmapDevice::getImageFilterCache() {
528     SkImageFilterCache* cache = SkImageFilterCache::Get();
529     cache->ref();
530     return cache;
531 }
532 
533 ///////////////////////////////////////////////////////////////////////////////////////////////////
534 
onShouldDisableLCD(const SkPaint & paint) const535 bool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const {
536     if (kN32_SkColorType != fBitmap.colorType() ||
537         paint.getPathEffect() ||
538         paint.isFakeBoldText() ||
539         paint.getStyle() != SkPaint::kFill_Style ||
540         !paint.isSrcOver())
541     {
542         return true;
543     }
544     return false;
545 }
546 
547 ///////////////////////////////////////////////////////////////////////////////////////////////////
548 
onSave()549 void SkBitmapDevice::onSave() {
550     fRCStack.save();
551 }
552 
onRestore()553 void SkBitmapDevice::onRestore() {
554     fRCStack.restore();
555 }
556 
onClipRect(const SkRect & rect,SkClipOp op,bool aa)557 void SkBitmapDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) {
558     fRCStack.clipRect(this->ctm(), rect, op, aa);
559 }
560 
onClipRRect(const SkRRect & rrect,SkClipOp op,bool aa)561 void SkBitmapDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
562     fRCStack.clipRRect(this->ctm(), rrect, op, aa);
563 }
564 
onClipPath(const SkPath & path,SkClipOp op,bool aa)565 void SkBitmapDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) {
566     fRCStack.clipPath(this->ctm(), path, op, aa);
567 }
568 
onClipRegion(const SkRegion & rgn,SkClipOp op)569 void SkBitmapDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) {
570     SkIPoint origin = this->getOrigin();
571     SkRegion tmp;
572     const SkRegion* ptr = &rgn;
573     if (origin.fX | origin.fY) {
574         // translate from "global/canvas" coordinates to relative to this device
575         rgn.translate(-origin.fX, -origin.fY, &tmp);
576         ptr = &tmp;
577     }
578     fRCStack.clipRegion(*ptr, op);
579 }
580 
onSetDeviceClipRestriction(SkIRect * mutableClipRestriction)581 void SkBitmapDevice::onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) {
582     fRCStack.setDeviceClipRestriction(mutableClipRestriction);
583     if (!mutableClipRestriction->isEmpty()) {
584         SkRegion rgn(*mutableClipRestriction);
585         fRCStack.clipRegion(rgn, SkClipOp::kIntersect);
586     }
587 }
588 
onClipIsAA() const589 bool SkBitmapDevice::onClipIsAA() const {
590     const SkRasterClip& rc = fRCStack.rc();
591     return !rc.isEmpty() && rc.isAA();
592 }
593 
onAsRgnClip(SkRegion * rgn) const594 void SkBitmapDevice::onAsRgnClip(SkRegion* rgn) const {
595     const SkRasterClip& rc = fRCStack.rc();
596     if (rc.isAA()) {
597         rgn->setRect(rc.getBounds());
598     } else {
599         *rgn = rc.bwRgn();
600     }
601 }
602 
validateDevBounds(const SkIRect & drawClipBounds)603 void SkBitmapDevice::validateDevBounds(const SkIRect& drawClipBounds) {
604 #ifdef SK_DEBUG
605     const SkIRect& stackBounds = fRCStack.rc().getBounds();
606     SkASSERT(drawClipBounds == stackBounds);
607 #endif
608 }
609 
onGetClipType() const610 SkBaseDevice::ClipType SkBitmapDevice::onGetClipType() const {
611     const SkRasterClip& rc = fRCStack.rc();
612     if (rc.isEmpty()) {
613         return kEmpty_ClipType;
614     } else if (rc.isRect()) {
615         return kRect_ClipType;
616     } else {
617         return kComplex_ClipType;
618     }
619 }
620