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 "SkColorPriv.h"
11 #include "SkData.h"
12 #include "SkFilterQuality.h"
13 #include "SkMallocPixelRef.h"
14 #include "SkMask.h"
15 #include "SkMath.h"
16 #include "SkPixelRef.h"
17 #include "SkReadBuffer.h"
18 #include "SkRect.h"
19 #include "SkScalar.h"
20 #include "SkTemplates.h"
21 #include "SkUnPreMultiply.h"
22 #include "SkWriteBuffer.h"
23 
24 #include <string.h>
25 
reset_return_false(SkBitmap * bm)26 static bool reset_return_false(SkBitmap* bm) {
27     bm->reset();
28     return false;
29 }
30 
SkBitmap()31 SkBitmap::SkBitmap() {
32     sk_bzero(this, sizeof(*this));
33 }
34 
SkBitmap(const SkBitmap & src)35 SkBitmap::SkBitmap(const SkBitmap& src) {
36     SkDEBUGCODE(src.validate();)
37     sk_bzero(this, sizeof(*this));
38     *this = src;
39     SkDEBUGCODE(this->validate();)
40 }
41 
SkBitmap(SkBitmap && other)42 SkBitmap::SkBitmap(SkBitmap&& other) : SkBitmap() { this->swap(other); }
43 
~SkBitmap()44 SkBitmap::~SkBitmap() {
45     SkDEBUGCODE(this->validate();)
46     this->freePixels();
47 }
48 
operator =(const SkBitmap & src)49 SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
50     if (this != &src) {
51         this->freePixels();
52         memcpy(this, &src, sizeof(src));
53 
54         // inc src reference counts
55         SkSafeRef(src.fPixelRef);
56 
57         // we reset our locks if we get blown away
58         fPixelLockCount = 0;
59 
60         if (fPixelRef) {
61             // ignore the values from the memcpy
62             fPixels = nullptr;
63             fColorTable = nullptr;
64             // Note that what to for genID is somewhat arbitrary. We have no
65             // way to track changes to raw pixels across multiple SkBitmaps.
66             // Would benefit from an SkRawPixelRef type created by
67             // setPixels.
68             // Just leave the memcpy'ed one but they'll get out of sync
69             // as soon either is modified.
70         }
71     }
72 
73     SkDEBUGCODE(this->validate();)
74     return *this;
75 }
76 
operator =(SkBitmap && other)77 SkBitmap& SkBitmap::operator=(SkBitmap&& other) {
78     if (this != &other) {
79         this->swap(other);
80         other.reset();
81     }
82     return *this;
83 }
84 
swap(SkBitmap & other)85 void SkBitmap::swap(SkBitmap& other) {
86     SkTSwap(fColorTable, other.fColorTable);
87     SkTSwap(fPixelRef, other.fPixelRef);
88     SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin);
89     SkTSwap(fPixelLockCount, other.fPixelLockCount);
90     SkTSwap(fPixels, other.fPixels);
91     SkTSwap(fInfo, other.fInfo);
92     SkTSwap(fRowBytes, other.fRowBytes);
93     SkTSwap(fFlags, other.fFlags);
94 
95     SkDEBUGCODE(this->validate();)
96 }
97 
reset()98 void SkBitmap::reset() {
99     this->freePixels();
100     sk_bzero(this, sizeof(*this));
101 }
102 
getBounds(SkRect * bounds) const103 void SkBitmap::getBounds(SkRect* bounds) const {
104     SkASSERT(bounds);
105     bounds->set(0, 0,
106                 SkIntToScalar(fInfo.width()), SkIntToScalar(fInfo.height()));
107 }
108 
getBounds(SkIRect * bounds) const109 void SkBitmap::getBounds(SkIRect* bounds) const {
110     SkASSERT(bounds);
111     bounds->set(0, 0, fInfo.width(), fInfo.height());
112 }
113 
114 ///////////////////////////////////////////////////////////////////////////////
115 
setInfo(const SkImageInfo & info,size_t rowBytes)116 bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) {
117     SkAlphaType newAT = info.alphaType();
118     if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) {
119         return reset_return_false(this);
120     }
121     // don't look at info.alphaType(), since newAT is the real value...
122 
123     // require that rowBytes fit in 31bits
124     int64_t mrb = info.minRowBytes64();
125     if ((int32_t)mrb != mrb) {
126         return reset_return_false(this);
127     }
128     if ((int64_t)rowBytes != (int32_t)rowBytes) {
129         return reset_return_false(this);
130     }
131 
132     if (info.width() < 0 || info.height() < 0) {
133         return reset_return_false(this);
134     }
135 
136     if (kUnknown_SkColorType == info.colorType()) {
137         rowBytes = 0;
138     } else if (0 == rowBytes) {
139         rowBytes = (size_t)mrb;
140     } else if (!info.validRowBytes(rowBytes)) {
141         return reset_return_false(this);
142     }
143 
144     this->freePixels();
145 
146     fInfo = info.makeAlphaType(newAT);
147     fRowBytes = SkToU32(rowBytes);
148     return true;
149 }
150 
setAlphaType(SkAlphaType newAlphaType)151 bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) {
152     if (!SkColorTypeValidateAlphaType(fInfo.colorType(), newAlphaType, &newAlphaType)) {
153         return false;
154     }
155     if (fInfo.alphaType() != newAlphaType) {
156         fInfo = fInfo.makeAlphaType(newAlphaType);
157         if (fPixelRef) {
158             fPixelRef->changeAlphaType(newAlphaType);
159         }
160     }
161     return true;
162 }
163 
updatePixelsFromRef() const164 void SkBitmap::updatePixelsFromRef() const {
165     if (fPixelRef) {
166         if (fPixelLockCount > 0) {
167             SkASSERT(fPixelRef->isLocked());
168 
169             void* p = fPixelRef->pixels();
170             if (p) {
171                 p = (char*)p
172                     + fPixelRefOrigin.fY * fRowBytes
173                     + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
174             }
175             fPixels = p;
176             fColorTable = fPixelRef->colorTable();
177         } else {
178             SkASSERT(0 == fPixelLockCount);
179             fPixels = nullptr;
180             fColorTable = nullptr;
181         }
182     }
183 }
184 
setPixelRef(SkPixelRef * pr,int dx,int dy)185 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
186 #ifdef SK_DEBUG
187     if (pr) {
188         if (kUnknown_SkColorType != fInfo.colorType()) {
189             const SkImageInfo& prInfo = pr->info();
190             SkASSERT(fInfo.width() <= prInfo.width());
191             SkASSERT(fInfo.height() <= prInfo.height());
192             SkASSERT(fInfo.colorType() == prInfo.colorType());
193             switch (prInfo.alphaType()) {
194                 case kUnknown_SkAlphaType:
195                     SkASSERT(fInfo.alphaType() == kUnknown_SkAlphaType);
196                     break;
197                 case kOpaque_SkAlphaType:
198                 case kPremul_SkAlphaType:
199                     SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType ||
200                              fInfo.alphaType() == kPremul_SkAlphaType);
201                     break;
202                 case kUnpremul_SkAlphaType:
203                     SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType ||
204                              fInfo.alphaType() == kUnpremul_SkAlphaType);
205                     break;
206             }
207         }
208     }
209 #endif
210 
211     if (pr) {
212         const SkImageInfo& info = pr->info();
213         fPixelRefOrigin.set(SkTPin(dx, 0, info.width()), SkTPin(dy, 0, info.height()));
214     } else {
215         // ignore dx,dy if there is no pixelref
216         fPixelRefOrigin.setZero();
217     }
218 
219     if (fPixelRef != pr) {
220         this->freePixels();
221         SkASSERT(nullptr == fPixelRef);
222 
223         SkSafeRef(pr);
224         fPixelRef = pr;
225         this->updatePixelsFromRef();
226     }
227 
228     SkDEBUGCODE(this->validate();)
229     return pr;
230 }
231 
lockPixels() const232 void SkBitmap::lockPixels() const {
233     if (fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) {
234         fPixelRef->lockPixels();
235         this->updatePixelsFromRef();
236     }
237     SkDEBUGCODE(this->validate();)
238 }
239 
unlockPixels() const240 void SkBitmap::unlockPixels() const {
241     SkASSERT(nullptr == fPixelRef || fPixelLockCount > 0);
242 
243     if (fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) {
244         fPixelRef->unlockPixels();
245         this->updatePixelsFromRef();
246     }
247     SkDEBUGCODE(this->validate();)
248 }
249 
lockPixelsAreWritable() const250 bool SkBitmap::lockPixelsAreWritable() const {
251     return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false;
252 }
253 
setPixels(void * p,SkColorTable * ctable)254 void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
255     if (nullptr == p) {
256         this->setPixelRef(nullptr);
257         return;
258     }
259 
260     if (kUnknown_SkColorType == fInfo.colorType()) {
261         this->setPixelRef(nullptr);
262         return;
263     }
264 
265     SkPixelRef* pr = SkMallocPixelRef::NewDirect(fInfo, p, fRowBytes, ctable);
266     if (nullptr == pr) {
267         this->setPixelRef(nullptr);
268         return;
269     }
270 
271     this->setPixelRef(pr)->unref();
272 
273     // since we're already allocated, we lockPixels right away
274     this->lockPixels();
275     SkDEBUGCODE(this->validate();)
276 }
277 
tryAllocPixels(Allocator * allocator,SkColorTable * ctable)278 bool SkBitmap::tryAllocPixels(Allocator* allocator, SkColorTable* ctable) {
279     HeapAllocator stdalloc;
280 
281     if (nullptr == allocator) {
282         allocator = &stdalloc;
283     }
284     return allocator->allocPixelRef(this, ctable);
285 }
286 
287 ///////////////////////////////////////////////////////////////////////////////
288 
tryAllocPixels(const SkImageInfo & requestedInfo,size_t rowBytes)289 bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) {
290     if (kIndex_8_SkColorType == requestedInfo.colorType()) {
291         return reset_return_false(this);
292     }
293     if (!this->setInfo(requestedInfo, rowBytes)) {
294         return reset_return_false(this);
295     }
296 
297     // setInfo may have corrected info (e.g. 565 is always opaque).
298     const SkImageInfo& correctedInfo = this->info();
299     // setInfo may have computed a valid rowbytes if 0 were passed in
300     rowBytes = this->rowBytes();
301 
302     SkMallocPixelRef::PRFactory defaultFactory;
303 
304     SkPixelRef* pr = defaultFactory.create(correctedInfo, rowBytes, nullptr);
305     if (nullptr == pr) {
306         return reset_return_false(this);
307     }
308     this->setPixelRef(pr)->unref();
309 
310     // TODO: lockPixels could/should return bool or void*/nullptr
311     this->lockPixels();
312     if (nullptr == this->getPixels()) {
313         return reset_return_false(this);
314     }
315     return true;
316 }
317 
tryAllocPixels(const SkImageInfo & requestedInfo,SkPixelRefFactory * factory,SkColorTable * ctable)318 bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactory* factory,
319                                 SkColorTable* ctable) {
320     if (kIndex_8_SkColorType == requestedInfo.colorType() && nullptr == ctable) {
321         return reset_return_false(this);
322     }
323     if (!this->setInfo(requestedInfo)) {
324         return reset_return_false(this);
325     }
326 
327     // setInfo may have corrected info (e.g. 565 is always opaque).
328     const SkImageInfo& correctedInfo = this->info();
329 
330     SkMallocPixelRef::PRFactory defaultFactory;
331     if (nullptr == factory) {
332         factory = &defaultFactory;
333     }
334 
335     SkPixelRef* pr = factory->create(correctedInfo, correctedInfo.minRowBytes(), ctable);
336     if (nullptr == pr) {
337         return reset_return_false(this);
338     }
339     this->setPixelRef(pr)->unref();
340 
341     // TODO: lockPixels could/should return bool or void*/nullptr
342     this->lockPixels();
343     if (nullptr == this->getPixels()) {
344         return reset_return_false(this);
345     }
346     return true;
347 }
348 
invoke_release_proc(void (* proc)(void * pixels,void * ctx),void * pixels,void * ctx)349 static void invoke_release_proc(void (*proc)(void* pixels, void* ctx), void* pixels, void* ctx) {
350     if (proc) {
351         proc(pixels, ctx);
352     }
353 }
354 
installPixels(const SkImageInfo & requestedInfo,void * pixels,size_t rb,SkColorTable * ct,void (* releaseProc)(void * addr,void * context),void * context)355 bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
356                              SkColorTable* ct, void (*releaseProc)(void* addr, void* context),
357                              void* context) {
358     if (!this->setInfo(requestedInfo, rb)) {
359         invoke_release_proc(releaseProc, pixels, context);
360         this->reset();
361         return false;
362     }
363     if (nullptr == pixels) {
364         invoke_release_proc(releaseProc, pixels, context);
365         return true;    // we behaved as if they called setInfo()
366     }
367 
368     // setInfo may have corrected info (e.g. 565 is always opaque).
369     const SkImageInfo& correctedInfo = this->info();
370 
371     SkPixelRef* pr = SkMallocPixelRef::NewWithProc(correctedInfo, rb, ct, pixels, releaseProc,
372                                                    context);
373     if (!pr) {
374         this->reset();
375         return false;
376     }
377 
378     this->setPixelRef(pr)->unref();
379 
380     // since we're already allocated, we lockPixels right away
381     this->lockPixels();
382     SkDEBUGCODE(this->validate();)
383     return true;
384 }
385 
installPixels(const SkPixmap & pixmap)386 bool SkBitmap::installPixels(const SkPixmap& pixmap) {
387     return this->installPixels(pixmap.info(), pixmap.writable_addr(),
388                                pixmap.rowBytes(), pixmap.ctable(),
389                                nullptr, nullptr);
390 }
391 
installMaskPixels(const SkMask & mask)392 bool SkBitmap::installMaskPixels(const SkMask& mask) {
393     if (SkMask::kA8_Format != mask.fFormat) {
394         this->reset();
395         return false;
396     }
397     return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
398                                                    mask.fBounds.height()),
399                                mask.fImage, mask.fRowBytes);
400 }
401 
402 ///////////////////////////////////////////////////////////////////////////////
403 
freePixels()404 void SkBitmap::freePixels() {
405     if (fPixelRef) {
406         if (fPixelLockCount > 0) {
407             fPixelRef->unlockPixels();
408         }
409         fPixelRef->unref();
410         fPixelRef = nullptr;
411         fPixelRefOrigin.setZero();
412     }
413     fPixelLockCount = 0;
414     fPixels = nullptr;
415     fColorTable = nullptr;
416 }
417 
getGenerationID() const418 uint32_t SkBitmap::getGenerationID() const {
419     return (fPixelRef) ? fPixelRef->getGenerationID() : 0;
420 }
421 
notifyPixelsChanged() const422 void SkBitmap::notifyPixelsChanged() const {
423     SkASSERT(!this->isImmutable());
424     if (fPixelRef) {
425         fPixelRef->notifyPixelsChanged();
426     }
427 }
428 
getTexture() const429 GrTexture* SkBitmap::getTexture() const {
430     return fPixelRef ? fPixelRef->getTexture() : nullptr;
431 }
432 
433 ///////////////////////////////////////////////////////////////////////////////
434 
435 /** We explicitly use the same allocator for our pixels that SkMask does,
436  so that we can freely assign memory allocated by one class to the other.
437  */
allocPixelRef(SkBitmap * dst,SkColorTable * ctable)438 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
439                                             SkColorTable* ctable) {
440     const SkImageInfo info = dst->info();
441     if (kUnknown_SkColorType == info.colorType()) {
442 //        SkDebugf("unsupported config for info %d\n", dst->config());
443         return false;
444     }
445 
446     SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), ctable);
447     if (nullptr == pr) {
448         return false;
449     }
450 
451     dst->setPixelRef(pr)->unref();
452     // since we're already allocated, we lockPixels right away
453     dst->lockPixels();
454     return true;
455 }
456 
457 ///////////////////////////////////////////////////////////////////////////////
458 
copy_pixels_to(const SkPixmap & src,void * const dst,size_t dstSize,size_t dstRowBytes,bool preserveDstPad)459 static bool copy_pixels_to(const SkPixmap& src, void* const dst, size_t dstSize,
460                            size_t dstRowBytes, bool preserveDstPad) {
461     const SkImageInfo& info = src.info();
462 
463     if (0 == dstRowBytes) {
464         dstRowBytes = src.rowBytes();
465     }
466     if (dstRowBytes < info.minRowBytes()) {
467         return false;
468     }
469 
470     if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == src.rowBytes()) {
471         size_t safeSize = src.getSafeSize();
472         if (safeSize > dstSize || safeSize == 0)
473             return false;
474         else {
475             // This implementation will write bytes beyond the end of each row,
476             // excluding the last row, if the bitmap's stride is greater than
477             // strictly required by the current config.
478             memcpy(dst, src.addr(), safeSize);
479             return true;
480         }
481     } else {
482         // If destination has different stride than us, then copy line by line.
483         if (info.getSafeSize(dstRowBytes) > dstSize) {
484             return false;
485         } else {
486             // Just copy what we need on each line.
487             size_t rowBytes = info.minRowBytes();
488             const uint8_t* srcP = reinterpret_cast<const uint8_t*>(src.addr());
489             uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
490             for (int row = 0; row < info.height(); ++row) {
491                 memcpy(dstP, srcP, rowBytes);
492                 srcP += src.rowBytes();
493                 dstP += dstRowBytes;
494             }
495 
496             return true;
497         }
498     }
499 }
500 
copyPixelsTo(void * dst,size_t dstSize,size_t dstRB,bool preserveDstPad) const501 bool SkBitmap::copyPixelsTo(void* dst, size_t dstSize, size_t dstRB, bool preserveDstPad) const {
502     if (nullptr == dst) {
503         return false;
504     }
505     SkAutoPixmapUnlock result;
506     if (!this->requestLock(&result)) {
507         return false;
508     }
509     return copy_pixels_to(result.pixmap(), dst, dstSize, dstRB, preserveDstPad);
510 }
511 
512 ///////////////////////////////////////////////////////////////////////////////
513 
isImmutable() const514 bool SkBitmap::isImmutable() const {
515     return fPixelRef ? fPixelRef->isImmutable() : false;
516 }
517 
setImmutable()518 void SkBitmap::setImmutable() {
519     if (fPixelRef) {
520         fPixelRef->setImmutable();
521     }
522 }
523 
isVolatile() const524 bool SkBitmap::isVolatile() const {
525     return (fFlags & kImageIsVolatile_Flag) != 0;
526 }
527 
setIsVolatile(bool isVolatile)528 void SkBitmap::setIsVolatile(bool isVolatile) {
529     if (isVolatile) {
530         fFlags |= kImageIsVolatile_Flag;
531     } else {
532         fFlags &= ~kImageIsVolatile_Flag;
533     }
534 }
535 
getAddr(int x,int y) const536 void* SkBitmap::getAddr(int x, int y) const {
537     SkASSERT((unsigned)x < (unsigned)this->width());
538     SkASSERT((unsigned)y < (unsigned)this->height());
539 
540     char* base = (char*)this->getPixels();
541     if (base) {
542         base += y * this->rowBytes();
543         switch (this->colorType()) {
544             case kRGBA_8888_SkColorType:
545             case kBGRA_8888_SkColorType:
546                 base += x << 2;
547                 break;
548             case kARGB_4444_SkColorType:
549             case kRGB_565_SkColorType:
550                 base += x << 1;
551                 break;
552             case kAlpha_8_SkColorType:
553             case kIndex_8_SkColorType:
554             case kGray_8_SkColorType:
555                 base += x;
556                 break;
557             default:
558                 SkDEBUGFAIL("Can't return addr for config");
559                 base = nullptr;
560                 break;
561         }
562     }
563     return base;
564 }
565 
566 #include "SkHalf.h"
567 
getColor(int x,int y) const568 SkColor SkBitmap::getColor(int x, int y) const {
569     SkASSERT((unsigned)x < (unsigned)this->width());
570     SkASSERT((unsigned)y < (unsigned)this->height());
571 
572     switch (this->colorType()) {
573         case kGray_8_SkColorType: {
574             uint8_t* addr = this->getAddr8(x, y);
575             return SkColorSetRGB(*addr, *addr, *addr);
576         }
577         case kAlpha_8_SkColorType: {
578             uint8_t* addr = this->getAddr8(x, y);
579             return SkColorSetA(0, addr[0]);
580         }
581         case kIndex_8_SkColorType: {
582             SkPMColor c = this->getIndex8Color(x, y);
583             return SkUnPreMultiply::PMColorToColor(c);
584         }
585         case kRGB_565_SkColorType: {
586             uint16_t* addr = this->getAddr16(x, y);
587             return SkPixel16ToColor(addr[0]);
588         }
589         case kARGB_4444_SkColorType: {
590             uint16_t* addr = this->getAddr16(x, y);
591             SkPMColor c = SkPixel4444ToPixel32(addr[0]);
592             return SkUnPreMultiply::PMColorToColor(c);
593         }
594         case kBGRA_8888_SkColorType: {
595             uint32_t* addr = this->getAddr32(x, y);
596             SkPMColor c = SkSwizzle_BGRA_to_PMColor(addr[0]);
597             return SkUnPreMultiply::PMColorToColor(c);
598         }
599         case kRGBA_8888_SkColorType: {
600             uint32_t* addr = this->getAddr32(x, y);
601             SkPMColor c = SkSwizzle_RGBA_to_PMColor(addr[0]);
602             return SkUnPreMultiply::PMColorToColor(c);
603         }
604         case kRGBA_F16_SkColorType: {
605             const uint64_t* addr = (const uint64_t*)fPixels + y * (fRowBytes >> 3) + x;
606             Sk4f p4 = SkHalfToFloat_01(addr[0]);
607             if (p4[3]) {
608                 float inva = 1 / p4[3];
609                 p4 = p4 * Sk4f(inva, inva, inva, 1);
610             }
611             SkColor c;
612             SkNx_cast<uint8_t>(p4 * Sk4f(255) + Sk4f(0.5f)).store(&c);
613             // p4 is RGBA, but we want BGRA, so we need to swap next
614             return SkSwizzle_RB(c);
615         }
616         default:
617             SkASSERT(false);
618             return 0;
619     }
620     SkASSERT(false);  // Not reached.
621     return 0;
622 }
623 
compute_is_opaque(const SkPixmap & pmap)624 static bool compute_is_opaque(const SkPixmap& pmap) {
625     const int height = pmap.height();
626     const int width = pmap.width();
627 
628     switch (pmap.colorType()) {
629         case kAlpha_8_SkColorType: {
630             unsigned a = 0xFF;
631             for (int y = 0; y < height; ++y) {
632                 const uint8_t* row = pmap.addr8(0, y);
633                 for (int x = 0; x < width; ++x) {
634                     a &= row[x];
635                 }
636                 if (0xFF != a) {
637                     return false;
638                 }
639             }
640             return true;
641         } break;
642         case kIndex_8_SkColorType: {
643             const SkColorTable* ctable = pmap.ctable();
644             if (nullptr == ctable) {
645                 return false;
646             }
647             const SkPMColor* table = ctable->readColors();
648             SkPMColor c = (SkPMColor)~0;
649             for (int i = ctable->count() - 1; i >= 0; --i) {
650                 c &= table[i];
651             }
652             return 0xFF == SkGetPackedA32(c);
653         } break;
654         case kRGB_565_SkColorType:
655         case kGray_8_SkColorType:
656             return true;
657             break;
658         case kARGB_4444_SkColorType: {
659             unsigned c = 0xFFFF;
660             for (int y = 0; y < height; ++y) {
661                 const SkPMColor16* row = pmap.addr16(0, y);
662                 for (int x = 0; x < width; ++x) {
663                     c &= row[x];
664                 }
665                 if (0xF != SkGetPackedA4444(c)) {
666                     return false;
667                 }
668             }
669             return true;
670         } break;
671         case kBGRA_8888_SkColorType:
672         case kRGBA_8888_SkColorType: {
673             SkPMColor c = (SkPMColor)~0;
674             for (int y = 0; y < height; ++y) {
675                 const SkPMColor* row = pmap.addr32(0, y);
676                 for (int x = 0; x < width; ++x) {
677                     c &= row[x];
678                 }
679                 if (0xFF != SkGetPackedA32(c)) {
680                     return false;
681                 }
682             }
683             return true;
684         }
685         default:
686             break;
687     }
688     return false;
689 }
690 
ComputeIsOpaque(const SkBitmap & bm)691 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
692     SkAutoPixmapUnlock result;
693     if (!bm.requestLock(&result)) {
694         return false;
695     }
696     return compute_is_opaque(result.pixmap());
697 }
698 
699 
700 ///////////////////////////////////////////////////////////////////////////////
701 ///////////////////////////////////////////////////////////////////////////////
702 
erase(SkColor c,const SkIRect & area) const703 void SkBitmap::erase(SkColor c, const SkIRect& area) const {
704     SkDEBUGCODE(this->validate();)
705 
706     switch (fInfo.colorType()) {
707         case kUnknown_SkColorType:
708         case kIndex_8_SkColorType:
709             // TODO: can we ASSERT that we never get here?
710             return; // can't erase. Should we bzero so the memory is not uninitialized?
711         default:
712             break;
713     }
714 
715     SkAutoPixmapUnlock result;
716     if (!this->requestLock(&result)) {
717         return;
718     }
719 
720     if (result.pixmap().erase(c, area)) {
721         this->notifyPixelsChanged();
722     }
723 }
724 
eraseColor(SkColor c) const725 void SkBitmap::eraseColor(SkColor c) const {
726     this->erase(c, SkIRect::MakeWH(this->width(), this->height()));
727 }
728 
729 //////////////////////////////////////////////////////////////////////////////////////
730 //////////////////////////////////////////////////////////////////////////////////////
731 
extractSubset(SkBitmap * result,const SkIRect & subset) const732 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
733     SkDEBUGCODE(this->validate();)
734 
735     if (nullptr == result || nullptr == fPixelRef) {
736         return false;   // no src pixels
737     }
738 
739     SkIRect srcRect, r;
740     srcRect.set(0, 0, this->width(), this->height());
741     if (!r.intersect(srcRect, subset)) {
742         return false;   // r is empty (i.e. no intersection)
743     }
744 
745     if (fPixelRef->getTexture() != nullptr) {
746         // Do a deep copy
747         SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), this->profileType(), &subset);
748         if (pixelRef != nullptr) {
749             SkBitmap dst;
750             dst.setInfo(SkImageInfo::Make(subset.width(), subset.height(),
751                                           this->colorType(), this->alphaType()));
752             dst.setIsVolatile(this->isVolatile());
753             dst.setPixelRef(pixelRef)->unref();
754             SkDEBUGCODE(dst.validate());
755             result->swap(dst);
756             return true;
757         }
758     }
759 
760     // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
761     // exited above.
762     SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
763     SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
764 
765     SkBitmap dst;
766     dst.setInfo(SkImageInfo::Make(r.width(), r.height(), this->colorType(), this->alphaType()),
767                 this->rowBytes());
768     dst.setIsVolatile(this->isVolatile());
769 
770     if (fPixelRef) {
771         SkIPoint origin = fPixelRefOrigin;
772         origin.fX += r.fLeft;
773         origin.fY += r.fTop;
774         // share the pixelref with a custom offset
775         dst.setPixelRef(fPixelRef, origin);
776     }
777     SkDEBUGCODE(dst.validate();)
778 
779     // we know we're good, so commit to result
780     result->swap(dst);
781     return true;
782 }
783 
784 ///////////////////////////////////////////////////////////////////////////////
785 
canCopyTo(SkColorType dstColorType) const786 bool SkBitmap::canCopyTo(SkColorType dstColorType) const {
787     const SkColorType srcCT = this->colorType();
788 
789     if (srcCT == kUnknown_SkColorType) {
790         return false;
791     }
792 
793     bool sameConfigs = (srcCT == dstColorType);
794     switch (dstColorType) {
795         case kAlpha_8_SkColorType:
796         case kRGB_565_SkColorType:
797         case kRGBA_8888_SkColorType:
798         case kBGRA_8888_SkColorType:
799             break;
800         case kIndex_8_SkColorType:
801             if (!sameConfigs) {
802                 return false;
803             }
804             break;
805         case kARGB_4444_SkColorType:
806             return sameConfigs || kN32_SkColorType == srcCT || kIndex_8_SkColorType == srcCT;
807         case kGray_8_SkColorType:
808             switch (srcCT) {
809                 case kGray_8_SkColorType:
810                 case kRGBA_8888_SkColorType:
811                 case kBGRA_8888_SkColorType:
812                     return true;
813                 default:
814                     break;
815             }
816             return false;
817         default:
818             return false;
819     }
820     return true;
821 }
822 
readPixels(const SkImageInfo & requestedDstInfo,void * dstPixels,size_t dstRB,int x,int y) const823 bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
824                           int x, int y) const {
825     SkAutoPixmapUnlock src;
826     if (!this->requestLock(&src)) {
827         return false;
828     }
829     return src.pixmap().readPixels(requestedDstInfo, dstPixels, dstRB, x, y);
830 }
831 
copyTo(SkBitmap * dst,SkColorType dstColorType,Allocator * alloc) const832 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc) const {
833     if (!this->canCopyTo(dstColorType)) {
834         return false;
835     }
836 
837     // if we have a texture, first get those pixels
838     SkBitmap tmpSrc;
839     const SkBitmap* src = this;
840 
841     if (fPixelRef) {
842         SkIRect subset;
843         subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
844                        fInfo.width(), fInfo.height());
845         if (fPixelRef->readPixels(&tmpSrc, dstColorType, &subset)) {
846             if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) {
847                 // FIXME: The only meaningful implementation of readPixels
848                 // (GrPixelRef) assumes premultiplied pixels.
849                 return false;
850             }
851             SkASSERT(tmpSrc.width() == this->width());
852             SkASSERT(tmpSrc.height() == this->height());
853 
854             // did we get lucky and we can just return tmpSrc?
855             if (tmpSrc.colorType() == dstColorType && nullptr == alloc) {
856                 dst->swap(tmpSrc);
857                 // If the result is an exact copy, clone the gen ID.
858                 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) {
859                     dst->pixelRef()->cloneGenID(*fPixelRef);
860                 }
861                 return true;
862             }
863 
864             // fall through to the raster case
865             src = &tmpSrc;
866         }
867     }
868 
869     SkAutoPixmapUnlock srcUnlocker;
870     if (!src->requestLock(&srcUnlocker)) {
871         return false;
872     }
873     const SkPixmap& srcPM = srcUnlocker.pixmap();
874 
875     const SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
876     SkBitmap tmpDst;
877     if (!tmpDst.setInfo(dstInfo)) {
878         return false;
879     }
880 
881     // allocate colortable if srcConfig == kIndex8_Config
882     SkAutoTUnref<SkColorTable> ctable;
883     if (dstColorType == kIndex_8_SkColorType) {
884         ctable.reset(SkRef(srcPM.ctable()));
885     }
886     if (!tmpDst.tryAllocPixels(alloc, ctable)) {
887         return false;
888     }
889 
890     SkAutoPixmapUnlock dstUnlocker;
891     if (!tmpDst.requestLock(&dstUnlocker)) {
892         return false;
893     }
894 
895     if (!srcPM.readPixels(dstUnlocker.pixmap())) {
896         return false;
897     }
898 
899     //  (for BitmapHeap) Clone the pixelref genID even though we have a new pixelref.
900     //  The old copyTo impl did this, so we continue it for now.
901     //
902     //  TODO: should we ignore rowbytes (i.e. getSize)? Then it could just be
903     //      if (src_pixelref->info == dst_pixelref->info)
904     //
905     if (srcPM.colorType() == dstColorType && tmpDst.getSize() == srcPM.getSize64()) {
906         SkPixelRef* dstPixelRef = tmpDst.pixelRef();
907         if (dstPixelRef->info() == fPixelRef->info()) {
908             dstPixelRef->cloneGenID(*fPixelRef);
909         }
910     }
911 
912     dst->swap(tmpDst);
913     return true;
914 }
915 
deepCopyTo(SkBitmap * dst) const916 bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
917     const SkColorType dstCT = this->colorType();
918     const SkColorProfileType dstPT = this->profileType();
919 
920     if (!this->canCopyTo(dstCT)) {
921         return false;
922     }
923 
924     // If we have a PixelRef, and it supports deep copy, use it.
925     // Currently supported only by texture-backed bitmaps.
926     if (fPixelRef) {
927         SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, dstPT, nullptr);
928         if (pixelRef) {
929             uint32_t rowBytes;
930             if (this->colorType() == dstCT && this->profileType() == dstPT) {
931                 // Since there is no subset to pass to deepCopy, and deepCopy
932                 // succeeded, the new pixel ref must be identical.
933                 SkASSERT(fPixelRef->info() == pixelRef->info());
934                 pixelRef->cloneGenID(*fPixelRef);
935                 // Use the same rowBytes as the original.
936                 rowBytes = fRowBytes;
937             } else {
938                 // With the new config, an appropriate fRowBytes will be computed by setInfo.
939                 rowBytes = 0;
940             }
941 
942             const SkImageInfo info = fInfo.makeColorType(dstCT);
943             if (!dst->setInfo(info, rowBytes)) {
944                 return false;
945             }
946             dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref();
947             return true;
948         }
949     }
950 
951     if (this->getTexture()) {
952         return false;
953     } else {
954         return this->copyTo(dst, dstCT, nullptr);
955     }
956 }
957 
958 ///////////////////////////////////////////////////////////////////////////////
959 
rect_memset(uint8_t * array,U8CPU value,SkISize size,size_t rowBytes)960 static void rect_memset(uint8_t* array, U8CPU value, SkISize size, size_t rowBytes) {
961     for (int y = 0; y < size.height(); ++y) {
962         memset(array, value, size.width());
963         array += rowBytes;
964     }
965 }
966 
get_bitmap_alpha(const SkPixmap & pmap,uint8_t * SK_RESTRICT alpha,int alphaRowBytes)967 static void get_bitmap_alpha(const SkPixmap& pmap, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
968     SkColorType colorType = pmap.colorType();
969     int         w = pmap.width();
970     int         h = pmap.height();
971     size_t      rb = pmap.rowBytes();
972 
973     if (kAlpha_8_SkColorType == colorType && !pmap.isOpaque()) {
974         const uint8_t* s = pmap.addr8(0, 0);
975         while (--h >= 0) {
976             memcpy(alpha, s, w);
977             s += rb;
978             alpha += alphaRowBytes;
979         }
980     } else if (kN32_SkColorType == colorType && !pmap.isOpaque()) {
981         const SkPMColor* SK_RESTRICT s = pmap.addr32(0, 0);
982         while (--h >= 0) {
983             for (int x = 0; x < w; x++) {
984                 alpha[x] = SkGetPackedA32(s[x]);
985             }
986             s = (const SkPMColor*)((const char*)s + rb);
987             alpha += alphaRowBytes;
988         }
989     } else if (kARGB_4444_SkColorType == colorType && !pmap.isOpaque()) {
990         const SkPMColor16* SK_RESTRICT s = pmap.addr16(0, 0);
991         while (--h >= 0) {
992             for (int x = 0; x < w; x++) {
993                 alpha[x] = SkPacked4444ToA32(s[x]);
994             }
995             s = (const SkPMColor16*)((const char*)s + rb);
996             alpha += alphaRowBytes;
997         }
998     } else if (kIndex_8_SkColorType == colorType && !pmap.isOpaque()) {
999         const SkColorTable* ct = pmap.ctable();
1000         if (ct) {
1001             const SkPMColor* SK_RESTRICT table = ct->readColors();
1002             const uint8_t* SK_RESTRICT s = pmap.addr8(0, 0);
1003             while (--h >= 0) {
1004                 for (int x = 0; x < w; x++) {
1005                     alpha[x] = SkGetPackedA32(table[s[x]]);
1006                 }
1007                 s += rb;
1008                 alpha += alphaRowBytes;
1009             }
1010         }
1011     } else {    // src is opaque, so just fill alpha[] with 0xFF
1012         rect_memset(alpha, 0xFF, pmap.info().dimensions(), alphaRowBytes);
1013     }
1014 }
1015 
GetBitmapAlpha(const SkBitmap & src,uint8_t * SK_RESTRICT alpha,int alphaRowBytes)1016 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
1017     SkASSERT(alpha != nullptr);
1018     SkASSERT(alphaRowBytes >= src.width());
1019 
1020     SkAutoPixmapUnlock apl;
1021     if (!src.requestLock(&apl)) {
1022         rect_memset(alpha, 0, src.info().dimensions(), alphaRowBytes);
1023         return false;
1024     }
1025     get_bitmap_alpha(apl.pixmap(), alpha, alphaRowBytes);
1026     return true;
1027 }
1028 
1029 #include "SkPaint.h"
1030 #include "SkMaskFilter.h"
1031 #include "SkMatrix.h"
1032 
extractAlpha(SkBitmap * dst,const SkPaint * paint,Allocator * allocator,SkIPoint * offset) const1033 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
1034                             Allocator *allocator, SkIPoint* offset) const {
1035     SkDEBUGCODE(this->validate();)
1036 
1037     SkBitmap    tmpBitmap;
1038     SkMatrix    identity;
1039     SkMask      srcM, dstM;
1040 
1041     srcM.fBounds.set(0, 0, this->width(), this->height());
1042     srcM.fRowBytes = SkAlign4(this->width());
1043     srcM.fFormat = SkMask::kA8_Format;
1044 
1045     SkMaskFilter* filter = paint ? paint->getMaskFilter() : nullptr;
1046 
1047     // compute our (larger?) dst bounds if we have a filter
1048     if (filter) {
1049         identity.reset();
1050         if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
1051             goto NO_FILTER_CASE;
1052         }
1053         dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
1054     } else {
1055     NO_FILTER_CASE:
1056         tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
1057         if (!tmpBitmap.tryAllocPixels(allocator, nullptr)) {
1058             // Allocation of pixels for alpha bitmap failed.
1059             SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1060                     tmpBitmap.width(), tmpBitmap.height());
1061             return false;
1062         }
1063         GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
1064         if (offset) {
1065             offset->set(0, 0);
1066         }
1067         tmpBitmap.swap(*dst);
1068         return true;
1069     }
1070     srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
1071     SkAutoMaskFreeImage srcCleanup(srcM.fImage);
1072 
1073     GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
1074     if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
1075         goto NO_FILTER_CASE;
1076     }
1077     SkAutoMaskFreeImage dstCleanup(dstM.fImage);
1078 
1079     tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
1080                       dstM.fRowBytes);
1081     if (!tmpBitmap.tryAllocPixels(allocator, nullptr)) {
1082         // Allocation of pixels for alpha bitmap failed.
1083         SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1084                 tmpBitmap.width(), tmpBitmap.height());
1085         return false;
1086     }
1087     memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
1088     if (offset) {
1089         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
1090     }
1091     SkDEBUGCODE(tmpBitmap.validate();)
1092 
1093     tmpBitmap.swap(*dst);
1094     return true;
1095 }
1096 
1097 ///////////////////////////////////////////////////////////////////////////////
1098 
write_raw_pixels(SkWriteBuffer * buffer,const SkPixmap & pmap)1099 static void write_raw_pixels(SkWriteBuffer* buffer, const SkPixmap& pmap) {
1100     const SkImageInfo& info = pmap.info();
1101     const size_t snugRB = info.width() * info.bytesPerPixel();
1102     const char* src = (const char*)pmap.addr();
1103     const size_t ramRB = pmap.rowBytes();
1104 
1105     buffer->write32(SkToU32(snugRB));
1106     info.flatten(*buffer);
1107 
1108     const size_t size = snugRB * info.height();
1109     SkAutoTMalloc<char> storage(size);
1110     char* dst = storage.get();
1111     for (int y = 0; y < info.height(); ++y) {
1112         memcpy(dst, src, snugRB);
1113         dst += snugRB;
1114         src += ramRB;
1115     }
1116     buffer->writeByteArray(storage.get(), size);
1117 
1118     const SkColorTable* ct = pmap.ctable();
1119     if (kIndex_8_SkColorType == info.colorType() && ct) {
1120         buffer->writeBool(true);
1121         ct->writeToBuffer(*buffer);
1122     } else {
1123         buffer->writeBool(false);
1124     }
1125 }
1126 
WriteRawPixels(SkWriteBuffer * buffer,const SkBitmap & bitmap)1127 void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
1128     const SkImageInfo info = bitmap.info();
1129     if (0 == info.width() || 0 == info.height() || nullptr == bitmap.pixelRef()) {
1130         buffer->writeUInt(0); // instead of snugRB, signaling no pixels
1131         return;
1132     }
1133 
1134     SkAutoPixmapUnlock result;
1135     if (!bitmap.requestLock(&result)) {
1136         buffer->writeUInt(0); // instead of snugRB, signaling no pixels
1137         return;
1138     }
1139 
1140     write_raw_pixels(buffer, result.pixmap());
1141 }
1142 
ReadRawPixels(SkReadBuffer * buffer,SkBitmap * bitmap)1143 bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
1144     const size_t snugRB = buffer->readUInt();
1145     if (0 == snugRB) {  // no pixels
1146         return false;
1147     }
1148 
1149     SkImageInfo info;
1150     info.unflatten(*buffer);
1151 
1152     // If there was an error reading "info", don't use it to compute minRowBytes()
1153     if (!buffer->validate(true)) {
1154         return false;
1155     }
1156 
1157     const size_t ramRB = info.minRowBytes();
1158     const int height = SkMax32(info.height(), 0);
1159     const uint64_t snugSize = sk_64_mul(snugRB, height);
1160     const uint64_t ramSize = sk_64_mul(ramRB, height);
1161     static const uint64_t max_size_t = (size_t)(-1);
1162     if (!buffer->validate((snugSize <= ramSize) && (ramSize <= max_size_t))) {
1163         return false;
1164     }
1165 
1166     SkAutoDataUnref data(SkData::NewUninitialized(SkToSizeT(ramSize)));
1167     unsigned char* dst = (unsigned char*)data->writable_data();
1168     buffer->readByteArray(dst, SkToSizeT(snugSize));
1169 
1170     if (snugSize != ramSize) {
1171         const unsigned char* srcRow = dst + snugRB * (height - 1);
1172         unsigned char* dstRow = dst + ramRB * (height - 1);
1173         for (int y = height - 1; y >= 1; --y) {
1174             memmove(dstRow, srcRow, snugRB);
1175             srcRow -= snugRB;
1176             dstRow -= ramRB;
1177         }
1178         SkASSERT(srcRow == dstRow); // first row does not need to be moved
1179     }
1180 
1181     SkAutoTUnref<SkColorTable> ctable;
1182     if (buffer->readBool()) {
1183         ctable.reset(SkColorTable::Create(*buffer));
1184         if (!ctable) {
1185             return false;
1186         }
1187 
1188         if (info.isEmpty()) {
1189             // require an empty ctable
1190             if (ctable->count() != 0) {
1191                 buffer->validate(false);
1192                 return false;
1193             }
1194         } else {
1195             // require a non-empty ctable
1196             if (ctable->count() == 0) {
1197                 buffer->validate(false);
1198                 return false;
1199             }
1200             unsigned char maxIndex = ctable->count() - 1;
1201             for (uint64_t i = 0; i < ramSize; ++i) {
1202                 dst[i] = SkTMin(dst[i], maxIndex);
1203             }
1204         }
1205     }
1206 
1207     SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewWithData(info, info.minRowBytes(),
1208                                                               ctable.get(), data.get()));
1209     if (!pr.get()) {
1210         return false;
1211     }
1212     bitmap->setInfo(pr->info());
1213     bitmap->setPixelRef(pr, 0, 0);
1214     return true;
1215 }
1216 
1217 enum {
1218     SERIALIZE_PIXELTYPE_NONE,
1219     SERIALIZE_PIXELTYPE_REF_DATA
1220 };
1221 
1222 ///////////////////////////////////////////////////////////////////////////////
1223 
RLEPixels(int width,int height)1224 SkBitmap::RLEPixels::RLEPixels(int width, int height) {
1225     fHeight = height;
1226     fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*));
1227 }
1228 
~RLEPixels()1229 SkBitmap::RLEPixels::~RLEPixels() {
1230     sk_free(fYPtrs);
1231 }
1232 
1233 ///////////////////////////////////////////////////////////////////////////////
1234 
1235 #ifdef SK_DEBUG
validate() const1236 void SkBitmap::validate() const {
1237     fInfo.validate();
1238 
1239     // ImageInfo may not require this, but Bitmap ensures that opaque-only
1240     // colorTypes report opaque for their alphatype
1241     if (kRGB_565_SkColorType == fInfo.colorType()) {
1242         SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
1243     }
1244 
1245     SkASSERT(fInfo.validRowBytes(fRowBytes));
1246     uint8_t allFlags = kImageIsVolatile_Flag;
1247 #ifdef SK_BUILD_FOR_ANDROID
1248     allFlags |= kHasHardwareMipMap_Flag;
1249 #endif
1250     SkASSERT((~allFlags & fFlags) == 0);
1251     SkASSERT(fPixelLockCount >= 0);
1252 
1253     if (fPixels) {
1254         SkASSERT(fPixelRef);
1255         SkASSERT(fPixelLockCount > 0);
1256         SkASSERT(fPixelRef->isLocked());
1257         SkASSERT(fPixelRef->rowBytes() == fRowBytes);
1258         SkASSERT(fPixelRefOrigin.fX >= 0);
1259         SkASSERT(fPixelRefOrigin.fY >= 0);
1260         SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
1261         SkASSERT(fPixelRef->info().height() >= (int)this->height() + fPixelRefOrigin.fY);
1262         SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
1263     } else {
1264         SkASSERT(nullptr == fColorTable);
1265     }
1266 }
1267 #endif
1268 
1269 #ifndef SK_IGNORE_TO_STRING
1270 #include "SkString.h"
toString(SkString * str) const1271 void SkBitmap::toString(SkString* str) const {
1272 
1273     static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
1274         "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
1275     };
1276 
1277     str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
1278                  gColorTypeNames[this->colorType()]);
1279 
1280     str->append(" (");
1281     if (this->isOpaque()) {
1282         str->append("opaque");
1283     } else {
1284         str->append("transparent");
1285     }
1286     if (this->isImmutable()) {
1287         str->append(", immutable");
1288     } else {
1289         str->append(", not-immutable");
1290     }
1291     str->append(")");
1292 
1293     SkPixelRef* pr = this->pixelRef();
1294     if (nullptr == pr) {
1295         // show null or the explicit pixel address (rare)
1296         str->appendf(" pixels:%p", this->getPixels());
1297     } else {
1298         const char* uri = pr->getURI();
1299         if (uri) {
1300             str->appendf(" uri:\"%s\"", uri);
1301         } else {
1302             str->appendf(" pixelref:%p", pr);
1303         }
1304     }
1305 
1306     str->append(")");
1307 }
1308 #endif
1309 
1310 ///////////////////////////////////////////////////////////////////////////////
1311 
requestLock(SkAutoPixmapUnlock * result) const1312 bool SkBitmap::requestLock(SkAutoPixmapUnlock* result) const {
1313     SkASSERT(result);
1314 
1315     SkPixelRef* pr = fPixelRef;
1316     if (nullptr == pr) {
1317         return false;
1318     }
1319 
1320     // We have to lock the whole thing (using the pixelref's dimensions) until the api supports
1321     // a partial lock (with offset/origin). Hence we can't use our fInfo.
1322     SkPixelRef::LockRequest req = { pr->info().dimensions(), kNone_SkFilterQuality };
1323     SkPixelRef::LockResult res;
1324     if (pr->requestLock(req, &res)) {
1325         SkASSERT(res.fPixels);
1326         // The bitmap may be a subset of the pixelref's dimensions
1327         SkASSERT(fPixelRefOrigin.x() + fInfo.width()  <= res.fSize.width());
1328         SkASSERT(fPixelRefOrigin.y() + fInfo.height() <= res.fSize.height());
1329         const void* addr = (const char*)res.fPixels + SkColorTypeComputeOffset(fInfo.colorType(),
1330                                                                                fPixelRefOrigin.x(),
1331                                                                                fPixelRefOrigin.y(),
1332                                                                                res.fRowBytes);
1333 
1334         result->reset(SkPixmap(this->info(), addr, res.fRowBytes, res.fCTable),
1335                       res.fUnlockProc, res.fUnlockContext);
1336         return true;
1337     }
1338     return false;
1339 }
1340 
peekPixels(SkPixmap * pmap) const1341 bool SkBitmap::peekPixels(SkPixmap* pmap) const {
1342     if (fPixels) {
1343         if (pmap) {
1344             pmap->reset(fInfo, fPixels, fRowBytes, fColorTable);
1345         }
1346         return true;
1347     }
1348     return false;
1349 }
1350 
1351 ///////////////////////////////////////////////////////////////////////////////
1352 
1353 #ifdef SK_DEBUG
validate() const1354 void SkImageInfo::validate() const {
1355     SkASSERT(fWidth >= 0);
1356     SkASSERT(fHeight >= 0);
1357     SkASSERT(SkColorTypeIsValid(fColorType));
1358     SkASSERT(SkAlphaTypeIsValid(fAlphaType));
1359 }
1360 #endif
1361