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