1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2008 The Android Open Source Project
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkData.h"
11cb93a386Sopenharmony_ci#include "include/core/SkMallocPixelRef.h"
12cb93a386Sopenharmony_ci#include "include/core/SkMath.h"
13cb93a386Sopenharmony_ci#include "include/core/SkPixelRef.h"
14cb93a386Sopenharmony_ci#include "include/core/SkRect.h"
15cb93a386Sopenharmony_ci#include "include/core/SkScalar.h"
16cb93a386Sopenharmony_ci#include "include/core/SkUnPreMultiply.h"
17cb93a386Sopenharmony_ci#include "include/private/SkColorData.h"
18cb93a386Sopenharmony_ci#include "include/private/SkHalf.h"
19cb93a386Sopenharmony_ci#include "include/private/SkImageInfoPriv.h"
20cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h"
21cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
22cb93a386Sopenharmony_ci#include "src/core/SkConvertPixels.h"
23cb93a386Sopenharmony_ci#include "src/core/SkMask.h"
24cb93a386Sopenharmony_ci#include "src/core/SkMaskFilterBase.h"
25cb93a386Sopenharmony_ci#include "src/core/SkMipmap.h"
26cb93a386Sopenharmony_ci#include "src/core/SkPixelRefPriv.h"
27cb93a386Sopenharmony_ci#include "src/core/SkPixmapPriv.h"
28cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h"
29cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h"
30cb93a386Sopenharmony_ci#include "src/core/SkWritePixelsRec.h"
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci#include <cstring>
33cb93a386Sopenharmony_ci#include <utility>
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_cistatic bool reset_return_false(SkBitmap* bm) {
36cb93a386Sopenharmony_ci    bm->reset();
37cb93a386Sopenharmony_ci    return false;
38cb93a386Sopenharmony_ci}
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_ciSkBitmap::SkBitmap() {}
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ciSkBitmap::SkBitmap(const SkBitmap& src)
43cb93a386Sopenharmony_ci    : fPixelRef      (src.fPixelRef)
44cb93a386Sopenharmony_ci    , fPixmap        (src.fPixmap)
45cb93a386Sopenharmony_ci    , fMips          (src.fMips)
46cb93a386Sopenharmony_ci{
47cb93a386Sopenharmony_ci    SkDEBUGCODE(src.validate();)
48cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
49cb93a386Sopenharmony_ci}
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ciSkBitmap::SkBitmap(SkBitmap&& other)
52cb93a386Sopenharmony_ci    : fPixelRef      (std::move(other.fPixelRef))
53cb93a386Sopenharmony_ci    , fPixmap        (std::move(other.fPixmap))
54cb93a386Sopenharmony_ci    , fMips          (std::move(other.fMips))
55cb93a386Sopenharmony_ci{
56cb93a386Sopenharmony_ci    SkASSERT(!other.fPixelRef);
57cb93a386Sopenharmony_ci    other.fPixmap.reset();
58cb93a386Sopenharmony_ci}
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_ciSkBitmap::~SkBitmap() {}
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_ciSkBitmap& SkBitmap::operator=(const SkBitmap& src) {
63cb93a386Sopenharmony_ci    if (this != &src) {
64cb93a386Sopenharmony_ci        fPixelRef       = src.fPixelRef;
65cb93a386Sopenharmony_ci        fPixmap         = src.fPixmap;
66cb93a386Sopenharmony_ci        fMips           = src.fMips;
67cb93a386Sopenharmony_ci    }
68cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
69cb93a386Sopenharmony_ci    return *this;
70cb93a386Sopenharmony_ci}
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_ciSkBitmap& SkBitmap::operator=(SkBitmap&& other) {
73cb93a386Sopenharmony_ci    if (this != &other) {
74cb93a386Sopenharmony_ci        fPixelRef       = std::move(other.fPixelRef);
75cb93a386Sopenharmony_ci        fPixmap         = std::move(other.fPixmap);
76cb93a386Sopenharmony_ci        fMips           = std::move(other.fMips);
77cb93a386Sopenharmony_ci        SkASSERT(!other.fPixelRef);
78cb93a386Sopenharmony_ci        other.fPixmap.reset();
79cb93a386Sopenharmony_ci    }
80cb93a386Sopenharmony_ci    return *this;
81cb93a386Sopenharmony_ci}
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_civoid SkBitmap::swap(SkBitmap& other) {
84cb93a386Sopenharmony_ci    using std::swap;
85cb93a386Sopenharmony_ci    swap(*this, other);
86cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
87cb93a386Sopenharmony_ci}
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_civoid SkBitmap::reset() {
90cb93a386Sopenharmony_ci    fPixelRef = nullptr;  // Free pixels.
91cb93a386Sopenharmony_ci    fPixmap.reset();
92cb93a386Sopenharmony_ci    fMips.reset();
93cb93a386Sopenharmony_ci}
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_civoid SkBitmap::getBounds(SkRect* bounds) const {
96cb93a386Sopenharmony_ci    SkASSERT(bounds);
97cb93a386Sopenharmony_ci    *bounds = SkRect::Make(this->dimensions());
98cb93a386Sopenharmony_ci}
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_civoid SkBitmap::getBounds(SkIRect* bounds) const {
101cb93a386Sopenharmony_ci    SkASSERT(bounds);
102cb93a386Sopenharmony_ci    *bounds = fPixmap.bounds();
103cb93a386Sopenharmony_ci}
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_cibool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) {
108cb93a386Sopenharmony_ci    SkAlphaType newAT = info.alphaType();
109cb93a386Sopenharmony_ci    if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) {
110cb93a386Sopenharmony_ci        return reset_return_false(this);
111cb93a386Sopenharmony_ci    }
112cb93a386Sopenharmony_ci    // don't look at info.alphaType(), since newAT is the real value...
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci    // require that rowBytes fit in 31bits
115cb93a386Sopenharmony_ci    int64_t mrb = info.minRowBytes64();
116cb93a386Sopenharmony_ci    if (!SkTFitsIn<int32_t>(mrb)) {
117cb93a386Sopenharmony_ci        return reset_return_false(this);
118cb93a386Sopenharmony_ci    }
119cb93a386Sopenharmony_ci    if (!SkTFitsIn<int32_t>(rowBytes)) {
120cb93a386Sopenharmony_ci        return reset_return_false(this);
121cb93a386Sopenharmony_ci    }
122cb93a386Sopenharmony_ci
123cb93a386Sopenharmony_ci    if (info.width() < 0 || info.height() < 0) {
124cb93a386Sopenharmony_ci        return reset_return_false(this);
125cb93a386Sopenharmony_ci    }
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci    if (kUnknown_SkColorType == info.colorType()) {
128cb93a386Sopenharmony_ci        rowBytes = 0;
129cb93a386Sopenharmony_ci    } else if (0 == rowBytes) {
130cb93a386Sopenharmony_ci        rowBytes = (size_t)mrb;
131cb93a386Sopenharmony_ci    } else if (!info.validRowBytes(rowBytes)) {
132cb93a386Sopenharmony_ci        return reset_return_false(this);
133cb93a386Sopenharmony_ci    }
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_ci    fPixelRef = nullptr;  // Free pixels.
136cb93a386Sopenharmony_ci    fPixmap.reset(info.makeAlphaType(newAT), nullptr, SkToU32(rowBytes));
137cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
138cb93a386Sopenharmony_ci    return true;
139cb93a386Sopenharmony_ci}
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci
143cb93a386Sopenharmony_cibool SkBitmap::setAlphaType(SkAlphaType newAlphaType) {
144cb93a386Sopenharmony_ci    if (!SkColorTypeValidateAlphaType(this->colorType(), newAlphaType, &newAlphaType)) {
145cb93a386Sopenharmony_ci        return false;
146cb93a386Sopenharmony_ci    }
147cb93a386Sopenharmony_ci    if (this->alphaType() != newAlphaType) {
148cb93a386Sopenharmony_ci        auto newInfo = fPixmap.info().makeAlphaType(newAlphaType);
149cb93a386Sopenharmony_ci        fPixmap.reset(std::move(newInfo), fPixmap.addr(), fPixmap.rowBytes());
150cb93a386Sopenharmony_ci    }
151cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
152cb93a386Sopenharmony_ci    return true;
153cb93a386Sopenharmony_ci}
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_ciSkIPoint SkBitmap::pixelRefOrigin() const {
156cb93a386Sopenharmony_ci    const char* addr = (const char*)fPixmap.addr();
157cb93a386Sopenharmony_ci    const char* pix = (const char*)(fPixelRef ? fPixelRef->pixels() : nullptr);
158cb93a386Sopenharmony_ci    size_t rb = this->rowBytes();
159cb93a386Sopenharmony_ci    if (!pix || 0 == rb) {
160cb93a386Sopenharmony_ci        return {0, 0};
161cb93a386Sopenharmony_ci    }
162cb93a386Sopenharmony_ci    SkASSERT(this->bytesPerPixel() > 0);
163cb93a386Sopenharmony_ci    SkASSERT(this->bytesPerPixel() == (1 << this->shiftPerPixel()));
164cb93a386Sopenharmony_ci    SkASSERT(addr >= pix);
165cb93a386Sopenharmony_ci    size_t off = addr - pix;
166cb93a386Sopenharmony_ci    return {SkToS32((off % rb) >> this->shiftPerPixel()), SkToS32(off / rb)};
167cb93a386Sopenharmony_ci}
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_civoid SkBitmap::setPixelRef(sk_sp<SkPixelRef> pr, int dx, int dy) {
170cb93a386Sopenharmony_ci#ifdef SK_DEBUG
171cb93a386Sopenharmony_ci    if (pr) {
172cb93a386Sopenharmony_ci        if (kUnknown_SkColorType != this->colorType()) {
173cb93a386Sopenharmony_ci            SkASSERT(dx >= 0 && this->width() + dx <= pr->width());
174cb93a386Sopenharmony_ci            SkASSERT(dy >= 0 && this->height() + dy <= pr->height());
175cb93a386Sopenharmony_ci        }
176cb93a386Sopenharmony_ci    }
177cb93a386Sopenharmony_ci#endif
178cb93a386Sopenharmony_ci    fPixelRef = kUnknown_SkColorType != this->colorType() ? std::move(pr) : nullptr;
179cb93a386Sopenharmony_ci    void* p = nullptr;
180cb93a386Sopenharmony_ci    size_t rowBytes = this->rowBytes();
181cb93a386Sopenharmony_ci    // ignore dx,dy if there is no pixelref
182cb93a386Sopenharmony_ci    if (fPixelRef) {
183cb93a386Sopenharmony_ci        rowBytes = fPixelRef->rowBytes();
184cb93a386Sopenharmony_ci        // TODO(reed):  Enforce that PixelRefs must have non-null pixels.
185cb93a386Sopenharmony_ci        p = fPixelRef->pixels();
186cb93a386Sopenharmony_ci        if (p) {
187cb93a386Sopenharmony_ci            p = (char*)p + dy * rowBytes + dx * this->bytesPerPixel();
188cb93a386Sopenharmony_ci        }
189cb93a386Sopenharmony_ci    }
190cb93a386Sopenharmony_ci    SkPixmapPriv::ResetPixmapKeepInfo(&fPixmap, p, rowBytes);
191cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
192cb93a386Sopenharmony_ci}
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_civoid SkBitmap::setPixels(void* p) {
195cb93a386Sopenharmony_ci    if (kUnknown_SkColorType == this->colorType()) {
196cb93a386Sopenharmony_ci        p = nullptr;
197cb93a386Sopenharmony_ci    }
198cb93a386Sopenharmony_ci    size_t rb = this->rowBytes();
199cb93a386Sopenharmony_ci    SkPixmapPriv::ResetPixmapKeepInfo(&fPixmap, p, rb);
200cb93a386Sopenharmony_ci    fPixelRef = p ? sk_make_sp<SkPixelRef>(this->width(), this->height(), p, rb) : nullptr;
201cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
202cb93a386Sopenharmony_ci}
203cb93a386Sopenharmony_ci
204cb93a386Sopenharmony_cibool SkBitmap::tryAllocPixels(Allocator* allocator) {
205cb93a386Sopenharmony_ci    HeapAllocator stdalloc;
206cb93a386Sopenharmony_ci
207cb93a386Sopenharmony_ci    if (nullptr == allocator) {
208cb93a386Sopenharmony_ci        allocator = &stdalloc;
209cb93a386Sopenharmony_ci    }
210cb93a386Sopenharmony_ci    return allocator->allocPixelRef(this);
211cb93a386Sopenharmony_ci}
212cb93a386Sopenharmony_ci
213cb93a386Sopenharmony_cibool SkBitmap::tryAllocN32Pixels(int width, int height, bool isOpaque) {
214cb93a386Sopenharmony_ci    SkImageInfo info = SkImageInfo::MakeN32(width, height,
215cb93a386Sopenharmony_ci            isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
216cb93a386Sopenharmony_ci    return this->tryAllocPixels(info);
217cb93a386Sopenharmony_ci}
218cb93a386Sopenharmony_ci
219cb93a386Sopenharmony_civoid SkBitmap::allocN32Pixels(int width, int height, bool isOpaque) {
220cb93a386Sopenharmony_ci    SkImageInfo info = SkImageInfo::MakeN32(width, height,
221cb93a386Sopenharmony_ci                                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
222cb93a386Sopenharmony_ci    this->allocPixels(info);
223cb93a386Sopenharmony_ci}
224cb93a386Sopenharmony_ci
225cb93a386Sopenharmony_civoid SkBitmap::allocPixels() {
226cb93a386Sopenharmony_ci    this->allocPixels((Allocator*)nullptr);
227cb93a386Sopenharmony_ci}
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_civoid SkBitmap::allocPixels(Allocator* allocator) {
230cb93a386Sopenharmony_ci    if (!this->tryAllocPixels(allocator)) {
231cb93a386Sopenharmony_ci        const SkImageInfo& info = this->info();
232cb93a386Sopenharmony_ci        SK_ABORT("SkBitmap::tryAllocPixels failed "
233cb93a386Sopenharmony_ci                 "ColorType:%d AlphaType:%d [w:%d h:%d] rb:%zu",
234cb93a386Sopenharmony_ci                 info.colorType(), info.alphaType(), info.width(), info.height(), this->rowBytes());
235cb93a386Sopenharmony_ci    }
236cb93a386Sopenharmony_ci}
237cb93a386Sopenharmony_ci
238cb93a386Sopenharmony_civoid SkBitmap::allocPixelsFlags(const SkImageInfo& info, uint32_t flags) {
239cb93a386Sopenharmony_ci    SkASSERT_RELEASE(this->tryAllocPixelsFlags(info, flags));
240cb93a386Sopenharmony_ci}
241cb93a386Sopenharmony_ci
242cb93a386Sopenharmony_civoid SkBitmap::allocPixels(const SkImageInfo& info, size_t rowBytes) {
243cb93a386Sopenharmony_ci    SkASSERT_RELEASE(this->tryAllocPixels(info, rowBytes));
244cb93a386Sopenharmony_ci}
245cb93a386Sopenharmony_ci
246cb93a386Sopenharmony_civoid SkBitmap::allocPixels(const SkImageInfo& info) {
247cb93a386Sopenharmony_ci    this->allocPixels(info, info.minRowBytes());
248cb93a386Sopenharmony_ci}
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
251cb93a386Sopenharmony_ci
252cb93a386Sopenharmony_cibool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) {
253cb93a386Sopenharmony_ci    if (!this->setInfo(requestedInfo, rowBytes)) {
254cb93a386Sopenharmony_ci        return reset_return_false(this);
255cb93a386Sopenharmony_ci    }
256cb93a386Sopenharmony_ci
257cb93a386Sopenharmony_ci    // setInfo may have corrected info (e.g. 565 is always opaque).
258cb93a386Sopenharmony_ci    const SkImageInfo& correctedInfo = this->info();
259cb93a386Sopenharmony_ci    if (kUnknown_SkColorType == correctedInfo.colorType()) {
260cb93a386Sopenharmony_ci        return true;
261cb93a386Sopenharmony_ci    }
262cb93a386Sopenharmony_ci    // setInfo may have computed a valid rowbytes if 0 were passed in
263cb93a386Sopenharmony_ci    rowBytes = this->rowBytes();
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_ci    sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(correctedInfo, rowBytes);
266cb93a386Sopenharmony_ci    if (!pr) {
267cb93a386Sopenharmony_ci        return reset_return_false(this);
268cb93a386Sopenharmony_ci    }
269cb93a386Sopenharmony_ci    this->setPixelRef(std::move(pr), 0, 0);
270cb93a386Sopenharmony_ci    if (nullptr == this->getPixels()) {
271cb93a386Sopenharmony_ci        return reset_return_false(this);
272cb93a386Sopenharmony_ci    }
273cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
274cb93a386Sopenharmony_ci    return true;
275cb93a386Sopenharmony_ci}
276cb93a386Sopenharmony_ci
277cb93a386Sopenharmony_cibool SkBitmap::tryAllocPixelsFlags(const SkImageInfo& requestedInfo, uint32_t allocFlags) {
278cb93a386Sopenharmony_ci    if (!this->setInfo(requestedInfo)) {
279cb93a386Sopenharmony_ci        return reset_return_false(this);
280cb93a386Sopenharmony_ci    }
281cb93a386Sopenharmony_ci
282cb93a386Sopenharmony_ci    // setInfo may have corrected info (e.g. 565 is always opaque).
283cb93a386Sopenharmony_ci    const SkImageInfo& correctedInfo = this->info();
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci    sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(correctedInfo,
286cb93a386Sopenharmony_ci                                                          correctedInfo.minRowBytes());
287cb93a386Sopenharmony_ci    if (!pr) {
288cb93a386Sopenharmony_ci        return reset_return_false(this);
289cb93a386Sopenharmony_ci    }
290cb93a386Sopenharmony_ci    this->setPixelRef(std::move(pr), 0, 0);
291cb93a386Sopenharmony_ci    if (nullptr == this->getPixels()) {
292cb93a386Sopenharmony_ci        return reset_return_false(this);
293cb93a386Sopenharmony_ci    }
294cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
295cb93a386Sopenharmony_ci    return true;
296cb93a386Sopenharmony_ci}
297cb93a386Sopenharmony_ci
298cb93a386Sopenharmony_cistatic void invoke_release_proc(void (*proc)(void* pixels, void* ctx), void* pixels, void* ctx) {
299cb93a386Sopenharmony_ci    if (proc) {
300cb93a386Sopenharmony_ci        proc(pixels, ctx);
301cb93a386Sopenharmony_ci    }
302cb93a386Sopenharmony_ci}
303cb93a386Sopenharmony_ci
304cb93a386Sopenharmony_cibool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
305cb93a386Sopenharmony_ci                             void (*releaseProc)(void* addr, void* context), void* context) {
306cb93a386Sopenharmony_ci    if (!this->setInfo(requestedInfo, rb)) {
307cb93a386Sopenharmony_ci        invoke_release_proc(releaseProc, pixels, context);
308cb93a386Sopenharmony_ci        this->reset();
309cb93a386Sopenharmony_ci        return false;
310cb93a386Sopenharmony_ci    }
311cb93a386Sopenharmony_ci    if (nullptr == pixels) {
312cb93a386Sopenharmony_ci        invoke_release_proc(releaseProc, pixels, context);
313cb93a386Sopenharmony_ci        return true;    // we behaved as if they called setInfo()
314cb93a386Sopenharmony_ci    }
315cb93a386Sopenharmony_ci
316cb93a386Sopenharmony_ci    // setInfo may have corrected info (e.g. 565 is always opaque).
317cb93a386Sopenharmony_ci    const SkImageInfo& correctedInfo = this->info();
318cb93a386Sopenharmony_ci    this->setPixelRef(
319cb93a386Sopenharmony_ci            SkMakePixelRefWithProc(correctedInfo.width(), correctedInfo.height(),
320cb93a386Sopenharmony_ci                                   rb, pixels, releaseProc, context), 0, 0);
321cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
322cb93a386Sopenharmony_ci    return true;
323cb93a386Sopenharmony_ci}
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_cibool SkBitmap::installPixels(const SkPixmap& pixmap) {
326cb93a386Sopenharmony_ci    return this->installPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(),
327cb93a386Sopenharmony_ci                               nullptr, nullptr);
328cb93a386Sopenharmony_ci}
329cb93a386Sopenharmony_ci
330cb93a386Sopenharmony_cibool SkBitmap::installMaskPixels(const SkMask& mask) {
331cb93a386Sopenharmony_ci    if (SkMask::kA8_Format != mask.fFormat) {
332cb93a386Sopenharmony_ci        this->reset();
333cb93a386Sopenharmony_ci        return false;
334cb93a386Sopenharmony_ci    }
335cb93a386Sopenharmony_ci    return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
336cb93a386Sopenharmony_ci                                                   mask.fBounds.height()),
337cb93a386Sopenharmony_ci                               mask.fImage, mask.fRowBytes);
338cb93a386Sopenharmony_ci}
339cb93a386Sopenharmony_ci
340cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
341cb93a386Sopenharmony_ci
342cb93a386Sopenharmony_ciuint32_t SkBitmap::getGenerationID() const {
343cb93a386Sopenharmony_ci    return fPixelRef ? fPixelRef->getGenerationID() : 0;
344cb93a386Sopenharmony_ci}
345cb93a386Sopenharmony_ci
346cb93a386Sopenharmony_civoid SkBitmap::notifyPixelsChanged() const {
347cb93a386Sopenharmony_ci    SkASSERT(!this->isImmutable());
348cb93a386Sopenharmony_ci    if (fPixelRef) {
349cb93a386Sopenharmony_ci        fPixelRef->notifyPixelsChanged();
350cb93a386Sopenharmony_ci    }
351cb93a386Sopenharmony_ci}
352cb93a386Sopenharmony_ci
353cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
354cb93a386Sopenharmony_ci
355cb93a386Sopenharmony_ci/** We explicitly use the same allocator for our pixels that SkMask does,
356cb93a386Sopenharmony_ci so that we can freely assign memory allocated by one class to the other.
357cb93a386Sopenharmony_ci */
358cb93a386Sopenharmony_cibool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst) {
359cb93a386Sopenharmony_ci    const SkImageInfo& info = dst->info();
360cb93a386Sopenharmony_ci    if (kUnknown_SkColorType == info.colorType()) {
361cb93a386Sopenharmony_ci//        SkDebugf("unsupported config for info %d\n", dst->config());
362cb93a386Sopenharmony_ci        return false;
363cb93a386Sopenharmony_ci    }
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_ci    sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, dst->rowBytes());
366cb93a386Sopenharmony_ci    if (!pr) {
367cb93a386Sopenharmony_ci        return false;
368cb93a386Sopenharmony_ci    }
369cb93a386Sopenharmony_ci
370cb93a386Sopenharmony_ci    dst->setPixelRef(std::move(pr), 0, 0);
371cb93a386Sopenharmony_ci    SkDEBUGCODE(dst->validate();)
372cb93a386Sopenharmony_ci    return true;
373cb93a386Sopenharmony_ci}
374cb93a386Sopenharmony_ci
375cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
376cb93a386Sopenharmony_ci
377cb93a386Sopenharmony_cibool SkBitmap::isImmutable() const {
378cb93a386Sopenharmony_ci    return fPixelRef ? fPixelRef->isImmutable() : false;
379cb93a386Sopenharmony_ci}
380cb93a386Sopenharmony_ci
381cb93a386Sopenharmony_civoid SkBitmap::setImmutable() {
382cb93a386Sopenharmony_ci    if (fPixelRef) {
383cb93a386Sopenharmony_ci        fPixelRef->setImmutable();
384cb93a386Sopenharmony_ci    }
385cb93a386Sopenharmony_ci}
386cb93a386Sopenharmony_ci
387cb93a386Sopenharmony_civoid* SkBitmap::getAddr(int x, int y) const {
388cb93a386Sopenharmony_ci    SkASSERT((unsigned)x < (unsigned)this->width());
389cb93a386Sopenharmony_ci    SkASSERT((unsigned)y < (unsigned)this->height());
390cb93a386Sopenharmony_ci
391cb93a386Sopenharmony_ci    char* base = (char*)this->getPixels();
392cb93a386Sopenharmony_ci    if (base) {
393cb93a386Sopenharmony_ci        base += (y * this->rowBytes()) + (x << this->shiftPerPixel());
394cb93a386Sopenharmony_ci    }
395cb93a386Sopenharmony_ci    return base;
396cb93a386Sopenharmony_ci}
397cb93a386Sopenharmony_ci
398cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
399cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
400cb93a386Sopenharmony_ci
401cb93a386Sopenharmony_civoid SkBitmap::erase(SkColor c, const SkIRect& area) const {
402cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
403cb93a386Sopenharmony_ci
404cb93a386Sopenharmony_ci    if (kUnknown_SkColorType == this->colorType()) {
405cb93a386Sopenharmony_ci        // TODO: can we ASSERT that we never get here?
406cb93a386Sopenharmony_ci        return; // can't erase. Should we bzero so the memory is not uninitialized?
407cb93a386Sopenharmony_ci    }
408cb93a386Sopenharmony_ci
409cb93a386Sopenharmony_ci    SkPixmap result;
410cb93a386Sopenharmony_ci    if (!this->peekPixels(&result)) {
411cb93a386Sopenharmony_ci        return;
412cb93a386Sopenharmony_ci    }
413cb93a386Sopenharmony_ci
414cb93a386Sopenharmony_ci    if (result.erase(c, area)) {
415cb93a386Sopenharmony_ci        this->notifyPixelsChanged();
416cb93a386Sopenharmony_ci    }
417cb93a386Sopenharmony_ci}
418cb93a386Sopenharmony_ci
419cb93a386Sopenharmony_civoid SkBitmap::eraseColor(SkColor c) const {
420cb93a386Sopenharmony_ci    this->erase(c, SkIRect::MakeWH(this->width(), this->height()));
421cb93a386Sopenharmony_ci}
422cb93a386Sopenharmony_ci
423cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////
424cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////
425cb93a386Sopenharmony_ci
426cb93a386Sopenharmony_cibool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
427cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
428cb93a386Sopenharmony_ci
429cb93a386Sopenharmony_ci    if (nullptr == result || !fPixelRef) {
430cb93a386Sopenharmony_ci        return false;   // no src pixels
431cb93a386Sopenharmony_ci    }
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_ci    SkIRect srcRect, r;
434cb93a386Sopenharmony_ci    srcRect.setWH(this->width(), this->height());
435cb93a386Sopenharmony_ci    if (!r.intersect(srcRect, subset)) {
436cb93a386Sopenharmony_ci        return false;   // r is empty (i.e. no intersection)
437cb93a386Sopenharmony_ci    }
438cb93a386Sopenharmony_ci
439cb93a386Sopenharmony_ci    // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
440cb93a386Sopenharmony_ci    // exited above.
441cb93a386Sopenharmony_ci    SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
442cb93a386Sopenharmony_ci    SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
443cb93a386Sopenharmony_ci
444cb93a386Sopenharmony_ci    SkBitmap dst;
445cb93a386Sopenharmony_ci    dst.setInfo(this->info().makeDimensions(r.size()), this->rowBytes());
446cb93a386Sopenharmony_ci
447cb93a386Sopenharmony_ci    if (fPixelRef) {
448cb93a386Sopenharmony_ci        SkIPoint origin = this->pixelRefOrigin();
449cb93a386Sopenharmony_ci        // share the pixelref with a custom offset
450cb93a386Sopenharmony_ci        dst.setPixelRef(fPixelRef, origin.x() + r.fLeft, origin.y() + r.fTop);
451cb93a386Sopenharmony_ci    }
452cb93a386Sopenharmony_ci    SkDEBUGCODE(dst.validate();)
453cb93a386Sopenharmony_ci
454cb93a386Sopenharmony_ci    // we know we're good, so commit to result
455cb93a386Sopenharmony_ci    result->swap(dst);
456cb93a386Sopenharmony_ci    return true;
457cb93a386Sopenharmony_ci}
458cb93a386Sopenharmony_ci
459cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
460cb93a386Sopenharmony_ci
461cb93a386Sopenharmony_cibool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
462cb93a386Sopenharmony_ci                          int x, int y) const {
463cb93a386Sopenharmony_ci    SkPixmap src;
464cb93a386Sopenharmony_ci    if (!this->peekPixels(&src)) {
465cb93a386Sopenharmony_ci        return false;
466cb93a386Sopenharmony_ci    }
467cb93a386Sopenharmony_ci    return src.readPixels(requestedDstInfo, dstPixels, dstRB, x, y);
468cb93a386Sopenharmony_ci}
469cb93a386Sopenharmony_ci
470cb93a386Sopenharmony_cibool SkBitmap::readPixels(const SkPixmap& dst, int srcX, int srcY) const {
471cb93a386Sopenharmony_ci    return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
472cb93a386Sopenharmony_ci}
473cb93a386Sopenharmony_ci
474cb93a386Sopenharmony_cibool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY) {
475cb93a386Sopenharmony_ci    if (!SkImageInfoValidConversion(this->info(), src.info())) {
476cb93a386Sopenharmony_ci        return false;
477cb93a386Sopenharmony_ci    }
478cb93a386Sopenharmony_ci
479cb93a386Sopenharmony_ci    SkWritePixelsRec rec(src.info(), src.addr(), src.rowBytes(), dstX, dstY);
480cb93a386Sopenharmony_ci    if (!rec.trim(this->width(), this->height())) {
481cb93a386Sopenharmony_ci        return false;
482cb93a386Sopenharmony_ci    }
483cb93a386Sopenharmony_ci
484cb93a386Sopenharmony_ci    void* dstPixels = this->getAddr(rec.fX, rec.fY);
485cb93a386Sopenharmony_ci    const SkImageInfo dstInfo = this->info().makeDimensions(rec.fInfo.dimensions());
486cb93a386Sopenharmony_ci    if (!SkConvertPixels(dstInfo,     dstPixels, this->rowBytes(),
487cb93a386Sopenharmony_ci                         rec.fInfo, rec.fPixels,   rec.fRowBytes)) {
488cb93a386Sopenharmony_ci        return false;
489cb93a386Sopenharmony_ci    }
490cb93a386Sopenharmony_ci    this->notifyPixelsChanged();
491cb93a386Sopenharmony_ci    return true;
492cb93a386Sopenharmony_ci}
493cb93a386Sopenharmony_ci
494cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
495cb93a386Sopenharmony_ci
496cb93a386Sopenharmony_cistatic bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
497cb93a386Sopenharmony_ci    SkASSERT(alpha != nullptr);
498cb93a386Sopenharmony_ci    SkASSERT(alphaRowBytes >= src.width());
499cb93a386Sopenharmony_ci
500cb93a386Sopenharmony_ci    SkPixmap pmap;
501cb93a386Sopenharmony_ci    if (!src.peekPixels(&pmap)) {
502cb93a386Sopenharmony_ci        for (int y = 0; y < src.height(); ++y) {
503cb93a386Sopenharmony_ci            memset(alpha, 0, src.width());
504cb93a386Sopenharmony_ci            alpha += alphaRowBytes;
505cb93a386Sopenharmony_ci        }
506cb93a386Sopenharmony_ci        return false;
507cb93a386Sopenharmony_ci    }
508cb93a386Sopenharmony_ci    return SkConvertPixels(SkImageInfo::MakeA8(pmap.width(), pmap.height()), alpha, alphaRowBytes,
509cb93a386Sopenharmony_ci                           pmap.info(), pmap.addr(), pmap.rowBytes());
510cb93a386Sopenharmony_ci}
511cb93a386Sopenharmony_ci
512cb93a386Sopenharmony_ci#include "include/core/SkMaskFilter.h"
513cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h"
514cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
515cb93a386Sopenharmony_ci
516cb93a386Sopenharmony_cibool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
517cb93a386Sopenharmony_ci                            Allocator *allocator, SkIPoint* offset) const {
518cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
519cb93a386Sopenharmony_ci
520cb93a386Sopenharmony_ci    SkBitmap    tmpBitmap;
521cb93a386Sopenharmony_ci    SkMatrix    identity;
522cb93a386Sopenharmony_ci    SkMask      srcM, dstM;
523cb93a386Sopenharmony_ci
524cb93a386Sopenharmony_ci    if (this->width() == 0 || this->height() == 0) {
525cb93a386Sopenharmony_ci        return false;
526cb93a386Sopenharmony_ci    }
527cb93a386Sopenharmony_ci    srcM.fBounds.setWH(this->width(), this->height());
528cb93a386Sopenharmony_ci    srcM.fRowBytes = SkAlign4(this->width());
529cb93a386Sopenharmony_ci    srcM.fFormat = SkMask::kA8_Format;
530cb93a386Sopenharmony_ci
531cb93a386Sopenharmony_ci    SkMaskFilter* filter = paint ? paint->getMaskFilter() : nullptr;
532cb93a386Sopenharmony_ci
533cb93a386Sopenharmony_ci    // compute our (larger?) dst bounds if we have a filter
534cb93a386Sopenharmony_ci    if (filter) {
535cb93a386Sopenharmony_ci        identity.reset();
536cb93a386Sopenharmony_ci        if (!as_MFB(filter)->filterMask(&dstM, srcM, identity, nullptr)) {
537cb93a386Sopenharmony_ci            goto NO_FILTER_CASE;
538cb93a386Sopenharmony_ci        }
539cb93a386Sopenharmony_ci        dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
540cb93a386Sopenharmony_ci    } else {
541cb93a386Sopenharmony_ci    NO_FILTER_CASE:
542cb93a386Sopenharmony_ci        tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
543cb93a386Sopenharmony_ci        if (!tmpBitmap.tryAllocPixels(allocator)) {
544cb93a386Sopenharmony_ci            // Allocation of pixels for alpha bitmap failed.
545cb93a386Sopenharmony_ci            SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
546cb93a386Sopenharmony_ci                    tmpBitmap.width(), tmpBitmap.height());
547cb93a386Sopenharmony_ci            return false;
548cb93a386Sopenharmony_ci        }
549cb93a386Sopenharmony_ci        GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
550cb93a386Sopenharmony_ci        if (offset) {
551cb93a386Sopenharmony_ci            offset->set(0, 0);
552cb93a386Sopenharmony_ci        }
553cb93a386Sopenharmony_ci        tmpBitmap.swap(*dst);
554cb93a386Sopenharmony_ci        return true;
555cb93a386Sopenharmony_ci    }
556cb93a386Sopenharmony_ci    srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
557cb93a386Sopenharmony_ci    SkAutoMaskFreeImage srcCleanup(srcM.fImage);
558cb93a386Sopenharmony_ci
559cb93a386Sopenharmony_ci    GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
560cb93a386Sopenharmony_ci    if (!as_MFB(filter)->filterMask(&dstM, srcM, identity, nullptr)) {
561cb93a386Sopenharmony_ci        goto NO_FILTER_CASE;
562cb93a386Sopenharmony_ci    }
563cb93a386Sopenharmony_ci    SkAutoMaskFreeImage dstCleanup(dstM.fImage);
564cb93a386Sopenharmony_ci
565cb93a386Sopenharmony_ci    tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
566cb93a386Sopenharmony_ci                      dstM.fRowBytes);
567cb93a386Sopenharmony_ci    if (!tmpBitmap.tryAllocPixels(allocator)) {
568cb93a386Sopenharmony_ci        // Allocation of pixels for alpha bitmap failed.
569cb93a386Sopenharmony_ci        SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
570cb93a386Sopenharmony_ci                tmpBitmap.width(), tmpBitmap.height());
571cb93a386Sopenharmony_ci        return false;
572cb93a386Sopenharmony_ci    }
573cb93a386Sopenharmony_ci    memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
574cb93a386Sopenharmony_ci    if (offset) {
575cb93a386Sopenharmony_ci        offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
576cb93a386Sopenharmony_ci    }
577cb93a386Sopenharmony_ci    SkDEBUGCODE(tmpBitmap.validate();)
578cb93a386Sopenharmony_ci
579cb93a386Sopenharmony_ci    tmpBitmap.swap(*dst);
580cb93a386Sopenharmony_ci    return true;
581cb93a386Sopenharmony_ci}
582cb93a386Sopenharmony_ci
583cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
584cb93a386Sopenharmony_ci
585cb93a386Sopenharmony_ci#ifdef SK_DEBUG
586cb93a386Sopenharmony_civoid SkBitmap::validate() const {
587cb93a386Sopenharmony_ci    this->info().validate();
588cb93a386Sopenharmony_ci
589cb93a386Sopenharmony_ci    SkASSERT(this->info().validRowBytes(this->rowBytes()));
590cb93a386Sopenharmony_ci
591cb93a386Sopenharmony_ci    if (fPixelRef && fPixelRef->pixels()) {
592cb93a386Sopenharmony_ci        SkASSERT(this->getPixels());
593cb93a386Sopenharmony_ci    } else {
594cb93a386Sopenharmony_ci        SkASSERT(!this->getPixels());
595cb93a386Sopenharmony_ci    }
596cb93a386Sopenharmony_ci
597cb93a386Sopenharmony_ci    if (this->getPixels()) {
598cb93a386Sopenharmony_ci        SkASSERT(fPixelRef);
599cb93a386Sopenharmony_ci        SkASSERT(fPixelRef->rowBytes() == this->rowBytes());
600cb93a386Sopenharmony_ci        SkIPoint origin = this->pixelRefOrigin();
601cb93a386Sopenharmony_ci        SkASSERT(origin.fX >= 0);
602cb93a386Sopenharmony_ci        SkASSERT(origin.fY >= 0);
603cb93a386Sopenharmony_ci        SkASSERT(fPixelRef->width() >= (int)this->width() + origin.fX);
604cb93a386Sopenharmony_ci        SkASSERT(fPixelRef->height() >= (int)this->height() + origin.fY);
605cb93a386Sopenharmony_ci        SkASSERT(fPixelRef->rowBytes() >= this->info().minRowBytes());
606cb93a386Sopenharmony_ci    }
607cb93a386Sopenharmony_ci}
608cb93a386Sopenharmony_ci#endif
609cb93a386Sopenharmony_ci
610cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
611cb93a386Sopenharmony_ci
612cb93a386Sopenharmony_cibool SkBitmap::peekPixels(SkPixmap* pmap) const {
613cb93a386Sopenharmony_ci    if (this->getPixels()) {
614cb93a386Sopenharmony_ci        if (pmap) {
615cb93a386Sopenharmony_ci            *pmap = fPixmap;
616cb93a386Sopenharmony_ci        }
617cb93a386Sopenharmony_ci        return true;
618cb93a386Sopenharmony_ci    }
619cb93a386Sopenharmony_ci    return false;
620cb93a386Sopenharmony_ci}
621cb93a386Sopenharmony_ci
622cb93a386Sopenharmony_cisk_sp<SkImage> SkBitmap::asImage() const {
623cb93a386Sopenharmony_ci    return SkImage::MakeFromBitmap(*this);
624cb93a386Sopenharmony_ci}
625