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