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