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