~ubuntu-branches/ubuntu/karmic/gears/karmic

« back to all changes in this revision

Viewing changes to third_party/skia/src/core/SkBitmap.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Lesicnik
  • Date: 2009-04-30 19:15:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090430191525-0790sb5wzg8ou0xb
Tags: upstream-0.5.21.0~svn3334+dfsg
ImportĀ upstreamĀ versionĀ 0.5.21.0~svn3334+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2006-2008 The Android Open Source Project
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *      http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#include "SkBitmap.h"
 
18
#include "SkColorPriv.h"
 
19
#include "SkDither.h"
 
20
#include "SkFlattenable.h"
 
21
#include "SkMallocPixelRef.h"
 
22
#include "SkMask.h"
 
23
#include "SkPixelRef.h"
 
24
#include "SkThread.h"
 
25
#include "SkUtils.h"
 
26
#include "SkPackBits.h"
 
27
#include <new>
 
28
 
 
29
#ifdef SK_SUPPORT_MIPMAP
 
30
struct MipLevel {
 
31
    void*       fPixels;
 
32
    uint32_t    fRowBytes;
 
33
    uint16_t    fWidth, fHeight;
 
34
};
 
35
 
 
36
struct SkBitmap::MipMap : SkNoncopyable {
 
37
    int32_t fRefCnt;
 
38
    int     fLevelCount;
 
39
//  MipLevel    fLevel[fLevelCount];
 
40
//  Pixels[]
 
41
    
 
42
    static MipMap* Alloc(int levelCount, size_t pixelSize) {
 
43
        MipMap* mm = (MipMap*)sk_malloc_throw(sizeof(MipMap) +
 
44
                                              levelCount * sizeof(MipLevel) +
 
45
                                              pixelSize);
 
46
        mm->fRefCnt = 1;
 
47
        mm->fLevelCount = levelCount;
 
48
        return mm;
 
49
    }
 
50
 
 
51
    const MipLevel* levels() const { return (const MipLevel*)(this + 1); }
 
52
    MipLevel* levels() { return (MipLevel*)(this + 1); }
 
53
 
 
54
    const void* pixels() const { return levels() + fLevelCount; }
 
55
    void* pixels() { return levels() + fLevelCount; }
 
56
    
 
57
    void safeRef() {
 
58
        if (this) {
 
59
            SkASSERT(fRefCnt > 0);
 
60
            sk_atomic_inc(&fRefCnt);
 
61
        }
 
62
    }
 
63
    void safeUnref() {
 
64
        if (this) {
 
65
            SkASSERT(fRefCnt > 0);
 
66
            if (sk_atomic_dec(&fRefCnt) == 1) {
 
67
                sk_free(this);
 
68
            }
 
69
        }
 
70
    }
 
71
};
 
72
#endif
 
73
 
 
74
///////////////////////////////////////////////////////////////////////////////
 
75
///////////////////////////////////////////////////////////////////////////////
 
76
 
 
77
SkBitmap::SkBitmap() {
 
78
    bzero(this, sizeof(*this));
 
79
}
 
80
 
 
81
SkBitmap::SkBitmap(const SkBitmap& src) {
 
82
    SkDEBUGCODE(src.validate();)
 
83
    bzero(this, sizeof(*this));
 
84
    *this = src;
 
85
    SkDEBUGCODE(this->validate();)
 
86
}
 
87
 
 
88
SkBitmap::~SkBitmap() {
 
89
    SkDEBUGCODE(this->validate();)
 
90
    this->freePixels();
 
91
}
 
92
 
 
93
SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
 
94
    if (this != &src) {
 
95
        this->freePixels();
 
96
        memcpy(this, &src, sizeof(src));
 
97
 
 
98
        // inc src reference counts
 
99
        src.fPixelRef->safeRef();
 
100
#ifdef SK_SUPPORT_MIPMAP
 
101
        src.fMipMap->safeRef();
 
102
#endif
 
103
 
 
104
        // we reset our locks if we get blown away
 
105
        fPixelLockCount = 0;
 
106
        
 
107
        /*  The src could be in 3 states
 
108
            1. no pixelref, in which case we just copy/ref the pixels/ctable
 
109
            2. unlocked pixelref, pixels/ctable should be null
 
110
            3. locked pixelref, we should lock the ref again ourselves
 
111
        */
 
112
        if (NULL == fPixelRef) {
 
113
            // leave fPixels as it is
 
114
            fColorTable->safeRef(); // ref the user's ctable if present
 
115
        } else {    // we have a pixelref, so pixels/ctable reflect it
 
116
            // ignore the values from the memcpy
 
117
            fPixels = NULL;
 
118
            fColorTable = NULL;
 
119
        }
 
120
    }
 
121
 
 
122
    SkDEBUGCODE(this->validate();)
 
123
    return *this;
 
124
}
 
125
 
 
126
void SkBitmap::swap(SkBitmap& other) {
 
127
    SkTSwap<SkColorTable*>(fColorTable, other.fColorTable);
 
128
    SkTSwap<SkPixelRef*>(fPixelRef, other.fPixelRef);
 
129
    SkTSwap<size_t>(fPixelRefOffset, other.fPixelRefOffset);
 
130
    SkTSwap<int>(fPixelLockCount, other.fPixelLockCount);
 
131
#ifdef SK_SUPPORT_MIPMAP
 
132
    SkTSwap<MipMap*>(fMipMap, other.fMipMap);
 
133
#endif
 
134
    SkTSwap<void*>(fPixels, other.fPixels);
 
135
    SkTSwap<uint16_t>(fWidth, other.fWidth);
 
136
    SkTSwap<uint16_t>(fHeight, other.fHeight);
 
137
    SkTSwap<uint32_t>(fRowBytes, other.fRowBytes);
 
138
    SkTSwap<uint8_t>(fConfig, other.fConfig);
 
139
    SkTSwap<uint8_t>(fFlags, other.fFlags);
 
140
    SkTSwap<uint8_t>(fBytesPerPixel, other.fBytesPerPixel);
 
141
 
 
142
    SkDEBUGCODE(this->validate();)
 
143
}
 
144
 
 
145
void SkBitmap::reset() {
 
146
    this->freePixels();
 
147
    bzero(this, sizeof(*this));
 
148
}
 
