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