• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkAtomics.h"
9 #include "SkBitmap.h"
10 #include "SkColorData.h"
11 #include "SkColorTable.h"
12 #include "SkConvertPixels.h"
13 #include "SkData.h"
14 #include "SkFilterQuality.h"
15 #include "SkHalf.h"
16 #include "SkImageInfoPriv.h"
17 #include "SkMallocPixelRef.h"
18 #include "SkMask.h"
19 #include "SkMaskFilterBase.h"
20 #include "SkMath.h"
21 #include "SkPixelRef.h"
22 #include "SkPixmapPriv.h"
23 #include "SkReadBuffer.h"
24 #include "SkRect.h"
25 #include "SkScalar.h"
26 #include "SkTemplates.h"
27 #include "SkUnPreMultiply.h"
28 #include "SkWriteBuffer.h"
29 #include "SkWritePixelsRec.h"
30 
31 #include <string.h>
32 
reset_return_false(SkBitmap * bm)33 static bool reset_return_false(SkBitmap* bm) {
34     bm->reset();
35     return false;
36 }
37 
SkBitmap()38 SkBitmap::SkBitmap() : fFlags(0) {}
39 
SkBitmap(const SkBitmap & src)40 SkBitmap::SkBitmap(const SkBitmap& src)
41     : fPixelRef      (src.fPixelRef)
42     , fPixmap        (src.fPixmap)
43     , fFlags         (src.fFlags)
44 {
45     SkDEBUGCODE(src.validate();)
46     SkDEBUGCODE(this->validate();)
47 }
48 
SkBitmap(SkBitmap && other)49 SkBitmap::SkBitmap(SkBitmap&& other)
50     : fPixelRef      (std::move(other.fPixelRef))
51     , fPixmap        (std::move(other.fPixmap))
52     , fFlags                   (other.fFlags)
53 {
54     SkASSERT(!other.fPixelRef);
55     other.fPixmap.reset();
56     other.fFlags          = 0;
57 }
58 
~SkBitmap()59 SkBitmap::~SkBitmap() {}
60 
operator =(const SkBitmap & src)61 SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
62     if (this != &src) {
63         fPixelRef       = src.fPixelRef;
64         fPixmap         = src.fPixmap;
65         fFlags          = src.fFlags;
66     }
67     SkDEBUGCODE(this->validate();)
68     return *this;
69 }
70 
operator =(SkBitmap && other)71 SkBitmap& SkBitmap::operator=(SkBitmap&& other) {
72     if (this != &other) {
73         fPixelRef       = std::move(other.fPixelRef);
74         fPixmap         = std::move(other.fPixmap);
75         fFlags          = other.fFlags;
76         SkASSERT(!other.fPixelRef);
77         other.fPixmap.reset();
78         other.fFlags          = 0;
79     }
80     return *this;
81 }
82 
swap(SkBitmap & other)83 void SkBitmap::swap(SkBitmap& other) {
84     SkTSwap(*this, other);
85     SkDEBUGCODE(this->validate();)
86 }
87 
reset()88 void SkBitmap::reset() {
89     fPixelRef = nullptr;  // Free pixels.
90     fPixmap.reset();
91     fFlags = 0;
92 }
93 
getBounds(SkRect * bounds) const94 void SkBitmap::getBounds(SkRect* bounds) const {
95     SkASSERT(bounds);
96     *bounds = SkRect::Make(this->dimensions());
97 }
98 
getBounds(SkIRect * bounds) const99 void SkBitmap::getBounds(SkIRect* bounds) const {
100     SkASSERT(bounds);
101     *bounds = fPixmap.bounds();
102 }
103 
104 ///////////////////////////////////////////////////////////////////////////////
105 
setInfo(const SkImageInfo & info,size_t rowBytes)106 bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) {
107     SkAlphaType newAT = info.alphaType();
108     if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) {
109         return reset_return_false(this);
110     }
111     // don't look at info.alphaType(), since newAT is the real value...
112 
113     // require that rowBytes fit in 31bits
114     int64_t mrb = info.minRowBytes64();
115     if ((int32_t)mrb != mrb) {
116         return reset_return_false(this);
117     }
118     if ((int64_t)rowBytes != (int32_t)rowBytes) {
119         return reset_return_false(this);
120     }
121 
122     if (info.width() < 0 || info.height() < 0) {
123         return reset_return_false(this);
124     }
125 
126     if (kUnknown_SkColorType == info.colorType()) {
127         rowBytes = 0;
128     } else if (0 == rowBytes) {
129         rowBytes = (size_t)mrb;
130     } else if (!info.validRowBytes(rowBytes)) {
131         return reset_return_false(this);
132     }
133 
134     fPixelRef = nullptr;  // Free pixels.
135     fPixmap.reset(info.makeAlphaType(newAT), nullptr, SkToU32(rowBytes));
136     SkDEBUGCODE(this->validate();)
137     return true;
138 }
139 
140 
141 
setAlphaType(SkAlphaType newAlphaType)142 bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) {
143     if (!SkColorTypeValidateAlphaType(this->colorType(), newAlphaType, &newAlphaType)) {
144         return false;
145     }
146     if (this->alphaType() != newAlphaType) {
147         auto newInfo = fPixmap.info().makeAlphaType(newAlphaType);
148         fPixmap.reset(std::move(newInfo), fPixmap.addr(), fPixmap.rowBytes());
149     }
150     SkDEBUGCODE(this->validate();)
151     return true;
152 }
153 
pixelRefOrigin() const154 SkIPoint SkBitmap::pixelRefOrigin() const {
155     const char* addr = (const char*)fPixmap.addr();
156     const char* pix = (const char*)(fPixelRef ? fPixelRef->pixels() : nullptr);
157     size_t rb = this->rowBytes();
158     if (!pix || 0 == rb) {
159         return {0, 0};
160     }
161     SkASSERT(this->bytesPerPixel() > 0);
162     SkASSERT(this->bytesPerPixel() == (1 << this->shiftPerPixel()));
163     SkASSERT(addr >= pix);
164     size_t off = addr - pix;
165     return {SkToS32((off % rb) >> this->shiftPerPixel()), SkToS32(off / rb)};
166 }
167 
setPixelRef(sk_sp<SkPixelRef> pr,int dx,int dy)168 void SkBitmap::setPixelRef(sk_sp<SkPixelRef> pr, int dx, int dy) {
169 #ifdef SK_DEBUG
170     if (pr) {
171         if (kUnknown_SkColorType != this->colorType()) {
172             SkASSERT(dx >= 0 && this->width() + dx <= pr->width());
173             SkASSERT(dy >= 0 && this->height() + dy <= pr->height());
174         }
175     }
176 #endif
177     fPixelRef = kUnknown_SkColorType != this->colorType() ? std::move(pr) : nullptr;
178     void* p = nullptr;
179     size_t rowBytes = this->rowBytes();
180     // ignore dx,dy if there is no pixelref
181     if (fPixelRef) {
182         rowBytes = fPixelRef->rowBytes();
183         // TODO(reed):  Enforce that PixelRefs must have non-null pixels.
184         p = fPixelRef->pixels();
185         if (p) {
186             p = (char*)p + dy * rowBytes + dx * this->bytesPerPixel();
187         }
188     }
189     SkPixmapPriv::ResetPixmapKeepInfo(&fPixmap, p, rowBytes);
190     SkDEBUGCODE(this->validate();)
191 }
192 
setPixels(void * p)193 void SkBitmap::setPixels(void* p) {
194     if (nullptr == p) {
195         this->setPixelRef(nullptr, 0, 0);
196         return;
197     }
198 
199     if (kUnknown_SkColorType == this->colorType()) {
200         this->setPixelRef(nullptr, 0, 0);
201         return;
202     }
203 
204     this->setPixelRef(SkMallocPixelRef::MakeDirect(this->info(), p, this->rowBytes()), 0, 0);
205     if (!fPixelRef) {
206         return;
207     }
208     SkDEBUGCODE(this->validate();)
209 }
210 
tryAllocPixels(Allocator * allocator)211 bool SkBitmap::tryAllocPixels(Allocator* allocator) {
212     HeapAllocator stdalloc;
213 
214     if (nullptr == allocator) {
215         allocator = &stdalloc;
216     }
217     return allocator->allocPixelRef(this);
218 }
219 
220 ///////////////////////////////////////////////////////////////////////////////
221 
tryAllocPixels(const SkImageInfo & requestedInfo,size_t rowBytes)222 bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) {
223     if (!this->setInfo(requestedInfo, rowBytes)) {
224         return reset_return_false(this);
225     }
226 
227     // setInfo may have corrected info (e.g. 565 is always opaque).
228     const SkImageInfo& correctedInfo = this->info();
229     if (kUnknown_SkColorType == correctedInfo.colorType()) {
230         return true;
231     }
232     // setInfo may have computed a valid rowbytes if 0 were passed in
233     rowBytes = this->rowBytes();
234 
235     sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(correctedInfo, rowBytes);
236     if (!pr) {
237         return reset_return_false(this);
238     }
239     this->setPixelRef(std::move(pr), 0, 0);
240     if (nullptr == this->getPixels()) {
241         return reset_return_false(this);
242     }
243     SkDEBUGCODE(this->validate();)
244     return true;
245 }
246 
tryAllocPixelsFlags(const SkImageInfo & requestedInfo,uint32_t allocFlags)247 bool SkBitmap::tryAllocPixelsFlags(const SkImageInfo& requestedInfo, uint32_t allocFlags) {
248     if (!this->setInfo(requestedInfo)) {
249         return reset_return_false(this);
250     }
251 
252     // setInfo may have corrected info (e.g. 565 is always opaque).
253     const SkImageInfo& correctedInfo = this->info();
254 
255     sk_sp<SkPixelRef> pr = (allocFlags & kZeroPixels_AllocFlag) ?
256         SkMallocPixelRef::MakeZeroed(correctedInfo, correctedInfo.minRowBytes()) :
257         SkMallocPixelRef::MakeAllocate(correctedInfo, correctedInfo.minRowBytes());
258     if (!pr) {
259         return reset_return_false(this);
260     }
261     this->setPixelRef(std::move(pr), 0, 0);
262     if (nullptr == this->getPixels()) {
263         return reset_return_false(this);
264     }
265     SkDEBUGCODE(this->validate();)
266     return true;
267 }
268 
invoke_release_proc(void (* proc)(void * pixels,void * ctx),void * pixels,void * ctx)269 static void invoke_release_proc(void (*proc)(void* pixels, void* ctx), void* pixels, void* ctx) {
270     if (proc) {
271         proc(pixels, ctx);
272     }
273 }
274 
installPixels(const SkImageInfo & requestedInfo,void * pixels,size_t rb,void (* releaseProc)(void * addr,void * context),void * context)275 bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
276                              void (*releaseProc)(void* addr, void* context), void* context) {
277     if (!this->setInfo(requestedInfo, rb)) {
278         invoke_release_proc(releaseProc, pixels, context);
279         this->reset();
280         return false;
281     }
282     if (nullptr == pixels) {
283         invoke_release_proc(releaseProc, pixels, context);
284         return true;    // we behaved as if they called setInfo()
285     }
286 
287     // setInfo may have corrected info (e.g. 565 is always opaque).
288     const SkImageInfo& correctedInfo = this->info();
289 
290     sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeWithProc(correctedInfo, rb, pixels,
291                                                           releaseProc, context);
292     if (!pr) {
293         this->reset();
294         return false;
295     }
296 
297     this->setPixelRef(std::move(pr), 0, 0);
298     SkDEBUGCODE(this->validate();)
299     return true;
300 }
301 
installPixels(const SkPixmap & pixmap)302 bool SkBitmap::installPixels(const SkPixmap& pixmap) {
303     return this->installPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(),
304                                nullptr, nullptr);
305 }
306 
installMaskPixels(const SkMask & mask)307 bool SkBitmap::installMaskPixels(const SkMask& mask) {
308     if (SkMask::kA8_Format != mask.fFormat) {
309         this->reset();
310         return false;
311     }
312     return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
313                                                    mask.fBounds.height()),
314                                mask.fImage, mask.fRowBytes);
315 }
316 
317 ///////////////////////////////////////////////////////////////////////////////
318 
getGenerationID() const319 uint32_t SkBitmap::getGenerationID() const {
320     return fPixelRef ? fPixelRef->getGenerationID() : 0;
321 }
322 
notifyPixelsChanged() const323 void SkBitmap::notifyPixelsChanged() const {
324     SkASSERT(!this->isImmutable());
325     if (fPixelRef) {
326         fPixelRef->notifyPixelsChanged();
327     }
328 }
329 
330 ///////////////////////////////////////////////////////////////////////////////
331 
332 /** We explicitly use the same allocator for our pixels that SkMask does,
333  so that we can freely assign memory allocated by one class to the other.
334  */
allocPixelRef(SkBitmap * dst)335 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst) {
336     const SkImageInfo info = dst->info();
337     if (kUnknown_SkColorType == info.colorType()) {
338 //        SkDebugf("unsupported config for info %d\n", dst->config());
339         return false;
340     }
341 
342     sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, dst->rowBytes());
343     if (!pr) {
344         return false;
345     }
346 
347     dst->setPixelRef(std::move(pr), 0, 0);
348     SkDEBUGCODE(dst->validate();)
349     return true;
350 }
351 
352 ///////////////////////////////////////////////////////////////////////////////
353 
isImmutable() const354 bool SkBitmap::isImmutable() const {
355     return fPixelRef ? fPixelRef->isImmutable() : false;
356 }
357 
setImmutable()358 void SkBitmap::setImmutable() {
359     if (fPixelRef) {
360         fPixelRef->setImmutable();
361     }
362 }
363 
isVolatile() const364 bool SkBitmap::isVolatile() const {
365     return (fFlags & kImageIsVolatile_Flag) != 0;
366 }
367 
setIsVolatile(bool isVolatile)368 void SkBitmap::setIsVolatile(bool isVolatile) {
369     if (isVolatile) {
370         fFlags |= kImageIsVolatile_Flag;
371     } else {
372         fFlags &= ~kImageIsVolatile_Flag;
373     }
374 }
375 
getAddr(int x,int y) const376 void* SkBitmap::getAddr(int x, int y) const {
377     SkASSERT((unsigned)x < (unsigned)this->width());
378     SkASSERT((unsigned)y < (unsigned)this->height());
379 
380     char* base = (char*)this->getPixels();
381     if (base) {
382         base += y * this->rowBytes();
383         switch (this->colorType()) {
384             case kRGBA_F16_SkColorType:
385                 base += x << 3;
386                 break;
387             case kRGBA_8888_SkColorType:
388             case kBGRA_8888_SkColorType:
389                 base += x << 2;
390                 break;
391             case kARGB_4444_SkColorType:
392             case kRGB_565_SkColorType:
393                 base += x << 1;
394                 break;
395             case kAlpha_8_SkColorType:
396             case kGray_8_SkColorType:
397                 base += x;
398                 break;
399             default:
400                 SkDEBUGFAIL("Can't return addr for config");
401                 base = nullptr;
402                 break;
403         }
404     }
405     return base;
406 }
407 
408 ///////////////////////////////////////////////////////////////////////////////
409 ///////////////////////////////////////////////////////////////////////////////
410 
erase(SkColor c,const SkIRect & area) const411 void SkBitmap::erase(SkColor c, const SkIRect& area) const {
412     SkDEBUGCODE(this->validate();)
413 
414     switch (this->colorType()) {
415         case kUnknown_SkColorType:
416             // TODO: can we ASSERT that we never get here?
417             return; // can't erase. Should we bzero so the memory is not uninitialized?
418         default:
419             break;
420     }
421 
422     SkPixmap result;
423     if (!this->peekPixels(&result)) {
424         return;
425     }
426 
427     if (result.erase(c, area)) {
428         this->notifyPixelsChanged();
429     }
430 }
431 
eraseColor(SkColor c) const432 void SkBitmap::eraseColor(SkColor c) const {
433     this->erase(c, SkIRect::MakeWH(this->width(), this->height()));
434 }
435 
436 //////////////////////////////////////////////////////////////////////////////////////
437 //////////////////////////////////////////////////////////////////////////////////////
438 
extractSubset(SkBitmap * result,const SkIRect & subset) const439 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
440     SkDEBUGCODE(this->validate();)
441 
442     if (nullptr == result || !fPixelRef) {
443         return false;   // no src pixels
444     }
445 
446     SkIRect srcRect, r;
447     srcRect.set(0, 0, this->width(), this->height());
448     if (!r.intersect(srcRect, subset)) {
449         return false;   // r is empty (i.e. no intersection)
450     }
451 
452     // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
453     // exited above.
454     SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
455     SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
456 
457     SkBitmap dst;
458     dst.setInfo(this->info().makeWH(r.width(), r.height()), this->rowBytes());
459     dst.setIsVolatile(this->isVolatile());
460 
461     if (fPixelRef) {
462         SkIPoint origin = this->pixelRefOrigin();
463         // share the pixelref with a custom offset
464         dst.setPixelRef(fPixelRef, origin.x() + r.fLeft, origin.y() + r.fTop);
465     }
466     SkDEBUGCODE(dst.validate();)
467 
468     // we know we're good, so commit to result
469     result->swap(dst);
470     return true;
471 }
472 
473 ///////////////////////////////////////////////////////////////////////////////
474 
readPixels(const SkImageInfo & requestedDstInfo,void * dstPixels,size_t dstRB,int x,int y,SkTransferFunctionBehavior behavior) const475 bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
476                           int x, int y, SkTransferFunctionBehavior behavior) const {
477     SkPixmap src;
478     if (!this->peekPixels(&src)) {
479         return false;
480     }
481     return src.readPixels(requestedDstInfo, dstPixels, dstRB, x, y, behavior);
482 }
483 
readPixels(const SkPixmap & dst,int srcX,int srcY) const484 bool SkBitmap::readPixels(const SkPixmap& dst, int srcX, int srcY) const {
485     return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
486 }
487 
writePixels(const SkPixmap & src,int dstX,int dstY,SkTransferFunctionBehavior behavior)488 bool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY,
489                            SkTransferFunctionBehavior behavior) {
490     if (!SkImageInfoValidConversion(this->info(), src.info())) {
491         return false;
492     }
493 
494     SkWritePixelsRec rec(src.info(), src.addr(), src.rowBytes(), dstX, dstY);
495     if (!rec.trim(this->width(), this->height())) {
496         return false;
497     }
498 
499     void* dstPixels = this->getAddr(rec.fX, rec.fY);
500     const SkImageInfo dstInfo = this->info().makeWH(rec.fInfo.width(), rec.fInfo.height());
501     SkConvertPixels(dstInfo, dstPixels, this->rowBytes(), rec.fInfo, rec.fPixels, rec.fRowBytes,
502                     nullptr, behavior);
503     this->notifyPixelsChanged();
504     return true;
505 }
506 
507 ///////////////////////////////////////////////////////////////////////////////
508 
GetBitmapAlpha(const SkBitmap & src,uint8_t * SK_RESTRICT alpha,int alphaRowBytes)509 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
510     SkASSERT(alpha != nullptr);
511     SkASSERT(alphaRowBytes >= src.width());
512 
513     SkPixmap pmap;
514     if (!src.peekPixels(&pmap)) {
515         for (int y = 0; y < src.height(); ++y) {
516             memset(alpha, 0, src.width());
517             alpha += alphaRowBytes;
518         }
519         return false;
520     }
521     SkConvertPixels(SkImageInfo::MakeA8(pmap.width(), pmap.height()), alpha, alphaRowBytes,
522                     pmap.info(), pmap.addr(), pmap.rowBytes(), nullptr,
523                     SkTransferFunctionBehavior::kRespect);
524     return true;
525 }
526 
527 #include "SkPaint.h"
528 #include "SkMaskFilter.h"
529 #include "SkMatrix.h"
530 
extractAlpha(SkBitmap * dst,const SkPaint * paint,Allocator * allocator,SkIPoint * offset) const531 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
532                             Allocator *allocator, SkIPoint* offset) const {
533     SkDEBUGCODE(this->validate();)
534 
535     SkBitmap    tmpBitmap;
536     SkMatrix    identity;
537     SkMask      srcM, dstM;
538 
539     srcM.fBounds.set(0, 0, this->width(), this->height());
540     srcM.fRowBytes = SkAlign4(this->width());
541     srcM.fFormat = SkMask::kA8_Format;
542 
543     SkMaskFilter* filter = paint ? paint->getMaskFilter() : nullptr;
544 
545     // compute our (larger?) dst bounds if we have a filter
546     if (filter) {
547         identity.reset();
548         if (!as_MFB(filter)->filterMask(&dstM, srcM, identity, nullptr)) {
549             goto NO_FILTER_CASE;
550         }
551         dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
552     } else {
553     NO_FILTER_CASE:
554         tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
555         if (!tmpBitmap.tryAllocPixels(allocator)) {
556             // Allocation of pixels for alpha bitmap failed.
557             SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
558                     tmpBitmap.width(), tmpBitmap.height());
559             return false;
560         }
561         GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
562         if (offset) {
563             offset->set(0, 0);
564         }
565         tmpBitmap.swap(*dst);
566         return true;
567     }
568     srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
569     SkAutoMaskFreeImage srcCleanup(srcM.fImage);
570 
571     GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
572     if (!as_MFB(filter)->filterMask(&dstM, srcM, identity, nullptr)) {
573         goto NO_FILTER_CASE;
574     }
575     SkAutoMaskFreeImage dstCleanup(dstM.fImage);
576 
577     tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
578                       dstM.fRowBytes);
579     if (!tmpBitmap.tryAllocPixels(allocator)) {
580         // Allocation of pixels for alpha bitmap failed.
581         SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
582                 tmpBitmap.width(), tmpBitmap.height());
583         return false;
584     }
585     memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
586     if (offset) {
587         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
588     }
589     SkDEBUGCODE(tmpBitmap.validate();)
590 
591     tmpBitmap.swap(*dst);
592     return true;
593 }
594 
595 ///////////////////////////////////////////////////////////////////////////////
596 
597 #ifdef SK_DEBUG
validate() const598 void SkBitmap::validate() const {
599     this->info().validate();
600 
601     // ImageInfo may not require this, but Bitmap ensures that opaque-only
602     // colorTypes report opaque for their alphatype
603     if (kRGB_565_SkColorType == this->colorType()) {
604         SkASSERT(kOpaque_SkAlphaType == this->alphaType());
605     }
606 
607     SkASSERT(this->info().validRowBytes(this->rowBytes()));
608     uint8_t allFlags = kImageIsVolatile_Flag;
609 #ifdef SK_BUILD_FOR_ANDROID
610     allFlags |= kHasHardwareMipMap_Flag;
611 #endif
612     SkASSERT((~allFlags & fFlags) == 0);
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 #ifndef SK_IGNORE_TO_STRING
634 #include "SkString.h"
toString(SkString * str) const635 void SkBitmap::toString(SkString* str) const {
636 
637     static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
638         "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
639     };
640 
641     str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
642                  gColorTypeNames[this->colorType()]);
643 
644     str->append(" (");
645     if (this->isOpaque()) {
646         str->append("opaque");
647     } else {
648         str->append("transparent");
649     }
650     if (this->isImmutable()) {
651         str->append(", immutable");
652     } else {
653         str->append(", not-immutable");
654     }
655     str->append(")");
656 
657     str->appendf(" pixelref:%p", this->pixelRef());
658     str->append(")");
659 }
660 #endif
661 
662 ///////////////////////////////////////////////////////////////////////////////
663 
peekPixels(SkPixmap * pmap) const664 bool SkBitmap::peekPixels(SkPixmap* pmap) const {
665     if (this->getPixels()) {
666         if (pmap) {
667             *pmap = fPixmap;
668         }
669         return true;
670     }
671     return false;
672 }
673 
674 ///////////////////////////////////////////////////////////////////////////////
675 
676 #ifdef SK_DEBUG
validate() const677 void SkImageInfo::validate() const {
678     SkASSERT(fWidth >= 0);
679     SkASSERT(fHeight >= 0);
680     SkASSERT(SkColorTypeIsValid(fColorType));
681     SkASSERT(SkAlphaTypeIsValid(fAlphaType));
682 }
683 #endif
684