149
 
 
150
int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
 
151
    int bpp;
 
152
    switch (config) {
 
153
        case kNo_Config:
 
154
        case kA1_Config:
 
155
            bpp = 0;   // not applicable
 
156
            break;
 
157
        case kRLE_Index8_Config:
 
158
        case kA8_Config:
 
159
        case kIndex8_Config:
 
160
            bpp = 1;
 
161
            break;
 
162
        case kRGB_565_Config:
 
163
        case kARGB_4444_Config:
 
164
            bpp = 2;
 
165
            break;
 
166
        case kARGB_8888_Config:
 
167
            bpp = 4;
 
168
            break;
 
169
        default:
 
170
            SkASSERT(!"unknown config");
 
171
            bpp = 0;   // error
 
172
            break;
 
173
    }
 
174
    return bpp;
 
175
}
 
176
 
 
177
int SkBitmap::ComputeRowBytes(Config c, int width) {
 
178
    int rowBytes = 0;
 
179
 
 
180
    switch (c) {
 
181
        case kNo_Config:
 
182
        case kRLE_Index8_Config:
 
183
            // assume that the bitmap has no pixels to draw to
 
184
            rowBytes = 0;
 
185
            break;
 
186
        case kA1_Config:
 
187
            rowBytes = (width + 7) >> 3;
 
188
            break;
 
189
        case kA8_Config:
 
190
        case kIndex8_Config:
 
191
            rowBytes = width;
 
192
            break;
 
193
        case kRGB_565_Config:
 
194
        case kARGB_4444_Config:
 
195
            rowBytes = width << 1;
 
196
            break;
 
197
        case kARGB_8888_Config:
 
198
            rowBytes = width << 2;
 
199
            break;
 
200
        default:
 
201
            SkASSERT(!"unknown config");
 
202
            break;
 
203
    }
 
204
    return rowBytes;
 
205
}
 
206
 
 
207
Sk64 SkBitmap::ComputeSize64(Config c, int width, int height) {
 
208
    Sk64 size;
 
209
    size.setMul(SkBitmap::ComputeRowBytes(c, width), height);
 
210
    return size;
 
211
}
 
212
 
 
213
size_t SkBitmap::ComputeSize(Config c, int width, int height) {
 
214
    Sk64 size = SkBitmap::ComputeSize64(c, width, height);
 
215
    if (size.isNeg() || !size.is32()) {
 
216
        return 0;
 
217
    }
 
218
    return size.get32();
 
219
}
 
220
 
 
221
void SkBitmap::setConfig(Config c, int width, int height, int rowBytes) {
 
222
    this->freePixels();
 
223
 
 
224
    if (rowBytes == 0) {
 
225
        rowBytes = SkBitmap::ComputeRowBytes(c, width);
 
226
    }
 
227
    fConfig     = SkToU8(c);
 
228
    fWidth      = SkToU16(width);
 
229
    fHeight     = SkToU16(height);
 
230
    fRowBytes   = rowBytes;
 
231
 
 
232
    fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c);
 
233
 
 
234
    SkDEBUGCODE(this->validate();)
 
235
}
 
236
 
 
237
void SkBitmap::updatePixelsFromRef() const {
 
238
    if (NULL != fPixelRef) {
 
239
        if (fPixelLockCount > 0) {
 
240
            SkASSERT(fPixelRef->getLockCount() > 0);
 
241
            
 
242
            void* p = fPixelRef->pixels();
 
243
            if (NULL != p) {
 
244
                p = (char*)p + fPixelRefOffset;
 
245
            }
 
246
            fPixels = p;
 
247
            SkRefCnt_SafeAssign(fColorTable, fPixelRef->colorTable());
 
248
        } else {
 
249
            SkASSERT(0 == fPixelLockCount);
 
250
            fPixels = NULL;
 
251
            fColorTable->safeUnref();
 
252
            fColorTable = NULL;
 
253
        }
 
254
    }
 
255
}
 
256
 
 
257
SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) {
 
258
    // do this first, we that we never have a non-zero offset with a null ref
 
259
    if (NULL == pr) {
 
260
        offset = 0;
 
261
    }
 
262
 
 
263
    if (fPixelRef != pr || fPixelRefOffset != offset) {
 
264
        if (fPixelRef != pr) {
 
265
            this->freePixels();
 
266
            SkASSERT(NULL == fPixelRef);
 
267
            
 
268
            pr->safeRef();
 
269
            fPixelRef = pr;
 
270
        }
 
271
        fPixelRefOffset = offset;
 
272
        this->updatePixelsFromRef();
 
273
    }
 
274
 
 
275
    SkDEBUGCODE(this->validate();)
 
276
    return pr;
 
277
}
 
278
 
 
279
void SkBitmap::lockPixels() const {
 
280
    if (NULL != fPixelRef && 1 == ++fPixelLockCount) {
 
281
        fPixelRef->lockPixels();
 
282
        this->updatePixelsFromRef();
 
283
    }
 
284
    SkDEBUGCODE(this->validate();)
 
285
}
 
286
 
 
287
void SkBitmap::unlockPixels() const {
 
288
    SkASSERT(NULL == fPixelRef || fPixelLockCount > 0);
 
289
 
 
290
    if (NULL != fPixelRef && 0 == --fPixelLockCount) {
 
291
        fPixelRef->unlockPixels();
 
292
        this->updatePixelsFromRef();
 
293
    }
 
294
    SkDEBUGCODE(this->validate();)
 
295
}
 
296
 
 
297
void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
 
298
    this->freePixels();
 
299
    fPixels = p;
 
300
    SkRefCnt_SafeAssign(fColorTable, ctable);
 
301
 
 
302
    SkDEBUGCODE(this->validate();)
 
303
}
 
304
 
 
305
bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) {
 
306
    HeapAllocator stdalloc;
 
307
 
 
308
    if (NULL == allocator) {
 
309
        allocator = &stdalloc;
 
310
    }
 
311
    return allocator->allocPixelRef(this, ctable);
 
312
}
 
