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