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