313
 
 
314
void SkBitmap::freePixels() {
 
315
    // if we're gonna free the pixels, we certainly need to free the mipmap
 
316
    this->freeMipMap();
 
317
 
 
318
    fColorTable->safeUnref();
 
319
    fColorTable = NULL;
 
320
 
 
321
    if (NULL != fPixelRef) {
 
322
        if (fPixelLockCount > 0) {
 
323
            fPixelRef->unlockPixels();
 
324
        }
 
325
        fPixelRef->unref();
 
326
        fPixelRef = NULL;
 
327
        fPixelRefOffset = 0;
 
328
    }
 
329
    fPixelLockCount = 0;
 
330
    fPixels = NULL;
 
331
}
 
332
 
 
333
void SkBitmap::freeMipMap() {
 
334
#ifdef SK_SUPPORT_MIPMAP
 
335
    fMipMap->safeUnref();
 
336
    fMipMap = NULL;
 
337
#endif
 
338
}
 
339
 
 
340
uint32_t SkBitmap::getGenerationID() const {
 
341
    return fPixelRef ? fPixelRef->getGenerationID() : 0;
 
342
}
 
343
 
 
344
void SkBitmap::notifyPixelsChanged() const {
 
345
    if (fPixelRef) {
 
346
        fPixelRef->notifyPixelsChanged();
 
347
    }
 
348
}
 
349
 
 
350
///////////////////////////////////////////////////////////////////////////////
 
351
 
 
352
SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size,
 
353
                                   SkColorTable* ctable) {
 
354
    SkASSERT(storage);
 
355
    fStorage = storage;
 
356
    fSize = size;
 
357
    fCTable = ctable;
 
358
    ctable->safeRef();
 
359
}
 
360
 
 
361
SkMallocPixelRef::~SkMallocPixelRef() {
 
362
    fCTable->safeUnref();
 
363
    sk_free(fStorage);
 
364
}
 
365
 
 
366
void* SkMallocPixelRef::onLockPixels(SkColorTable** ct) {
 
367
    *ct = fCTable;
 
368
    return fStorage;
 
369
}
 
370
 
 
371
void SkMallocPixelRef::onUnlockPixels() {
 
372
    // nothing to do
 
373
}
 
374
 
 
375
void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
 
376
    this->INHERITED::flatten(buffer);
 
377
    
 
378
    buffer.write32(fSize);
 
379
    buffer.writePad(fStorage, fSize);
 
380
    if (fCTable) {
 
381
        buffer.writeBool(true);
 
382
        fCTable->flatten(buffer);
 
383
    } else {
 
384
        buffer.writeBool(false);
 
385
    }
 
386
}
 
387
 
 
388
SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer) : INHERITED(buffer, NULL) {
 
389
    fSize = buffer.readU32();
 
390
    fStorage = sk_malloc_throw(fSize);
 
391
    buffer.read(fStorage, fSize);
 
392
    if (buffer.readBool()) {
 
393
        fCTable = SkNEW_ARGS(SkColorTable, (buffer));
 
394
    } else {
 
395
        fCTable = NULL;
 
396
    }
 
397
}
 
398
 
 
399
static SkPixelRef::Registrar reg("SkMallocPixelRef",
 
400
                                 SkMallocPixelRef::Create);
 
401
 
 
402
/** We explicitly use the same allocator for our pixels that SkMask does,
 
403
 so that we can freely assign memory allocated by one class to the other.
 
404
 */
 
405
bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
 
406
                                            SkColorTable* ctable) {
 
407
    Sk64 size = dst->getSize64();
 
408
    if (size.isNeg() || !size.is32()) {
 
409
        return false;
 
410
    }
 
411
    
 
412
    void* addr = sk_malloc_flags(size.get32(), 0);  // returns NULL on failure
 
413
    if (NULL == addr) {
 
414
        return false;
 
415
    }
 
416
    
 
417
    dst->setPixelRef(new SkMallocPixelRef(addr, size.get32(), ctable))->unref();
 
418
    // since we're already allocated, we lockPixels right away
 
419
    dst->lockPixels();
 
420
    return true;
 
421
}
 
422
 
 
423
///////////////////////////////////////////////////////////////////////////////
 
424
 
 
425
bool SkBitmap::isOpaque() const {
 
426
    switch (fConfig) {
 
427
        case kNo_Config:
 
428
            return true;
 
429
 
 
430
        case kA1_Config:
 
431
        case kA8_Config:
 
432
        case kARGB_4444_Config:
 
433
        case kARGB_8888_Config:
 
434
            return (fFlags & kImageIsOpaque_Flag) != 0;
 
435
 
 
436
        case kIndex8_Config:
 
437
        case kRLE_Index8_Config: {
 
438
                uint32_t flags = 0;
 
439
 
 
440
                this->lockPixels();
 
441
                // if lockPixels failed, we may not have a ctable ptr
 
442
                if (fColorTable) {
 
443
                    flags = fColorTable->getFlags();
 
444
                }
 
445
                this->unlockPixels();
 
446
 
 
447
                return (flags & SkColorTable::kColorsAreOpaque_Flag) != 0;
 
448
            }
 
449
 
 
450
        case kRGB_565_Config:
 
451
            return true;
 
452
 
 
453
        default:
 
454
            SkASSERT(!"unknown bitmap config pased to isOpaque");
 
455
            return false;
 
456
    }
 
457
}
 
458
 
 
459
void SkBitmap::setIsOpaque(bool isOpaque) {
 
460
    /*  we record this regardless of fConfig, though it is ignored in
 
461
        isOpaque() for configs that can't support per-pixel alpha.
 
462
    */
 
463
    if (isOpaque) {
 
464
        fFlags |= kImageIsOpaque_Flag;
 
465
    } else {
 
466
        fFlags &= ~kImageIsOpaque_Flag;
 
467
    }
 
468
}
 
