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