• 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 "SkImagePriv.h"
15 #include "SkMallocPixelRef.h"
16 #include "SkMask.h"
17 #include "SkOrderedReadBuffer.h"
18 #include "SkOrderedWriteBuffer.h"
19 #include "SkPixelRef.h"
20 #include "SkThread.h"
21 #include "SkUnPreMultiply.h"
22 #include "SkUtils.h"
23 #include "SkValidationUtils.h"
24 #include "SkPackBits.h"
25 #include <new>
26 
isPos32Bits(const Sk64 & value)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(SkToS32(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(fAlphaType, other.fAlphaType);
147     SkTSwap(fFlags, other.fFlags);
148     SkTSwap(fBytesPerPixel, other.fBytesPerPixel);
149 
150     SkDEBUGCODE(this->validate();)
151 }
152 
reset()153 void SkBitmap::reset() {
154     this->freePixels();
155     sk_bzero(this, sizeof(*this));
156 }
157 
ComputeBytesPerPixel(SkBitmap::Config config)158 int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
159     int bpp;
160     switch (config) {
161         case kNo_Config:
162             bpp = 0;   // not applicable
163             break;
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 size_t 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             break;
194         case kA8_Config:
195         case kIndex8_Config:
196             rowBytes.set(width);
197             break;
198         case kRGB_565_Config:
199         case kARGB_4444_Config:
200             rowBytes.set(width);
201             rowBytes.shiftLeft(1);
202             break;
203         case kARGB_8888_Config:
204             rowBytes.set(width);
205             rowBytes.shiftLeft(2);
206             break;
207         default:
208             SkDEBUGFAIL("unknown config");
209             break;
210     }
211     return isPos32Bits(rowBytes) ? rowBytes.get32() : 0;
212 }
213 
ComputeSize64(Config c,int width,int height)214 Sk64 SkBitmap::ComputeSize64(Config c, int width, int height) {
215     Sk64 size;
216     size.setMul(SkToS32(SkBitmap::ComputeRowBytes(c, width)), height);
217     return size;
218 }
219 
ComputeSize(Config c,int width,int height)220 size_t SkBitmap::ComputeSize(Config c, int width, int height) {
221     Sk64 size = SkBitmap::ComputeSize64(c, width, height);
222     return isPos32Bits(size) ? size.get32() : 0;
223 }
224 
ComputeSafeSize64(Config config,uint32_t width,uint32_t height,size_t rowBytes)225 Sk64 SkBitmap::ComputeSafeSize64(Config config,
226                                  uint32_t width,
227                                  uint32_t height,
228                                  size_t rowBytes) {
229     Sk64 safeSize;
230     safeSize.setZero();
231     if (height > 0) {
232         // TODO: Handle the case where the return value from
233         // ComputeRowBytes is more than 31 bits.
234         safeSize.set(SkToS32(ComputeRowBytes(config, width)));
235         Sk64 sizeAllButLastRow;
236         sizeAllButLastRow.setMul(height - 1, SkToS32(rowBytes));
237         safeSize.add(sizeAllButLastRow);
238     }
239     SkASSERT(!safeSize.isNeg());
240     return safeSize;
241 }
242 
ComputeSafeSize(Config config,uint32_t width,uint32_t height,size_t rowBytes)243 size_t SkBitmap::ComputeSafeSize(Config config,
244                                  uint32_t width,
245                                  uint32_t height,
246                                  size_t rowBytes) {
247     Sk64 safeSize = ComputeSafeSize64(config, width, height, rowBytes);
248     return (safeSize.is32() ? safeSize.get32() : 0);
249 }
250 
getBounds(SkRect * bounds) const251 void SkBitmap::getBounds(SkRect* bounds) const {
252     SkASSERT(bounds);
253     bounds->set(0, 0,
254                 SkIntToScalar(fWidth), SkIntToScalar(fHeight));
255 }
256 
getBounds(SkIRect * bounds) const257 void SkBitmap::getBounds(SkIRect* bounds) const {
258     SkASSERT(bounds);
259     bounds->set(0, 0, fWidth, fHeight);
260 }
261 
262 ///////////////////////////////////////////////////////////////////////////////
263 
validate_alphaType(SkBitmap::Config config,SkAlphaType alphaType,SkAlphaType * canonical=NULL)264 static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType,
265                                SkAlphaType* canonical = NULL) {
266     switch (config) {
267         case SkBitmap::kNo_Config:
268             alphaType = kIgnore_SkAlphaType;
269             break;
270         case SkBitmap::kA8_Config:
271             if (kUnpremul_SkAlphaType == alphaType) {
272                 alphaType = kPremul_SkAlphaType;
273             }
274             // fall-through
275         case SkBitmap::kIndex8_Config:
276         case SkBitmap::kARGB_4444_Config:
277         case SkBitmap::kARGB_8888_Config:
278             if (kIgnore_SkAlphaType == alphaType) {
279                 return false;
280             }
281             break;
282         case SkBitmap::kRGB_565_Config:
283             alphaType = kOpaque_SkAlphaType;
284             break;
285         default:
286             return false;
287     }
288     if (canonical) {
289         *canonical = alphaType;
290     }
291     return true;
292 }
293 
setConfig(Config config,int width,int height,size_t rowBytes,SkAlphaType alphaType)294 bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
295                          SkAlphaType alphaType) {
296     if ((width | height) < 0) {
297         goto BAD_CONFIG;
298     }
299     if (rowBytes == 0) {
300         rowBytes = SkBitmap::ComputeRowBytes(config, width);
301         if (0 == rowBytes && kNo_Config != config && width > 0) {
302             goto BAD_CONFIG;
303         }
304     }
305 
306     if (!validate_alphaType(config, alphaType, &alphaType)) {
307         goto BAD_CONFIG;
308     }
309 
310     this->freePixels();
311 
312     fConfig     = SkToU8(config);
313     fAlphaType  = SkToU8(alphaType);
314     fWidth      = width;
315     fHeight     = height;
316     fRowBytes   = SkToU32(rowBytes);
317 
318     fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(config);
319 
320     SkDEBUGCODE(this->validate();)
321     return true;
322 
323     // if we got here, we had an error, so we reset the bitmap to empty
324 BAD_CONFIG:
325     this->reset();
326     return false;
327 }
328 
setConfig(const SkImageInfo & info,size_t rowBytes)329 bool SkBitmap::setConfig(const SkImageInfo& info, size_t rowBytes) {
330     return this->setConfig(SkImageInfoToBitmapConfig(info), info.fWidth,
331                            info.fHeight, rowBytes, info.fAlphaType);
332 }
333 
setAlphaType(SkAlphaType alphaType)334 bool SkBitmap::setAlphaType(SkAlphaType alphaType) {
335     if (!validate_alphaType(this->config(), alphaType, &alphaType)) {
336         return false;
337     }
338     fAlphaType = SkToU8(alphaType);
339     return true;
340 }
341 
updatePixelsFromRef() const342 void SkBitmap::updatePixelsFromRef() const {
343     if (NULL != fPixelRef) {
344         if (fPixelLockCount > 0) {
345             SkASSERT(fPixelRef->isLocked());
346 
347             void* p = fPixelRef->pixels();
348             if (NULL != p) {
349                 p = (char*)p + fPixelRefOffset;
350             }
351             fPixels = p;
352             SkRefCnt_SafeAssign(fColorTable, fPixelRef->colorTable());
353         } else {
354             SkASSERT(0 == fPixelLockCount);
355             fPixels = NULL;
356             if (fColorTable) {
357                 fColorTable->unref();
358                 fColorTable = NULL;
359             }
360         }
361     }
362 }
363 
config_to_colorType(SkBitmap::Config config,SkColorType * ctOut)364 static bool config_to_colorType(SkBitmap::Config config, SkColorType* ctOut) {
365     SkColorType ct;
366     switch (config) {
367         case SkBitmap::kA8_Config:
368             ct = kAlpha_8_SkColorType;
369             break;
370         case SkBitmap::kIndex8_Config:
371             ct = kIndex_8_SkColorType;
372             break;
373         case SkBitmap::kRGB_565_Config:
374             ct = kRGB_565_SkColorType;
375             break;
376         case SkBitmap::kARGB_4444_Config:
377             ct = kARGB_4444_SkColorType;
378             break;
379         case SkBitmap::kARGB_8888_Config:
380             ct = kPMColor_SkColorType;
381             break;
382         case SkBitmap::kNo_Config:
383         default:
384             return false;
385     }
386     if (ctOut) {
387         *ctOut = ct;
388     }
389     return true;
390 }
391 
asImageInfo(SkImageInfo * info) const392 bool SkBitmap::asImageInfo(SkImageInfo* info) const {
393     SkColorType ct;
394     if (!config_to_colorType(this->config(), &ct)) {
395         return false;
396     }
397     if (info) {
398         info->fWidth = fWidth;
399         info->fHeight = fHeight;
400         info->fAlphaType = this->alphaType();
401         info->fColorType = ct;
402     }
403     return true;
404 }
405 
setPixelRef(SkPixelRef * pr,size_t offset)406 SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) {
407     // do this first, we that we never have a non-zero offset with a null ref
408     if (NULL == pr) {
409         offset = 0;
410     }
411 
412     if (fPixelRef != pr || fPixelRefOffset != offset) {
413         if (fPixelRef != pr) {
414             this->freePixels();
415             SkASSERT(NULL == fPixelRef);
416 
417             SkSafeRef(pr);
418             fPixelRef = pr;
419         }
420         fPixelRefOffset = offset;
421         this->updatePixelsFromRef();
422     }
423 
424     SkDEBUGCODE(this->validate();)
425     return pr;
426 }
427 
lockPixels() const428 void SkBitmap::lockPixels() const {
429     if (NULL != fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) {
430         fPixelRef->lockPixels();
431         this->updatePixelsFromRef();
432     }
433     SkDEBUGCODE(this->validate();)
434 }
435 
unlockPixels() const436 void SkBitmap::unlockPixels() const {
437     SkASSERT(NULL == fPixelRef || fPixelLockCount > 0);
438 
439     if (NULL != fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) {
440         fPixelRef->unlockPixels();
441         this->updatePixelsFromRef();
442     }
443     SkDEBUGCODE(this->validate();)
444 }
445 
lockPixelsAreWritable() const446 bool SkBitmap::lockPixelsAreWritable() const {
447     return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false;
448 }
449 
setPixels(void * p,SkColorTable * ctable)450 void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
451     if (NULL == p) {
452         this->setPixelRef(NULL, 0);
453         return;
454     }
455 
456     SkImageInfo info;
457     if (!this->asImageInfo(&info)) {
458         this->setPixelRef(NULL, 0);
459         return;
460     }
461 
462     SkPixelRef* pr = SkMallocPixelRef::NewDirect(info, p, fRowBytes, ctable);
463     if (NULL == pr) {
464         this->setPixelRef(NULL, 0);
465         return;
466     }
467 
468     this->setPixelRef(pr)->unref();
469 
470     // since we're already allocated, we lockPixels right away
471     this->lockPixels();
472     SkDEBUGCODE(this->validate();)
473 }
474 
allocPixels(Allocator * allocator,SkColorTable * ctable)475 bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) {
476     HeapAllocator stdalloc;
477 
478     if (NULL == allocator) {
479         allocator = &stdalloc;
480     }
481     return allocator->allocPixelRef(this, ctable);
482 }
483 
freePixels()484 void SkBitmap::freePixels() {
485     // if we're gonna free the pixels, we certainly need to free the mipmap
486     this->freeMipMap();
487 
488     if (fColorTable) {
489         fColorTable->unref();
490         fColorTable = NULL;
491     }
492 
493     if (NULL != fPixelRef) {
494         if (fPixelLockCount > 0) {
495             fPixelRef->unlockPixels();
496         }
497         fPixelRef->unref();
498         fPixelRef = NULL;
499         fPixelRefOffset = 0;
500     }
501     fPixelLockCount = 0;
502     fPixels = NULL;
503 }
504 
freeMipMap()505 void SkBitmap::freeMipMap() {
506     if (fMipMap) {
507         fMipMap->unref();
508         fMipMap = NULL;
509     }
510 }
511 
getGenerationID() const512 uint32_t SkBitmap::getGenerationID() const {
513     return (fPixelRef) ? fPixelRef->getGenerationID() : 0;
514 }
515 
notifyPixelsChanged() const516 void SkBitmap::notifyPixelsChanged() const {
517     SkASSERT(!this->isImmutable());
518     if (fPixelRef) {
519         fPixelRef->notifyPixelsChanged();
520     }
521 }
522 
getTexture() const523 GrTexture* SkBitmap::getTexture() const {
524     return fPixelRef ? fPixelRef->getTexture() : NULL;
525 }
526 
527 ///////////////////////////////////////////////////////////////////////////////
528 
529 /** We explicitly use the same allocator for our pixels that SkMask does,
530  so that we can freely assign memory allocated by one class to the other.
531  */
allocPixelRef(SkBitmap * dst,SkColorTable * ctable)532 bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
533                                             SkColorTable* ctable) {
534     SkImageInfo info;
535     if (!dst->asImageInfo(&info)) {
536 //        SkDebugf("unsupported config for info %d\n", dst->config());
537         return false;
538     }
539 
540     SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(),
541                                                    ctable);
542     if (NULL == pr) {
543         return false;
544     }
545 
546     dst->setPixelRef(pr, 0)->unref();
547     // since we're already allocated, we lockPixels right away
548     dst->lockPixels();
549     return true;
550 }
551 
552 ///////////////////////////////////////////////////////////////////////////////
553 
getSafeSize() const554 size_t SkBitmap::getSafeSize() const {
555     // This is intended to be a size_t version of ComputeSafeSize64(), just
556     // faster. The computation is meant to be identical.
557     return (fHeight ? ((fHeight - 1) * fRowBytes) +
558             ComputeRowBytes(this->config(), fWidth): 0);
559 }
560 
getSafeSize64() const561 Sk64 SkBitmap::getSafeSize64() const {
562     return ComputeSafeSize64(this->config(), fWidth, fHeight, fRowBytes);
563 }
564 
copyPixelsTo(void * const dst,size_t dstSize,size_t dstRowBytes,bool preserveDstPad) const565 bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
566                             size_t dstRowBytes, bool preserveDstPad) const {
567 
568     if (0 == dstRowBytes) {
569         dstRowBytes = fRowBytes;
570     }
571 
572     if (dstRowBytes < ComputeRowBytes(this->config(), fWidth) ||
573         dst == NULL || (getPixels() == NULL && pixelRef() == NULL))
574         return false;
575 
576     if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) {
577         size_t safeSize = this->getSafeSize();
578         if (safeSize > dstSize || safeSize == 0)
579             return false;
580         else {
581             SkAutoLockPixels lock(*this);
582             // This implementation will write bytes beyond the end of each row,
583             // excluding the last row, if the bitmap's stride is greater than
584             // strictly required by the current config.
585             memcpy(dst, getPixels(), safeSize);
586 
587             return true;
588         }
589     } else {
590         // If destination has different stride than us, then copy line by line.
591         if (ComputeSafeSize(this->config(), fWidth, fHeight, dstRowBytes) >
592             dstSize)
593             return false;
594         else {
595             // Just copy what we need on each line.
596             size_t rowBytes = ComputeRowBytes(this->config(), fWidth);
597             SkAutoLockPixels lock(*this);
598             const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels());
599             uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
600             for (uint32_t row = 0; row < fHeight;
601                  row++, srcP += fRowBytes, dstP += dstRowBytes) {
602                 memcpy(dstP, srcP, rowBytes);
603             }
604 
605             return true;
606         }
607     }
608 }
609 
610 ///////////////////////////////////////////////////////////////////////////////
611 
isImmutable() const612 bool SkBitmap::isImmutable() const {
613     return fPixelRef ? fPixelRef->isImmutable() :
614         fFlags & kImageIsImmutable_Flag;
615 }
616 
setImmutable()617 void SkBitmap::setImmutable() {
618     if (fPixelRef) {
619         fPixelRef->setImmutable();
620     } else {
621         fFlags |= kImageIsImmutable_Flag;
622     }
623 }
624 
isVolatile() const625 bool SkBitmap::isVolatile() const {
626     return (fFlags & kImageIsVolatile_Flag) != 0;
627 }
628 
setIsVolatile(bool isVolatile)629 void SkBitmap::setIsVolatile(bool isVolatile) {
630     if (isVolatile) {
631         fFlags |= kImageIsVolatile_Flag;
632     } else {
633         fFlags &= ~kImageIsVolatile_Flag;
634     }
635 }
636 
getAddr(int x,int y) const637 void* SkBitmap::getAddr(int x, int y) const {
638     SkASSERT((unsigned)x < (unsigned)this->width());
639     SkASSERT((unsigned)y < (unsigned)this->height());
640 
641     char* base = (char*)this->getPixels();
642     if (base) {
643         base += y * this->rowBytes();
644         switch (this->config()) {
645             case SkBitmap::kARGB_8888_Config:
646                 base += x << 2;
647                 break;
648             case SkBitmap::kARGB_4444_Config:
649             case SkBitmap::kRGB_565_Config:
650                 base += x << 1;
651                 break;
652             case SkBitmap::kA8_Config:
653             case SkBitmap::kIndex8_Config:
654                 base += x;
655                 break;
656                 break;
657             default:
658                 SkDEBUGFAIL("Can't return addr for config");
659                 base = NULL;
660                 break;
661         }
662     }
663     return base;
664 }
665 
getColor(int x,int y) const666 SkColor SkBitmap::getColor(int x, int y) const {
667     SkASSERT((unsigned)x < (unsigned)this->width());
668     SkASSERT((unsigned)y < (unsigned)this->height());
669 
670     switch (this->config()) {
671         case SkBitmap::kA8_Config: {
672             uint8_t* addr = this->getAddr8(x, y);
673             return SkColorSetA(0, addr[0]);
674         }
675         case SkBitmap::kIndex8_Config: {
676             SkPMColor c = this->getIndex8Color(x, y);
677             return SkUnPreMultiply::PMColorToColor(c);
678         }
679         case SkBitmap::kRGB_565_Config: {
680             uint16_t* addr = this->getAddr16(x, y);
681             return SkPixel16ToColor(addr[0]);
682         }
683         case SkBitmap::kARGB_4444_Config: {
684             uint16_t* addr = this->getAddr16(x, y);
685             SkPMColor c = SkPixel4444ToPixel32(addr[0]);
686             return SkUnPreMultiply::PMColorToColor(c);
687         }
688         case SkBitmap::kARGB_8888_Config: {
689             uint32_t* addr = this->getAddr32(x, y);
690             return SkUnPreMultiply::PMColorToColor(addr[0]);
691         }
692         case kNo_Config:
693         default:
694             SkASSERT(false);
695             return 0;
696     }
697     SkASSERT(false);  // Not reached.
698     return 0;
699 }
700 
ComputeIsOpaque(const SkBitmap & bm)701 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
702     SkAutoLockPixels alp(bm);
703     if (!bm.getPixels()) {
704         return false;
705     }
706 
707     const int height = bm.height();
708     const int width = bm.width();
709 
710     switch (bm.config()) {
711         case SkBitmap::kA8_Config: {
712             unsigned a = 0xFF;
713             for (int y = 0; y < height; ++y) {
714                 const uint8_t* row = bm.getAddr8(0, y);
715                 for (int x = 0; x < width; ++x) {
716                     a &= row[x];
717                 }
718                 if (0xFF != a) {
719                     return false;
720                 }
721             }
722             return true;
723         } break;
724         case SkBitmap::kIndex8_Config: {
725             SkAutoLockColors alc(bm);
726             const SkPMColor* table = alc.colors();
727             if (!table) {
728                 return false;
729             }
730             SkPMColor c = (SkPMColor)~0;
731             for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) {
732                 c &= table[i];
733             }
734             return 0xFF == SkGetPackedA32(c);
735         } break;
736         case SkBitmap::kRGB_565_Config:
737             return true;
738             break;
739         case SkBitmap::kARGB_4444_Config: {
740             unsigned c = 0xFFFF;
741             for (int y = 0; y < height; ++y) {
742                 const SkPMColor16* row = bm.getAddr16(0, y);
743                 for (int x = 0; x < width; ++x) {
744                     c &= row[x];
745                 }
746                 if (0xF != SkGetPackedA4444(c)) {
747                     return false;
748                 }
749             }
750             return true;
751         } break;
752         case SkBitmap::kARGB_8888_Config: {
753             SkPMColor c = (SkPMColor)~0;
754             for (int y = 0; y < height; ++y) {
755                 const SkPMColor* row = bm.getAddr32(0, y);
756                 for (int x = 0; x < width; ++x) {
757                     c &= row[x];
758                 }
759                 if (0xFF != SkGetPackedA32(c)) {
760                     return false;
761                 }
762             }
763             return true;
764         }
765         default:
766             break;
767     }
768     return false;
769 }
770 
771 
772 ///////////////////////////////////////////////////////////////////////////////
773 ///////////////////////////////////////////////////////////////////////////////
774 
pack_8888_to_4444(unsigned a,unsigned r,unsigned g,unsigned b)775 static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) {
776     unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) |
777                      (SkR32To4444(r) << SK_R4444_SHIFT) |
778                      (SkG32To4444(g) << SK_G4444_SHIFT) |
779                      (SkB32To4444(b) << SK_B4444_SHIFT);
780     return SkToU16(pixel);
781 }
782 
internalErase(const SkIRect & area,U8CPU a,U8CPU r,U8CPU g,U8CPU b) const783 void SkBitmap::internalErase(const SkIRect& area,
784                              U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
785 #ifdef SK_DEBUG
786     SkDEBUGCODE(this->validate();)
787     SkASSERT(!area.isEmpty());
788     {
789         SkIRect total = { 0, 0, this->width(), this->height() };
790         SkASSERT(total.contains(area));
791     }
792 #endif
793 
794     if (kNo_Config == fConfig || kIndex8_Config == fConfig) {
795         return;
796     }
797 
798     SkAutoLockPixels alp(*this);
799     // perform this check after the lock call
800     if (!this->readyToDraw()) {
801         return;
802     }
803 
804     int height = area.height();
805     const int width = area.width();
806     const int rowBytes = fRowBytes;
807 
808     // make rgb premultiplied
809     if (255 != a) {
810         r = SkAlphaMul(r, a);
811         g = SkAlphaMul(g, a);
812         b = SkAlphaMul(b, a);
813     }
814 
815     switch (fConfig) {
816         case kA8_Config: {
817             uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
818             while (--height >= 0) {
819                 memset(p, a, width);
820                 p += rowBytes;
821             }
822             break;
823         }
824         case kARGB_4444_Config:
825         case kRGB_565_Config: {
826             uint16_t* p = this->getAddr16(area.fLeft, area.fTop);;
827             uint16_t v;
828 
829             if (kARGB_4444_Config == fConfig) {
830                 v = pack_8888_to_4444(a, r, g, b);
831             } else {
832                 v = SkPackRGB16(r >> (8 - SK_R16_BITS),
833                                 g >> (8 - SK_G16_BITS),
834                                 b >> (8 - SK_B16_BITS));
835             }
836             while (--height >= 0) {
837                 sk_memset16(p, v, width);
838                 p = (uint16_t*)((char*)p + rowBytes);
839             }
840             break;
841         }
842         case kARGB_8888_Config: {
843             uint32_t* p = this->getAddr32(area.fLeft, area.fTop);
844             uint32_t  v = SkPackARGB32(a, r, g, b);
845 
846             while (--height >= 0) {
847                 sk_memset32(p, v, width);
848                 p = (uint32_t*)((char*)p + rowBytes);
849             }
850             break;
851         }
852     }
853 
854     this->notifyPixelsChanged();
855 }
856 
eraseARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b) const857 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
858     SkIRect area = { 0, 0, this->width(), this->height() };
859     if (!area.isEmpty()) {
860         this->internalErase(area, a, r, g, b);
861     }
862 }
863 
eraseArea(const SkIRect & rect,SkColor c) const864 void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const {
865     SkIRect area = { 0, 0, this->width(), this->height() };
866     if (area.intersect(rect)) {
867         this->internalErase(area, SkColorGetA(c), SkColorGetR(c),
868                             SkColorGetG(c), SkColorGetB(c));
869     }
870 }
871 
872 //////////////////////////////////////////////////////////////////////////////////////
873 //////////////////////////////////////////////////////////////////////////////////////
874 
875 #define SUB_OFFSET_FAILURE  ((size_t)-1)
876 
877 /**
878  *  Based on the Config and rowBytes() of bm, return the offset into an SkPixelRef of the pixel at
879  *  (x, y).
880  *  Note that the SkPixelRef does not need to be set yet. deepCopyTo takes advantage of this fact.
881  *  Also note that (x, y) may be outside the range of (0 - width(), 0 - height()), so long as it is
882  *  within the bounds of the SkPixelRef being used.
883  */
get_sub_offset(const SkBitmap & bm,int x,int y)884 static size_t get_sub_offset(const SkBitmap& bm, int x, int y) {
885     switch (bm.config()) {
886         case SkBitmap::kA8_Config:
887         case SkBitmap:: kIndex8_Config:
888             // x is fine as is for the calculation
889             break;
890 
891         case SkBitmap::kRGB_565_Config:
892         case SkBitmap::kARGB_4444_Config:
893             x <<= 1;
894             break;
895 
896         case SkBitmap::kARGB_8888_Config:
897             x <<= 2;
898             break;
899 
900         case SkBitmap::kNo_Config:
901         default:
902             return SUB_OFFSET_FAILURE;
903     }
904     return y * bm.rowBytes() + x;
905 }
906 
907 /**
908  *  Using the pixelRefOffset(), rowBytes(), and Config of bm, determine the (x, y) coordinate of the
909  *  upper left corner of bm relative to its SkPixelRef.
910  *  x and y must be non-NULL.
911  */
912 bool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes,
913                                    int32_t* x, int32_t* y);
get_upper_left_from_offset(SkBitmap::Config config,size_t offset,size_t rowBytes,int32_t * x,int32_t * y)914 bool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes,
915                                    int32_t* x, int32_t* y) {
916     SkASSERT(x != NULL && y != NULL);
917     if (0 == offset) {
918         *x = *y = 0;
919         return true;
920     }
921     // Use integer division to find the correct y position.
922     // The remainder will be the x position, after we reverse get_sub_offset.
923     SkTDivMod(offset, rowBytes, y, x);
924     switch (config) {
925         case SkBitmap::kA8_Config:
926             // Fall through.
927         case SkBitmap::kIndex8_Config:
928             // x is unmodified
929             break;
930 
931         case SkBitmap::kRGB_565_Config:
932             // Fall through.
933         case SkBitmap::kARGB_4444_Config:
934             *x >>= 1;
935             break;
936 
937         case SkBitmap::kARGB_8888_Config:
938             *x >>= 2;
939             break;
940 
941         case SkBitmap::kNo_Config:
942             // Fall through.
943         default:
944             return false;
945     }
946     return true;
947 }
948 
get_upper_left_from_offset(const SkBitmap & bm,int32_t * x,int32_t * y)949 static bool get_upper_left_from_offset(const SkBitmap& bm, int32_t* x, int32_t* y) {
950     return get_upper_left_from_offset(bm.config(), bm.pixelRefOffset(), bm.rowBytes(), x, y);
951 }
952 
extractSubset(SkBitmap * result,const SkIRect & subset) const953 bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
954     SkDEBUGCODE(this->validate();)
955 
956     if (NULL == result || NULL == fPixelRef) {
957         return false;   // no src pixels
958     }
959 
960     SkIRect srcRect, r;
961     srcRect.set(0, 0, this->width(), this->height());
962     if (!r.intersect(srcRect, subset)) {
963         return false;   // r is empty (i.e. no intersection)
964     }
965 
966     if (fPixelRef->getTexture() != NULL) {
967         // Do a deep copy
968         SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset);
969         if (pixelRef != NULL) {
970             SkBitmap dst;
971             dst.setConfig(this->config(), subset.width(), subset.height(), 0,
972                           this->alphaType());
973             dst.setIsVolatile(this->isVolatile());
974             dst.setPixelRef(pixelRef)->unref();
975             SkDEBUGCODE(dst.validate());
976             result->swap(dst);
977             return true;
978         }
979     }
980 
981     // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
982     // exited above.
983     SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
984     SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
985 
986     size_t offset = get_sub_offset(*this, r.fLeft, r.fTop);
987     if (SUB_OFFSET_FAILURE == offset) {
988         return false;   // config not supported
989     }
990 
991     SkBitmap dst;
992     dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(),
993                   this->alphaType());
994     dst.setIsVolatile(this->isVolatile());
995 
996     if (fPixelRef) {
997         // share the pixelref with a custom offset
998         dst.setPixelRef(fPixelRef, fPixelRefOffset + offset);
999     }
1000     SkDEBUGCODE(dst.validate();)
1001 
1002     // we know we're good, so commit to result
1003     result->swap(dst);
1004     return true;
1005 }
1006 
1007 ///////////////////////////////////////////////////////////////////////////////
1008 
1009 #include "SkCanvas.h"
1010 #include "SkPaint.h"
1011 
canCopyTo(Config dstConfig) const1012 bool SkBitmap::canCopyTo(Config dstConfig) const {
1013     if (this->config() == kNo_Config) {
1014         return false;
1015     }
1016 
1017     bool sameConfigs = (this->config() == dstConfig);
1018     switch (dstConfig) {
1019         case kA8_Config:
1020         case kRGB_565_Config:
1021         case kARGB_8888_Config:
1022             break;
1023         case kIndex8_Config:
1024             if (!sameConfigs) {
1025                 return false;
1026             }
1027             break;
1028         case kARGB_4444_Config:
1029             return sameConfigs || kARGB_8888_Config == this->config();
1030         default:
1031             return false;
1032     }
1033     return true;
1034 }
1035 
copyTo(SkBitmap * dst,Config dstConfig,Allocator * alloc) const1036 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
1037     if (!this->canCopyTo(dstConfig)) {
1038         return false;
1039     }
1040 
1041     // if we have a texture, first get those pixels
1042     SkBitmap tmpSrc;
1043     const SkBitmap* src = this;
1044 
1045     if (fPixelRef) {
1046         SkIRect subset;
1047         if (get_upper_left_from_offset(*this, &subset.fLeft, &subset.fTop)) {
1048             subset.fRight = subset.fLeft + fWidth;
1049             subset.fBottom = subset.fTop + fHeight;
1050             if (fPixelRef->readPixels(&tmpSrc, &subset)) {
1051                 SkASSERT(tmpSrc.width() == this->width());
1052                 SkASSERT(tmpSrc.height() == this->height());
1053 
1054                 // did we get lucky and we can just return tmpSrc?
1055                 if (tmpSrc.config() == dstConfig && NULL == alloc) {
1056                     dst->swap(tmpSrc);
1057                     if (dst->pixelRef() && this->config() == dstConfig) {
1058                         // TODO(scroggo): fix issue 1742
1059                         dst->pixelRef()->cloneGenID(*fPixelRef);
1060                     }
1061                     return true;
1062                 }
1063 
1064                 // fall through to the raster case
1065                 src = &tmpSrc;
1066             }
1067         }
1068     }
1069 
1070     // we lock this now, since we may need its colortable
1071     SkAutoLockPixels srclock(*src);
1072     if (!src->readyToDraw()) {
1073         return false;
1074     }
1075 
1076     SkBitmap tmpDst;
1077     tmpDst.setConfig(dstConfig, src->width(), src->height(), 0,
1078                      src->alphaType());
1079 
1080     // allocate colortable if srcConfig == kIndex8_Config
1081     SkColorTable* ctable = (dstConfig == kIndex8_Config) ?
1082     new SkColorTable(*src->getColorTable()) : NULL;
1083     SkAutoUnref au(ctable);
1084     if (!tmpDst.allocPixels(alloc, ctable)) {
1085         return false;
1086     }
1087 
1088     if (!tmpDst.readyToDraw()) {
1089         // allocator/lock failed
1090         return false;
1091     }
1092 
1093     /* do memcpy for the same configs cases, else use drawing
1094     */
1095     if (src->config() == dstConfig) {
1096         if (tmpDst.getSize() == src->getSize()) {
1097             memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize());
1098             SkPixelRef* pixelRef = tmpDst.pixelRef();
1099             if (NULL != pixelRef && NULL != fPixelRef) {
1100                 // TODO(scroggo): fix issue 1742
1101                 pixelRef->cloneGenID(*fPixelRef);
1102             }
1103         } else {
1104             const char* srcP = reinterpret_cast<const char*>(src->getPixels());
1105             char* dstP = reinterpret_cast<char*>(tmpDst.getPixels());
1106             // to be sure we don't read too much, only copy our logical pixels
1107             size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel();
1108             for (int y = 0; y < tmpDst.height(); y++) {
1109                 memcpy(dstP, srcP, bytesToCopy);
1110                 srcP += src->rowBytes();
1111                 dstP += tmpDst.rowBytes();
1112             }
1113         }
1114     } else if (SkBitmap::kARGB_4444_Config == dstConfig
1115                && SkBitmap::kARGB_8888_Config == src->config()) {
1116         SkASSERT(src->height() == tmpDst.height());
1117         SkASSERT(src->width() == tmpDst.width());
1118         for (int y = 0; y < src->height(); ++y) {
1119             SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y);
1120             SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y);
1121             DITHER_4444_SCAN(y);
1122             for (int x = 0; x < src->width(); ++x) {
1123                 dstRow[x] = SkDitherARGB32To4444(srcRow[x],
1124                                                  DITHER_VALUE(x));
1125             }
1126         }
1127     } else {
1128         // Always clear the dest in case one of the blitters accesses it
1129         // TODO: switch the allocation of tmpDst to call sk_calloc_throw
1130         tmpDst.eraseColor(SK_ColorTRANSPARENT);
1131 
1132         SkCanvas canvas(tmpDst);
1133         SkPaint  paint;
1134 
1135         paint.setDither(true);
1136         canvas.drawBitmap(*src, 0, 0, &paint);
1137     }
1138 
1139     dst->swap(tmpDst);
1140     return true;
1141 }
1142 
deepCopyTo(SkBitmap * dst,Config dstConfig) const1143 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
1144     if (!this->canCopyTo(dstConfig)) {
1145         return false;
1146     }
1147 
1148     // If we have a PixelRef, and it supports deep copy, use it.
1149     // Currently supported only by texture-backed bitmaps.
1150     if (fPixelRef) {
1151         SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig);
1152         if (pixelRef) {
1153             uint32_t rowBytes;
1154             if (dstConfig == fConfig) {
1155                 // TODO(scroggo): fix issue 1742
1156                 pixelRef->cloneGenID(*fPixelRef);
1157                 // Use the same rowBytes as the original.
1158                 rowBytes = fRowBytes;
1159             } else {
1160                 // With the new config, an appropriate fRowBytes will be computed by setConfig.
1161                 rowBytes = 0;
1162             }
1163             dst->setConfig(dstConfig, fWidth, fHeight, rowBytes);
1164 
1165             size_t pixelRefOffset;
1166             if (0 == fPixelRefOffset || dstConfig == fConfig) {
1167                 // Use the same offset as the original.
1168                 pixelRefOffset = fPixelRefOffset;
1169             } else {
1170                 // Find the correct offset in the new config. This needs to be done after calling
1171                 // setConfig so dst's fConfig and fRowBytes have been set properly.
1172                 int32_t x, y;
1173                 if (!get_upper_left_from_offset(*this, &x, &y)) {
1174                     return false;
1175                 }
1176                 pixelRefOffset = get_sub_offset(*dst, x, y);
1177                 if (SUB_OFFSET_FAILURE == pixelRefOffset) {
1178                     return false;
1179                 }
1180             }
1181             dst->setPixelRef(pixelRef, pixelRefOffset)->unref();
1182             return true;
1183         }
1184     }
1185 
1186     if (this->getTexture()) {
1187         return false;
1188     } else {
1189         return this->copyTo(dst, dstConfig, NULL);
1190     }
1191 }
1192 
1193 ///////////////////////////////////////////////////////////////////////////////
1194 ///////////////////////////////////////////////////////////////////////////////
1195 
downsampleby2_proc32(SkBitmap * dst,int x,int y,const SkBitmap & src)1196 static void downsampleby2_proc32(SkBitmap* dst, int x, int y,
1197                                  const SkBitmap& src) {
1198     x <<= 1;
1199     y <<= 1;
1200     const SkPMColor* p = src.getAddr32(x, y);
1201     const SkPMColor* baseP = p;
1202     SkPMColor c, ag, rb;
1203 
1204     c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
1205     if (x < src.width() - 1) {
1206         p += 1;
1207     }
1208     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
1209 
1210     p = baseP;
1211     if (y < src.height() - 1) {
1212         p += src.rowBytes() >> 2;
1213     }
1214     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
1215     if (x < src.width() - 1) {
1216         p += 1;
1217     }
1218     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
1219 
1220     *dst->getAddr32(x >> 1, y >> 1) =
1221         ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
1222 }
1223 
expand16(U16CPU c)1224 static inline uint32_t expand16(U16CPU c) {
1225     return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
1226 }
1227 
1228 // returns dirt in the top 16bits, but we don't care, since we only
1229 // store the low 16bits.
pack16(uint32_t c)1230 static inline U16CPU pack16(uint32_t c) {
1231     return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE);
1232 }
1233 
downsampleby2_proc16(SkBitmap * dst,int x,int y,const SkBitmap & src)1234 static void downsampleby2_proc16(SkBitmap* dst, int x, int y,
1235                                  const SkBitmap& src) {
1236     x <<= 1;
1237     y <<= 1;
1238     const uint16_t* p = src.getAddr16(x, y);
1239     const uint16_t* baseP = p;
1240     SkPMColor       c;
1241 
1242     c = expand16(*p);
1243     if (x < src.width() - 1) {
1244         p += 1;
1245     }
1246     c += expand16(*p);
1247 
1248     p = baseP;
1249     if (y < src.height() - 1) {
1250         p += src.rowBytes() >> 1;
1251     }
1252     c += expand16(*p);
1253     if (x < src.width() - 1) {
1254         p += 1;
1255     }
1256     c += expand16(*p);
1257 
1258     *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
1259 }
1260 
expand4444(U16CPU c)1261 static uint32_t expand4444(U16CPU c) {
1262     return (c & 0xF0F) | ((c & ~0xF0F) << 12);
1263 }
1264 
collaps4444(uint32_t c)1265 static U16CPU collaps4444(uint32_t c) {
1266     return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
1267 }
1268 
downsampleby2_proc4444(SkBitmap * dst,int x,int y,const SkBitmap & src)1269 static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
1270                                    const SkBitmap& src) {
1271     x <<= 1;
1272     y <<= 1;
1273     const uint16_t* p = src.getAddr16(x, y);
1274     const uint16_t* baseP = p;
1275     uint32_t        c;
1276 
1277     c = expand4444(*p);
1278     if (x < src.width() - 1) {
1279         p += 1;
1280     }
1281     c += expand4444(*p);
1282 
1283     p = baseP;
1284     if (y < src.height() - 1) {
1285         p += src.rowBytes() >> 1;
1286     }
1287     c += expand4444(*p);
1288     if (x < src.width() - 1) {
1289         p += 1;
1290     }
1291     c += expand4444(*p);
1292 
1293     *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
1294 }
1295 
buildMipMap(bool forceRebuild)1296 void SkBitmap::buildMipMap(bool forceRebuild) {
1297     if (forceRebuild)
1298         this->freeMipMap();
1299     else if (fMipMap)
1300         return; // we're already built
1301 
1302     SkASSERT(NULL == fMipMap);
1303 
1304     void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
1305 
1306     const SkBitmap::Config config = this->config();
1307 
1308     switch (config) {
1309         case kARGB_8888_Config:
1310             proc = downsampleby2_proc32;
1311             break;
1312         case kRGB_565_Config:
1313             proc = downsampleby2_proc16;
1314             break;
1315         case kARGB_4444_Config:
1316             proc = downsampleby2_proc4444;
1317             break;
1318         case kIndex8_Config:
1319         case kA8_Config:
1320         default:
1321             return; // don't build mipmaps for these configs
1322     }
1323 
1324     SkAutoLockPixels alp(*this);
1325     if (!this->readyToDraw()) {
1326         return;
1327     }
1328 
1329     // whip through our loop to compute the exact size needed
1330     size_t  size = 0;
1331     int     maxLevels = 0;
1332     {
1333         int width = this->width();
1334         int height = this->height();
1335         for (;;) {
1336             width >>= 1;
1337             height >>= 1;
1338             if (0 == width || 0 == height) {
1339                 break;
1340             }
1341             size += ComputeRowBytes(config, width) * height;
1342             maxLevels += 1;
1343         }
1344     }
1345 
1346     // nothing to build
1347     if (0 == maxLevels) {
1348         return;
1349     }
1350 
1351     SkBitmap srcBM(*this);
1352     srcBM.lockPixels();
1353     if (!srcBM.readyToDraw()) {
1354         return;
1355     }
1356 
1357     MipMap* mm = MipMap::Alloc(maxLevels, size);
1358     if (NULL == mm) {
1359         return;
1360     }
1361 
1362     MipLevel*   level = mm->levels();
1363     uint8_t*    addr = (uint8_t*)mm->pixels();
1364     int         width = this->width();
1365     int         height = this->height();
1366     uint32_t    rowBytes;
1367     SkBitmap    dstBM;
1368 
1369     for (int i = 0; i < maxLevels; i++) {
1370         width >>= 1;
1371         height >>= 1;
1372         rowBytes = SkToU32(ComputeRowBytes(config, width));
1373 
1374         level[i].fPixels   = addr;
1375         level[i].fWidth    = width;
1376         level[i].fHeight   = height;
1377         level[i].fRowBytes = rowBytes;
1378 
1379         dstBM.setConfig(config, width, height, rowBytes);
1380         dstBM.setPixels(addr);
1381 
1382         srcBM.lockPixels();
1383         for (int y = 0; y < height; y++) {
1384             for (int x = 0; x < width; x++) {
1385                 proc(&dstBM, x, y, srcBM);
1386             }
1387         }
1388         srcBM.unlockPixels();
1389 
1390         srcBM = dstBM;
1391         addr += height * rowBytes;
1392     }
1393     SkASSERT(addr == (uint8_t*)mm->pixels() + size);
1394     fMipMap = mm;
1395 }
1396 
hasMipMap() const1397 bool SkBitmap::hasMipMap() const {
1398     return fMipMap != NULL;
1399 }
1400 
extractMipLevel(SkBitmap * dst,SkFixed sx,SkFixed sy)1401 int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) {
1402     if (NULL == fMipMap) {
1403         return 0;
1404     }
1405 
1406     int level = ComputeMipLevel(sx, sy) >> 16;
1407     SkASSERT(level >= 0);
1408     if (level <= 0) {
1409         return 0;
1410     }
1411 
1412     if (level >= fMipMap->fLevelCount) {
1413         level = fMipMap->fLevelCount - 1;
1414     }
1415     if (dst) {
1416         const MipLevel& mip = fMipMap->levels()[level - 1];
1417         dst->setConfig((SkBitmap::Config)this->config(),
1418                        mip.fWidth, mip.fHeight, mip.fRowBytes);
1419         dst->setPixels(mip.fPixels);
1420     }
1421     return level;
1422 }
1423 
ComputeMipLevel(SkFixed sx,SkFixed sy)1424 SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) {
1425     sx = SkAbs32(sx);
1426     sy = SkAbs32(sy);
1427     if (sx < sy) {
1428         sx = sy;
1429     }
1430     if (sx < SK_Fixed1) {
1431         return 0;
1432     }
1433     int clz = SkCLZ(sx);
1434     SkASSERT(clz >= 1 && clz <= 15);
1435     return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16);
1436 }
1437 
1438 ///////////////////////////////////////////////////////////////////////////////
1439 
GetBitmapAlpha(const SkBitmap & src,uint8_t * SK_RESTRICT alpha,int alphaRowBytes)1440 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
1441                            int alphaRowBytes) {
1442     SkASSERT(alpha != NULL);
1443     SkASSERT(alphaRowBytes >= src.width());
1444 
1445     SkBitmap::Config config = src.config();
1446     int              w = src.width();
1447     int              h = src.height();
1448     size_t           rb = src.rowBytes();
1449 
1450     SkAutoLockPixels alp(src);
1451     if (!src.readyToDraw()) {
1452         // zero out the alpha buffer and return
1453         while (--h >= 0) {
1454             memset(alpha, 0, w);
1455             alpha += alphaRowBytes;
1456         }
1457         return false;
1458     }
1459 
1460     if (SkBitmap::kA8_Config == config && !src.isOpaque()) {
1461         const uint8_t* s = src.getAddr8(0, 0);
1462         while (--h >= 0) {
1463             memcpy(alpha, s, w);
1464             s += rb;
1465             alpha += alphaRowBytes;
1466         }
1467     } else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) {
1468         const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
1469         while (--h >= 0) {
1470             for (int x = 0; x < w; x++) {
1471                 alpha[x] = SkGetPackedA32(s[x]);
1472             }
1473             s = (const SkPMColor*)((const char*)s + rb);
1474             alpha += alphaRowBytes;
1475         }
1476     } else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) {
1477         const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
1478         while (--h >= 0) {
1479             for (int x = 0; x < w; x++) {
1480                 alpha[x] = SkPacked4444ToA32(s[x]);
1481             }
1482             s = (const SkPMColor16*)((const char*)s + rb);
1483             alpha += alphaRowBytes;
1484         }
1485     } else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) {
1486         SkColorTable* ct = src.getColorTable();
1487         if (ct) {
1488             const SkPMColor* SK_RESTRICT table = ct->lockColors();
1489             const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
1490             while (--h >= 0) {
1491                 for (int x = 0; x < w; x++) {
1492                     alpha[x] = SkGetPackedA32(table[s[x]]);
1493                 }
1494                 s += rb;
1495                 alpha += alphaRowBytes;
1496             }
1497             ct->unlockColors();
1498         }
1499     } else {    // src is opaque, so just fill alpha[] with 0xFF
1500         memset(alpha, 0xFF, h * alphaRowBytes);
1501     }
1502     return true;
1503 }
1504 
1505 #include "SkPaint.h"
1506 #include "SkMaskFilter.h"
1507 #include "SkMatrix.h"
1508 
extractAlpha(SkBitmap * dst,const SkPaint * paint,Allocator * allocator,SkIPoint * offset) const1509 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
1510                             Allocator *allocator, SkIPoint* offset) const {
1511     SkDEBUGCODE(this->validate();)
1512 
1513     SkBitmap    tmpBitmap;
1514     SkMatrix    identity;
1515     SkMask      srcM, dstM;
1516 
1517     srcM.fBounds.set(0, 0, this->width(), this->height());
1518     srcM.fRowBytes = SkAlign4(this->width());
1519     srcM.fFormat = SkMask::kA8_Format;
1520 
1521     SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL;
1522 
1523     // compute our (larger?) dst bounds if we have a filter
1524     if (NULL != filter) {
1525         identity.reset();
1526         srcM.fImage = NULL;
1527         if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
1528             goto NO_FILTER_CASE;
1529         }
1530         dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
1531     } else {
1532     NO_FILTER_CASE:
1533         tmpBitmap.setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
1534                        srcM.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         GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
1542         if (offset) {
1543             offset->set(0, 0);
1544         }
1545         tmpBitmap.swap(*dst);
1546         return true;
1547     }
1548     srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
1549     SkAutoMaskFreeImage srcCleanup(srcM.fImage);
1550 
1551     GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
1552     if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
1553         goto NO_FILTER_CASE;
1554     }
1555     SkAutoMaskFreeImage dstCleanup(dstM.fImage);
1556 
1557     tmpBitmap.setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
1558                    dstM.fBounds.height(), dstM.fRowBytes);
1559     if (!tmpBitmap.allocPixels(allocator, NULL)) {
1560         // Allocation of pixels for alpha bitmap failed.
1561         SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1562                 tmpBitmap.width(), tmpBitmap.height());
1563         return false;
1564     }
1565     memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
1566     if (offset) {
1567         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
1568     }
1569     SkDEBUGCODE(tmpBitmap.validate();)
1570 
1571     tmpBitmap.swap(*dst);
1572     return true;
1573 }
1574 
1575 ///////////////////////////////////////////////////////////////////////////////
1576 
1577 enum {
1578     SERIALIZE_PIXELTYPE_NONE,
1579     SERIALIZE_PIXELTYPE_REF_DATA
1580 };
1581 
flatten(SkFlattenableWriteBuffer & buffer) const1582 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const {
1583     buffer.writeInt(fWidth);
1584     buffer.writeInt(fHeight);
1585     buffer.writeInt(fRowBytes);
1586     buffer.writeInt(fConfig);
1587     buffer.writeInt(fAlphaType);
1588 
1589     if (fPixelRef) {
1590         if (fPixelRef->getFactory()) {
1591             buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA);
1592             buffer.writeUInt(SkToU32(fPixelRefOffset));
1593             buffer.writeFlattenable(fPixelRef);
1594             return;
1595         }
1596         // if we get here, we can't record the pixels
1597         buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
1598     } else {
1599         buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
1600     }
1601 }
1602 
unflatten(SkFlattenableReadBuffer & buffer)1603 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) {
1604     this->reset();
1605 
1606     int width = buffer.readInt();
1607     int height = buffer.readInt();
1608     int rowBytes = buffer.readInt();
1609     Config config = (Config)buffer.readInt();
1610     SkAlphaType alphaType = (SkAlphaType)buffer.readInt();
1611     buffer.validate((width >= 0) && (height >= 0) && (rowBytes >= 0) &&
1612                     SkIsValidConfig(config) && validate_alphaType(config, alphaType));
1613 
1614     bool configIsValid = this->setConfig(config, width, height, rowBytes, alphaType);
1615     // Note : Using (fRowBytes >= (fWidth * fBytesPerPixel)) in the following test can create false
1616     //        positives if the multiplication causes an integer overflow. Use the division instead.
1617     buffer.validate(configIsValid && (fBytesPerPixel > 0) &&
1618                     ((fRowBytes / fBytesPerPixel) >= fWidth));
1619 
1620     int reftype = buffer.readInt();
1621     if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) ||
1622                         (SERIALIZE_PIXELTYPE_NONE == reftype))) {
1623         switch (reftype) {
1624             case SERIALIZE_PIXELTYPE_REF_DATA: {
1625                 size_t offset = buffer.readUInt();
1626                 SkPixelRef* pr = buffer.readPixelRef();
1627                 if (!buffer.validate((NULL == pr) ||
1628                        (pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) {
1629                     offset = 0;
1630                 }
1631                 SkSafeUnref(this->setPixelRef(pr, offset));
1632                 break;
1633             }
1634             case SERIALIZE_PIXELTYPE_NONE:
1635                 break;
1636             default:
1637                 SkDEBUGFAIL("unrecognized pixeltype in serialized data");
1638                 sk_throw();
1639         }
1640     }
1641 }
1642 
1643 ///////////////////////////////////////////////////////////////////////////////
1644 
RLEPixels(int width,int height)1645 SkBitmap::RLEPixels::RLEPixels(int width, int height) {
1646     fHeight = height;
1647     fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*));
1648 }
1649 
~RLEPixels()1650 SkBitmap::RLEPixels::~RLEPixels() {
1651     sk_free(fYPtrs);
1652 }
1653 
1654 ///////////////////////////////////////////////////////////////////////////////
1655 
1656 #ifdef SK_DEBUG
validate() const1657 void SkBitmap::validate() const {
1658     SkASSERT(fConfig < kConfigCount);
1659     SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth));
1660     uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag;
1661 #ifdef SK_BUILD_FOR_ANDROID
1662     allFlags |= kHasHardwareMipMap_Flag;
1663 #endif
1664     SkASSERT(fFlags <= allFlags);
1665     SkASSERT(fPixelLockCount >= 0);
1666     SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000);
1667     SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel);
1668 
1669 #if 0   // these asserts are not thread-correct, so disable for now
1670     if (fPixelRef) {
1671         if (fPixelLockCount > 0) {
1672             SkASSERT(fPixelRef->isLocked());
1673         } else {
1674             SkASSERT(NULL == fPixels);
1675             SkASSERT(NULL == fColorTable);
1676         }
1677     }
1678 #endif
1679 }
1680 #endif
1681 
1682 #ifdef SK_DEVELOPER
toString(SkString * str) const1683 void SkBitmap::toString(SkString* str) const {
1684 
1685     static const char* gConfigNames[kConfigCount] = {
1686         "NONE", "A8", "INDEX8", "565", "4444", "8888"
1687     };
1688 
1689     str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
1690                  gConfigNames[this->config()]);
1691 
1692     str->append(" (");
1693     if (this->isOpaque()) {
1694         str->append("opaque");
1695     } else {
1696         str->append("transparent");
1697     }
1698     if (this->isImmutable()) {
1699         str->append(", immutable");
1700     } else {
1701         str->append(", not-immutable");
1702     }
1703     str->append(")");
1704 
1705     SkPixelRef* pr = this->pixelRef();
1706     if (NULL == pr) {
1707         // show null or the explicit pixel address (rare)
1708         str->appendf(" pixels:%p", this->getPixels());
1709     } else {
1710         const char* uri = pr->getURI();
1711         if (NULL != uri) {
1712             str->appendf(" uri:\"%s\"", uri);
1713         } else {
1714             str->appendf(" pixelref:%p", pr);
1715         }
1716     }
1717 
1718     str->append(")");
1719 }
1720 #endif
1721