469
 
 
470
void* SkBitmap::getAddr(int x, int y) const {
 
471
    SkASSERT((unsigned)x < (unsigned)this->width());
 
472
    SkASSERT((unsigned)y < (unsigned)this->height());
 
473
 
 
474
    char* base = (char*)this->getPixels();
 
475
    if (base) {
 
476
        base += y * this->rowBytes();
 
477
        switch (this->config()) {
 
478
            case SkBitmap::kARGB_8888_Config:
 
479
                base += x << 2;
 
480
                break;
 
481
            case SkBitmap::kARGB_4444_Config:
 
482
            case SkBitmap::kRGB_565_Config:
 
483
                base += x << 1;
 
484
                break;
 
485
            case SkBitmap::kA8_Config:
 
486
            case SkBitmap::kIndex8_Config:
 
487
                base += x;
 
488
                break;
 
489
            case SkBitmap::kA1_Config:
 
490
                base += x >> 3;
 
491
                break;
 
492
            case kRLE_Index8_Config:
 
493
                SkASSERT(!"Can't return addr for kRLE_Index8_Config");
 
494
                base = NULL;
 
495
                break;
 
496
            default:
 
497
                SkASSERT(!"Can't return addr for config");
 
498
                base = NULL;
 
499
                break;
 
500
        }
 
501
    }
 
502
    return base;
 
503
}
 
504
 
 
505
///////////////////////////////////////////////////////////////////////////////
 
506
///////////////////////////////////////////////////////////////////////////////
 
507
 
 
508
void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
 
509
    SkDEBUGCODE(this->validate();)
 
510
 
 
511
    if (0 == fWidth || 0 == fHeight ||
 
512
            kNo_Config == fConfig || kIndex8_Config == fConfig) {
 
513
        return;
 
514
    }
 
515
 
 
516
    SkAutoLockPixels alp(*this);
 
517
    // perform this check after the lock call
 
518
    if (!this->readyToDraw()) {
 
519
        return;
 
520
    }
 
521
 
 
522
    int height = fHeight;
 
523
    const int width = fWidth;
 
524
    const int rowBytes = fRowBytes;
 
525
 
 
526
    // make rgb premultiplied
 
527
    if (255 != a) {
 
528
        r = SkAlphaMul(r, a);
 
529
        g = SkAlphaMul(g, a);
 
530
        b = SkAlphaMul(b, a);
 
531
    }
 
532
 
 
533
    switch (fConfig) {
 
534
        case kA1_Config: {
 
535
            uint8_t* p = (uint8_t*)fPixels;
 
536
            const int count = (width + 7) >> 3;
 
537
            a = (a >> 7) ? 0xFF : 0;
 
538
            SkASSERT(count <= rowBytes);
 
539
            while (--height >= 0) {
 
540
                memset(p, a, count);
 
541
                p += rowBytes;
 
542
            }
 
543
            break;
 
544
        }
 
545
        case kA8_Config: {
 
546
            uint8_t* p = (uint8_t*)fPixels;
 
547
            while (--height >= 0) {
 
548
                memset(p, a, width);
 
549
                p += rowBytes;
 
550
            }
 
551
            break;
 
552
        }
 
553
        case kARGB_4444_Config:
 
554
        case kRGB_565_Config: {
 
555
            uint16_t* p = (uint16_t*)fPixels;
 
556
            uint16_t v;
 
557
            
 
558
            if (kARGB_4444_Config == fConfig) {
 
559
                v = SkPackARGB4444(a >> 4, r >> 4, g >> 4, b >> 4);
 
560
            } else {    // kRGB_565_Config
 
561
                v = SkPackRGB16(r >> (8 - SK_R16_BITS), g >> (8 - SK_G16_BITS),
 
562
                                b >> (8 - SK_B16_BITS));
 
563
            }
 
564
            while (--height >= 0) {
 
565
                sk_memset16(p, v, width);
 
566
                p = (uint16_t*)((char*)p + rowBytes);
 
567
            }
 
568
            break;
 
569
        }
 
570
        case kARGB_8888_Config: {
 
571
            uint32_t* p = (uint32_t*)fPixels;
 
572
            uint32_t  v = SkPackARGB32(a, r, g, b);
 
573
 
 
574
            while (--height >= 0) {
 
575
                sk_memset32(p, v, width);
 
576
                p = (uint32_t*)((char*)p + rowBytes);
 
577
            }
 
578
            break;
 
579
        }
 
580
    }
 
581
    
 
582
    this->notifyPixelsChanged();
 
583
}
 
584
 
 
585
//////////////////////////////////////////////////////////////////////////////////////
 
586
//////////////////////////////////////////////////////////////////////////////////////
 
587
 
 
588
#define SUB_OFFSET_FAILURE  ((size_t)-1)
 
589
 
 
590
static size_t getSubOffset(const SkBitmap& bm, int x, int y) {
 
591
    SkASSERT((unsigned)x < (unsigned)bm.width());
 
592
    SkASSERT((unsigned)y < (unsigned)bm.height());
 
593
    
 
594
    switch (bm.getConfig()) {
 
595
        case SkBitmap::kA8_Config:
 
596
        case SkBitmap:: kIndex8_Config:
 
597
            // x is fine as is for the calculation
 
598
            break;
 
599
 
 
600
        case SkBitmap::kRGB_565_Config:
 
601
        case SkBitmap::kARGB_4444_Config:
 
602
            x <<= 1;
 
603
            break;
 
604
 
 
605
        case SkBitmap::kARGB_8888_Config:
 
606
            x <<= 2;
 
607
            break;
 
608
 
 
609
        case SkBitmap::kNo_Config:
 
610
        case SkBitmap::kA1_Config:
 
611
        default:
 
612
            return SUB_OFFSET_FAILURE;
 
613
    }
 
614
    return y * bm.rowBytes() + x;
 
615
}
 
616
 
 
617
bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
 
618
    SkDEBUGCODE(this->validate();)
 
619
 
 
620
    if (NULL == result || (NULL == fPixelRef && NULL == fPixels)) {
 
621
        return false;   // no src pixels
 
622
    }
 
623
 
 
624
    SkIRect srcRect, r;
 
625
    srcRect.set(0, 0, this->width(), this->height());
 
626
    if (!r.intersect(srcRect, subset)) {
 
627
        return false;   // r is empty (i.e. no intersection)
 
628
    }
 
