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