SkBitmap.cpp revision b236d1a37bd8ee936587faa0a55128a1f901cb5a
1/*
2 * Copyright 2008 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkAtomics.h"
9#include "SkBitmap.h"
10#include "SkColorPriv.h"
11#include "SkData.h"
12#include "SkFilterQuality.h"
13#include "SkMallocPixelRef.h"
14#include "SkMask.h"
15#include "SkMath.h"
16#include "SkPixelRef.h"
17#include "SkReadBuffer.h"
18#include "SkRect.h"
19#include "SkScalar.h"
20#include "SkUnPreMultiply.h"
21#include "SkWriteBuffer.h"
22
23#include <string.h>
24
25static bool reset_return_false(SkBitmap* bm) {
26    bm->reset();
27    return false;
28}
29
30SkBitmap::SkBitmap() {
31    sk_bzero(this, sizeof(*this));
32}
33
34SkBitmap::SkBitmap(const SkBitmap& src) {
35    SkDEBUGCODE(src.validate();)
36    sk_bzero(this, sizeof(*this));
37    *this = src;
38    SkDEBUGCODE(this->validate();)
39}
40
41SkBitmap::~SkBitmap() {
42    SkDEBUGCODE(this->validate();)
43    this->freePixels();
44}
45
46SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
47    if (this != &src) {
48        this->freePixels();
49        memcpy(this, &src, sizeof(src));
50
51        // inc src reference counts
52        SkSafeRef(src.fPixelRef);
53
54        // we reset our locks if we get blown away
55        fPixelLockCount = 0;
56
57        if (fPixelRef) {
58            // ignore the values from the memcpy
59            fPixels = nullptr;
60            fColorTable = nullptr;
61            // Note that what to for genID is somewhat arbitrary. We have no
62            // way to track changes to raw pixels across multiple SkBitmaps.
63            // Would benefit from an SkRawPixelRef type created by
64            // setPixels.
65            // Just leave the memcpy'ed one but they'll get out of sync
66            // as soon either is modified.
67        }
68    }
69
70    SkDEBUGCODE(this->validate();)
71    return *this;
72}
73
74void SkBitmap::swap(SkBitmap& other) {
75    SkTSwap(fColorTable, other.fColorTable);
76    SkTSwap(fPixelRef, other.fPixelRef);
77    SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin);
78    SkTSwap(fPixelLockCount, other.fPixelLockCount);
79    SkTSwap(fPixels, other.fPixels);
80    SkTSwap(fInfo, other.fInfo);
81    SkTSwap(fRowBytes, other.fRowBytes);
82    SkTSwap(fFlags, other.fFlags);
83
84    SkDEBUGCODE(this->validate();)
85}
86
87void SkBitmap::reset() {
88    this->freePixels();
89    sk_bzero(this, sizeof(*this));
90}
91
92void SkBitmap::getBounds(SkRect* bounds) const {
93    SkASSERT(bounds);
94    bounds->set(0, 0,
95                SkIntToScalar(fInfo.width()), SkIntToScalar(fInfo.height()));
96}
97
98void SkBitmap::getBounds(SkIRect* bounds) const {
99    SkASSERT(bounds);
100    bounds->set(0, 0, fInfo.width(), fInfo.height());
101}
102
103///////////////////////////////////////////////////////////////////////////////
104
105bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) {
106    SkAlphaType newAT = info.alphaType();
107    if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) {
108        return reset_return_false(this);
109    }
110    // don't look at info.alphaType(), since newAT is the real value...
111
112    // require that rowBytes fit in 31bits
113    int64_t mrb = info.minRowBytes64();
114    if ((int32_t)mrb != mrb) {
115        return reset_return_false(this);
116    }
117    if ((int64_t)rowBytes != (int32_t)rowBytes) {
118        return reset_return_false(this);
119    }
120
121    if (info.width() < 0 || info.height() < 0) {
122        return reset_return_false(this);
123    }
124
125    if (kUnknown_SkColorType == info.colorType()) {
126        rowBytes = 0;
127    } else if (0 == rowBytes) {
128        rowBytes = (size_t)mrb;
129    } else if (!info.validRowBytes(rowBytes)) {
130        return reset_return_false(this);
131    }
132
133    this->freePixels();
134
135    fInfo = info.makeAlphaType(newAT);
136    fRowBytes = SkToU32(rowBytes);
137    return true;
138}
139
140bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) {
141    if (!SkColorTypeValidateAlphaType(fInfo.colorType(), newAlphaType, &newAlphaType)) {
142        return false;
143    }
144    if (fInfo.alphaType() != newAlphaType) {
145        fInfo = fInfo.makeAlphaType(newAlphaType);
146        if (fPixelRef) {
147            fPixelRef->changeAlphaType(newAlphaType);
148        }
149    }
150    return true;
151}
152
153void SkBitmap::updatePixelsFromRef() const {
154    if (fPixelRef) {
155        if (fPixelLockCount > 0) {
156            SkASSERT(fPixelRef->isLocked());
157
158            void* p = fPixelRef->pixels();
159            if (p) {
160                p = (char*)p
161                    + fPixelRefOrigin.fY * fRowBytes
162                    + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
163            }
164            fPixels = p;
165            fColorTable = fPixelRef->colorTable();
166        } else {
167            SkASSERT(0 == fPixelLockCount);
168            fPixels = nullptr;
169            fColorTable = nullptr;
170        }
171    }
172}
173
174SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
175#ifdef SK_DEBUG
176    if (pr) {
177        if (kUnknown_SkColorType != fInfo.colorType()) {
178            const SkImageInfo& prInfo = pr->info();
179            SkASSERT(fInfo.width() <= prInfo.width());
180            SkASSERT(fInfo.height() <= prInfo.height());
181            SkASSERT(fInfo.colorType() == prInfo.colorType());
182            switch (prInfo.alphaType()) {
183                case kUnknown_SkAlphaType:
184                    SkASSERT(fInfo.alphaType() == kUnknown_SkAlphaType);
185                    break;
186                case kOpaque_SkAlphaType:
187                case kPremul_SkAlphaType:
188                    SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType ||
189                             fInfo.alphaType() == kPremul_SkAlphaType);
190                    break;
191                case kUnpremul_SkAlphaType:
192                    SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType ||
193                             fInfo.alphaType() == kUnpremul_SkAlphaType);
194                    break;
195            }
196        }
197    }
198#endif
199
200    if (pr) {
201        const SkImageInfo& info = pr->info();
202        fPixelRefOrigin.set(SkTPin(dx, 0, info.width()), SkTPin(dy, 0, info.height()));
203    } else {
204        // ignore dx,dy if there is no pixelref
205        fPixelRefOrigin.setZero();
206    }
207
208    if (fPixelRef != pr) {
209        this->freePixels();
210        SkASSERT(nullptr == fPixelRef);
211
212        SkSafeRef(pr);
213        fPixelRef = pr;
214        this->updatePixelsFromRef();
215    }
216
217    SkDEBUGCODE(this->validate();)
218    return pr;
219}
220
221void SkBitmap::lockPixels() const {
222    if (fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) {
223        fPixelRef->lockPixels();
224        this->updatePixelsFromRef();
225    }
226    SkDEBUGCODE(this->validate();)
227}
228
229void SkBitmap::unlockPixels() const {
230    SkASSERT(nullptr == fPixelRef || fPixelLockCount > 0);
231
232    if (fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) {
233        fPixelRef->unlockPixels();
234        this->updatePixelsFromRef();
235    }
236    SkDEBUGCODE(this->validate();)
237}
238
239bool SkBitmap::lockPixelsAreWritable() const {
240    return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false;
241}
242
243void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
244    if (nullptr == p) {
245        this->setPixelRef(nullptr);
246        return;
247    }
248
249    if (kUnknown_SkColorType == fInfo.colorType()) {
250        this->setPixelRef(nullptr);
251        return;
252    }
253
254    SkPixelRef* pr = SkMallocPixelRef::NewDirect(fInfo, p, fRowBytes, ctable);
255    if (nullptr == pr) {
256        this->setPixelRef(nullptr);
257        return;
258    }
259
260    this->setPixelRef(pr)->unref();
261
262    // since we're already allocated, we lockPixels right away
263    this->lockPixels();
264    SkDEBUGCODE(this->validate();)
265}
266
267bool SkBitmap::tryAllocPixels(Allocator* allocator, SkColorTable* ctable) {
268    HeapAllocator stdalloc;
269
270    if (nullptr == allocator) {
271        allocator = &stdalloc;
272    }
273    return allocator->allocPixelRef(this, ctable);
274}
275
276///////////////////////////////////////////////////////////////////////////////
277
278bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) {
279    if (kIndex_8_SkColorType == requestedInfo.colorType()) {
280        return reset_return_false(this);
281    }
282    if (!this->setInfo(requestedInfo, rowBytes)) {
283        return reset_return_false(this);
284    }
285
286    // setInfo may have corrected info (e.g. 565 is always opaque).
287    const SkImageInfo& correctedInfo = this->info();
288    // setInfo may have computed a valid rowbytes if 0 were passed in
289    rowBytes = this->rowBytes();
290
291    SkMallocPixelRef::PRFactory defaultFactory;
292
293    SkPixelRef* pr = defaultFactory.create(correctedInfo, rowBytes, nullptr);
294    if (nullptr == pr) {
295        return reset_return_false(this);
296    }
297    this->setPixelRef(pr)->unref();
298
299    // TODO: lockPixels could/should return bool or void*/nullptr
300    this->lockPixels();
301    if (nullptr == this->getPixels()) {
302        return reset_return_false(this);
303    }
304    return true;
305}
306
307bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactory* factory,
308                                SkColorTable* ctable) {
309    if (kIndex_8_SkColorType == requestedInfo.colorType() && nullptr == ctable) {
310        return reset_return_false(this);
311    }
312    if (!this->setInfo(requestedInfo)) {
313        return reset_return_false(this);
314    }
315
316    // setInfo may have corrected info (e.g. 565 is always opaque).
317    const SkImageInfo& correctedInfo = this->info();
318
319    SkMallocPixelRef::PRFactory defaultFactory;
320    if (nullptr == factory) {
321        factory = &defaultFactory;
322    }
323
324    SkPixelRef* pr = factory->create(correctedInfo, correctedInfo.minRowBytes(), ctable);
325    if (nullptr == pr) {
326        return reset_return_false(this);
327    }
328    this->setPixelRef(pr)->unref();
329
330    // TODO: lockPixels could/should return bool or void*/nullptr
331    this->lockPixels();
332    if (nullptr == this->getPixels()) {
333        return reset_return_false(this);
334    }
335    return true;
336}
337
338static void invoke_release_proc(void (*proc)(void* pixels, void* ctx), void* pixels, void* ctx) {
339    if (proc) {
340        proc(pixels, ctx);
341    }
342}
343
344bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
345                             SkColorTable* ct, void (*releaseProc)(void* addr, void* context),
346                             void* context) {
347    if (!this->setInfo(requestedInfo, rb)) {
348        invoke_release_proc(releaseProc, pixels, context);
349        this->reset();
350        return false;
351    }
352    if (nullptr == pixels) {
353        invoke_release_proc(releaseProc, pixels, context);
354        return true;    // we behaved as if they called setInfo()
355    }
356
357    // setInfo may have corrected info (e.g. 565 is always opaque).
358    const SkImageInfo& correctedInfo = this->info();
359
360    SkPixelRef* pr = SkMallocPixelRef::NewWithProc(correctedInfo, rb, ct, pixels, releaseProc,
361                                                   context);
362    if (!pr) {
363        this->reset();
364        return false;
365    }
366
367    this->setPixelRef(pr)->unref();
368
369    // since we're already allocated, we lockPixels right away
370    this->lockPixels();
371    SkDEBUGCODE(this->validate();)
372    return true;
373}
374
375bool SkBitmap::installMaskPixels(const SkMask& mask) {
376    if (SkMask::kA8_Format != mask.fFormat) {
377        this->reset();
378        return false;
379    }
380    return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
381                                                   mask.fBounds.height()),
382                               mask.fImage, mask.fRowBytes);
383}
384
385///////////////////////////////////////////////////////////////////////////////
386
387void SkBitmap::freePixels() {
388    if (fPixelRef) {
389        if (fPixelLockCount > 0) {
390            fPixelRef->unlockPixels();
391        }
392        fPixelRef->unref();
393        fPixelRef = nullptr;
394        fPixelRefOrigin.setZero();
395    }
396    fPixelLockCount = 0;
397    fPixels = nullptr;
398    fColorTable = nullptr;
399}
400
401uint32_t SkBitmap::getGenerationID() const {
402    return (fPixelRef) ? fPixelRef->getGenerationID() : 0;
403}
404
405void SkBitmap::notifyPixelsChanged() const {
406    SkASSERT(!this->isImmutable());
407    if (fPixelRef) {
408        fPixelRef->notifyPixelsChanged();
409    }
410}
411
412GrTexture* SkBitmap::getTexture() const {
413    return fPixelRef ? fPixelRef->getTexture() : nullptr;
414}
415
416///////////////////////////////////////////////////////////////////////////////
417
418/** We explicitly use the same allocator for our pixels that SkMask does,
419 so that we can freely assign memory allocated by one class to the other.
420 */
421bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
422                                            SkColorTable* ctable) {
423    const SkImageInfo info = dst->info();
424    if (kUnknown_SkColorType == info.colorType()) {
425//        SkDebugf("unsupported config for info %d\n", dst->config());
426        return false;
427    }
428
429    SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), ctable);
430    if (nullptr == pr) {
431        return false;
432    }
433
434    dst->setPixelRef(pr)->unref();
435    // since we're already allocated, we lockPixels right away
436    dst->lockPixels();
437    return true;
438}
439
440///////////////////////////////////////////////////////////////////////////////
441
442static bool copy_pixels_to(const SkPixmap& src, void* const dst, size_t dstSize,
443                           size_t dstRowBytes, bool preserveDstPad) {
444    const SkImageInfo& info = src.info();
445
446    if (0 == dstRowBytes) {
447        dstRowBytes = src.rowBytes();
448    }
449    if (dstRowBytes < info.minRowBytes()) {
450        return false;
451    }
452
453    if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == src.rowBytes()) {
454        size_t safeSize = src.getSafeSize();
455        if (safeSize > dstSize || safeSize == 0)
456            return false;
457        else {
458            // This implementation will write bytes beyond the end of each row,
459            // excluding the last row, if the bitmap's stride is greater than
460            // strictly required by the current config.
461            memcpy(dst, src.addr(), safeSize);
462            return true;
463        }
464    } else {
465        // If destination has different stride than us, then copy line by line.
466        if (info.getSafeSize(dstRowBytes) > dstSize) {
467            return false;
468        } else {
469            // Just copy what we need on each line.
470            size_t rowBytes = info.minRowBytes();
471            const uint8_t* srcP = reinterpret_cast<const uint8_t*>(src.addr());
472            uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
473            for (int row = 0; row < info.height(); ++row) {
474                memcpy(dstP, srcP, rowBytes);
475                srcP += src.rowBytes();
476                dstP += dstRowBytes;
477            }
478
479            return true;
480        }
481    }
482}
483
484bool SkBitmap::copyPixelsTo(void* dst, size_t dstSize, size_t dstRB, bool preserveDstPad) const {
485    if (nullptr == dst) {
486        return false;
487    }
488    SkAutoPixmapUnlock result;
489    if (!this->requestLock(&result)) {
490        return false;
491    }
492    return copy_pixels_to(result.pixmap(), dst, dstSize, dstRB, preserveDstPad);
493}
494
495///////////////////////////////////////////////////////////////////////////////
496
497bool SkBitmap::isImmutable() const {
498    return fPixelRef ? fPixelRef->isImmutable() : false;
499}
500
501void SkBitmap::setImmutable() {
502    if (fPixelRef) {
503        fPixelRef->setImmutable();
504    }
505}
506
507bool SkBitmap::isVolatile() const {
508    return (fFlags & kImageIsVolatile_Flag) != 0;
509}
510
511void SkBitmap::setIsVolatile(bool isVolatile) {
512    if (isVolatile) {
513        fFlags |= kImageIsVolatile_Flag;
514    } else {
515        fFlags &= ~kImageIsVolatile_Flag;
516    }
517}
518
519void* SkBitmap::getAddr(int x, int y) const {
520    SkASSERT((unsigned)x < (unsigned)this->width());
521    SkASSERT((unsigned)y < (unsigned)this->height());
522
523    char* base = (char*)this->getPixels();
524    if (base) {
525        base += y * this->rowBytes();
526        switch (this->colorType()) {
527            case kRGBA_8888_SkColorType:
528            case kBGRA_8888_SkColorType:
529                base += x << 2;
530                break;
531            case kARGB_4444_SkColorType:
532            case kRGB_565_SkColorType:
533                base += x << 1;
534                break;
535            case kAlpha_8_SkColorType:
536            case kIndex_8_SkColorType:
537            case kGray_8_SkColorType:
538                base += x;
539                break;
540            default:
541                SkDEBUGFAIL("Can't return addr for config");
542                base = nullptr;
543                break;
544        }
545    }
546    return base;
547}
548
549SkColor SkBitmap::getColor(int x, int y) const {
550    SkASSERT((unsigned)x < (unsigned)this->width());
551    SkASSERT((unsigned)y < (unsigned)this->height());
552
553    switch (this->colorType()) {
554        case kGray_8_SkColorType: {
555            uint8_t* addr = this->getAddr8(x, y);
556            return SkColorSetRGB(*addr, *addr, *addr);
557        }
558        case kAlpha_8_SkColorType: {
559            uint8_t* addr = this->getAddr8(x, y);
560            return SkColorSetA(0, addr[0]);
561        }
562        case kIndex_8_SkColorType: {
563            SkPMColor c = this->getIndex8Color(x, y);
564            return SkUnPreMultiply::PMColorToColor(c);
565        }
566        case kRGB_565_SkColorType: {
567            uint16_t* addr = this->getAddr16(x, y);
568            return SkPixel16ToColor(addr[0]);
569        }
570        case kARGB_4444_SkColorType: {
571            uint16_t* addr = this->getAddr16(x, y);
572            SkPMColor c = SkPixel4444ToPixel32(addr[0]);
573            return SkUnPreMultiply::PMColorToColor(c);
574        }
575        case kBGRA_8888_SkColorType:
576        case kRGBA_8888_SkColorType: {
577            uint32_t* addr = this->getAddr32(x, y);
578            return SkUnPreMultiply::PMColorToColor(addr[0]);
579        }
580        default:
581            SkASSERT(false);
582            return 0;
583    }
584    SkASSERT(false);  // Not reached.
585    return 0;
586}
587
588static bool compute_is_opaque(const SkPixmap& pmap) {
589    const int height = pmap.height();
590    const int width = pmap.width();
591
592    switch (pmap.colorType()) {
593        case kAlpha_8_SkColorType: {
594            unsigned a = 0xFF;
595            for (int y = 0; y < height; ++y) {
596                const uint8_t* row = pmap.addr8(0, y);
597                for (int x = 0; x < width; ++x) {
598                    a &= row[x];
599                }
600                if (0xFF != a) {
601                    return false;
602                }
603            }
604            return true;
605        } break;
606        case kIndex_8_SkColorType: {
607            const SkColorTable* ctable = pmap.ctable();
608            if (nullptr == ctable) {
609                return false;
610            }
611            const SkPMColor* table = ctable->readColors();
612            SkPMColor c = (SkPMColor)~0;
613            for (int i = ctable->count() - 1; i >= 0; --i) {
614                c &= table[i];
615            }
616            return 0xFF == SkGetPackedA32(c);
617        } break;
618        case kRGB_565_SkColorType:
619        case kGray_8_SkColorType:
620            return true;
621            break;
622        case kARGB_4444_SkColorType: {
623            unsigned c = 0xFFFF;
624            for (int y = 0; y < height; ++y) {
625                const SkPMColor16* row = pmap.addr16(0, y);
626                for (int x = 0; x < width; ++x) {
627                    c &= row[x];
628                }
629                if (0xF != SkGetPackedA4444(c)) {
630                    return false;
631                }
632            }
633            return true;
634        } break;
635        case kBGRA_8888_SkColorType:
636        case kRGBA_8888_SkColorType: {
637            SkPMColor c = (SkPMColor)~0;
638            for (int y = 0; y < height; ++y) {
639                const SkPMColor* row = pmap.addr32(0, y);
640                for (int x = 0; x < width; ++x) {
641                    c &= row[x];
642                }
643                if (0xFF != SkGetPackedA32(c)) {
644                    return false;
645                }
646            }
647            return true;
648        }
649        default:
650            break;
651    }
652    return false;
653}
654
655bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
656    SkAutoPixmapUnlock result;
657    if (!bm.requestLock(&result)) {
658        return false;
659    }
660    return compute_is_opaque(result.pixmap());
661}
662
663
664///////////////////////////////////////////////////////////////////////////////
665///////////////////////////////////////////////////////////////////////////////
666
667void SkBitmap::erase(SkColor c, const SkIRect& area) const {
668    SkDEBUGCODE(this->validate();)
669
670    switch (fInfo.colorType()) {
671        case kUnknown_SkColorType:
672        case kIndex_8_SkColorType:
673            // TODO: can we ASSERT that we never get here?
674            return; // can't erase. Should we bzero so the memory is not uninitialized?
675        default:
676            break;
677    }
678
679    SkAutoPixmapUnlock result;
680    if (!this->requestLock(&result)) {
681        return;
682    }
683
684    if (result.pixmap().erase(c, area)) {
685        this->notifyPixelsChanged();
686    }
687}
688
689void SkBitmap::eraseColor(SkColor c) const {
690    this->erase(c, SkIRect::MakeWH(this->width(), this->height()));
691}
692
693//////////////////////////////////////////////////////////////////////////////////////
694//////////////////////////////////////////////////////////////////////////////////////
695
696bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
697    SkDEBUGCODE(this->validate();)
698
699    if (nullptr == result || nullptr == fPixelRef) {
700        return false;   // no src pixels
701    }
702
703    SkIRect srcRect, r;
704    srcRect.set(0, 0, this->width(), this->height());
705    if (!r.intersect(srcRect, subset)) {
706        return false;   // r is empty (i.e. no intersection)
707    }
708
709    if (fPixelRef->getTexture() != nullptr) {
710        // Do a deep copy
711        SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), this->profileType(), &subset);
712        if (pixelRef != nullptr) {
713            SkBitmap dst;
714            dst.setInfo(SkImageInfo::Make(subset.width(), subset.height(),
715                                          this->colorType(), this->alphaType()));
716            dst.setIsVolatile(this->isVolatile());
717            dst.setPixelRef(pixelRef)->unref();
718            SkDEBUGCODE(dst.validate());
719            result->swap(dst);
720            return true;
721        }
722    }
723
724    // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
725    // exited above.
726    SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
727    SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
728
729    SkBitmap dst;
730    dst.setInfo(SkImageInfo::Make(r.width(), r.height(), this->colorType(), this->alphaType()),
731                this->rowBytes());
732    dst.setIsVolatile(this->isVolatile());
733
734    if (fPixelRef) {
735        SkIPoint origin = fPixelRefOrigin;
736        origin.fX += r.fLeft;
737        origin.fY += r.fTop;
738        // share the pixelref with a custom offset
739        dst.setPixelRef(fPixelRef, origin);
740    }
741    SkDEBUGCODE(dst.validate();)
742
743    // we know we're good, so commit to result
744    result->swap(dst);
745    return true;
746}
747
748///////////////////////////////////////////////////////////////////////////////
749
750bool SkBitmap::canCopyTo(SkColorType dstColorType) const {
751    const SkColorType srcCT = this->colorType();
752
753    if (srcCT == kUnknown_SkColorType) {
754        return false;
755    }
756
757    bool sameConfigs = (srcCT == dstColorType);
758    switch (dstColorType) {
759        case kAlpha_8_SkColorType:
760        case kRGB_565_SkColorType:
761        case kRGBA_8888_SkColorType:
762        case kBGRA_8888_SkColorType:
763            break;
764        case kIndex_8_SkColorType:
765            if (!sameConfigs) {
766                return false;
767            }
768            break;
769        case kARGB_4444_SkColorType:
770            return sameConfigs || kN32_SkColorType == srcCT || kIndex_8_SkColorType == srcCT;
771        case kGray_8_SkColorType:
772            switch (srcCT) {
773                case kGray_8_SkColorType:
774                case kRGBA_8888_SkColorType:
775                case kBGRA_8888_SkColorType:
776                    return true;
777                default:
778                    break;
779            }
780            return false;
781        default:
782            return false;
783    }
784    return true;
785}
786
787bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
788                          int x, int y) const {
789    SkAutoPixmapUnlock src;
790    if (!this->requestLock(&src)) {
791        return false;
792    }
793    return src.pixmap().readPixels(requestedDstInfo, dstPixels, dstRB, x, y);
794}
795
796bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc) const {
797    if (!this->canCopyTo(dstColorType)) {
798        return false;
799    }
800
801    // if we have a texture, first get those pixels
802    SkBitmap tmpSrc;
803    const SkBitmap* src = this;
804
805    if (fPixelRef) {
806        SkIRect subset;
807        subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
808                       fInfo.width(), fInfo.height());
809        if (fPixelRef->readPixels(&tmpSrc, &subset)) {
810            if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) {
811                // FIXME: The only meaningful implementation of readPixels
812                // (GrPixelRef) assumes premultiplied pixels.
813                return false;
814            }
815            SkASSERT(tmpSrc.width() == this->width());
816            SkASSERT(tmpSrc.height() == this->height());
817
818            // did we get lucky and we can just return tmpSrc?
819            if (tmpSrc.colorType() == dstColorType && nullptr == alloc) {
820                dst->swap(tmpSrc);
821                // If the result is an exact copy, clone the gen ID.
822                if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) {
823                    dst->pixelRef()->cloneGenID(*fPixelRef);
824                }
825                return true;
826            }
827
828            // fall through to the raster case
829            src = &tmpSrc;
830        }
831    }
832
833    SkAutoPixmapUnlock srcUnlocker;
834    if (!src->requestLock(&srcUnlocker)) {
835        return false;
836    }
837    const SkPixmap& srcPM = srcUnlocker.pixmap();
838
839    const SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
840    SkBitmap tmpDst;
841    if (!tmpDst.setInfo(dstInfo)) {
842        return false;
843    }
844
845    // allocate colortable if srcConfig == kIndex8_Config
846    SkAutoTUnref<SkColorTable> ctable;
847    if (dstColorType == kIndex_8_SkColorType) {
848        ctable.reset(SkRef(srcPM.ctable()));
849    }
850    if (!tmpDst.tryAllocPixels(alloc, ctable)) {
851        return false;
852    }
853
854    SkAutoPixmapUnlock dstUnlocker;
855    if (!tmpDst.requestLock(&dstUnlocker)) {
856        return false;
857    }
858
859    if (!srcPM.readPixels(dstUnlocker.pixmap())) {
860        return false;
861    }
862
863    //  (for BitmapHeap) Clone the pixelref genID even though we have a new pixelref.
864    //  The old copyTo impl did this, so we continue it for now.
865    //
866    //  TODO: should we ignore rowbytes (i.e. getSize)? Then it could just be
867    //      if (src_pixelref->info == dst_pixelref->info)
868    //
869    if (srcPM.colorType() == dstColorType && tmpDst.getSize() == srcPM.getSize64()) {
870        SkPixelRef* dstPixelRef = tmpDst.pixelRef();
871        if (dstPixelRef->info() == fPixelRef->info()) {
872            dstPixelRef->cloneGenID(*fPixelRef);
873        }
874    }
875
876    dst->swap(tmpDst);
877    return true;
878}
879
880bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
881    const SkColorType dstCT = this->colorType();
882    const SkColorProfileType dstPT = this->profileType();
883
884    if (!this->canCopyTo(dstCT)) {
885        return false;
886    }
887
888    // If we have a PixelRef, and it supports deep copy, use it.
889    // Currently supported only by texture-backed bitmaps.
890    if (fPixelRef) {
891        SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, dstPT, nullptr);
892        if (pixelRef) {
893            uint32_t rowBytes;
894            if (this->colorType() == dstCT && this->profileType() == dstPT) {
895                // Since there is no subset to pass to deepCopy, and deepCopy
896                // succeeded, the new pixel ref must be identical.
897                SkASSERT(fPixelRef->info() == pixelRef->info());
898                pixelRef->cloneGenID(*fPixelRef);
899                // Use the same rowBytes as the original.
900                rowBytes = fRowBytes;
901            } else {
902                // With the new config, an appropriate fRowBytes will be computed by setInfo.
903                rowBytes = 0;
904            }
905
906            const SkImageInfo info = fInfo.makeColorType(dstCT);
907            if (!dst->setInfo(info, rowBytes)) {
908                return false;
909            }
910            dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref();
911            return true;
912        }
913    }
914
915    if (this->getTexture()) {
916        return false;
917    } else {
918        return this->copyTo(dst, dstCT, nullptr);
919    }
920}
921
922///////////////////////////////////////////////////////////////////////////////
923
924static void rect_memset(uint8_t* array, U8CPU value, SkISize size, size_t rowBytes) {
925    for (int y = 0; y < size.height(); ++y) {
926        memset(array, value, size.width());
927        array += rowBytes;
928    }
929}
930
931static void get_bitmap_alpha(const SkPixmap& pmap, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
932    SkColorType colorType = pmap.colorType();
933    int         w = pmap.width();
934    int         h = pmap.height();
935    size_t      rb = pmap.rowBytes();
936
937    if (kAlpha_8_SkColorType == colorType && !pmap.isOpaque()) {
938        const uint8_t* s = pmap.addr8(0, 0);
939        while (--h >= 0) {
940            memcpy(alpha, s, w);
941            s += rb;
942            alpha += alphaRowBytes;
943        }
944    } else if (kN32_SkColorType == colorType && !pmap.isOpaque()) {
945        const SkPMColor* SK_RESTRICT s = pmap.addr32(0, 0);
946        while (--h >= 0) {
947            for (int x = 0; x < w; x++) {
948                alpha[x] = SkGetPackedA32(s[x]);
949            }
950            s = (const SkPMColor*)((const char*)s + rb);
951            alpha += alphaRowBytes;
952        }
953    } else if (kARGB_4444_SkColorType == colorType && !pmap.isOpaque()) {
954        const SkPMColor16* SK_RESTRICT s = pmap.addr16(0, 0);
955        while (--h >= 0) {
956            for (int x = 0; x < w; x++) {
957                alpha[x] = SkPacked4444ToA32(s[x]);
958            }
959            s = (const SkPMColor16*)((const char*)s + rb);
960            alpha += alphaRowBytes;
961        }
962    } else if (kIndex_8_SkColorType == colorType && !pmap.isOpaque()) {
963        const SkColorTable* ct = pmap.ctable();
964        if (ct) {
965            const SkPMColor* SK_RESTRICT table = ct->readColors();
966            const uint8_t* SK_RESTRICT s = pmap.addr8(0, 0);
967            while (--h >= 0) {
968                for (int x = 0; x < w; x++) {
969                    alpha[x] = SkGetPackedA32(table[s[x]]);
970                }
971                s += rb;
972                alpha += alphaRowBytes;
973            }
974        }
975    } else {    // src is opaque, so just fill alpha[] with 0xFF
976        rect_memset(alpha, 0xFF, pmap.info().dimensions(), alphaRowBytes);
977    }
978}
979
980static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
981    SkASSERT(alpha != nullptr);
982    SkASSERT(alphaRowBytes >= src.width());
983
984    SkAutoPixmapUnlock apl;
985    if (!src.requestLock(&apl)) {
986        rect_memset(alpha, 0, src.info().dimensions(), alphaRowBytes);
987        return false;
988    }
989    get_bitmap_alpha(apl.pixmap(), alpha, alphaRowBytes);
990    return true;
991}
992
993#include "SkPaint.h"
994#include "SkMaskFilter.h"
995#include "SkMatrix.h"
996
997bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
998                            Allocator *allocator, SkIPoint* offset) const {
999    SkDEBUGCODE(this->validate();)
1000
1001    SkBitmap    tmpBitmap;
1002    SkMatrix    identity;
1003    SkMask      srcM, dstM;
1004
1005    srcM.fBounds.set(0, 0, this->width(), this->height());
1006    srcM.fRowBytes = SkAlign4(this->width());
1007    srcM.fFormat = SkMask::kA8_Format;
1008
1009    SkMaskFilter* filter = paint ? paint->getMaskFilter() : nullptr;
1010
1011    // compute our (larger?) dst bounds if we have a filter
1012    if (filter) {
1013        identity.reset();
1014        srcM.fImage = nullptr;
1015        if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
1016            goto NO_FILTER_CASE;
1017        }
1018        dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
1019    } else {
1020    NO_FILTER_CASE:
1021        tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
1022        if (!tmpBitmap.tryAllocPixels(allocator, nullptr)) {
1023            // Allocation of pixels for alpha bitmap failed.
1024            SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1025                    tmpBitmap.width(), tmpBitmap.height());
1026            return false;
1027        }
1028        GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
1029        if (offset) {
1030            offset->set(0, 0);
1031        }
1032        tmpBitmap.swap(*dst);
1033        return true;
1034    }
1035    srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
1036    SkAutoMaskFreeImage srcCleanup(srcM.fImage);
1037
1038    GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
1039    if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
1040        goto NO_FILTER_CASE;
1041    }
1042    SkAutoMaskFreeImage dstCleanup(dstM.fImage);
1043
1044    tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
1045                      dstM.fRowBytes);
1046    if (!tmpBitmap.tryAllocPixels(allocator, nullptr)) {
1047        // Allocation of pixels for alpha bitmap failed.
1048        SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1049                tmpBitmap.width(), tmpBitmap.height());
1050        return false;
1051    }
1052    memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
1053    if (offset) {
1054        offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
1055    }
1056    SkDEBUGCODE(tmpBitmap.validate();)
1057
1058    tmpBitmap.swap(*dst);
1059    return true;
1060}
1061
1062///////////////////////////////////////////////////////////////////////////////
1063
1064static void write_raw_pixels(SkWriteBuffer* buffer, const SkPixmap& pmap) {
1065    const SkImageInfo& info = pmap.info();
1066    const size_t snugRB = info.width() * info.bytesPerPixel();
1067    const char* src = (const char*)pmap.addr();
1068    const size_t ramRB = pmap.rowBytes();
1069
1070    buffer->write32(SkToU32(snugRB));
1071    info.flatten(*buffer);
1072
1073    const size_t size = snugRB * info.height();
1074    SkAutoMalloc storage(size);
1075    char* dst = (char*)storage.get();
1076    for (int y = 0; y < info.height(); ++y) {
1077        memcpy(dst, src, snugRB);
1078        dst += snugRB;
1079        src += ramRB;
1080    }
1081    buffer->writeByteArray(storage.get(), size);
1082
1083    const SkColorTable* ct = pmap.ctable();
1084    if (kIndex_8_SkColorType == info.colorType() && ct) {
1085        buffer->writeBool(true);
1086        ct->writeToBuffer(*buffer);
1087    } else {
1088        buffer->writeBool(false);
1089    }
1090}
1091
1092void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
1093    const SkImageInfo info = bitmap.info();
1094    if (0 == info.width() || 0 == info.height() || nullptr == bitmap.pixelRef()) {
1095        buffer->writeUInt(0); // instead of snugRB, signaling no pixels
1096        return;
1097    }
1098
1099    SkAutoPixmapUnlock result;
1100    if (!bitmap.requestLock(&result)) {
1101        buffer->writeUInt(0); // instead of snugRB, signaling no pixels
1102        return;
1103    }
1104
1105    write_raw_pixels(buffer, result.pixmap());
1106}
1107
1108bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
1109    const size_t snugRB = buffer->readUInt();
1110    if (0 == snugRB) {  // no pixels
1111        return false;
1112    }
1113
1114    SkImageInfo info;
1115    info.unflatten(*buffer);
1116
1117    // If there was an error reading "info", don't use it to compute minRowBytes()
1118    if (!buffer->validate(true)) {
1119        return false;
1120    }
1121
1122    const size_t ramRB = info.minRowBytes();
1123    const int height = SkMax32(info.height(), 0);
1124    const uint64_t snugSize = sk_64_mul(snugRB, height);
1125    const uint64_t ramSize = sk_64_mul(ramRB, height);
1126    static const uint64_t max_size_t = (size_t)(-1);
1127    if (!buffer->validate((snugSize <= ramSize) && (ramSize <= max_size_t))) {
1128        return false;
1129    }
1130
1131    SkAutoDataUnref data(SkData::NewUninitialized(SkToSizeT(ramSize)));
1132    unsigned char* dst = (unsigned char*)data->writable_data();
1133    buffer->readByteArray(dst, SkToSizeT(snugSize));
1134
1135    if (snugSize != ramSize) {
1136        const unsigned char* srcRow = dst + snugRB * (height - 1);
1137        unsigned char* dstRow = dst + ramRB * (height - 1);
1138        for (int y = height - 1; y >= 1; --y) {
1139            memmove(dstRow, srcRow, snugRB);
1140            srcRow -= snugRB;
1141            dstRow -= ramRB;
1142        }
1143        SkASSERT(srcRow == dstRow); // first row does not need to be moved
1144    }
1145
1146    SkAutoTUnref<SkColorTable> ctable;
1147    if (buffer->readBool()) {
1148        ctable.reset(SkColorTable::Create(*buffer));
1149        if (!ctable) {
1150            return false;
1151        }
1152
1153        if (info.isEmpty()) {
1154            // require an empty ctable
1155            if (ctable->count() != 0) {
1156                buffer->validate(false);
1157                return false;
1158            }
1159        } else {
1160            // require a non-empty ctable
1161            if (ctable->count() == 0) {
1162                buffer->validate(false);
1163                return false;
1164            }
1165            unsigned char maxIndex = ctable->count() - 1;
1166            for (uint64_t i = 0; i < ramSize; ++i) {
1167                dst[i] = SkTMin(dst[i], maxIndex);
1168            }
1169        }
1170    }
1171
1172    SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewWithData(info, info.minRowBytes(),
1173                                                              ctable.get(), data.get()));
1174    if (!pr.get()) {
1175        return false;
1176    }
1177    bitmap->setInfo(pr->info());
1178    bitmap->setPixelRef(pr, 0, 0);
1179    return true;
1180}
1181
1182enum {
1183    SERIALIZE_PIXELTYPE_NONE,
1184    SERIALIZE_PIXELTYPE_REF_DATA
1185};
1186
1187///////////////////////////////////////////////////////////////////////////////
1188
1189SkBitmap::RLEPixels::RLEPixels(int width, int height) {
1190    fHeight = height;
1191    fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*));
1192}
1193
1194SkBitmap::RLEPixels::~RLEPixels() {
1195    sk_free(fYPtrs);
1196}
1197
1198///////////////////////////////////////////////////////////////////////////////
1199
1200#ifdef SK_DEBUG
1201void SkBitmap::validate() const {
1202    fInfo.validate();
1203
1204    // ImageInfo may not require this, but Bitmap ensures that opaque-only
1205    // colorTypes report opaque for their alphatype
1206    if (kRGB_565_SkColorType == fInfo.colorType()) {
1207        SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
1208    }
1209
1210    SkASSERT(fInfo.validRowBytes(fRowBytes));
1211    uint8_t allFlags = kImageIsVolatile_Flag;
1212#ifdef SK_BUILD_FOR_ANDROID
1213    allFlags |= kHasHardwareMipMap_Flag;
1214#endif
1215    SkASSERT((~allFlags & fFlags) == 0);
1216    SkASSERT(fPixelLockCount >= 0);
1217
1218    if (fPixels) {
1219        SkASSERT(fPixelRef);
1220        SkASSERT(fPixelLockCount > 0);
1221        SkASSERT(fPixelRef->isLocked());
1222        SkASSERT(fPixelRef->rowBytes() == fRowBytes);
1223        SkASSERT(fPixelRefOrigin.fX >= 0);
1224        SkASSERT(fPixelRefOrigin.fY >= 0);
1225        SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
1226        SkASSERT(fPixelRef->info().height() >= (int)this->height() + fPixelRefOrigin.fY);
1227        SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
1228    } else {
1229        SkASSERT(nullptr == fColorTable);
1230    }
1231}
1232#endif
1233
1234#ifndef SK_IGNORE_TO_STRING
1235#include "SkString.h"
1236void SkBitmap::toString(SkString* str) const {
1237
1238    static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
1239        "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
1240    };
1241
1242    str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
1243                 gColorTypeNames[this->colorType()]);
1244
1245    str->append(" (");
1246    if (this->isOpaque()) {
1247        str->append("opaque");
1248    } else {
1249        str->append("transparent");
1250    }
1251    if (this->isImmutable()) {
1252        str->append(", immutable");
1253    } else {
1254        str->append(", not-immutable");
1255    }
1256    str->append(")");
1257
1258    SkPixelRef* pr = this->pixelRef();
1259    if (nullptr == pr) {
1260        // show null or the explicit pixel address (rare)
1261        str->appendf(" pixels:%p", this->getPixels());
1262    } else {
1263        const char* uri = pr->getURI();
1264        if (uri) {
1265            str->appendf(" uri:\"%s\"", uri);
1266        } else {
1267            str->appendf(" pixelref:%p", pr);
1268        }
1269    }
1270
1271    str->append(")");
1272}
1273#endif
1274
1275///////////////////////////////////////////////////////////////////////////////
1276
1277bool SkBitmap::requestLock(SkAutoPixmapUnlock* result) const {
1278    SkASSERT(result);
1279
1280    SkPixelRef* pr = fPixelRef;
1281    if (nullptr == pr) {
1282        return false;
1283    }
1284
1285    // We have to lock the whole thing (using the pixelref's dimensions) until the api supports
1286    // a partial lock (with offset/origin). Hence we can't use our fInfo.
1287    SkPixelRef::LockRequest req = { pr->info().dimensions(), kNone_SkFilterQuality };
1288    SkPixelRef::LockResult res;
1289    if (pr->requestLock(req, &res)) {
1290        SkASSERT(res.fPixels);
1291        // The bitmap may be a subset of the pixelref's dimensions
1292        SkASSERT(fPixelRefOrigin.x() + fInfo.width()  <= res.fSize.width());
1293        SkASSERT(fPixelRefOrigin.y() + fInfo.height() <= res.fSize.height());
1294        const void* addr = (const char*)res.fPixels + SkColorTypeComputeOffset(fInfo.colorType(),
1295                                                                               fPixelRefOrigin.x(),
1296                                                                               fPixelRefOrigin.y(),
1297                                                                               res.fRowBytes);
1298
1299        result->reset(SkPixmap(this->info(), addr, res.fRowBytes, res.fCTable),
1300                      res.fUnlockProc, res.fUnlockContext);
1301        return true;
1302    }
1303    return false;
1304}
1305
1306bool SkBitmap::peekPixels(SkPixmap* pmap) const {
1307    if (fPixels) {
1308        if (pmap) {
1309            pmap->reset(fInfo, fPixels, fRowBytes, fColorTable);
1310        }
1311        return true;
1312    }
1313    return false;
1314}
1315
1316///////////////////////////////////////////////////////////////////////////////
1317
1318#ifdef SK_DEBUG
1319void SkImageInfo::validate() const {
1320    SkASSERT(fWidth >= 0);
1321    SkASSERT(fHeight >= 0);
1322    SkASSERT(SkColorTypeIsValid(fColorType));
1323    SkASSERT(SkAlphaTypeIsValid(fAlphaType));
1324}
1325#endif
1326