629
 
 
630
    if (kRLE_Index8_Config == fConfig) {
 
631
        SkAutoLockPixels alp(*this);
 
632
        // don't call readyToDraw(), since we can operate w/o a colortable
 
633
        // at this stage
 
634
        if (this->getPixels() == NULL) {
 
635
            return false;
 
636
        }
 
637
        SkBitmap bm;
 
638
        
 
639
        bm.setConfig(kIndex8_Config, r.width(), r.height());
 
640
        bm.allocPixels(this->getColorTable());
 
641
        if (NULL == bm.getPixels()) {
 
642
            return false;
 
643
        }
 
644
        
 
645
        const RLEPixels* rle = (const RLEPixels*)this->getPixels();
 
646
        uint8_t* dst = bm.getAddr8(0, 0);
 
647
        const int width = bm.width();
 
648
        const int rowBytes = bm.rowBytes();
 
649
            
 
650
        for (int y = r.fTop; y < r.fBottom; y++) {
 
651
            SkPackBits::Unpack8(dst, r.fLeft, width, rle->packedAtY(y));
 
652
            dst += rowBytes;
 
653
        }
 
654
        result->swap(bm);
 
655
        return true;
 
656
    }
 
657
 
 
658
    size_t offset = getSubOffset(*this, r.fLeft, r.fTop);
 
659
    if (SUB_OFFSET_FAILURE == offset) {
 
660
        return false;   // config not supported
 
661
    }
 
662
 
 
663
    SkBitmap dst;
 
664
    dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes());
 
665
 
 
666
    if (fPixelRef) {
 
667
        // share the pixelref with a custom offset
 
668
        dst.setPixelRef(fPixelRef, fPixelRefOffset + offset);
 
669
    } else {
 
670
        // share the pixels (owned by the caller)
 
671
        dst.setPixels((char*)fPixels + offset, this->getColorTable());
 
672
    }
 
673
    SkDEBUGCODE(dst.validate();)
 
674
 
 
675
    // we know we're good, so commit to result
 
676
    result->swap(dst);
 
677
    return true;
 
678
}
 
679
 
 
680
///////////////////////////////////////////////////////////////////////////////
 
681
 
 
682
#include "SkCanvas.h"
 
683
#include "SkPaint.h"
 
684
 
 
685
bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
 
686
    if (NULL == dst || this->width() == 0 || this->height() == 0) {
 
687
        return false;
 
688
    }
 
689
 
 
690
    switch (dstConfig) {
 
691
        case kA8_Config:
 
692
        case kARGB_4444_Config:
 
693
        case kRGB_565_Config:
 
694
        case kARGB_8888_Config:
 
695
            break;
 
696
        default:
 
697
            return false;
 
698
    }
 
699
    
 
700
    SkBitmap    tmp;
 
701
    
 
702
    tmp.setConfig(dstConfig, this->width(), this->height());
 
703
    // pass null for colortable, since we don't support Index8 config for dst
 
704
    if (!tmp.allocPixels(alloc, NULL)) {
 
705
        return false;
 
706
    }
 
707
    
 
708
    SkAutoLockPixels srclock(*this);
 
709
    SkAutoLockPixels dstlock(tmp);
 
710
    
 
711
    if (!this->readyToDraw() || !tmp.readyToDraw()) {
 
712
        // allocator/lock failed
 
713
        return false;
 
714
    }
 
715
 
 
716
    // if the src has alpha, we have to clear the dst first
 
717
    if (!this->isOpaque()) {
 
718
        tmp.eraseColor(0);
 
719
    }
 
720
 
 
721
    SkCanvas canvas(tmp);
 
722
    SkPaint  paint;
 
723
    
 
724
    paint.setDither(true);
 
725
    canvas.drawBitmap(*this, 0, 0, &paint);
 
726
    
 
727
    dst->swap(tmp);
 
728
    return true;
 
729
}
 
730
 
 
731
///////////////////////////////////////////////////////////////////////////////
 
732
///////////////////////////////////////////////////////////////////////////////
 
733
 
 
734
static void downsampleby2_proc32(SkBitmap* dst, int x, int y,
 
735
                                 const SkBitmap& src) {
 
736
    x <<= 1;
 
737
    y <<= 1;
 
738
    const SkPMColor* p = src.getAddr32(x, y);
 
739
    SkPMColor c, ag, rb;
 
740
 
 
741
    c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
 
742
    if (x < src.width() - 1) {
 
743
        p += 1;
 
744
    }
 
745
    c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
 
746
 
 
747
    if (y < src.height() - 1) {
 
748
        p = src.getAddr32(x, y + 1);
 
749
    }
 
750
    c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
 
751
    if (x < src.width() - 1) {
 
752
        p += 1;
 
753
    }
 
754
    c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
 
755
 
 
756
    *dst->getAddr32(x >> 1, y >> 1) =
 
757
        ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
 
758
}
 
759
 
 
760
static inline uint32_t expand16(U16CPU c) {
 
761
    return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
 
762
}
 
763
 
 
764
// returns dirt in the top 16bits, but we don't care, since we only
 
765
// store the low 16bits.
 
766
static inline U16CPU pack16(uint32_t c) {
 
767
    return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE);
 
768
}
 
769
 
 
770
static void downsampleby2_proc16(SkBitmap* dst, int x, int y,
 
771
                                 const SkBitmap& src) {
 
772
    x <<= 1;
 
773
    y <<= 1;
 
774
    const uint16_t* p = src.getAddr16(x, y);
 
775
    SkPMColor       c;
 
776
    
 
777
    c = expand16(*p);
 
778
    if (x < (int)src.width() - 1) {
 
779
        p += 1;
 
780
    }
 
781
    c += expand16(*p);
 
782
    
 
783
    if (y < (int)src.height() - 1) {
 
784
        p = src.getAddr16(x, y + 1);
 
785
    }
 
786
    c += expand16(*p);
 
787
    if (x < (int)src.width() - 1) {
 
788
        p += 1;
 
789
    }
 
790
    c += expand16(*p);
 
791
    
 
792
    *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
 
793
}
 
794
 
 
795
static uint32_t expand4444(U16CPU c) {
 
796
    return (c & 0xF0F) | ((c & ~0xF0F) << 12);
 
797
}
 
798
 
 
799
static U16CPU collaps4444(uint32_t c) {
 
800
    return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
 
801
}
 
802
 
 
803
static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
 
