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