• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2008 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #include "SkBitmap.h"
11 #include "SkColorPriv.h"
12 #include "SkDither.h"
13 #include "SkFlattenable.h"
14 #include "SkMallocPixelRef.h"
15 #include "SkMask.h"
16 #include "SkOrderedReadBuffer.h"
17 #include "SkOrderedWriteBuffer.h"
18 #include "SkPixelRef.h"
19 #include "SkThread.h"
20 #include "SkUnPreMultiply.h"
21 #include "SkUtils.h"
22 #include "SkPackBits.h"
23 #include <new>
24 
SK_DEFINE_INST_COUNT(SkBitmap::Allocator)25 SK_DEFINE_INST_COUNT(SkBitmap::Allocator)
26 
27 static bool isPos32Bits(const Sk64& value) {
28     return !value.isNeg() && value.is32();
29 }
30 
31 struct MipLevel {
32     void*       fPixels;
33     uint32_t    fRowBytes;
34     uint32_t    fWidth, fHeight;
35 };
36 
37 struct SkBitmap::MipMap : SkNoncopyable {
38     int32_t fRefCnt;
39     int     fLevelCount;
40 //  MipLevel    fLevel[fLevelCount];
41 //  Pixels[]
42 
AllocSkBitmap::MipMap43     static MipMap* Alloc(int levelCount, size_t pixelSize) {
44         if (levelCount < 0) {
45             return NULL;
46         }
47         Sk64 size;
48         size.setMul(levelCount + 1, sizeof(MipLevel));
49         size.add(sizeof(MipMap));
50         size.add(pixelSize);
51         if (!isPos32Bits(size)) {
52             return NULL;
53         }
54         MipMap* mm = (MipMap*)sk_malloc_throw(size.get32());
55         mm->fRefCnt = 1;
56         mm->fLevelCount = levelCount;
57         return mm;
58     }
59 
levelsSkBitmap::MipMap60     const MipLevel* levels() const { return (const MipLevel*)(this + 1); }
levelsSkBitmap::MipMap61     MipLevel* levels() { return (MipLevel*)(this + 1); }
62 
pixelsSkBitmap::MipMap63     const void* pixels() const { return levels() + fLevelCount; }
pixelsSkBitmap::MipMap64     void* pixels() { return levels() + fLevelCount; }
65 
refSkBitmap::MipMap66     void ref() {
67         if (SK_MaxS32 == sk_atomic_inc(&fRefCnt)) {
68             sk_throw();
69         }
70     }
unrefSkBitmap::MipMap71     void unref() {
72         SkASSERT(fRefCnt > 0);
73         if (sk_atomic_dec(&fRefCnt) == 1) {
74             sk_free(this);
75         }
76     }
77 };
78 
79 ///////////////////////////////////////////////////////////////////////////////
80 ///////////////////////////////////////////////////////////////////////////////
81 
SkBitmap()82 SkBitmap::SkBitmap() {
83     sk_bzero(this, sizeof(*this));
84 }
85 
SkBitmap(const SkBitmap & src)86 SkBitmap::SkBitmap(const SkBitmap& src) {
87     SkDEBUGCODE(src.validate();)
88     sk_bzero(this, sizeof(*this));
89     *this = src;
90     SkDEBUGCODE(this->validate();)
91 }
92 
~SkBitmap()93 SkBitmap::~SkBitmap() {
94     SkDEBUGCODE(this->validate();)
95     this->freePixels();
96 }
97 
operator =(const SkBitmap & src)98 SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
99     if (this != &src) {
100         this->freePixels();
101         memcpy(this, &src, sizeof(src));
102 
103         // inc src reference counts
104         SkSafeRef(src.fPixelRef);
105         SkSafeRef(src.fMipMap);
106 
107         // we reset our locks if we get blown away
108         fPixelLockCount = 0;
109 
110         /*  The src could be in 3 states
111             1. no pixelref, in which case we just copy/ref the pixels/ctable
112             2. unlocked pixelref, pixels/ctable should be null
113             3. locked pixelref, we should lock the ref again ourselves
114         */
115         if (NULL == fPixelRef) {
116             // leave fPixels as it is
117             SkSafeRef(fColorTable); // ref the user's ctable if present
118         } else {    // we have a pixelref, so pixels/ctable reflect it
119             // ignore the values from the memcpy
120             fPixels = NULL;
121             fColorTable = NULL;
122             // Note that what to for genID is somewhat arbitrary. We have no
123             // way to track changes to raw pixels across multiple SkBitmaps.
124             // Would benefit from an SkRawPixelRef type created by
125             // setPixels.
126             // Just leave the memcpy'ed one but they'll get out of sync
127             // as soon either is modified.
128         }
129     }
130 
131     SkDEBUGCODE(this->validate();)
132     return *this;
133 }
134 
swap(SkBitmap & other)135 void SkBitmap::swap(SkBitmap& other) {
136     SkTSwap(fColorTable, other.fColorTable);
137     SkTSwap(fPixelRef, other.fPixelRef);
138     SkTSwap(fPixelRefOffset, other.fPixelRefOffset);
139     SkTSwap(fPixelLockCount, other.fPixelLockCount);
140     SkTSwap(fMipMap, other.fMipMap);
141     SkTSwap(fPixels, other.fPixels);
142     SkTSwap(fRowBytes, other.fRowBytes);
143     SkTSwap(fWidth, other.fWidth);
144     SkTSwap(fHeight, other.fHeight);
145     SkTSwap(fConfig, other.fConfig);
146     SkTSwap(fFlags, other.fFlags);
147     SkTSwap(fBytesPerPixel, other.fBytesPerPixel);
148 
149     SkDEBUGCODE(this->validate();)
150 }
151 
reset()152 void SkBitmap::reset() {
153     this->freePixels();
154     sk_bzero(this, sizeof(*this));
155 }
156 
ComputeBytesPerPixel(SkBitmap::Config config)157 int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
158     int bpp;
159     switch (config) {
160         case kNo_Config:
161         case kA1_Config:
162             bpp = 0;   // not applicable
163             break;
164         case kRLE_Index8_Config:
165         case kA8_Config:
166         case kIndex8_Config:
167             bpp = 1;
168             break;
169         case kRGB_565_Config:
170         case kARGB_4444_Config:
171             bpp = 2;
172             break;
173         case kARGB_8888_Config:
174             bpp = 4;
175             break;
176         default:
177             SkDEBUGFAIL("unknown config");
178             bpp = 0;   // error
179             break;
180     }
181     return bpp;
182 }
183 
ComputeRowBytes(Config c,int width)184 int SkBitmap::ComputeRowBytes(Config c, int width) {
185     if (width < 0) {
186         return 0;
187     }
188 
189     Sk64 rowBytes;
190     rowBytes.setZero();
191 
192     switch (c) {
193         case kNo_Config:
194         case kRLE_Index8_Config:
195             break;
196         case kA1_Config:
197             rowBytes.set(width);
198             rowBytes.add(7);
199             rowBytes.shiftRight(3);
200             break;
201         case kA8_Config:
202         case kIndex8_Config:
203             rowBytes.set(width);
204             break;
205         case kRGB_565_Config:
206         case kARGB_4444_Config:
207             rowBytes.set(width);
208             rowBytes.shiftLeft(1);
209             break;
210         case kARGB_8888_Config:
211             rowBytes.set(width);
212             rowBytes.shiftLeft(2);
213             break;
214         default:
215             SkDEBUGFAIL("unknown config");
216             break;
217     }
218     return isPos32Bits(rowBytes) ? rowBytes.get32() : 0;
219 }
220 
ComputeSize64(Config c,int width,int height)221 Sk64 SkBitmap::ComputeSize64(Config c, int width, int height) {
222     Sk64 size;
223     size.setMul(SkBitmap::ComputeRowBytes(c, width), height);
224     return size;
225 }
226 
ComputeSize(Config c,int width,int height)227 size_t SkBitmap::ComputeSize(Config c, int width, int height) {
228     Sk64 size = SkBitmap::ComputeSize64(c, width, height);
229     return isPos32Bits(size) ? size.get32() : 0;
230 }
231 
ComputeSafeSize64(Config config,uint32_t width,uint32_t height,uint32_t rowBytes)232 Sk64 SkBitmap::ComputeSafeSize64(Config config,
233                                  uint32_t width,
234                                  uint32_t height,
235                                  uint32_t rowBytes) {
236     Sk64 safeSize;
237     safeSize.setZero();
238     if (height > 0) {
239         safeSize.set(ComputeRowBytes(config, width));
240         Sk64 sizeAllButLastRow;
241         sizeAllButLastRow.setMul(height - 1, rowBytes);
242         safeSize.add(sizeAllButLastRow);
243     }
244     SkASSERT(!safeSize.isNeg());
245     return safeSize;
246 }
247 
ComputeSafeSize(Config config,uint32_t width,uint32_t height,uint32_t rowBytes)248 size_t SkBitmap::ComputeSafeSize(Config config,
249                                  uint32_t width,
250                                  uint32_t height,
251                                  uint32_t rowBytes) {
252     Sk64 safeSize = ComputeSafeSize64(config, width, height, rowBytes);
253     return (safeSize.is32() ? safeSize.get32() : 0);
254 }
255 
getBounds(SkRect * bounds) const256 void SkBitmap::getBounds(SkRect* bounds) const {
257     SkASSERT(bounds);
258     bounds->set(0, 0,
259                 SkIntToScalar(fWidth), SkIntToScalar(fHeight));
260 }
261 
getBounds(SkIRect * bounds) const262 void SkBitmap::getBounds(SkIRect* bounds) const {
263     SkASSERT(bounds);
264     bounds->set(0, 0, fWidth, fHeight);
265 }
266 
267 ///////////////////////////////////////////////////////////////////////////////
268 
setConfig(Config c,int width,int height,int rowBytes)269 void SkBitmap::setConfig(Config c, int width, int height, int rowBytes) {
270     this->freePixels();
271 
272     if ((width | height | rowBytes) < 0) {
273         goto err;
274     }
275 
276     if (rowBytes == 0) {
277         rowBytes = SkBitmap::ComputeRowBytes(c, width);
278         if (0 == rowBytes && kNo_Config != c) {
279             goto err;
280         }
281     }
282 
283     fConfig     = SkToU8(c);
284     fWidth      = width;
285     fHeight     = height;
286     fRowBytes   = rowBytes;
287 
288     fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c);
289 
290     SkDEBUGCODE(this->validate();)
291     return;
292 
293     // if we got here, we had an error, so we reset the bitmap to empty
294 err:
295     this->reset();
296 }
297 
updatePixelsFromRef() const298 void SkBitmap::updatePixelsFromRef() const {
299     if (NULL != fPixelRef) {
300         if (fPixelLockCount > 0) {
301             SkASSERT(fPixelRef->isLocked());
302 
303             void* p = fPixelRef->pixels();
304             if (NULL != p) {
305                 p = (char*)p + fPixelRefOffset;
306             }
307             fPixels = p;
308             SkRefCnt_SafeAssign(fColorTable, fPixelRef->colorTable());
309         } else {
310             SkASSERT(0 == fPixelLockCount);
311             fPixels = NULL;
312             if (fColorTable) {
313                 fColorTable->unref();
314                 fColorTable = NULL;
315             }
316         }
317     }
318 }
319 
setPixelRef(SkPixelRef * pr,size_t offset)320 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) {
321     // do this first, we that we never have a non-zero offset with a null ref
322     if (NULL == pr) {
323         offset = 0;
324     }
325 
326     if (fPixelRef != pr || fPixelRefOffset != offset) {
327         if (fPixelRef != pr) {
328             this->freePixels();
329             SkASSERT(NULL == fPixelRef);
330 
331             SkSafeRef(pr);
332             fPixelRef = pr;
333         }
334         fPixelRefOffset = offset;
335         this->updatePixelsFromRef();
336     }
337 
338     SkDEBUGCODE(this->validate();)
339     return pr;
340 }
341 
lockPixels() const342 void SkBitmap::lockPixels() const {
343     if (NULL != fPixelRef && 1 == ++fPixelLockCount) {
344         fPixelRef->lockPixels();
345         this->updatePixelsFromRef();
346     }
347     SkDEBUGCODE(this->validate();)
348 }
349 
unlockPixels() const350 void SkBitmap::unlockPixels() const {
351     SkASSERT(NULL == fPixelRef || fPixelLockCount > 0);
352 
353     if (NULL != fPixelRef && 0 == --fPixelLockCount) {
354         fPixelRef->unlockPixels();
355         this->updatePixelsFromRef();
356     }
357     SkDEBUGCODE(this->validate();)
358 }
359 
lockPixelsAreWritable() const360 bool SkBitmap::lockPixelsAreWritable() const {
361     return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false;
362 }
363 
setPixels(void * p,SkColorTable * ctable)364 void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
365     if (NULL == p) {
366         this->setPixelRef(NULL, 0);
367         return;
368     }
369 
370     Sk64 size = this->getSize64();
371     SkASSERT(!size.isNeg() && size.is32());
372 
373     this->setPixelRef(new SkMallocPixelRef(p, size.get32(), ctable, false))->unref();
374     // since we're already allocated, we lockPixels right away
375     this->lockPixels();
376     SkDEBUGCODE(this->validate();)
377 }
378 
allocPixels(Allocator * allocator,SkColorTable * ctable)379 bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) {
380     HeapAllocator stdalloc;
381 
382     if (NULL == allocator) {
383         allocator = &stdalloc;
384     }
385     return allocator->allocPixelRef(this, ctable);
386 }
387 
freePixels()388 void SkBitmap::freePixels() {
389     // if we're gonna free the pixels, we certainly need to free the mipmap
390     this->freeMipMap();
391 
392     if (fColorTable) {
393         fColorTable->unref();
394         fColorTable = NULL;
395     }
396 
397     if (NULL != fPixelRef) {
398         if (fPixelLockCount > 0) {
399             fPixelRef->unlockPixels();
400         }
401         fPixelRef->unref();
402         fPixelRef = NULL;
403         fPixelRefOffset = 0;
404     }
405     fPixelLockCount = 0;
406     fPixels = NULL;
407 }
408 
freeMipMap()409 void SkBitmap::freeMipMap() {
410     if (fMipMap) {
411         fMipMap->unref();
412         fMipMap = NULL;
413     }
414 }
415 
getGenerationID() const416 uint32_t SkBitmap::getGenerationID() const {
417     return (fPixelRef) ? fPixelRef->getGenerationID() : 0;
418 }
419 
notifyPixelsChanged() const420 void SkBitmap::notifyPixelsChanged() const {
421     SkASSERT(!this->isImmutable());
422     if (fPixelRef) {
423         fPixelRef->notifyPixelsChanged();
424     }
425 }
426 
getTexture() const427 SkGpuTexture* SkBitmap::getTexture() const {
428     return fPixelRef ? fPixelRef->getTexture() : NULL;
429 }
430 
431 ///////////////////////////////////////////////////////////////////////////////
432 
433 /** We explicitly use the same allocator for our pixels that SkMask does,
434  so that we can freely assign memory allocated by one class to the other.
435  */
allocPixelRef(SkBitmap * dst,SkColorTable * ctable)436 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
437                                             SkColorTable* ctable) {
438     Sk64 size = dst->getSize64();
439     if (size.isNeg() || !size.is32()) {
440         return false;
441     }
442 
443     void* addr = sk_malloc_flags(size.get32(), 0);  // returns NULL on failure
444     if (NULL == addr) {
445         return false;
446     }
447 
448     dst->setPixelRef(new SkMallocPixelRef(addr, size.get32(), ctable))->unref();
449     // since we're already allocated, we lockPixels right away
450     dst->lockPixels();
451     return true;
452 }
453 
454 ///////////////////////////////////////////////////////////////////////////////
455 
getSafeSize() const456 size_t SkBitmap::getSafeSize() const {
457     // This is intended to be a size_t version of ComputeSafeSize64(), just
458     // faster. The computation is meant to be identical.
459     return (fHeight ? ((fHeight - 1) * fRowBytes) +
460             ComputeRowBytes(getConfig(), fWidth): 0);
461 }
462 
getSafeSize64() const463 Sk64 SkBitmap::getSafeSize64() const {
464     return ComputeSafeSize64(getConfig(), fWidth, fHeight, fRowBytes);
465 }
466 
copyPixelsTo(void * const dst,size_t dstSize,int dstRowBytes,bool preserveDstPad) const467 bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
468                             int dstRowBytes, bool preserveDstPad) const {
469 
470     if (dstRowBytes == -1)
471         dstRowBytes = fRowBytes;
472     SkASSERT(dstRowBytes >= 0);
473 
474     if (getConfig() == kRLE_Index8_Config ||
475         dstRowBytes < ComputeRowBytes(getConfig(), fWidth) ||
476         dst == NULL || (getPixels() == NULL && pixelRef() == NULL))
477         return false;
478 
479     if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) {
480         size_t safeSize = getSafeSize();
481         if (safeSize > dstSize || safeSize == 0)
482             return false;
483         else {
484             SkAutoLockPixels lock(*this);
485             // This implementation will write bytes beyond the end of each row,
486             // excluding the last row, if the bitmap's stride is greater than
487             // strictly required by the current config.
488             memcpy(dst, getPixels(), safeSize);
489 
490             return true;
491         }
492     } else {
493         // If destination has different stride than us, then copy line by line.
494         if (ComputeSafeSize(getConfig(), fWidth, fHeight, dstRowBytes) >
495             dstSize)
496             return false;
497         else {
498             // Just copy what we need on each line.
499             uint32_t rowBytes = ComputeRowBytes(getConfig(), fWidth);
500             SkAutoLockPixels lock(*this);
501             const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels());
502             uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
503             for (uint32_t row = 0; row < fHeight;
504                  row++, srcP += fRowBytes, dstP += dstRowBytes) {
505                 memcpy(dstP, srcP, rowBytes);
506             }
507 
508             return true;
509         }
510     }
511 }
512 
513 ///////////////////////////////////////////////////////////////////////////////
514 
isImmutable() const515 bool SkBitmap::isImmutable() const {
516     return fPixelRef ? fPixelRef->isImmutable() :
517         fFlags & kImageIsImmutable_Flag;
518 }
519 
setImmutable()520 void SkBitmap::setImmutable() {
521     if (fPixelRef) {
522         fPixelRef->setImmutable();
523     } else {
524         fFlags |= kImageIsImmutable_Flag;
525     }
526 }
527 
isOpaque() const528 bool SkBitmap::isOpaque() const {
529     switch (fConfig) {
530         case kNo_Config:
531             return true;
532 
533         case kA1_Config:
534         case kA8_Config:
535         case kARGB_4444_Config:
536         case kARGB_8888_Config:
537             return (fFlags & kImageIsOpaque_Flag) != 0;
538 
539         case kIndex8_Config:
540         case kRLE_Index8_Config: {
541                 uint32_t flags = 0;
542 
543                 this->lockPixels();
544                 // if lockPixels failed, we may not have a ctable ptr
545                 if (fColorTable) {
546                     flags = fColorTable->getFlags();
547                 }
548                 this->unlockPixels();
549 
550                 return (flags & SkColorTable::kColorsAreOpaque_Flag) != 0;
551             }
552 
553         case kRGB_565_Config:
554             return true;
555 
556         default:
557             SkDEBUGFAIL("unknown bitmap config pased to isOpaque");
558             return false;
559     }
560 }
561 
setIsOpaque(bool isOpaque)562 void SkBitmap::setIsOpaque(bool isOpaque) {
563     /*  we record this regardless of fConfig, though it is ignored in
564         isOpaque() for configs that can't support per-pixel alpha.
565     */
566     if (isOpaque) {
567         fFlags |= kImageIsOpaque_Flag;
568     } else {
569         fFlags &= ~kImageIsOpaque_Flag;
570     }
571 }
572 
isVolatile() const573 bool SkBitmap::isVolatile() const {
574     return (fFlags & kImageIsVolatile_Flag) != 0;
575 }
576 
setIsVolatile(bool isVolatile)577 void SkBitmap::setIsVolatile(bool isVolatile) {
578     if (isVolatile) {
579         fFlags |= kImageIsVolatile_Flag;
580     } else {
581         fFlags &= ~kImageIsVolatile_Flag;
582     }
583 }
584 
getAddr(int x,int y) const585 void* SkBitmap::getAddr(int x, int y) const {
586     SkASSERT((unsigned)x < (unsigned)this->width());
587     SkASSERT((unsigned)y < (unsigned)this->height());
588 
589     char* base = (char*)this->getPixels();
590     if (base) {
591         base += y * this->rowBytes();
592         switch (this->config()) {
593             case SkBitmap::kARGB_8888_Config:
594                 base += x << 2;
595                 break;
596             case SkBitmap::kARGB_4444_Config:
597             case SkBitmap::kRGB_565_Config:
598                 base += x << 1;
599                 break;
600             case SkBitmap::kA8_Config:
601             case SkBitmap::kIndex8_Config:
602                 base += x;
603                 break;
604             case SkBitmap::kA1_Config:
605                 base += x >> 3;
606                 break;
607             case kRLE_Index8_Config:
608                 SkDEBUGFAIL("Can't return addr for kRLE_Index8_Config");
609                 base = NULL;
610                 break;
611             default:
612                 SkDEBUGFAIL("Can't return addr for config");
613                 base = NULL;
614                 break;
615         }
616     }
617     return base;
618 }
619 
getColor(int x,int y) const620 SkColor SkBitmap::getColor(int x, int y) const {
621     SkASSERT((unsigned)x < (unsigned)this->width());
622     SkASSERT((unsigned)y < (unsigned)this->height());
623 
624     switch (this->config()) {
625         case SkBitmap::kA1_Config: {
626             uint8_t* addr = this->getAddr1(x, y);
627             uint8_t mask = 1 << (7  - (x % 8));
628             if (addr[0] & mask) {
629                 return SK_ColorBLACK;
630             } else {
631                 return 0;
632             }
633         }
634         case SkBitmap::kA8_Config: {
635             uint8_t* addr = this->getAddr8(x, y);
636             return SkColorSetA(0, addr[0]);
637         }
638         case SkBitmap::kIndex8_Config: {
639             SkPMColor c = this->getIndex8Color(x, y);
640             return SkUnPreMultiply::PMColorToColor(c);
641         }
642         case SkBitmap::kRGB_565_Config: {
643             uint16_t* addr = this->getAddr16(x, y);
644             return SkPixel16ToColor(addr[0]);
645         }
646         case SkBitmap::kARGB_4444_Config: {
647             uint16_t* addr = this->getAddr16(x, y);
648             SkPMColor c = SkPixel4444ToPixel32(addr[0]);
649             return SkUnPreMultiply::PMColorToColor(c);
650         }
651         case SkBitmap::kARGB_8888_Config: {
652             uint32_t* addr = this->getAddr32(x, y);
653             return SkUnPreMultiply::PMColorToColor(addr[0]);
654         }
655         case kRLE_Index8_Config: {
656             uint8_t dst;
657             const SkBitmap::RLEPixels* rle =
658                 (const SkBitmap::RLEPixels*)this->getPixels();
659             SkPackBits::Unpack8(&dst, x, 1, rle->packedAtY(y));
660             return SkUnPreMultiply::PMColorToColor((*fColorTable)[dst]);
661         }
662         case kNo_Config:
663         case kConfigCount:
664             SkASSERT(false);
665             return 0;
666     }
667     SkASSERT(false);  // Not reached.
668     return 0;
669 }
670 
ComputeIsOpaque(const SkBitmap & bm)671 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
672     SkAutoLockPixels alp(bm);
673     if (!bm.getPixels()) {
674         return false;
675     }
676 
677     const int height = bm.height();
678     const int width = bm.width();
679 
680     switch (bm.config()) {
681         case SkBitmap::kA1_Config: {
682             // TODO
683         } break;
684         case SkBitmap::kA8_Config: {
685             unsigned a = 0xFF;
686             for (int y = 0; y < height; ++y) {
687                 const uint8_t* row = bm.getAddr8(0, y);
688                 for (int x = 0; x < width; ++x) {
689                     a &= row[x];
690                 }
691                 if (0xFF != a) {
692                     return false;
693                 }
694             }
695             return true;
696         } break;
697         case kRLE_Index8_Config:
698         case SkBitmap::kIndex8_Config: {
699             SkAutoLockColors alc(bm);
700             const SkPMColor* table = alc.colors();
701             if (!table) {
702                 return false;
703             }
704             SkPMColor c = (SkPMColor)~0;
705             for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) {
706                 c &= table[i];
707             }
708             return 0xFF == SkGetPackedA32(c);
709         } break;
710         case SkBitmap::kRGB_565_Config:
711             return true;
712             break;
713         case SkBitmap::kARGB_4444_Config: {
714             unsigned c = 0xFFFF;
715             for (int y = 0; y < height; ++y) {
716                 const SkPMColor16* row = bm.getAddr16(0, y);
717                 for (int x = 0; x < width; ++x) {
718                     c &= row[x];
719                 }
720                 if (0xF != SkGetPackedA4444(c)) {
721                     return false;
722                 }
723             }
724             return true;
725         } break;
726         case SkBitmap::kARGB_8888_Config: {
727             SkPMColor c = (SkPMColor)~0;
728             for (int y = 0; y < height; ++y) {
729                 const SkPMColor* row = bm.getAddr32(0, y);
730                 for (int x = 0; x < width; ++x) {
731                     c &= row[x];
732                 }
733                 if (0xFF != SkGetPackedA32(c)) {
734                     return false;
735                 }
736             }
737             return true;
738         }
739         default:
740             break;
741     }
742     return false;
743 }
744 
745 
746 ///////////////////////////////////////////////////////////////////////////////
747 ///////////////////////////////////////////////////////////////////////////////
748 
eraseARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b) const749 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
750     SkDEBUGCODE(this->validate();)
751 
752     if (0 == fWidth || 0 == fHeight ||
753             kNo_Config == fConfig || kIndex8_Config == fConfig) {
754         return;
755     }
756 
757     SkAutoLockPixels alp(*this);
758     // perform this check after the lock call
759     if (!this->readyToDraw()) {
760         return;
761     }
762 
763     int height = fHeight;
764     const int width = fWidth;
765     const int rowBytes = fRowBytes;
766 
767     // make rgb premultiplied
768     if (255 != a) {
769         r = SkAlphaMul(r, a);
770         g = SkAlphaMul(g, a);
771         b = SkAlphaMul(b, a);
772     }
773 
774     switch (fConfig) {
775         case kA1_Config: {
776             uint8_t* p = (uint8_t*)fPixels;
777             const int count = (width + 7) >> 3;
778             a = (a >> 7) ? 0xFF : 0;
779             SkASSERT(count <= rowBytes);
780             while (--height >= 0) {
781                 memset(p, a, count);
782                 p += rowBytes;
783             }
784             break;
785         }
786         case kA8_Config: {
787             uint8_t* p = (uint8_t*)fPixels;
788             while (--height >= 0) {
789                 memset(p, a, width);
790                 p += rowBytes;
791             }
792             break;
793         }
794         case kARGB_4444_Config:
795         case kRGB_565_Config: {
796             uint16_t* p = (uint16_t*)fPixels;
797             uint16_t v;
798 
799             if (kARGB_4444_Config == fConfig) {
800                 v = SkPackARGB4444(a >> 4, r >> 4, g >> 4, b >> 4);
801             } else {    // kRGB_565_Config
802                 v = SkPackRGB16(r >> (8 - SK_R16_BITS), g >> (8 - SK_G16_BITS),
803                                 b >> (8 - SK_B16_BITS));
804             }
805             while (--height >= 0) {
806                 sk_memset16(p, v, width);
807                 p = (uint16_t*)((char*)p + rowBytes);
808             }
809             break;
810         }
811         case kARGB_8888_Config: {
812             uint32_t* p = (uint32_t*)fPixels;
813             uint32_t  v = SkPackARGB32(a, r, g, b);
814 
815             while (--height >= 0) {
816                 sk_memset32(p, v, width);
817                 p = (uint32_t*)((char*)p + rowBytes);
818             }
819             break;
820         }
821     }
822 
823     this->notifyPixelsChanged();
824 }
825 
826 //////////////////////////////////////////////////////////////////////////////////////
827 //////////////////////////////////////////////////////////////////////////////////////
828 
829 #define SUB_OFFSET_FAILURE  ((size_t)-1)
830 
831 // Declare these non-static so they can be tested by GpuBitmapCopyTest.
832 size_t getSubOffset(const SkBitmap& bm, int x, int y);
833 bool getUpperLeftFromOffset(const SkBitmap& bm, int* x, int* y);
834 
835 /**
836  *  Based on the Config and rowBytes() of bm, return the offset into an SkPixelRef of the pixel at
837  *  (x, y).
838  *  Note that the SkPixelRef does not need to be set yet. deepCopyTo takes advantage of this fact.
839  *  Also note that (x, y) may be outside the range of (0 - width(), 0 - height()), so long as it is
840  *  within the bounds of the SkPixelRef being used.
841  */
getSubOffset(const SkBitmap & bm,int x,int y)842 size_t getSubOffset(const SkBitmap& bm, int x, int y) {
843     switch (bm.getConfig()) {
844         case SkBitmap::kA8_Config:
845         case SkBitmap:: kIndex8_Config:
846             // x is fine as is for the calculation
847             break;
848 
849         case SkBitmap::kRGB_565_Config:
850         case SkBitmap::kARGB_4444_Config:
851             x <<= 1;
852             break;
853 
854         case SkBitmap::kARGB_8888_Config:
855             x <<= 2;
856             break;
857 
858         case SkBitmap::kNo_Config:
859         case SkBitmap::kA1_Config:
860         default:
861             return SUB_OFFSET_FAILURE;
862     }
863     return y * bm.rowBytes() + x;
864 }
865 
866 /**
867  *  Using the pixelRefOffset(), rowBytes(), and Config of bm, determine the (x, y) coordinate of the
868  *  upper left corner of bm relative to its SkPixelRef.
869  *  x and y must be non-NULL.
870  */
getUpperLeftFromOffset(const SkBitmap & bm,int * x,int * y)871 bool getUpperLeftFromOffset(const SkBitmap& bm, int* x, int* y) {
872     SkASSERT(x != NULL && y != NULL);
873     const size_t offset = bm.pixelRefOffset();
874     if (0 == offset) {
875         *x = *y = 0;
876         return true;
877     }
878     // Use integer division to find the correct y position.
879     *y = offset / bm.rowBytes();
880     // The remainder will be the x position, after we reverse getSubOffset.
881     *x = offset % bm.rowBytes();
882     switch (bm.getConfig()) {
883         case SkBitmap::kA8_Config:
884             // Fall through.
885         case SkBitmap::kIndex8_Config:
886             // x is unmodified
887             break;
888 
889         case SkBitmap::kRGB_565_Config:
890             // Fall through.
891         case SkBitmap::kARGB_4444_Config:
892             *x >>= 1;
893             break;
894 
895         case SkBitmap::kARGB_8888_Config:
896             *x >>= 2;
897             break;
898 
899         case SkBitmap::kNo_Config:
900             // Fall through.
901         case SkBitmap::kA1_Config:
902             // Fall through.
903         default:
904             return false;
905     }
906     return true;
907 }
908 
extractSubset(SkBitmap * result,const SkIRect & subset) const909 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
910     SkDEBUGCODE(this->validate();)
911 
912     if (NULL == result || NULL == fPixelRef) {
913         return false;   // no src pixels
914     }
915 
916     SkIRect srcRect, r;
917     srcRect.set(0, 0, this->width(), this->height());
918     if (!r.intersect(srcRect, subset)) {
919         return false;   // r is empty (i.e. no intersection)
920     }
921 
922     if (fPixelRef->getTexture() != NULL) {
923         // Do a deep copy
924         SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset);
925         if (pixelRef != NULL) {
926             SkBitmap dst;
927             dst.setConfig(this->config(), subset.width(), subset.height());
928             dst.setIsVolatile(this->isVolatile());
929             dst.setIsOpaque(this->isOpaque());
930             dst.setPixelRef(pixelRef)->unref();
931             SkDEBUGCODE(dst.validate());
932             result->swap(dst);
933             return true;
934         }
935     }
936 
937     if (kRLE_Index8_Config == fConfig) {
938         SkAutoLockPixels alp(*this);
939         // don't call readyToDraw(), since we can operate w/o a colortable
940         // at this stage
941         if (this->getPixels() == NULL) {
942             return false;
943         }
944         SkBitmap bm;
945 
946         bm.setConfig(kIndex8_Config, r.width(), r.height());
947         bm.allocPixels(this->getColorTable());
948         if (NULL == bm.getPixels()) {
949             return false;
950         }
951 
952         const RLEPixels* rle = (const RLEPixels*)this->getPixels();
953         uint8_t* dst = bm.getAddr8(0, 0);
954         const int width = bm.width();
955         const int rowBytes = bm.rowBytes();
956 
957         for (int y = r.fTop; y < r.fBottom; y++) {
958             SkPackBits::Unpack8(dst, r.fLeft, width, rle->packedAtY(y));
959             dst += rowBytes;
960         }
961         result->swap(bm);
962         return true;
963     }
964 
965     // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
966     // exited above.
967     SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
968     SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
969 
970     size_t offset = getSubOffset(*this, r.fLeft, r.fTop);
971     if (SUB_OFFSET_FAILURE == offset) {
972         return false;   // config not supported
973     }
974 
975     SkBitmap dst;
976     dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes());
977     dst.setIsVolatile(this->isVolatile());
978     dst.setIsOpaque(this->isOpaque());
979 
980     if (fPixelRef) {
981         // share the pixelref with a custom offset
982         dst.setPixelRef(fPixelRef, fPixelRefOffset + offset);
983     }
984     SkDEBUGCODE(dst.validate();)
985 
986     // we know we're good, so commit to result
987     result->swap(dst);
988     return true;
989 }
990 
991 ///////////////////////////////////////////////////////////////////////////////
992 
993 #include "SkCanvas.h"
994 #include "SkPaint.h"
995 
canCopyTo(Config dstConfig) const996 bool SkBitmap::canCopyTo(Config dstConfig) const {
997     if (this->getConfig() == kNo_Config) {
998         return false;
999     }
1000 
1001     bool sameConfigs = (this->config() == dstConfig);
1002     switch (dstConfig) {
1003         case kA8_Config:
1004         case kARGB_4444_Config:
1005         case kRGB_565_Config:
1006         case kARGB_8888_Config:
1007             break;
1008         case kA1_Config:
1009         case kIndex8_Config:
1010             if (!sameConfigs) {
1011                 return false;
1012             }
1013             break;
1014         default:
1015             return false;
1016     }
1017 
1018     // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config
1019     if (this->getConfig() == kA1_Config && !sameConfigs) {
1020         return false;
1021     }
1022 
1023     return true;
1024 }
1025 
copyTo(SkBitmap * dst,Config dstConfig,Allocator * alloc) const1026 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
1027     if (!this->canCopyTo(dstConfig)) {
1028         return false;
1029     }
1030 
1031     // if we have a texture, first get those pixels
1032     SkBitmap tmpSrc;
1033     const SkBitmap* src = this;
1034 
1035     if (fPixelRef) {
1036         SkIRect subset;
1037         if (getUpperLeftFromOffset(*this, &subset.fLeft, &subset.fTop)) {
1038             subset.fRight = subset.fLeft + fWidth;
1039             subset.fBottom = subset.fTop + fHeight;
1040             if (fPixelRef->readPixels(&tmpSrc, &subset)) {
1041                 SkASSERT(tmpSrc.width() == this->width());
1042                 SkASSERT(tmpSrc.height() == this->height());
1043 
1044                 // did we get lucky and we can just return tmpSrc?
1045                 if (tmpSrc.config() == dstConfig && NULL == alloc) {
1046                     dst->swap(tmpSrc);
1047                     if (dst->pixelRef() && this->config() == dstConfig) {
1048                         dst->pixelRef()->fGenerationID = fPixelRef->getGenerationID();
1049                     }
1050                     return true;
1051                 }
1052 
1053                 // fall through to the raster case
1054                 src = &tmpSrc;
1055             }
1056         }
1057     }
1058 
1059     // we lock this now, since we may need its colortable
1060     SkAutoLockPixels srclock(*src);
1061     if (!src->readyToDraw()) {
1062         return false;
1063     }
1064 
1065     SkBitmap tmpDst;
1066     tmpDst.setConfig(dstConfig, src->width(), src->height());
1067 
1068     // allocate colortable if srcConfig == kIndex8_Config
1069     SkColorTable* ctable = (dstConfig == kIndex8_Config) ?
1070     new SkColorTable(*src->getColorTable()) : NULL;
1071     SkAutoUnref au(ctable);
1072     if (!tmpDst.allocPixels(alloc, ctable)) {
1073         return false;
1074     }
1075 
1076     if (!tmpDst.readyToDraw()) {
1077         // allocator/lock failed
1078         return false;
1079     }
1080 
1081     /* do memcpy for the same configs cases, else use drawing
1082     */
1083     if (src->config() == dstConfig) {
1084         if (tmpDst.getSize() == src->getSize()) {
1085             memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize());
1086             SkPixelRef* pixelRef = tmpDst.pixelRef();
1087             if (pixelRef != NULL) {
1088                 pixelRef->fGenerationID = this->getGenerationID();
1089             }
1090         } else {
1091             const char* srcP = reinterpret_cast<const char*>(src->getPixels());
1092             char* dstP = reinterpret_cast<char*>(tmpDst.getPixels());
1093             // to be sure we don't read too much, only copy our logical pixels
1094             size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel();
1095             for (int y = 0; y < tmpDst.height(); y++) {
1096                 memcpy(dstP, srcP, bytesToCopy);
1097                 srcP += src->rowBytes();
1098                 dstP += tmpDst.rowBytes();
1099             }
1100         }
1101     } else {
1102         // if the src has alpha, we have to clear the dst first
1103         if (!src->isOpaque()) {
1104             tmpDst.eraseColor(SK_ColorTRANSPARENT);
1105         }
1106 
1107         SkCanvas canvas(tmpDst);
1108         SkPaint  paint;
1109 
1110         paint.setDither(true);
1111         canvas.drawBitmap(*src, 0, 0, &paint);
1112     }
1113 
1114     tmpDst.setIsOpaque(src->isOpaque());
1115 
1116     dst->swap(tmpDst);
1117     return true;
1118 }
1119 
deepCopyTo(SkBitmap * dst,Config dstConfig) const1120 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
1121     if (!this->canCopyTo(dstConfig)) {
1122         return false;
1123     }
1124 
1125     // If we have a PixelRef, and it supports deep copy, use it.
1126     // Currently supported only by texture-backed bitmaps.
1127     if (fPixelRef) {
1128         SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig);
1129         if (pixelRef) {
1130             uint32_t rowBytes;
1131             if (dstConfig == fConfig) {
1132                 pixelRef->fGenerationID = fPixelRef->getGenerationID();
1133                 // Use the same rowBytes as the original.
1134                 rowBytes = fRowBytes;
1135             } else {
1136                 // With the new config, an appropriate fRowBytes will be computed by setConfig.
1137                 rowBytes = 0;
1138             }
1139             dst->setConfig(dstConfig, fWidth, fHeight, rowBytes);
1140 
1141             size_t pixelRefOffset;
1142             if (0 == fPixelRefOffset || dstConfig == fConfig) {
1143                 // Use the same offset as the original.
1144                 pixelRefOffset = fPixelRefOffset;
1145             } else {
1146                 // Find the correct offset in the new config. This needs to be done after calling
1147                 // setConfig so dst's fConfig and fRowBytes have been set properly.
1148                 int x, y;
1149                 if (!getUpperLeftFromOffset(*this, &x, &y)) {
1150                     return false;
1151                 }
1152                 pixelRefOffset = getSubOffset(*dst, x, y);
1153                 if (SUB_OFFSET_FAILURE == pixelRefOffset) {
1154                     return false;
1155                 }
1156             }
1157             dst->setPixelRef(pixelRef, pixelRefOffset)->unref();
1158             return true;
1159         }
1160     }
1161 
1162     if (this->getTexture()) {
1163         return false;
1164     } else {
1165         return this->copyTo(dst, dstConfig, NULL);
1166     }
1167 }
1168 
1169 ///////////////////////////////////////////////////////////////////////////////
1170 ///////////////////////////////////////////////////////////////////////////////
1171 
downsampleby2_proc32(SkBitmap * dst,int x,int y,const SkBitmap & src)1172 static void downsampleby2_proc32(SkBitmap* dst, int x, int y,
1173                                  const SkBitmap& src) {
1174     x <<= 1;
1175     y <<= 1;
1176     const SkPMColor* p = src.getAddr32(x, y);
1177     const SkPMColor* baseP = p;
1178     SkPMColor c, ag, rb;
1179 
1180     c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
1181     if (x < src.width() - 1) {
1182         p += 1;
1183     }
1184     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
1185 
1186     p = baseP;
1187     if (y < src.height() - 1) {
1188         p += src.rowBytes() >> 2;
1189     }
1190     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
1191     if (x < src.width() - 1) {
1192         p += 1;
1193     }
1194     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
1195 
1196     *dst->getAddr32(x >> 1, y >> 1) =
1197         ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
1198 }
1199 
expand16(U16CPU c)1200 static inline uint32_t expand16(U16CPU c) {
1201     return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
1202 }
1203 
1204 // returns dirt in the top 16bits, but we don't care, since we only
1205 // store the low 16bits.
pack16(uint32_t c)1206 static inline U16CPU pack16(uint32_t c) {
1207     return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE);
1208 }
1209 
downsampleby2_proc16(SkBitmap * dst,int x,int y,const SkBitmap & src)1210 static void downsampleby2_proc16(SkBitmap* dst, int x, int y,
1211                                  const SkBitmap& src) {
1212     x <<= 1;
1213     y <<= 1;
1214     const uint16_t* p = src.getAddr16(x, y);
1215     const uint16_t* baseP = p;
1216     SkPMColor       c;
1217 
1218     c = expand16(*p);
1219     if (x < src.width() - 1) {
1220         p += 1;
1221     }
1222     c += expand16(*p);
1223 
1224     p = baseP;
1225     if (y < src.height() - 1) {
1226         p += src.rowBytes() >> 1;
1227     }
1228     c += expand16(*p);
1229     if (x < src.width() - 1) {
1230         p += 1;
1231     }
1232     c += expand16(*p);
1233 
1234     *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
1235 }
1236 
expand4444(U16CPU c)1237 static uint32_t expand4444(U16CPU c) {
1238     return (c & 0xF0F) | ((c & ~0xF0F) << 12);
1239 }
1240 
collaps4444(uint32_t c)1241 static U16CPU collaps4444(uint32_t c) {
1242     return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
1243 }
1244 
downsampleby2_proc4444(SkBitmap * dst,int x,int y,const SkBitmap & src)1245 static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
1246                                    const SkBitmap& src) {
1247     x <<= 1;
1248     y <<= 1;
1249     const uint16_t* p = src.getAddr16(x, y);
1250     const uint16_t* baseP = p;
1251     uint32_t        c;
1252 
1253     c = expand4444(*p);
1254     if (x < src.width() - 1) {
1255         p += 1;
1256     }
1257     c += expand4444(*p);
1258 
1259     p = baseP;
1260     if (y < src.height() - 1) {
1261         p += src.rowBytes() >> 1;
1262     }
1263     c += expand4444(*p);
1264     if (x < src.width() - 1) {
1265         p += 1;
1266     }
1267     c += expand4444(*p);
1268 
1269     *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
1270 }
1271 
buildMipMap(bool forceRebuild)1272 void SkBitmap::buildMipMap(bool forceRebuild) {
1273     if (forceRebuild)
1274         this->freeMipMap();
1275     else if (fMipMap)
1276         return; // we're already built
1277 
1278     SkASSERT(NULL == fMipMap);
1279 
1280     void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
1281 
1282     const SkBitmap::Config config = this->getConfig();
1283 
1284     switch (config) {
1285         case kARGB_8888_Config:
1286             proc = downsampleby2_proc32;
1287             break;
1288         case kRGB_565_Config:
1289             proc = downsampleby2_proc16;
1290             break;
1291         case kARGB_4444_Config:
1292             proc = downsampleby2_proc4444;
1293             break;
1294         case kIndex8_Config:
1295         case kA8_Config:
1296         default:
1297             return; // don't build mipmaps for these configs
1298     }
1299 
1300     SkAutoLockPixels alp(*this);
1301     if (!this->readyToDraw()) {
1302         return;
1303     }
1304 
1305     // whip through our loop to compute the exact size needed
1306     size_t  size = 0;
1307     int     maxLevels = 0;
1308     {
1309         int width = this->width();
1310         int height = this->height();
1311         for (;;) {
1312             width >>= 1;
1313             height >>= 1;
1314             if (0 == width || 0 == height) {
1315                 break;
1316             }
1317             size += ComputeRowBytes(config, width) * height;
1318             maxLevels += 1;
1319         }
1320     }
1321 
1322     // nothing to build
1323     if (0 == maxLevels) {
1324         return;
1325     }
1326 
1327     SkBitmap srcBM(*this);
1328     srcBM.lockPixels();
1329     if (!srcBM.readyToDraw()) {
1330         return;
1331     }
1332 
1333     MipMap* mm = MipMap::Alloc(maxLevels, size);
1334     if (NULL == mm) {
1335         return;
1336     }
1337 
1338     MipLevel*   level = mm->levels();
1339     uint8_t*    addr = (uint8_t*)mm->pixels();
1340     int         width = this->width();
1341     int         height = this->height();
1342     unsigned    rowBytes;
1343     SkBitmap    dstBM;
1344 
1345     for (int i = 0; i < maxLevels; i++) {
1346         width >>= 1;
1347         height >>= 1;
1348         rowBytes = ComputeRowBytes(config, width);
1349 
1350         level[i].fPixels   = addr;
1351         level[i].fWidth    = width;
1352         level[i].fHeight   = height;
1353         level[i].fRowBytes = rowBytes;
1354 
1355         dstBM.setConfig(config, width, height, rowBytes);
1356         dstBM.setPixels(addr);
1357 
1358         srcBM.lockPixels();
1359         for (int y = 0; y < height; y++) {
1360             for (int x = 0; x < width; x++) {
1361                 proc(&dstBM, x, y, srcBM);
1362             }
1363         }
1364         srcBM.unlockPixels();
1365 
1366         srcBM = dstBM;
1367         addr += height * rowBytes;
1368     }
1369     SkASSERT(addr == (uint8_t*)mm->pixels() + size);
1370     fMipMap = mm;
1371 }
1372 
hasMipMap() const1373 bool SkBitmap::hasMipMap() const {
1374     return fMipMap != NULL;
1375 }
1376 
extractMipLevel(SkBitmap * dst,SkFixed sx,SkFixed sy)1377 int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) {
1378     if (NULL == fMipMap) {
1379         return 0;
1380     }
1381 
1382     int level = ComputeMipLevel(sx, sy) >> 16;
1383     SkASSERT(level >= 0);
1384     if (level <= 0) {
1385         return 0;
1386     }
1387 
1388     if (level >= fMipMap->fLevelCount) {
1389         level = fMipMap->fLevelCount - 1;
1390     }
1391     if (dst) {
1392         const MipLevel& mip = fMipMap->levels()[level - 1];
1393         dst->setConfig((SkBitmap::Config)this->config(),
1394                        mip.fWidth, mip.fHeight, mip.fRowBytes);
1395         dst->setPixels(mip.fPixels);
1396     }
1397     return level;
1398 }
1399 
ComputeMipLevel(SkFixed sx,SkFixed sy)1400 SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) {
1401     sx = SkAbs32(sx);
1402     sy = SkAbs32(sy);
1403     if (sx < sy) {
1404         sx = sy;
1405     }
1406     if (sx < SK_Fixed1) {
1407         return 0;
1408     }
1409     int clz = SkCLZ(sx);
1410     SkASSERT(clz >= 1 && clz <= 15);
1411     return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16);
1412 }
1413 
1414 ///////////////////////////////////////////////////////////////////////////////
1415 
GetBitmapAlpha(const SkBitmap & src,uint8_t * SK_RESTRICT alpha,int alphaRowBytes)1416 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
1417                            int alphaRowBytes) {
1418     SkASSERT(alpha != NULL);
1419     SkASSERT(alphaRowBytes >= src.width());
1420 
1421     SkBitmap::Config config = src.getConfig();
1422     int              w = src.width();
1423     int              h = src.height();
1424     int              rb = src.rowBytes();
1425 
1426     SkAutoLockPixels alp(src);
1427     if (!src.readyToDraw()) {
1428         // zero out the alpha buffer and return
1429         while (--h >= 0) {
1430             memset(alpha, 0, w);
1431             alpha += alphaRowBytes;
1432         }
1433         return false;
1434     }
1435 
1436     if (SkBitmap::kA8_Config == config && !src.isOpaque()) {
1437         const uint8_t* s = src.getAddr8(0, 0);
1438         while (--h >= 0) {
1439             memcpy(alpha, s, w);
1440             s += rb;
1441             alpha += alphaRowBytes;
1442         }
1443     } else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) {
1444         const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
1445         while (--h >= 0) {
1446             for (int x = 0; x < w; x++) {
1447                 alpha[x] = SkGetPackedA32(s[x]);
1448             }
1449             s = (const SkPMColor*)((const char*)s + rb);
1450             alpha += alphaRowBytes;
1451         }
1452     } else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) {
1453         const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
1454         while (--h >= 0) {
1455             for (int x = 0; x < w; x++) {
1456                 alpha[x] = SkPacked4444ToA32(s[x]);
1457             }
1458             s = (const SkPMColor16*)((const char*)s + rb);
1459             alpha += alphaRowBytes;
1460         }
1461     } else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) {
1462         SkColorTable* ct = src.getColorTable();
1463         if (ct) {
1464             const SkPMColor* SK_RESTRICT table = ct->lockColors();
1465             const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
1466             while (--h >= 0) {
1467                 for (int x = 0; x < w; x++) {
1468                     alpha[x] = SkGetPackedA32(table[s[x]]);
1469                 }
1470                 s += rb;
1471                 alpha += alphaRowBytes;
1472             }
1473             ct->unlockColors(false);
1474         }
1475     } else {    // src is opaque, so just fill alpha[] with 0xFF
1476         memset(alpha, 0xFF, h * alphaRowBytes);
1477     }
1478     return true;
1479 }
1480 
1481 #include "SkPaint.h"
1482 #include "SkMaskFilter.h"
1483 #include "SkMatrix.h"
1484 
extractAlpha(SkBitmap * dst,const SkPaint * paint,Allocator * allocator,SkIPoint * offset) const1485 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
1486                             Allocator *allocator, SkIPoint* offset) const {
1487     SkDEBUGCODE(this->validate();)
1488 
1489     SkBitmap    tmpBitmap;
1490     SkMatrix    identity;
1491     SkMask      srcM, dstM;
1492 
1493     srcM.fBounds.set(0, 0, this->width(), this->height());
1494     srcM.fRowBytes = SkAlign4(this->width());
1495     srcM.fFormat = SkMask::kA8_Format;
1496 
1497     SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL;
1498 
1499     // compute our (larger?) dst bounds if we have a filter
1500     if (NULL != filter) {
1501         identity.reset();
1502         srcM.fImage = NULL;
1503         if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
1504             goto NO_FILTER_CASE;
1505         }
1506         dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
1507     } else {
1508     NO_FILTER_CASE:
1509         tmpBitmap.setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
1510                        srcM.fRowBytes);
1511         if (!tmpBitmap.allocPixels(allocator, NULL)) {
1512             // Allocation of pixels for alpha bitmap failed.
1513             SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1514                     tmpBitmap.width(), tmpBitmap.height());
1515             return false;
1516         }
1517         GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
1518         if (offset) {
1519             offset->set(0, 0);
1520         }
1521         tmpBitmap.swap(*dst);
1522         return true;
1523     }
1524     srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
1525     SkAutoMaskFreeImage srcCleanup(srcM.fImage);
1526 
1527     GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
1528     if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
1529         goto NO_FILTER_CASE;
1530     }
1531     SkAutoMaskFreeImage dstCleanup(dstM.fImage);
1532 
1533     tmpBitmap.setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
1534                    dstM.fBounds.height(), dstM.fRowBytes);
1535     if (!tmpBitmap.allocPixels(allocator, NULL)) {
1536         // Allocation of pixels for alpha bitmap failed.
1537         SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1538                 tmpBitmap.width(), tmpBitmap.height());
1539         return false;
1540     }
1541     memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
1542     if (offset) {
1543         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
1544     }
1545     SkDEBUGCODE(tmpBitmap.validate();)
1546 
1547     tmpBitmap.swap(*dst);
1548     return true;
1549 }
1550 
1551 ///////////////////////////////////////////////////////////////////////////////
1552 
1553 enum {
1554     SERIALIZE_PIXELTYPE_NONE,
1555     SERIALIZE_PIXELTYPE_REF_DATA
1556 };
1557 
flatten(SkFlattenableWriteBuffer & buffer) const1558 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const {
1559     buffer.writeInt(fWidth);
1560     buffer.writeInt(fHeight);
1561     buffer.writeInt(fRowBytes);
1562     buffer.writeInt(fConfig);
1563     buffer.writeBool(this->isOpaque());
1564 
1565     if (fPixelRef) {
1566         if (fPixelRef->getFactory()) {
1567             buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA);
1568             buffer.writeUInt(fPixelRefOffset);
1569             buffer.writeFlattenable(fPixelRef);
1570             return;
1571         }
1572         // if we get here, we can't record the pixels
1573         buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
1574     } else {
1575         buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
1576     }
1577 }
1578 
unflatten(SkFlattenableReadBuffer & buffer)1579 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) {
1580     this->reset();
1581 
1582     int width = buffer.readInt();
1583     int height = buffer.readInt();
1584     int rowBytes = buffer.readInt();
1585     int config = buffer.readInt();
1586 
1587     this->setConfig((Config)config, width, height, rowBytes);
1588     this->setIsOpaque(buffer.readBool());
1589 
1590     int reftype = buffer.readInt();
1591     switch (reftype) {
1592         case SERIALIZE_PIXELTYPE_REF_DATA: {
1593             size_t offset = buffer.readUInt();
1594             SkPixelRef* pr = buffer.readFlattenableT<SkPixelRef>();
1595             SkSafeUnref(this->setPixelRef(pr, offset));
1596             break;
1597         }
1598         case SERIALIZE_PIXELTYPE_NONE:
1599             break;
1600         default:
1601             SkDEBUGFAIL("unrecognized pixeltype in serialized data");
1602             sk_throw();
1603     }
1604 }
1605 
1606 ///////////////////////////////////////////////////////////////////////////////
1607 
RLEPixels(int width,int height)1608 SkBitmap::RLEPixels::RLEPixels(int width, int height) {
1609     fHeight = height;
1610     fYPtrs = (uint8_t**)sk_malloc_throw(height * sizeof(uint8_t*));
1611     sk_bzero(fYPtrs, height * sizeof(uint8_t*));
1612 }
1613 
~RLEPixels()1614 SkBitmap::RLEPixels::~RLEPixels() {
1615     sk_free(fYPtrs);
1616 }
1617 
1618 ///////////////////////////////////////////////////////////////////////////////
1619 
1620 #ifdef SK_DEBUG
validate() const1621 void SkBitmap::validate() const {
1622     SkASSERT(fConfig < kConfigCount);
1623     SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth));
1624     SkASSERT(fFlags <= (kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag));
1625     SkASSERT(fPixelLockCount >= 0);
1626     SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000);
1627     SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel);
1628 
1629 #if 0   // these asserts are not thread-correct, so disable for now
1630     if (fPixelRef) {
1631         if (fPixelLockCount > 0) {
1632             SkASSERT(fPixelRef->isLocked());
1633         } else {
1634             SkASSERT(NULL == fPixels);
1635             SkASSERT(NULL == fColorTable);
1636         }
1637     }
1638 #endif
1639 }
1640 #endif
1641 
1642 #ifdef SK_DEVELOPER
toString(SkString * str) const1643 void SkBitmap::toString(SkString* str) const {
1644 
1645     static const char* gConfigNames[kConfigCount] = {
1646         "NONE", "A1", "A8", "INDEX8", "565", "4444", "8888", "RLE"
1647     };
1648 
1649     str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
1650                  gConfigNames[this->config()]);
1651 
1652     str->append(" (");
1653     if (this->isOpaque()) {
1654         str->append("opaque");
1655     } else {
1656         str->append("transparent");
1657     }
1658     if (this->isImmutable()) {
1659         str->append(", immutable");
1660     } else {
1661         str->append(", not-immutable");
1662     }
1663     str->append(")");
1664 
1665     SkPixelRef* pr = this->pixelRef();
1666     if (NULL == pr) {
1667         // show null or the explicit pixel address (rare)
1668         str->appendf(" pixels:%p", this->getPixels());
1669     } else {
1670         const char* uri = pr->getURI();
1671         if (NULL != uri) {
1672             str->appendf(" uri:\"%s\"", uri);
1673         } else {
1674             str->appendf(" pixelref:%p", pr);
1675         }
1676     }
1677 
1678     str->append(")");
1679 }
1680 #endif
1681