804
                                   const SkBitmap& src) {
 
805
    x <<= 1;
 
806
    y <<= 1;
 
807
    const uint16_t* p = src.getAddr16(x, y);
 
808
    uint32_t        c;
 
809
    
 
810
    c = expand4444(*p);
 
811
    if (x < src.width() - 1) {
 
812
        p += 1;
 
813
    }
 
814
    c += expand4444(*p);
 
815
    
 
816
    if (y < src.height() - 1) {
 
817
        p = src.getAddr16(x, y + 1);
 
818
    }
 
819
    c += expand4444(*p);
 
820
    if (x < src.width() - 1) {
 
821
        p += 1;
 
822
    }
 
823
    c += expand4444(*p);
 
824
    
 
825
    *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
 
826
}
 
827
 
 
828
void SkBitmap::buildMipMap(bool forceRebuild) {
 
829
#ifdef SK_SUPPORT_MIPMAP
 
830
    if (forceRebuild)
 
831
        this->freeMipMap();
 
832
    else if (fMipMap)
 
833
        return; // we're already built
 
834
 
 
835
    SkASSERT(NULL == fMipMap);
 
836
 
 
837
    void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
 
838
 
 
839
    const SkBitmap::Config config = this->getConfig();
 
840
 
 
841
    switch (config) {
 
842
        case kARGB_8888_Config:
 
843
            proc = downsampleby2_proc32;
 
844
            break;
 
845
        case kRGB_565_Config:
 
846
            proc = downsampleby2_proc16;
 
847
            break;
 
848
        case kARGB_4444_Config:
 
849
            proc = downsampleby2_proc4444;
 
850
            break;
 
851
        case kIndex8_Config:
 
852
        case kA8_Config:
 
853
        default:
 
854
            return; // don't build mipmaps for these configs
 
855
    }
 
856
 
 
857
    // whip through our loop to compute the exact size needed
 
858
    size_t  size = 0;
 
859
    int     maxLevels = 0;
 
860
    {
 
861
        unsigned    width = this->width();
 
862
        unsigned    height = this->height();
 
863
        for (;;) {
 
864
            width >>= 1;
 
865
            height >>= 1;
 
866
            if (0 == width || 0 == height) {
 
867
                break;
 
868
            }
 
869
            size += ComputeRowBytes(config, width) * height;
 
870
            maxLevels += 1;
 
871
        }
 
872
    }
 
873
    if (0 == maxLevels) {
 
874
        return;
 
875
    }
 
876
 
 
877
    MipMap*     mm = MipMap::Alloc(maxLevels, size);
 
878
    MipLevel*   level = mm->levels();
 
879
    uint8_t*    addr = (uint8_t*)mm->pixels();
 
880
 
 
881
    unsigned    width = this->width();
 
882
    unsigned    height = this->height();
 
883
    unsigned    rowBytes = this->rowBytes();
 
884
    SkBitmap    srcBM(*this), dstBM;
 
885
 
 
886
    srcBM.lockPixels();
 
887
 
 
888
    for (int i = 0; i < maxLevels; i++) {
 
889
        width >>= 1;
 
890
        height >>= 1;
 
891
        rowBytes = ComputeRowBytes(config, width);
 
892
 
 
893
        level[i].fPixels   = addr;
 
894
        level[i].fWidth    = SkToU16(width);
 
895
        level[i].fHeight   = SkToU16(height);
 
896
        level[i].fRowBytes = SkToU16(rowBytes);
 
897
 
 
898
        dstBM.setConfig(config, width, height, rowBytes);
 
899
        dstBM.setPixels(addr);
 
900
    
 
901
        for (unsigned y = 0; y < height; y++) {
 
902
            for (unsigned x = 0; x < width; x++) {
 
903
                proc(&dstBM, x, y, srcBM);
 
904
            }
 
905
        }
 
906
 
 
907
        srcBM = dstBM;
 
908
        addr += height * rowBytes;
 
909
    }
 
910
    SkASSERT(addr == (uint8_t*)mm->pixels() + size);
 
911
    fMipMap = mm;
 
912
#endif
 
913
}
 
914
 
 
915
bool SkBitmap::hasMipMap() const {
 
916
#ifdef SK_SUPPORT_MIPMAP
 
917
    return fMipMap != NULL;
 
918
#else
 
919
    return false;
 
920
#endif
 
921
}
 
922
 
 
923
int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) {
 
924
#ifdef SK_SUPPORT_MIPMAP
 
925
    if (NULL == fMipMap)
 
926
        return 0;
 
927
    
 
928
    int level = ComputeMipLevel(sx, sy) >> 16;
 
929
    SkASSERT(level >= 0);
 
930
    if (level <= 0) {
 
931
        return 0;
 
932
    }
 
933
 
 
934
    if (level >= fMipMap->fLevelCount) {
 
935
        level = fMipMap->fLevelCount - 1;
 
936
    }
 
937
    if (dst) {
 
938
        const MipLevel& mip = fMipMap->levels()[level - 1];
 
939
        dst->setConfig((SkBitmap::Config)this->config(),
 
940
                       mip.fWidth, mip.fHeight, mip.fRowBytes);
 
941
        dst->setPixels(mip.fPixels);
 
942
    }
 
943
    return level;
 
944
#else
 
945
    return 0;
 
946
#endif
 
947
}
 
948
 
 
949
SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) {
 
950
#ifdef SK_SUPPORT_MIPMAP
 
951
    sx = SkAbs32(sx);
 
952
    sy = SkAbs32(sy);
 
953
    if (sx < sy) {
 
954
        sx = sy;
 
955
    }
 
956
    if (sx < SK_Fixed1) {
 
957
        return 0;
 
958
    }
 
959
    int clz = SkCLZ(sx);
 
960
    SkASSERT(clz >= 1 && clz <= 15);
 
961
    return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16);
 
962
#else
 
963
    return 0;
 
964
#endif
 
965
}
 
966
 
 
967
///////////////////////////////////////////////////////////////////////////////
 
