2
* Copyright (C) 2006-2008 The Android Open Source Project
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
8
* http://www.apache.org/licenses/LICENSE-2.0
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.
18
#include "SkColorPriv.h"
20
#include "SkFlattenable.h"
21
#include "SkMallocPixelRef.h"
23
#include "SkPixelRef.h"
26
#include "SkPackBits.h"
29
#ifdef SK_SUPPORT_MIPMAP
33
uint16_t fWidth, fHeight;
36
struct SkBitmap::MipMap : SkNoncopyable {
39
// MipLevel fLevel[fLevelCount];
42
static MipMap* Alloc(int levelCount, size_t pixelSize) {
43
MipMap* mm = (MipMap*)sk_malloc_throw(sizeof(MipMap) +
44
levelCount * sizeof(MipLevel) +
47
mm->fLevelCount = levelCount;
51
const MipLevel* levels() const { return (const MipLevel*)(this + 1); }
52
MipLevel* levels() { return (MipLevel*)(this + 1); }
54
const void* pixels() const { return levels() + fLevelCount; }
55
void* pixels() { return levels() + fLevelCount; }
59
SkASSERT(fRefCnt > 0);
60
sk_atomic_inc(&fRefCnt);
65
SkASSERT(fRefCnt > 0);
66
if (sk_atomic_dec(&fRefCnt) == 1) {
74
///////////////////////////////////////////////////////////////////////////////
75
///////////////////////////////////////////////////////////////////////////////
77
SkBitmap::SkBitmap() {
78
bzero(this, sizeof(*this));
81
SkBitmap::SkBitmap(const SkBitmap& src) {
82
SkDEBUGCODE(src.validate();)
83
bzero(this, sizeof(*this));
85
SkDEBUGCODE(this->validate();)
88
SkBitmap::~SkBitmap() {
89
SkDEBUGCODE(this->validate();)
93
SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
96
memcpy(this, &src, sizeof(src));
98
// inc src reference counts
99
src.fPixelRef->safeRef();
100
#ifdef SK_SUPPORT_MIPMAP
101
src.fMipMap->safeRef();
104
// we reset our locks if we get blown away
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
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
122
SkDEBUGCODE(this->validate();)
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);
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);
142
SkDEBUGCODE(this->validate();)
145
void SkBitmap::reset() {
147
bzero(this, sizeof(*this));
150
int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
155
bpp = 0; // not applicable
157
case kRLE_Index8_Config:
162
case kRGB_565_Config:
163
case kARGB_4444_Config:
166
case kARGB_8888_Config:
170
SkASSERT(!"unknown config");
177
int SkBitmap::ComputeRowBytes(Config c, int width) {
182
case kRLE_Index8_Config:
183
// assume that the bitmap has no pixels to draw to
187
rowBytes = (width + 7) >> 3;
193
case kRGB_565_Config:
194
case kARGB_4444_Config:
195
rowBytes = width << 1;
197
case kARGB_8888_Config:
198
rowBytes = width << 2;
201
SkASSERT(!"unknown config");
207
Sk64 SkBitmap::ComputeSize64(Config c, int width, int height) {
209
size.setMul(SkBitmap::ComputeRowBytes(c, width), height);
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()) {
221
void SkBitmap::setConfig(Config c, int width, int height, int rowBytes) {
225
rowBytes = SkBitmap::ComputeRowBytes(c, width);
228
fWidth = SkToU16(width);
229
fHeight = SkToU16(height);
230
fRowBytes = rowBytes;
232
fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c);
234
SkDEBUGCODE(this->validate();)
237
void SkBitmap::updatePixelsFromRef() const {
238
if (NULL != fPixelRef) {
239
if (fPixelLockCount > 0) {
240
SkASSERT(fPixelRef->getLockCount() > 0);
242
void* p = fPixelRef->pixels();
244
p = (char*)p + fPixelRefOffset;
247
SkRefCnt_SafeAssign(fColorTable, fPixelRef->colorTable());
249
SkASSERT(0 == fPixelLockCount);
251
fColorTable->safeUnref();
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
263
if (fPixelRef != pr || fPixelRefOffset != offset) {
264
if (fPixelRef != pr) {
266
SkASSERT(NULL == fPixelRef);
271
fPixelRefOffset = offset;
272
this->updatePixelsFromRef();
275
SkDEBUGCODE(this->validate();)
279
void SkBitmap::lockPixels() const {
280
if (NULL != fPixelRef && 1 == ++fPixelLockCount) {
281
fPixelRef->lockPixels();
282
this->updatePixelsFromRef();
284
SkDEBUGCODE(this->validate();)
287
void SkBitmap::unlockPixels() const {
288
SkASSERT(NULL == fPixelRef || fPixelLockCount > 0);
290
if (NULL != fPixelRef && 0 == --fPixelLockCount) {
291
fPixelRef->unlockPixels();
292
this->updatePixelsFromRef();
294
SkDEBUGCODE(this->validate();)
297
void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
300
SkRefCnt_SafeAssign(fColorTable, ctable);
302
SkDEBUGCODE(this->validate();)
305
bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) {
306
HeapAllocator stdalloc;
308
if (NULL == allocator) {
309
allocator = &stdalloc;
311
return allocator->allocPixelRef(this, ctable);
314
void SkBitmap::freePixels() {
315
// if we're gonna free the pixels, we certainly need to free the mipmap
318
fColorTable->safeUnref();
321
if (NULL != fPixelRef) {
322
if (fPixelLockCount > 0) {
323
fPixelRef->unlockPixels();
333
void SkBitmap::freeMipMap() {
334
#ifdef SK_SUPPORT_MIPMAP
335
fMipMap->safeUnref();
340
uint32_t SkBitmap::getGenerationID() const {
341
return fPixelRef ? fPixelRef->getGenerationID() : 0;
344
void SkBitmap::notifyPixelsChanged() const {
346
fPixelRef->notifyPixelsChanged();
350
///////////////////////////////////////////////////////////////////////////////
352
SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size,
353
SkColorTable* ctable) {
361
SkMallocPixelRef::~SkMallocPixelRef() {
362
fCTable->safeUnref();
366
void* SkMallocPixelRef::onLockPixels(SkColorTable** ct) {
371
void SkMallocPixelRef::onUnlockPixels() {
375
void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
376
this->INHERITED::flatten(buffer);
378
buffer.write32(fSize);
379
buffer.writePad(fStorage, fSize);
381
buffer.writeBool(true);
382
fCTable->flatten(buffer);
384
buffer.writeBool(false);
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));
399
static SkPixelRef::Registrar reg("SkMallocPixelRef",
400
SkMallocPixelRef::Create);
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.
405
bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
406
SkColorTable* ctable) {
407
Sk64 size = dst->getSize64();
408
if (size.isNeg() || !size.is32()) {
412
void* addr = sk_malloc_flags(size.get32(), 0); // returns NULL on failure
417
dst->setPixelRef(new SkMallocPixelRef(addr, size.get32(), ctable))->unref();
418
// since we're already allocated, we lockPixels right away
423
///////////////////////////////////////////////////////////////////////////////
425
bool SkBitmap::isOpaque() const {
432
case kARGB_4444_Config:
433
case kARGB_8888_Config:
434
return (fFlags & kImageIsOpaque_Flag) != 0;
437
case kRLE_Index8_Config: {
441
// if lockPixels failed, we may not have a ctable ptr
443
flags = fColorTable->getFlags();
445
this->unlockPixels();
447
return (flags & SkColorTable::kColorsAreOpaque_Flag) != 0;
450
case kRGB_565_Config:
454
SkASSERT(!"unknown bitmap config pased to isOpaque");
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.
464
fFlags |= kImageIsOpaque_Flag;
466
fFlags &= ~kImageIsOpaque_Flag;
470
void* SkBitmap::getAddr(int x, int y) const {
471
SkASSERT((unsigned)x < (unsigned)this->width());
472
SkASSERT((unsigned)y < (unsigned)this->height());
474
char* base = (char*)this->getPixels();
476
base += y * this->rowBytes();
477
switch (this->config()) {
478
case SkBitmap::kARGB_8888_Config:
481
case SkBitmap::kARGB_4444_Config:
482
case SkBitmap::kRGB_565_Config:
485
case SkBitmap::kA8_Config:
486
case SkBitmap::kIndex8_Config:
489
case SkBitmap::kA1_Config:
492
case kRLE_Index8_Config:
493
SkASSERT(!"Can't return addr for kRLE_Index8_Config");
497
SkASSERT(!"Can't return addr for config");
505
///////////////////////////////////////////////////////////////////////////////
506
///////////////////////////////////////////////////////////////////////////////
508
void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
509
SkDEBUGCODE(this->validate();)
511
if (0 == fWidth || 0 == fHeight ||
512
kNo_Config == fConfig || kIndex8_Config == fConfig) {
516
SkAutoLockPixels alp(*this);
517
// perform this check after the lock call
518
if (!this->readyToDraw()) {
522
int height = fHeight;
523
const int width = fWidth;
524
const int rowBytes = fRowBytes;
526
// make rgb premultiplied
528
r = SkAlphaMul(r, a);
529
g = SkAlphaMul(g, a);
530
b = SkAlphaMul(b, a);
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) {
546
uint8_t* p = (uint8_t*)fPixels;
547
while (--height >= 0) {
553
case kARGB_4444_Config:
554
case kRGB_565_Config: {
555
uint16_t* p = (uint16_t*)fPixels;
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));
564
while (--height >= 0) {
565
sk_memset16(p, v, width);
566
p = (uint16_t*)((char*)p + rowBytes);
570
case kARGB_8888_Config: {
571
uint32_t* p = (uint32_t*)fPixels;
572
uint32_t v = SkPackARGB32(a, r, g, b);
574
while (--height >= 0) {
575
sk_memset32(p, v, width);
576
p = (uint32_t*)((char*)p + rowBytes);
582
this->notifyPixelsChanged();
585
//////////////////////////////////////////////////////////////////////////////////////
586
//////////////////////////////////////////////////////////////////////////////////////
588
#define SUB_OFFSET_FAILURE ((size_t)-1)
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());
594
switch (bm.getConfig()) {
595
case SkBitmap::kA8_Config:
596
case SkBitmap:: kIndex8_Config:
597
// x is fine as is for the calculation
600
case SkBitmap::kRGB_565_Config:
601
case SkBitmap::kARGB_4444_Config:
605
case SkBitmap::kARGB_8888_Config:
609
case SkBitmap::kNo_Config:
610
case SkBitmap::kA1_Config:
612
return SUB_OFFSET_FAILURE;
614
return y * bm.rowBytes() + x;
617
bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
618
SkDEBUGCODE(this->validate();)
620
if (NULL == result || (NULL == fPixelRef && NULL == fPixels)) {
621
return false; // no src pixels
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)
630
if (kRLE_Index8_Config == fConfig) {
631
SkAutoLockPixels alp(*this);
632
// don't call readyToDraw(), since we can operate w/o a colortable
634
if (this->getPixels() == NULL) {
639
bm.setConfig(kIndex8_Config, r.width(), r.height());
640
bm.allocPixels(this->getColorTable());
641
if (NULL == bm.getPixels()) {
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();
650
for (int y = r.fTop; y < r.fBottom; y++) {
651
SkPackBits::Unpack8(dst, r.fLeft, width, rle->packedAtY(y));
658
size_t offset = getSubOffset(*this, r.fLeft, r.fTop);
659
if (SUB_OFFSET_FAILURE == offset) {
660
return false; // config not supported
664
dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes());
667
// share the pixelref with a custom offset
668
dst.setPixelRef(fPixelRef, fPixelRefOffset + offset);
670
// share the pixels (owned by the caller)
671
dst.setPixels((char*)fPixels + offset, this->getColorTable());
673
SkDEBUGCODE(dst.validate();)
675
// we know we're good, so commit to result
680
///////////////////////////////////////////////////////////////////////////////
682
#include "SkCanvas.h"
685
bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
686
if (NULL == dst || this->width() == 0 || this->height() == 0) {
692
case kARGB_4444_Config:
693
case kRGB_565_Config:
694
case kARGB_8888_Config:
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)) {
708
SkAutoLockPixels srclock(*this);
709
SkAutoLockPixels dstlock(tmp);
711
if (!this->readyToDraw() || !tmp.readyToDraw()) {
712
// allocator/lock failed
716
// if the src has alpha, we have to clear the dst first
717
if (!this->isOpaque()) {
721
SkCanvas canvas(tmp);
724
paint.setDither(true);
725
canvas.drawBitmap(*this, 0, 0, &paint);
731
///////////////////////////////////////////////////////////////////////////////
732
///////////////////////////////////////////////////////////////////////////////
734
static void downsampleby2_proc32(SkBitmap* dst, int x, int y,
735
const SkBitmap& src) {
738
const SkPMColor* p = src.getAddr32(x, y);
741
c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
742
if (x < src.width() - 1) {
745
c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
747
if (y < src.height() - 1) {
748
p = src.getAddr32(x, y + 1);
750
c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
751
if (x < src.width() - 1) {
754
c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
756
*dst->getAddr32(x >> 1, y >> 1) =
757
((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
760
static inline uint32_t expand16(U16CPU c) {
761
return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
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);
770
static void downsampleby2_proc16(SkBitmap* dst, int x, int y,
771
const SkBitmap& src) {
774
const uint16_t* p = src.getAddr16(x, y);
778
if (x < (int)src.width() - 1) {
783
if (y < (int)src.height() - 1) {
784
p = src.getAddr16(x, y + 1);
787
if (x < (int)src.width() - 1) {
792
*dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
795
static uint32_t expand4444(U16CPU c) {
796
return (c & 0xF0F) | ((c & ~0xF0F) << 12);
799
static U16CPU collaps4444(uint32_t c) {
800
return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
803
static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
804
const SkBitmap& src) {
807
const uint16_t* p = src.getAddr16(x, y);
811
if (x < src.width() - 1) {
816
if (y < src.height() - 1) {
817
p = src.getAddr16(x, y + 1);
820
if (x < src.width() - 1) {
825
*dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
828
void SkBitmap::buildMipMap(bool forceRebuild) {
829
#ifdef SK_SUPPORT_MIPMAP
833
return; // we're already built
835
SkASSERT(NULL == fMipMap);
837
void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
839
const SkBitmap::Config config = this->getConfig();
842
case kARGB_8888_Config:
843
proc = downsampleby2_proc32;
845
case kRGB_565_Config:
846
proc = downsampleby2_proc16;
848
case kARGB_4444_Config:
849
proc = downsampleby2_proc4444;
854
return; // don't build mipmaps for these configs
857
// whip through our loop to compute the exact size needed
861
unsigned width = this->width();
862
unsigned height = this->height();
866
if (0 == width || 0 == height) {
869
size += ComputeRowBytes(config, width) * height;
873
if (0 == maxLevels) {
877
MipMap* mm = MipMap::Alloc(maxLevels, size);
878
MipLevel* level = mm->levels();
879
uint8_t* addr = (uint8_t*)mm->pixels();
881
unsigned width = this->width();
882
unsigned height = this->height();
883
unsigned rowBytes = this->rowBytes();
884
SkBitmap srcBM(*this), dstBM;
888
for (int i = 0; i < maxLevels; i++) {
891
rowBytes = ComputeRowBytes(config, width);
893
level[i].fPixels = addr;
894
level[i].fWidth = SkToU16(width);
895
level[i].fHeight = SkToU16(height);
896
level[i].fRowBytes = SkToU16(rowBytes);
898
dstBM.setConfig(config, width, height, rowBytes);
899
dstBM.setPixels(addr);
901
for (unsigned y = 0; y < height; y++) {
902
for (unsigned x = 0; x < width; x++) {
903
proc(&dstBM, x, y, srcBM);
908
addr += height * rowBytes;
910
SkASSERT(addr == (uint8_t*)mm->pixels() + size);
915
bool SkBitmap::hasMipMap() const {
916
#ifdef SK_SUPPORT_MIPMAP
917
return fMipMap != NULL;
923
int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) {
924
#ifdef SK_SUPPORT_MIPMAP
928
int level = ComputeMipLevel(sx, sy) >> 16;
929
SkASSERT(level >= 0);
934
if (level >= fMipMap->fLevelCount) {
935
level = fMipMap->fLevelCount - 1;
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);
949
SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) {
950
#ifdef SK_SUPPORT_MIPMAP
956
if (sx < SK_Fixed1) {
960
SkASSERT(clz >= 1 && clz <= 15);
961
return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16);
967
///////////////////////////////////////////////////////////////////////////////
969
static void GetBitmapAlpha(const SkBitmap& src, uint8_t SK_RESTRICT alpha[],
971
SkASSERT(alpha != NULL);
972
SkASSERT(alphaRowBytes >= src.width());
974
SkBitmap::Config config = src.getConfig();
976
int h = src.height();
977
int rb = src.rowBytes();
979
if (SkBitmap::kA8_Config == config && !src.isOpaque()) {
980
const uint8_t* s = src.getAddr8(0, 0);
984
alpha += alphaRowBytes;
986
} else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) {
987
const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
989
for (int x = 0; x < w; x++) {
990
alpha[x] = SkGetPackedA32(s[x]);
992
s = (const SkPMColor*)((const char*)s + rb);
993
alpha += alphaRowBytes;
995
} else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) {
996
const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
998
for (int x = 0; x < w; x++) {
999
alpha[x] = SkPacked4444ToA32(s[x]);
1001
s = (const SkPMColor16*)((const char*)s + rb);
1002
alpha += alphaRowBytes;
1004
} else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) {
1005
SkColorTable* ct = src.getColorTable();
1007
const SkPMColor* SK_RESTRICT table = ct->lockColors();
1008
const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
1010
for (int x = 0; x < w; x++) {
1011
alpha[x] = SkGetPackedA32(table[s[x]]);
1014
alpha += alphaRowBytes;
1016
ct->unlockColors(false);
1018
} else { // src is opaque, so just fill alpha[] with 0xFF
1019
memset(alpha, 0xFF, h * alphaRowBytes);
1023
#include "SkPaint.h"
1024
#include "SkMaskFilter.h"
1025
#include "SkMatrix.h"
1027
void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
1028
SkIPoint* offset) const {
1029
SkDEBUGCODE(this->validate();)
1034
srcM.fBounds.set(0, 0, this->width(), this->height());
1035
srcM.fRowBytes = SkAlign4(this->width());
1036
srcM.fFormat = SkMask::kA8_Format;
1038
SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL;
1040
// compute our (larger?) dst bounds if we have a filter
1041
if (NULL != filter) {
1044
if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
1045
goto NO_FILTER_CASE;
1047
dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
1050
dst->setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
1053
GetBitmapAlpha(*this, dst->getAddr8(0, 0), srcM.fRowBytes);
1060
SkAutoMaskImage srcCleanup(&srcM, true);
1062
GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
1063
if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
1064
goto NO_FILTER_CASE;
1067
SkAutoMaskImage dstCleanup(&dstM, false);
1069
dst->setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
1070
dstM.fBounds.height(), dstM.fRowBytes);
1072
memcpy(dst->getPixels(), dstM.fImage, dstM.computeImageSize());
1074
offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
1076
SkDEBUGCODE(dst->validate();)
1079
///////////////////////////////////////////////////////////////////////////////
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,
1089
static void writeString(SkFlattenableWriteBuffer& buffer, const char str[]) {
1090
size_t len = strlen(str);
1091
buffer.write32(len);
1092
buffer.writePad(str, len);
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);
1101
return SkPixelRef::NameToFactory(str);
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
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.
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());
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.
1125
if (!buffer.persistBitmapPixels()) {
1127
buffer.write8(SERIALIZE_PIXELTYPE_REF_PTR);
1128
buffer.write32(fPixelRefOffset);
1129
buffer.writeRefCnt(fPixelRef);
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
1136
buffer.write8(SERIALIZE_PIXELTYPE_NONE);
1143
SkPixelRef::Factory fact = fPixelRef->getFactory();
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);
1154
// if we get here, we can't record the pixels
1155
buffer.write8(SERIALIZE_PIXELTYPE_NONE);
1156
} else if (fPixels) {
1158
buffer.write8(SERIALIZE_PIXELTYPE_RAW_WITH_CTABLE);
1159
fColorTable->flatten(buffer);
1161
buffer.write8(SERIALIZE_PIXELTYPE_RAW_NO_CTABLE);
1163
buffer.writePad(fPixels, this->getSize());
1165
buffer.write8(SERIALIZE_PIXELTYPE_NONE);
1169
void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) {
1172
int width = buffer.readInt();
1173
int height = buffer.readInt();
1174
int rowBytes = buffer.readInt();
1175
int config = buffer.readU8();
1177
this->setConfig((Config)config, width, height, rowBytes);
1178
this->setIsOpaque(buffer.readBool());
1180
size_t size = this->getSize();
1181
int reftype = buffer.readU8();
1183
case SERIALIZE_PIXELTYPE_REF_PTR: {
1184
size_t offset = buffer.readU32();
1185
SkPixelRef* pr = (SkPixelRef*)buffer.readRefCnt();
1186
this->setPixelRef(pr, offset);
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();
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));
1202
if (this->allocPixels(ctable)) {
1204
buffer.read(this->getPixels(), size);
1205
this->unlockPixels();
1209
ctable->safeUnref();
1212
case SERIALIZE_PIXELTYPE_NONE:
1215
SkASSERT(!"unrecognized pixeltype in serialized data");
1220
///////////////////////////////////////////////////////////////////////////////
1222
SkBitmap::RLEPixels::RLEPixels(int width, int height) {
1224
fYPtrs = (uint8_t**)sk_malloc_throw(height * sizeof(uint8_t*));
1225
bzero(fYPtrs, height * sizeof(uint8_t*));
1228
SkBitmap::RLEPixels::~RLEPixels() {
1232
///////////////////////////////////////////////////////////////////////////////
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);
1243
#if 0 // these asserts are not thread-correct, so disable for now
1245
if (fPixelLockCount > 0) {
1246
SkASSERT(fPixelRef->getLockCount() > 0);
1248
SkASSERT(NULL == fPixels);
1249
SkASSERT(NULL == fColorTable);