xref: /aosp_15_r20/external/skia/src/core/SkBitmap.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2008 The Android Open Source Project
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 "include/core/SkBitmap.h"
9 
10 #include "include/core/SkColorSpace.h" // IWYU pragma: keep
11 #include "include/core/SkColorType.h"
12 #include "include/core/SkImage.h"
13 #include "include/core/SkMallocPixelRef.h"
14 #include "include/core/SkMatrix.h"
15 #include "include/core/SkPaint.h"
16 #include "include/core/SkPixelRef.h"
17 #include "include/core/SkRect.h"
18 #include "include/core/SkShader.h"
19 #include "include/core/SkTileMode.h"
20 #include "include/private/base/SkAlign.h"
21 #include "include/private/base/SkTFitsIn.h"
22 #include "include/private/base/SkTemplates.h"
23 #include "include/private/base/SkTo.h"
24 #include "src/core/SkConvertPixels.h"
25 #include "src/core/SkImageInfoPriv.h"
26 #include "src/core/SkImagePriv.h"
27 #include "src/core/SkMask.h"
28 #include "src/core/SkMaskFilterBase.h"
29 #include "src/core/SkMipmap.h"
30 #include "src/core/SkPixelRefPriv.h"
31 #include "src/core/SkWritePixelsRec.h"
32 #include "src/shaders/SkImageShader.h"
33 
34 #include <cstring>
35 #include <utility>
36 class SkMaskFilter;
37 
reset_return_false(SkBitmap * bm)38 static bool reset_return_false(SkBitmap* bm) {
39     bm->reset();
40     return false;
41 }
42 
SkBitmap()43 SkBitmap::SkBitmap() {}
44 
SkBitmap(const SkBitmap & src)45 SkBitmap::SkBitmap(const SkBitmap& src)
46     : fPixelRef      (src.fPixelRef)
47     , fPixmap        (src.fPixmap)
48     , fMips          (src.fMips)
49 {
50     SkDEBUGCODE(src.validate();)
51     SkDEBUGCODE(this->validate();)
52 }
53 
SkBitmap(SkBitmap && other)54 SkBitmap::SkBitmap(SkBitmap&& other)
55     : fPixelRef      (std::move(other.fPixelRef))
56     , fPixmap        (std::move(other.fPixmap))
57     , fMips          (std::move(other.fMips))
58 {
59     SkASSERT(!other.fPixelRef);
60     other.fPixmap.reset();
61 }
62 
~SkBitmap()63 SkBitmap::~SkBitmap() {}
64 
operator =(const SkBitmap & src)65 SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
66     if (this != &src) {
67         fPixelRef       = src.fPixelRef;
68         fPixmap         = src.fPixmap;
69         fMips           = src.fMips;
70     }
71     SkDEBUGCODE(this->validate();)
72     return *this;
73 }
74 
operator =(SkBitmap && other)75 SkBitmap& SkBitmap::operator=(SkBitmap&& other) {
76     if (this != &other) {
77         fPixelRef       = std::move(other.fPixelRef);
78         fPixmap         = std::move(other.fPixmap);
79         fMips           = std::move(other.fMips);
80         SkASSERT(!other.fPixelRef);
81         other.fPixmap.reset();
82     }
83     return *this;
84 }
85 
swap(SkBitmap & other)86 void SkBitmap::swap(SkBitmap& other) {
87     using std::swap;
88     swap(*this, other);
89     SkDEBUGCODE(this->validate();)
90 }
91 
reset()92 void SkBitmap::reset() {
93     fPixelRef = nullptr;  // Free pixels.
94     fPixmap.reset();
95     fMips.reset();
96 }
97 
getBounds(SkRect * bounds) const98 void SkBitmap::getBounds(SkRect* bounds) const {
99     SkASSERT(bounds);
100     *bounds = SkRect::Make(this->dimensions());
101 }
102 
getBounds(SkIRect * bounds) const103 void SkBitmap::getBounds(SkIRect* bounds) const {
104     SkASSERT(bounds);
105     *bounds = fPixmap.bounds();
106 }
107 
colorSpace() const108 SkColorSpace* SkBitmap::colorSpace() const { return fPixmap.colorSpace(); }
109 
refColorSpace() const110 sk_sp<SkColorSpace> SkBitmap::refColorSpace() const { return fPixmap.info().refColorSpace(); }
111 
112 ///////////////////////////////////////////////////////////////////////////////
113 
setInfo(const SkImageInfo & info,size_t rowBytes)114 bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) {
115     SkAlphaType newAT = info.alphaType();
116     if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) {
117         return reset_return_false(this);
118     }
119     // don't look at info.alphaType(), since newAT is the real value...
120 
121     // require that rowBytes fit in 31bits
122     int64_t mrb = info.minRowBytes64();
123     if (!SkTFitsIn<int32_t>(mrb)) {
124         return reset_return_false(this);
125     }
126     if (!SkTFitsIn<int32_t>(rowBytes)) {
127         return reset_return_false(this);
128     }
129 
130     if (info.width() < 0 || info.height() < 0) {
131         return reset_return_false(this);
132     }
133 
134     if (kUnknown_SkColorType == info.colorType()) {
135         rowBytes = 0;
136     } else if (0 == rowBytes) {
137         rowBytes = (size_t)mrb;
138     } else if (!info.validRowBytes(rowBytes)) {
139         return reset_return_false(this);
140     }
141 
142     fPixelRef = nullptr;  // Free pixels.
143     fPixmap.reset(info.makeAlphaType(newAT), nullptr, SkToU32(rowBytes));
144     SkDEBUGCODE(this->validate();)
145     return true;
146 }
147 
setAlphaType(SkAlphaType newAlphaType)148 bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) {
149     if (!SkColorTypeValidateAlphaType(this->colorType(), newAlphaType, &newAlphaType)) {
150         return false;
151     }
152     if (this->alphaType() != newAlphaType) {
153         auto newInfo = fPixmap.info().makeAlphaType(newAlphaType);
154         fPixmap.reset(std::move(newInfo), fPixmap.addr(), fPixmap.rowBytes());
155     }
156     SkDEBUGCODE(this->validate();)
157     return true;
158 }
159 
setColorSpace(sk_sp<SkColorSpace> newColorSpace)160 void SkBitmap::setColorSpace(sk_sp<SkColorSpace> newColorSpace) {
161     if (this->colorSpace() != newColorSpace.get()) {
162         SkImageInfo newInfo = fPixmap.info().makeColorSpace(std::move(newColorSpace));
163         fPixmap.reset(std::move(newInfo), fPixmap.addr(), fPixmap.rowBytes());
164     }
165     SkDEBUGCODE(this->validate();)
166 }
167 
pixelRefOrigin() const168 SkIPoint SkBitmap::pixelRefOrigin() const {
169     const char* addr = (const char*)fPixmap.addr();
170     const char* pix = (const char*)(fPixelRef ? fPixelRef->pixels() : nullptr);
171     size_t rb = this->rowBytes();
172     if (!pix || 0 == rb) {
173         return {0, 0};
174     }
175     SkASSERT(this->bytesPerPixel() > 0);
176     SkASSERT(this->bytesPerPixel() == (1 << this->shiftPerPixel()));
177     SkASSERT(addr >= pix);
178     size_t off = addr - pix;
179     return {SkToS32((off % rb) >> this->shiftPerPixel()), SkToS32(off / rb)};
180 }
181 
setPixelRef(sk_sp<SkPixelRef> pr,int dx,int dy)182 void SkBitmap::setPixelRef(sk_sp<SkPixelRef> pr, int dx, int dy) {
183 #ifdef SK_DEBUG
184     if (pr) {
185         if (kUnknown_SkColorType != this->colorType()) {
186             SkASSERT(dx >= 0 && this->width() + dx <= pr->width());
187             SkASSERT(dy >= 0 && this->height() + dy <= pr->height());
188         }
189     }
190 #endif
191     fPixelRef = kUnknown_SkColorType != this->colorType() ? std::move(pr) : nullptr;
192     void* p = nullptr;
193     size_t rowBytes = this->rowBytes();
194     // ignore dx,dy if there is no pixelref
195     if (fPixelRef) {
196         rowBytes = fPixelRef->rowBytes();
197         // TODO(reed):  Enforce that PixelRefs must have non-null pixels.
198         p = fPixelRef->pixels();
199         if (p) {
200             p = (char*)p + dy * rowBytes + dx * this->bytesPerPixel();
201         }
202     }
203     fPixmap.reset(fPixmap.info(), p, rowBytes);
204     SkDEBUGCODE(this->validate();)
205 }
206 
setPixels(void * p)207 void SkBitmap::setPixels(void* p) {
208     if (kUnknown_SkColorType == this->colorType()) {
209         p = nullptr;
210     }
211     size_t rb = this->rowBytes();
212     fPixmap.reset(fPixmap.info(), p, rb);
213     fPixelRef = p ? sk_make_sp<SkPixelRef>(this->width(), this->height(), p, rb) : nullptr;
214     SkDEBUGCODE(this->validate();)
215 }
216 
tryAllocPixels(Allocator * allocator)217 bool SkBitmap::tryAllocPixels(Allocator* allocator) {
218     HeapAllocator stdalloc;
219 
220     if (nullptr == allocator) {
221         allocator = &stdalloc;
222     }
223     return allocator->allocPixelRef(this);
224 }
225 
tryAllocN32Pixels(int width,int height,bool isOpaque)226 bool SkBitmap::tryAllocN32Pixels(int width, int height, bool isOpaque) {
227     SkImageInfo info = SkImageInfo::MakeN32(width, height,
228             isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
229     return this->tryAllocPixels(info);
230 }
231 
allocN32Pixels(int width,int height,bool isOpaque)232 void SkBitmap::allocN32Pixels(int width, int height, bool isOpaque) {
233     SkImageInfo info = SkImageInfo::MakeN32(width, height,
234                                         isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
235     this->allocPixels(info);
236 }
237 
allocPixels()238 void SkBitmap::allocPixels() {
239     this->allocPixels((Allocator*)nullptr);
240 }
241 
allocPixels(Allocator * allocator)242 void SkBitmap::allocPixels(Allocator* allocator) {
243     if (!this->tryAllocPixels(allocator)) {
244         const SkImageInfo& info = this->info();
245         SK_ABORT("SkBitmap::tryAllocPixels failed "
246                  "ColorType:%d AlphaType:%d [w:%d h:%d] rb:%zu",
247                  info.colorType(), info.alphaType(), info.width(), info.height(), this->rowBytes());
248     }
249 }
250 
allocPixelsFlags(const SkImageInfo & info,uint32_t flags)251 void SkBitmap::allocPixelsFlags(const SkImageInfo& info, uint32_t flags) {
252     SkASSERTF_RELEASE(this->tryAllocPixelsFlags(info, flags),
253                       "ColorType:%d AlphaType:%d [w:%d h:%d] rb:%zu flags: 0x%x",
254                       info.colorType(), info.alphaType(), info.width(), info.height(),
255                       this->rowBytes(), flags);
256 }
257 
allocPixels(const SkImageInfo & info,size_t rowBytes)258 void SkBitmap::allocPixels(const SkImageInfo& info, size_t rowBytes) {
259     SkASSERTF_RELEASE(this->tryAllocPixels(info, rowBytes),
260                       "ColorType:%d AlphaType:%d [w:%d h:%d] rb:%zu",
261                       info.colorType(), info.alphaType(), info.width(), info.height(),
262                       this->rowBytes());
263 }
264 
allocPixels(const SkImageInfo & info)265 void SkBitmap::allocPixels(const SkImageInfo& info) {
266     this->allocPixels(info, info.minRowBytes());
267 }
268 
269 ///////////////////////////////////////////////////////////////////////////////
270 
tryAllocPixels(const SkImageInfo & requestedInfo,size_t rowBytes)271 bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) {
272     if (!this->setInfo(requestedInfo, rowBytes)) {
273         return reset_return_false(this);
274     }
275 
276     // setInfo may have corrected info (e.g. 565 is always opaque).
277     const SkImageInfo& correctedInfo = this->info();
278     if (kUnknown_SkColorType == correctedInfo.colorType()) {
279         return true;
280     }
281     // setInfo may have computed a valid rowbytes if 0 were passed in
282     rowBytes = this->rowBytes();
283 
284     sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(correctedInfo, rowBytes);
285     if (!pr) {
286         return reset_return_false(this);
287     }
288     this->setPixelRef(std::move(pr), 0, 0);
289     if (nullptr == this->getPixels()) {
290         return reset_return_false(this);
291     }
292     SkDEBUGCODE(this->validate();)
293     return true;
294 }
295 
tryAllocPixelsFlags(const SkImageInfo & requestedInfo,uint32_t allocFlags)296 bool SkBitmap::tryAllocPixelsFlags(const SkImageInfo& requestedInfo, uint32_t allocFlags) {
297     if (!this->setInfo(requestedInfo)) {
298         return reset_return_false(this);
299     }
300 
301     // setInfo may have corrected info (e.g. 565 is always opaque).
302     const SkImageInfo& correctedInfo = this->info();
303 
304     sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(correctedInfo,
305                                                           correctedInfo.minRowBytes());
306     if (!pr) {
307         return reset_return_false(this);
308     }
309     this->setPixelRef(std::move(pr), 0, 0);
310     if (nullptr == this->getPixels()) {
311         return reset_return_false(this);
312     }
313     SkDEBUGCODE(this->validate();)
314     return true;
315 }
316 
invoke_release_proc(void (* proc)(void * pixels,void * ctx),void * pixels,void * ctx)317 static void invoke_release_proc(void (*proc)(void* pixels, void* ctx), void* pixels, void* ctx) {
318     if (proc) {
319         proc(pixels, ctx);
320     }
321 }
322 
installPixels(const SkImageInfo & requestedInfo,void * pixels,size_t rb,void (* releaseProc)(void * addr,void * context),void * context)323 bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
324                              void (*releaseProc)(void* addr, void* context), void* context) {
325     if (!this->setInfo(requestedInfo, rb)) {
326         invoke_release_proc(releaseProc, pixels, context);
327         this->reset();
328         return false;
329     }
330     if (nullptr == pixels) {
331         invoke_release_proc(releaseProc, pixels, context);
332         return true;    // we behaved as if they called setInfo()
333     }
334 
335     // setInfo may have corrected info (e.g. 565 is always opaque).
336     const SkImageInfo& correctedInfo = this->info();
337     this->setPixelRef(
338             SkMakePixelRefWithProc(correctedInfo.width(), correctedInfo.height(),
339                                    rb, pixels, releaseProc, context), 0, 0);
340     SkDEBUGCODE(this->validate();)
341     return true;
342 }
343 
installPixels(const SkPixmap & pixmap)344 bool SkBitmap::installPixels(const SkPixmap& pixmap) {
345     return this->installPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(),
346                                nullptr, nullptr);
347 }
348 
installMaskPixels(SkMaskBuilder & mask)349 bool SkBitmap::installMaskPixels(SkMaskBuilder& mask) {
350     if (SkMask::kA8_Format != mask.fFormat) {
351         this->reset();
352         return false;
353     }
354     return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
355                                                    mask.fBounds.height()),
356                                mask.image(), mask.fRowBytes);
357 }
358 
359 ///////////////////////////////////////////////////////////////////////////////
360 
getGenerationID() const361 uint32_t SkBitmap::getGenerationID() const {
362     return fPixelRef ? fPixelRef->getGenerationID() : 0;
363 }
364 
notifyPixelsChanged() const365 void SkBitmap::notifyPixelsChanged() const {
366     SkASSERT(!this->isImmutable());
367     if (fPixelRef) {
368         fPixelRef->notifyPixelsChanged();
369     }
370 }
371 
372 ///////////////////////////////////////////////////////////////////////////////
373 
374 /** We explicitly use the same allocator for our pixels that SkMask does,
375  so that we can freely assign memory allocated by one class to the other.
376  */
allocPixelRef(SkBitmap * dst)377 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst) {
378     const SkImageInfo& info = dst->info();
379     if (kUnknown_SkColorType == info.colorType()) {
380 //        SkDebugf("unsupported config for info %d\n", dst->config());
381         return false;
382     }
383 
384     sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, dst->rowBytes());
385     if (!pr) {
386         return false;
387     }
388 
389     dst->setPixelRef(std::move(pr), 0, 0);
390     SkDEBUGCODE(dst->validate();)
391     return true;
392 }
393 
394 ///////////////////////////////////////////////////////////////////////////////
395 
isImmutable() const396 bool SkBitmap::isImmutable() const {
397     return fPixelRef ? fPixelRef->isImmutable() : false;
398 }
399 
setImmutable()400 void SkBitmap::setImmutable() {
401     if (fPixelRef) {
402         fPixelRef->setImmutable();
403     }
404 }
405 
getAddr(int x,int y) const406 void* SkBitmap::getAddr(int x, int y) const {
407     SkASSERT((unsigned)x < (unsigned)this->width());
408     SkASSERT((unsigned)y < (unsigned)this->height());
409 
410     char* base = (char*)this->getPixels();
411     if (base) {
412         base += (y * this->rowBytes()) + (x << this->shiftPerPixel());
413     }
414     return base;
415 }
416 
417 ///////////////////////////////////////////////////////////////////////////////
418 ///////////////////////////////////////////////////////////////////////////////
419 
erase(SkColor4f c,const SkIRect & area) const420 void SkBitmap::erase(SkColor4f c, const SkIRect& area) const {
421     SkDEBUGCODE(this->validate();)
422 
423     if (kUnknown_SkColorType == this->colorType()) {
424         // TODO: can we ASSERT that we never get here?
425         return; // can't erase. Should we bzero so the memory is not uninitialized?
426     }
427 
428     SkPixmap result;
429     if (!this->peekPixels(&result)) {
430         return;
431     }
432 
433     if (result.erase(c, &area)) {
434         this->notifyPixelsChanged();
435     }
436 }
437 
erase(SkColor c,const SkIRect & area) const438 void SkBitmap::erase(SkColor c, const SkIRect& area) const {
439     this->erase(SkColor4f::FromColor(c), area);
440 }
441 
eraseColor(SkColor4f c) const442 void SkBitmap::eraseColor(SkColor4f c) const {
443     this->erase(c, SkIRect::MakeWH(this->width(), this->height()));
444 }
445 
eraseColor(SkColor c) const446 void SkBitmap::eraseColor(SkColor c) const {
447     this->erase(SkColor4f::FromColor(c), SkIRect::MakeWH(this->width(), this->height()));
448 }
449 
450 //////////////////////////////////////////////////////////////////////////////////////
451 //////////////////////////////////////////////////////////////////////////////////////
452 
extractSubset(SkBitmap * result,const SkIRect & subset) const453 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
454     SkDEBUGCODE(this->validate();)
455 
456     if (nullptr == result || !fPixelRef) {
457         return false;   // no src pixels
458     }
459 
460     SkIRect srcRect, r;
461     srcRect.setWH(this->width(), this->height());
462     if (!r.intersect(srcRect, subset)) {
463         return false;   // r is empty (i.e. no intersection)
464     }
465 
466     // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
467     // exited above.
468     SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
469     SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
470 
471     SkBitmap dst;
472     dst.setInfo(this->info().makeDimensions(r.size()), this->rowBytes());
473 
474     if (fPixelRef) {
475         SkIPoint origin = this->pixelRefOrigin();
476         // share the pixelref with a custom offset
477         dst.setPixelRef(fPixelRef, origin.x() + r.fLeft, origin.y() + r.fTop);
478     }
479     SkDEBUGCODE(dst.validate();)
480 
481     // we know we're good, so commit to result
482     result->swap(dst);
483     return true;
484 }
485 
486 ///////////////////////////////////////////////////////////////////////////////
487 
readPixels(const SkImageInfo & requestedDstInfo,void * dstPixels,size_t dstRB,int x,int y) const488 bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
489                           int x, int y) const {
490     SkPixmap src;
491     if (!this->peekPixels(&src)) {
492         return false;
493     }
494     return src.readPixels(requestedDstInfo, dstPixels, dstRB, x, y);
495 }
496 
readPixels(const SkPixmap & dst,int srcX,int srcY) const497 bool SkBitmap::readPixels(const SkPixmap& dst, int srcX, int srcY) const {
498     return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
499 }
500 
writePixels(const SkPixmap & src,int dstX,int dstY)501 bool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY) {
502     if (!SkImageInfoValidConversion(this->info(), src.info())) {
503         return false;
504     }
505 
506     SkWritePixelsRec rec(src.info(), src.addr(), src.rowBytes(), dstX, dstY);
507     if (!rec.trim(this->width(), this->height())) {
508         return false;
509     }
510 
511     void* dstPixels = this->getAddr(rec.fX, rec.fY);
512     const SkImageInfo dstInfo = this->info().makeDimensions(rec.fInfo.dimensions());
513     if (!SkConvertPixels(dstInfo,     dstPixels, this->rowBytes(),
514                          rec.fInfo, rec.fPixels,   rec.fRowBytes)) {
515         return false;
516     }
517     this->notifyPixelsChanged();
518     return true;
519 }
520 
521 ///////////////////////////////////////////////////////////////////////////////
522 
GetBitmapAlpha(const SkBitmap & src,uint8_t * SK_RESTRICT alpha,int alphaRowBytes)523 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
524     SkASSERT(alpha != nullptr);
525     SkASSERT(alphaRowBytes >= src.width());
526 
527     SkPixmap pmap;
528     if (!src.peekPixels(&pmap)) {
529         for (int y = 0; y < src.height(); ++y) {
530             memset(alpha, 0, src.width());
531             alpha += alphaRowBytes;
532         }
533         return false;
534     }
535     return SkConvertPixels(SkImageInfo::MakeA8(pmap.width(), pmap.height()), alpha, alphaRowBytes,
536                            pmap.info(), pmap.addr(), pmap.rowBytes());
537 }
538 
extractAlpha(SkBitmap * dst,const SkPaint * paint,Allocator * allocator,SkIPoint * offset) const539 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
540                             Allocator *allocator, SkIPoint* offset) const {
541     SkDEBUGCODE(this->validate();)
542 
543     SkBitmap    tmpBitmap;
544     SkMatrix    identity;
545     SkMaskBuilder      srcM, dstM;
546 
547     if (this->width() == 0 || this->height() == 0) {
548         return false;
549     }
550     srcM.bounds().setWH(this->width(), this->height());
551     srcM.rowBytes() = SkAlign4(this->width());
552     srcM.format() = SkMask::kA8_Format;
553 
554     SkMaskFilter* filter = paint ? paint->getMaskFilter() : nullptr;
555 
556     // compute our (larger?) dst bounds if we have a filter
557     if (filter) {
558         identity.reset();
559         if (!as_MFB(filter)->filterMask(&dstM, srcM, identity, nullptr)) {
560             goto NO_FILTER_CASE;
561         }
562         dstM.rowBytes() = SkAlign4(dstM.fBounds.width());
563     } else {
564     NO_FILTER_CASE:
565         tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
566         if (!tmpBitmap.tryAllocPixels(allocator)) {
567             // Allocation of pixels for alpha bitmap failed.
568             SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
569                     tmpBitmap.width(), tmpBitmap.height());
570             return false;
571         }
572         GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
573         if (offset) {
574             offset->set(0, 0);
575         }
576         tmpBitmap.swap(*dst);
577         return true;
578     }
579     srcM.image() = SkMaskBuilder::AllocImage(srcM.computeImageSize());
580     SkAutoMaskFreeImage srcCleanup(srcM.image());
581 
582     GetBitmapAlpha(*this, srcM.image(), srcM.fRowBytes);
583     if (!as_MFB(filter)->filterMask(&dstM, srcM, identity, nullptr)) {
584         goto NO_FILTER_CASE;
585     }
586     SkAutoMaskFreeImage dstCleanup(dstM.image());
587 
588     tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
589                       dstM.fRowBytes);
590     if (!tmpBitmap.tryAllocPixels(allocator)) {
591         // Allocation of pixels for alpha bitmap failed.
592         SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
593                 tmpBitmap.width(), tmpBitmap.height());
594         return false;
595     }
596     memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
597     if (offset) {
598         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
599     }
600     SkDEBUGCODE(tmpBitmap.validate();)
601 
602     tmpBitmap.swap(*dst);
603     return true;
604 }
605 
606 ///////////////////////////////////////////////////////////////////////////////
607 
608 #ifdef SK_DEBUG
validate() const609 void SkBitmap::validate() const {
610     this->info().validate();
611 
612     SkASSERT(this->info().validRowBytes(this->rowBytes()));
613 
614     if (fPixelRef && fPixelRef->pixels()) {
615         SkASSERT(this->getPixels());
616     } else {
617         SkASSERT(!this->getPixels());
618     }
619 
620     if (this->getPixels()) {
621         SkASSERT(fPixelRef);
622         SkASSERT(fPixelRef->rowBytes() == this->rowBytes());
623         SkIPoint origin = this->pixelRefOrigin();
624         SkASSERT(origin.fX >= 0);
625         SkASSERT(origin.fY >= 0);
626         SkASSERT(fPixelRef->width() >= (int)this->width() + origin.fX);
627         SkASSERT(fPixelRef->height() >= (int)this->height() + origin.fY);
628         SkASSERT(fPixelRef->rowBytes() >= this->info().minRowBytes());
629     }
630 }
631 #endif
632 
633 ///////////////////////////////////////////////////////////////////////////////
634 
peekPixels(SkPixmap * pmap) const635 bool SkBitmap::peekPixels(SkPixmap* pmap) const {
636     if (this->getPixels()) {
637         if (pmap) {
638             *pmap = fPixmap;
639         }
640         return true;
641     }
642     return false;
643 }
644 
asImage() const645 sk_sp<SkImage> SkBitmap::asImage() const { return SkImages::RasterFromBitmap(*this); }
646 
makeShader(const SkSamplingOptions & sampling,const SkMatrix & lm) const647 sk_sp<SkShader> SkBitmap::makeShader(const SkSamplingOptions& sampling,
648                                      const SkMatrix& lm) const {
649     return this->makeShader(SkTileMode::kClamp, SkTileMode::kClamp,
650                             sampling, &lm);
651 }
652 
makeShader(const SkSamplingOptions & sampling,const SkMatrix * lm) const653 sk_sp<SkShader> SkBitmap::makeShader(const SkSamplingOptions& sampling,
654                                      const SkMatrix* lm) const {
655     return this->makeShader(SkTileMode::kClamp, SkTileMode::kClamp,
656                             sampling, lm);
657 }
658 
makeShader(SkTileMode tmx,SkTileMode tmy,const SkSamplingOptions & sampling,const SkMatrix & lm) const659 sk_sp<SkShader> SkBitmap::makeShader(SkTileMode tmx, SkTileMode tmy,
660                                      const SkSamplingOptions& sampling,
661                                      const SkMatrix& lm) const {
662     if (!lm.invert(nullptr)) {
663         return nullptr;
664     }
665     return SkImageShader::Make(SkMakeImageFromRasterBitmap(*this, kIfMutable_SkCopyPixelsMode),
666                                tmx, tmy, sampling, &lm);
667 }
668 
makeShader(SkTileMode tmx,SkTileMode tmy,const SkSamplingOptions & sampling,const SkMatrix * lm) const669 sk_sp<SkShader> SkBitmap::makeShader(SkTileMode tmx, SkTileMode tmy,
670                                      const SkSamplingOptions& sampling,
671                                      const SkMatrix* lm) const {
672     if (lm && !lm->invert(nullptr)) {
673         return nullptr;
674     }
675     return SkImageShader::Make(SkMakeImageFromRasterBitmap(*this, kIfMutable_SkCopyPixelsMode),
676                                tmx, tmy, sampling, lm);
677 }
678