968
 
 
969
static void GetBitmapAlpha(const SkBitmap& src, uint8_t SK_RESTRICT alpha[],
 
970
                           int alphaRowBytes) {
 
971
    SkASSERT(alpha != NULL);
 
972
    SkASSERT(alphaRowBytes >= src.width());
 
973
 
 
974
    SkBitmap::Config config = src.getConfig();
 
975
    int              w = src.width();
 
976
    int              h = src.height();
 
977
    int              rb = src.rowBytes();
 
978
 
 
979
    if (SkBitmap::kA8_Config == config && !src.isOpaque()) {
 
980
        const uint8_t* s = src.getAddr8(0, 0);
 
981
        while (--h >= 0) {
 
982
            memcpy(alpha, s, w);
 
983
            s += rb;
 
984
            alpha += alphaRowBytes;
 
985
        }
 
986
    } else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) {
 
987
        const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
 
988
        while (--h >= 0) {
 
989
            for (int x = 0; x < w; x++) {
 
990
                alpha[x] = SkGetPackedA32(s[x]);
 
991
            }
 
992
            s = (const SkPMColor*)((const char*)s + rb);
 
993
            alpha += alphaRowBytes;
 
994
        }
 
995
    } else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) {
 
996
        const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
 
997
        while (--h >= 0) {
 
998
            for (int x = 0; x < w; x++) {
 
999
                alpha[x] = SkPacked4444ToA32(s[x]);
 
1000
            }
 
1001
            s = (const SkPMColor16*)((const char*)s + rb);
 
1002
            alpha += alphaRowBytes;
 
1003
        }
 
1004
    } else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) {
 
1005
        SkColorTable* ct = src.getColorTable();
 
1006
        if (ct) {
 
1007
            const SkPMColor* SK_RESTRICT table = ct->lockColors();
 
1008
            const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
 
1009
            while (--h >= 0) {
 
1010
                for (int x = 0; x < w; x++) {
 
1011
                    alpha[x] = SkGetPackedA32(table[s[x]]);
 
1012
                }
 
1013
                s += rb;
 
1014
                alpha += alphaRowBytes;
 
1015
            }
 
1016
            ct->unlockColors(false);
 
1017
        }
 
1018
    } else {    // src is opaque, so just fill alpha[] with 0xFF
 
1019
        memset(alpha, 0xFF, h * alphaRowBytes);
 
1020
    }
 
1021
}
 
1022
 
 
1023
#include "SkPaint.h"
 
1024
#include "SkMaskFilter.h"
 
1025
#include "SkMatrix.h"
 
1026
 
 
1027
void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
 
1028
                            SkIPoint* offset) const {
 
1029
    SkDEBUGCODE(this->validate();)
 
1030
 
 
1031
    SkMatrix    identity;
 
1032
    SkMask      srcM, dstM;
 
1033
 
 
1034
    srcM.fBounds.set(0, 0, this->width(), this->height());
 
1035
    srcM.fRowBytes = SkAlign4(this->width());
 
1036
    srcM.fFormat = SkMask::kA8_Format;
 
1037
 
 
1038
    SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL;
 
1039
 
 
1040
    // compute our (larger?) dst bounds if we have a filter
 
1041
    if (NULL != filter) {
 
1042
        identity.reset();
 
1043
        srcM.fImage = NULL;
 
1044
        if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
 
1045
            goto NO_FILTER_CASE;
 
1046
        }
 
1047
        dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
 
1048
    } else {
 
1049
    NO_FILTER_CASE:
 
1050
        dst->setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
 
1051
                       srcM.fRowBytes);
 
1052
        dst->allocPixels();        
 
1053
        GetBitmapAlpha(*this, dst->getAddr8(0, 0), srcM.fRowBytes);
 
1054
        if (offset) {
 
1055
            offset->set(0, 0);
 
1056
        }
 
1057
        return;
 
1058
    }
 
1059
 
 
1060
    SkAutoMaskImage srcCleanup(&srcM, true);
 
1061
 
 
1062
    GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
 
1063
    if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
 
1064
        goto NO_FILTER_CASE;
 
1065
    }
 
1066
 
 
1067
    SkAutoMaskImage dstCleanup(&dstM, false);
 
1068
 
 
1069
    dst->setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
 
1070
                   dstM.fBounds.height(), dstM.fRowBytes);
 
1071
    dst->allocPixels();
 
1072
    memcpy(dst->getPixels(), dstM.fImage, dstM.computeImageSize());
 
1073
    if (offset) {
 
1074
        offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
 
1075
    }
 
1076
    SkDEBUGCODE(dst->validate();)
 
1077
}
 
1078
 
 
1079
///////////////////////////////////////////////////////////////////////////////
 
1080
 
 
1081
enum {
 
1082
    SERIALIZE_PIXELTYPE_NONE,
 
1083
    SERIALIZE_PIXELTYPE_RAW_WITH_CTABLE,
 
1084
    SERIALIZE_PIXELTYPE_RAW_NO_CTABLE,
 
1085
    SERIALIZE_PIXELTYPE_REF_DATA,
 
1086
    SERIALIZE_PIXELTYPE_REF_PTR,
 
1087
};
 
1088
 
 
1089
static void writeString(SkFlattenableWriteBuffer& buffer, const char str[]) {
 
1090
    size_t len = strlen(str);
 
1091
    buffer.write32(len);
 
1092
    buffer.writePad(str, len);
 
1093
}
 
1094
 
 
1095
static SkPixelRef::Factory deserialize_factory(SkFlattenableReadBuffer& buffer) {
 
1096
    size_t len = buffer.readInt();
 
1097
    SkAutoSMalloc<256> storage(len + 1);
 
1098
    char* str = (char*)storage.get();
 
1099
    buffer.read(str, len);
 
1100
    str[len] = 0;
 
1101
    return SkPixelRef::NameToFactory(str);
 
1102
}
 
1103
 
 
1104
/*
 
1105
    It is tricky to know how much to flatten. If we don't have a pixelref (i.e.
 
1106
    we just have pixels, then we can only flatten the pixels, or write out an
 
1107
    empty bitmap.
 
1108
 
 
1109
    With a pixelref, we still have the question of recognizing when two sitings
 
1110
    of the same pixelref are the same, and when they are different. Perhaps we
 
1111
    should look at the generationID and keep a record of that in some dictionary
 
1112
    associated with the buffer. SkGLTextureCache does this sort of thing to know
 
1113
    when to create a new texture.
 
1114
*/
 
1115
void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const {
 
1116
    buffer.write32(fWidth);
 
1117
    buffer.write32(fHeight);
 
1118
    buffer.write32(fRowBytes);
 
1119
    buffer.write8(fConfig);
 
1120
    buffer.writeBool(this->isOpaque());
 
1121
    
 
1122
    /*  If we are called in this mode, then it is up to the caller to manage
 
1123
        the owner-counts on the pixelref, as we just record the ptr itself.
 
1124
    */
 
1125
    if (!buffer.persistBitmapPixels()) {
 
1126
        if (fPixelRef) {
 
1127
            buffer.write8(SERIALIZE_PIXELTYPE_REF_PTR);
 
1128
            buffer.write32(fPixelRefOffset);
 
1129
            buffer.writeRefCnt(fPixelRef);
 
1130
            return;
 
1131
        } else {
 
1132
            // we ignore the non-persist request, since we don't have a ref
 
1133
            // ... or we could just write an empty bitmap...
 
1134
            // (true) will write an empty bitmap, (false) will flatten the pix
 
1135
            if (true) {
 
1136
                buffer.write8(SERIALIZE_PIXELTYPE_NONE);
 
1137
                return;
 
1138
            }
 
1139
        }
 
1140
    }
 
1141
 
 
1142
    if (fPixelRef) {
 
1143
        SkPixelRef::Factory fact = fPixelRef->getFactory();
 
1144
        if (fact) {
 
1145
            const char* name = SkPixelRef::FactoryToName(fact);
 
1146
            if (name && *name) {
 
1147
                buffer.write8(SERIALIZE_PIXELTYPE_REF_DATA);
 
1148
                buffer.write32(fPixelRefOffset);
 
1149
                writeString(buffer, name);
 
1150
                fPixelRef->flatten(buffer);
 
1151
                return;
 
1152
            }
 
1153
        }
 
1154
        // if we get here, we can't record the pixels
 
1155
        buffer.write8(SERIALIZE_PIXELTYPE_NONE);
 
1156
    } else if (fPixels) {
 
1157
        if (fColorTable) {
 
1158
            buffer.write8(SERIALIZE_PIXELTYPE_RAW_WITH_CTABLE);
 
1159
            fColorTable->flatten(buffer);
 
1160
        } else {
 
1161
            buffer.write8(SERIALIZE_PIXELTYPE_RAW_NO_CTABLE);
 
1162
        }
 
1163
        buffer.writePad(fPixels, this->getSize());
 
1164
    } else {
 
1165
        buffer.write8(SERIALIZE_PIXELTYPE_NONE);
 
1166
    }
 
1167
}
 
1168
 
 
1169
void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) {
 
1170
    this->reset();
 
1171
    
 
1172
    int width = buffer.readInt();
 
1173
    int height = buffer.readInt();
 
1174
    int rowBytes = buffer.readInt();
 
1175
    int config = buffer.readU8();
 
1176
    
 
1177
    this->setConfig((Config)config, width, height, rowBytes);
 
1178
    this->setIsOpaque(buffer.readBool());
 
1179
    
 
1180
    size_t size = this->getSize();
 
1181
    int reftype = buffer.readU8();
 
1182
    switch (reftype) {
 
1183
        case SERIALIZE_PIXELTYPE_REF_PTR: {
 
1184
            size_t offset = buffer.readU32();
 
1185
            SkPixelRef* pr = (SkPixelRef*)buffer.readRefCnt();
 
1186
            this->setPixelRef(pr, offset);
 
1187
            break;
 
1188
        }
 
1189
        case SERIALIZE_PIXELTYPE_REF_DATA: {
 
1190
            size_t offset = buffer.readU32();
 
1191
            SkPixelRef::Factory fact = deserialize_factory(buffer);
 
1192
            SkPixelRef* pr = fact(buffer);
 
1193
            this->setPixelRef(pr, offset)->safeUnref();
 
1194
            break;
 
1195
        }
 
1196
        case SERIALIZE_PIXELTYPE_RAW_WITH_CTABLE:
 
1197
        case SERIALIZE_PIXELTYPE_RAW_NO_CTABLE: {
 
1198
            SkColorTable* ctable = NULL;
 
1199
            if (SERIALIZE_PIXELTYPE_RAW_WITH_CTABLE == reftype) {
 
1200
                ctable = SkNEW_ARGS(SkColorTable, (buffer));
 
1201
            }
 
1202
            if (this->allocPixels(ctable)) {
 
1203
                this->lockPixels();
 
1204
                buffer.read(this->getPixels(), size);
 
1205
                this->unlockPixels();
 
1206
            } else {
 
1207
                buffer.skip(size);
 
1208
            }
 
1209
            ctable->safeUnref();
 
1210
            break;
 
1211
        }
 
1212
        case SERIALIZE_PIXELTYPE_NONE:
 
1213
            break;
 
1214
        default:
 
1215
            SkASSERT(!"unrecognized pixeltype in serialized data");
 
1216
            sk_throw();
 
1217
    }
 
1218
}
 
1219
 
 
1220
///////////////////////////////////////////////////////////////////////////////
 
1221
 
 
1222
SkBitmap::RLEPixels::RLEPixels(int width, int height) {
 
1223
    fHeight = height;
 
1224
    fYPtrs = (uint8_t**)sk_malloc_throw(height * sizeof(uint8_t*));
 
1225
    bzero(fYPtrs, height * sizeof(uint8_t*));
 
1226
}
 
1227
 
 
1228
SkBitmap::RLEPixels::~RLEPixels() {
 
1229
    sk_free(fYPtrs);
 
1230
}
 
1231
 
 
1232
///////////////////////////////////////////////////////////////////////////////
 
1233
 
 
1234
#ifdef SK_DEBUG
 
1235
void SkBitmap::validate() const {
 
1236
    SkASSERT(fConfig < kConfigCount);
 
1237
    SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth));
 
1238
    SkASSERT(fFlags <= kImageIsOpaque_Flag);
 
1239
    SkASSERT(fPixelLockCount >= 0);
 
1240
    SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000);
 
1241
    SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel);
 
1242
 
 
1243
#if 0   // these asserts are not thread-correct, so disable for now
 
1244
    if (fPixelRef) {
 
1245
        if (fPixelLockCount > 0) {
 
1246
            SkASSERT(fPixelRef->getLockCount() > 0);
 
1247
        } else {
 
1248
            SkASSERT(NULL == fPixels);
 
1249
            SkASSERT(NULL == fColorTable);
 
1250
        }
 
1251
    }
 
1252
#endif
 
1253
}
 
1254
#endif
 
1255