blob: c3bc4a9d636a737daf6b43f622acaf6bcbec3200 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2008 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
herbb906daf2015-09-29 09:37:59 -07008#include "SkAtomics.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00009#include "SkBitmap.h"
Cary Clarka4083c92017-09-15 11:59:23 -040010#include "SkColorData.h"
Mike Reed086a4272017-07-18 10:53:11 -040011#include "SkColorTable.h"
Matt Sarett485c4992017-02-14 14:18:27 -050012#include "SkConvertPixels.h"
bungemand3ebb482015-08-05 13:57:49 -070013#include "SkData.h"
14#include "SkFilterQuality.h"
Hal Canary4cba3fe2016-12-07 14:59:27 -050015#include "SkHalf.h"
Matt Sarett03dd6d52017-01-23 12:15:09 -050016#include "SkImageInfoPriv.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017#include "SkMallocPixelRef.h"
18#include "SkMask.h"
bungemand3ebb482015-08-05 13:57:49 -070019#include "SkMath.h"
jvanverth02802f62015-07-02 06:42:49 -070020#include "SkPixelRef.h"
mtklein1b249332015-07-07 12:21:21 -070021#include "SkReadBuffer.h"
bungemand3ebb482015-08-05 13:57:49 -070022#include "SkRect.h"
23#include "SkScalar.h"
scroggo565901d2015-12-10 10:44:13 -080024#include "SkTemplates.h"
vandebo@chromium.org112706d2011-02-24 22:50:55 +000025#include "SkUnPreMultiply.h"
mtklein1b249332015-07-07 12:21:21 -070026#include "SkWriteBuffer.h"
Matt Sarett03dd6d52017-01-23 12:15:09 -050027#include "SkWritePixelsRec.h"
bungemand3ebb482015-08-05 13:57:49 -070028
29#include <string.h>
reed@android.com8a1c16f2008-12-17 15:59:43 +000030
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +000031static bool reset_return_false(SkBitmap* bm) {
32 bm->reset();
33 return false;
34}
35
Hal Canary1b3387b2016-12-12 13:48:12 -050036SkBitmap::SkBitmap()
Mike Reedb7120892017-04-14 17:16:36 -040037 : fPixels (nullptr)
Hal Canary1b3387b2016-12-12 13:48:12 -050038 , fPixelRefOrigin{0, 0}
39 , fRowBytes (0)
40 , fFlags (0) {}
reed@android.com8a1c16f2008-12-17 15:59:43 +000041
Hal Canary1b3387b2016-12-12 13:48:12 -050042SkBitmap::SkBitmap(const SkBitmap& src)
43 : fPixelRef (src.fPixelRef)
Mike Reedb7120892017-04-14 17:16:36 -040044 , fPixels (src.fPixels)
Hal Canary1b3387b2016-12-12 13:48:12 -050045 , fPixelRefOrigin(src.fPixelRefOrigin)
46 , fInfo (src.fInfo)
47 , fRowBytes (src.fRowBytes)
48 , fFlags (src.fFlags)
49{
reed@android.com8a1c16f2008-12-17 15:59:43 +000050 SkDEBUGCODE(src.validate();)
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 SkDEBUGCODE(this->validate();)
52}
53
Hal Canary1b3387b2016-12-12 13:48:12 -050054SkBitmap::SkBitmap(SkBitmap&& other)
55 : fPixelRef (std::move(other.fPixelRef))
Hal Canary1b3387b2016-12-12 13:48:12 -050056 , fPixels (other.fPixels)
Hal Canary1b3387b2016-12-12 13:48:12 -050057 , fPixelRefOrigin (other.fPixelRefOrigin)
58 , fInfo (std::move(other.fInfo))
59 , fRowBytes (other.fRowBytes)
Mike Reedb7120892017-04-14 17:16:36 -040060 , fFlags (other.fFlags)
61{
Hal Canary1b3387b2016-12-12 13:48:12 -050062 SkASSERT(!other.fPixelRef);
63 other.fInfo.reset();
Hal Canary1b3387b2016-12-12 13:48:12 -050064 other.fPixels = nullptr;
Hal Canary1b3387b2016-12-12 13:48:12 -050065 other.fPixelRefOrigin = SkIPoint{0, 0};
66 other.fRowBytes = 0;
67 other.fFlags = 0;
68}
halcanary023bda02015-12-14 10:19:17 -080069
Mike Reedb7120892017-04-14 17:16:36 -040070SkBitmap::~SkBitmap() {}
reed@android.com8a1c16f2008-12-17 15:59:43 +000071
72SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
73 if (this != &src) {
Hal Canary1b3387b2016-12-12 13:48:12 -050074 fPixelRef = src.fPixelRef;
Mike Reedb7120892017-04-14 17:16:36 -040075 fPixels = src.fPixels;
Hal Canary1b3387b2016-12-12 13:48:12 -050076 fPixelRefOrigin = src.fPixelRefOrigin;
77 fInfo = src.fInfo;
78 fRowBytes = src.fRowBytes;
79 fFlags = src.fFlags;
reed@android.com8a1c16f2008-12-17 15:59:43 +000080 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000081 SkDEBUGCODE(this->validate();)
82 return *this;
83}
84
halcanary023bda02015-12-14 10:19:17 -080085SkBitmap& SkBitmap::operator=(SkBitmap&& other) {
86 if (this != &other) {
Hal Canary1b3387b2016-12-12 13:48:12 -050087 fPixelRef = std::move(other.fPixelRef);
88 fInfo = std::move(other.fInfo);
Hal Canary1b3387b2016-12-12 13:48:12 -050089 fPixels = other.fPixels;
Hal Canary1b3387b2016-12-12 13:48:12 -050090 fPixelRefOrigin = other.fPixelRefOrigin;
91 fRowBytes = other.fRowBytes;
92 fFlags = other.fFlags;
93 SkASSERT(!other.fPixelRef);
94 other.fInfo.reset();
Hal Canary1b3387b2016-12-12 13:48:12 -050095 other.fPixels = nullptr;
Hal Canary1b3387b2016-12-12 13:48:12 -050096 other.fPixelRefOrigin = SkIPoint{0, 0};
97 other.fRowBytes = 0;
98 other.fFlags = 0;
halcanary023bda02015-12-14 10:19:17 -080099 }
100 return *this;
101}
102
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103void SkBitmap::swap(SkBitmap& other) {
Hal Canary1b3387b2016-12-12 13:48:12 -0500104 SkTSwap(*this, other);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105 SkDEBUGCODE(this->validate();)
106}
107
108void SkBitmap::reset() {
109 this->freePixels();
msarett23c51102016-05-27 07:39:02 -0700110 this->fInfo.reset();
reed@android.com4516f472009-06-29 16:25:36 +0000111 sk_bzero(this, sizeof(*this));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112}
113
reed@google.com86b2e432012-03-15 21:17:03 +0000114void SkBitmap::getBounds(SkRect* bounds) const {
115 SkASSERT(bounds);
116 bounds->set(0, 0,
reede5ea5002014-09-03 11:54:58 -0700117 SkIntToScalar(fInfo.width()), SkIntToScalar(fInfo.height()));
reed@google.com86b2e432012-03-15 21:17:03 +0000118}
119
reed@google.com80e14592012-03-16 14:58:07 +0000120void SkBitmap::getBounds(SkIRect* bounds) const {
121 SkASSERT(bounds);
reede5ea5002014-09-03 11:54:58 -0700122 bounds->set(0, 0, fInfo.width(), fInfo.height());
reed@google.com80e14592012-03-16 14:58:07 +0000123}
124
reed@google.com86b2e432012-03-15 21:17:03 +0000125///////////////////////////////////////////////////////////////////////////////
126
reede5ea5002014-09-03 11:54:58 -0700127bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) {
128 SkAlphaType newAT = info.alphaType();
129 if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) {
commit-bot@chromium.orgd5414e52014-02-13 22:30:38 +0000130 return reset_return_false(this);
131 }
reede5ea5002014-09-03 11:54:58 -0700132 // don't look at info.alphaType(), since newAT is the real value...
skia.committer@gmail.com02d6f542014-02-14 03:02:05 +0000133
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000134 // require that rowBytes fit in 31bits
135 int64_t mrb = info.minRowBytes64();
136 if ((int32_t)mrb != mrb) {
137 return reset_return_false(this);
reed@google.com383a6972013-10-21 14:00:07 +0000138 }
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000139 if ((int64_t)rowBytes != (int32_t)rowBytes) {
140 return reset_return_false(this);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000141 }
reed@android.com89bb83a2009-05-29 21:30:42 +0000142
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000143 if (info.width() < 0 || info.height() < 0) {
144 return reset_return_false(this);
145 }
146
147 if (kUnknown_SkColorType == info.colorType()) {
148 rowBytes = 0;
149 } else if (0 == rowBytes) {
150 rowBytes = (size_t)mrb;
reedf0aed972014-07-01 12:48:11 -0700151 } else if (!info.validRowBytes(rowBytes)) {
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000152 return reset_return_false(this);
reed@google.com383a6972013-10-21 14:00:07 +0000153 }
154
155 this->freePixels();
156
reede5ea5002014-09-03 11:54:58 -0700157 fInfo = info.makeAlphaType(newAT);
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000158 fRowBytes = SkToU32(rowBytes);
Mike Reedb7120892017-04-14 17:16:36 -0400159 SkDEBUGCODE(this->validate();)
reed@google.com383a6972013-10-21 14:00:07 +0000160 return true;
reed@google.com383a6972013-10-21 14:00:07 +0000161}
162
reede5ea5002014-09-03 11:54:58 -0700163bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) {
164 if (!SkColorTypeValidateAlphaType(fInfo.colorType(), newAlphaType, &newAlphaType)) {
reed@google.com383a6972013-10-21 14:00:07 +0000165 return false;
166 }
reede5ea5002014-09-03 11:54:58 -0700167 if (fInfo.alphaType() != newAlphaType) {
168 fInfo = fInfo.makeAlphaType(newAlphaType);
commit-bot@chromium.org0e8d0d62014-01-27 15:41:07 +0000169 }
Mike Reedb7120892017-04-14 17:16:36 -0400170 SkDEBUGCODE(this->validate();)
reed@google.com383a6972013-10-21 14:00:07 +0000171 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000172}
173
Mike Reedb7120892017-04-14 17:16:36 -0400174void SkBitmap::updatePixelsFromRef() {
175 void* p = nullptr;
bsalomon49f085d2014-09-05 13:34:00 -0700176 if (fPixelRef) {
Mike Reedb7120892017-04-14 17:16:36 -0400177 // wish we could assert that a pixelref *always* has pixels
178 p = fPixelRef->pixels();
179 if (p) {
180 SkASSERT(fRowBytes == fPixelRef->rowBytes());
181 p = (char*)p
182 + fPixelRefOrigin.fY * fRowBytes
183 + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184 }
185 }
Mike Reedb7120892017-04-14 17:16:36 -0400186 fPixels = p;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000187}
188
Hal Canary1b3387b2016-12-12 13:48:12 -0500189void SkBitmap::setPixelRef(sk_sp<SkPixelRef> pr, int dx, int dy) {
reed@google.comdcea5302014-01-03 13:43:01 +0000190#ifdef SK_DEBUG
reed@google.com672588b2014-01-08 15:42:01 +0000191 if (pr) {
commit-bot@chromium.org466f5f32014-05-27 21:30:37 +0000192 if (kUnknown_SkColorType != fInfo.colorType()) {
Matt Sarettf7583112017-05-01 10:22:31 -0400193 SkASSERT(fInfo.width() + dx <= pr->width());
194 SkASSERT(fInfo.height() + dy <= pr->height());
reed@google.comdcea5302014-01-03 13:43:01 +0000195 }
196 }
197#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198
Mike Reedb7120892017-04-14 17:16:36 -0400199 fPixelRef = std::move(pr);
200 if (fPixelRef) {
Matt Sarettf7583112017-05-01 10:22:31 -0400201 fPixelRefOrigin.set(SkTPin(dx, 0, fPixelRef->width()), SkTPin(dy, 0, fPixelRef->height()));
Mike Reedb7120892017-04-14 17:16:36 -0400202 this->updatePixelsFromRef();
reed@google.com672588b2014-01-08 15:42:01 +0000203 } else {
204 // ignore dx,dy if there is no pixelref
205 fPixelRefOrigin.setZero();
Mike Reedb7120892017-04-14 17:16:36 -0400206 fPixels = nullptr;
reed@google.com672588b2014-01-08 15:42:01 +0000207 }
208
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209 SkDEBUGCODE(this->validate();)
210}
211
Mike Reed086a4272017-07-18 10:53:11 -0400212void SkBitmap::setPixels(void* p) {
halcanary96fcdcc2015-08-27 07:41:13 -0700213 if (nullptr == p) {
Hal Canary1b3387b2016-12-12 13:48:12 -0500214 this->setPixelRef(nullptr, 0, 0);
reed@google.com8e1034e2012-07-30 13:16:35 +0000215 return;
216 }
217
commit-bot@chromium.org466f5f32014-05-27 21:30:37 +0000218 if (kUnknown_SkColorType == fInfo.colorType()) {
Hal Canary1b3387b2016-12-12 13:48:12 -0500219 this->setPixelRef(nullptr, 0, 0);
reed@google.combf790232013-12-13 19:45:58 +0000220 return;
221 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222
Mike Reed086a4272017-07-18 10:53:11 -0400223 this->setPixelRef(SkMallocPixelRef::MakeDirect(fInfo, p, fRowBytes), 0, 0);
Hal Canary1b3387b2016-12-12 13:48:12 -0500224 if (!fPixelRef) {
reed@google.combf790232013-12-13 19:45:58 +0000225 return;
226 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000227 SkDEBUGCODE(this->validate();)
228}
229
Mike Reed086a4272017-07-18 10:53:11 -0400230bool SkBitmap::tryAllocPixels(Allocator* allocator) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231 HeapAllocator stdalloc;
skia.committer@gmail.comd2ac07b2014-01-25 07:01:49 +0000232
halcanary96fcdcc2015-08-27 07:41:13 -0700233 if (nullptr == allocator) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234 allocator = &stdalloc;
235 }
Mike Reed086a4272017-07-18 10:53:11 -0400236 return allocator->allocPixelRef(this);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000237}
238
reed@google.com9ebcac52014-01-24 18:53:42 +0000239///////////////////////////////////////////////////////////////////////////////
240
reed84825042014-09-02 12:50:45 -0700241bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) {
reedf0aed972014-07-01 12:48:11 -0700242 if (!this->setInfo(requestedInfo, rowBytes)) {
reedbae704b2014-06-28 14:26:35 -0700243 return reset_return_false(this);
244 }
mtklein775b8192014-12-02 09:11:25 -0800245
reedbae704b2014-06-28 14:26:35 -0700246 // setInfo may have corrected info (e.g. 565 is always opaque).
247 const SkImageInfo& correctedInfo = this->info();
reedf0aed972014-07-01 12:48:11 -0700248 // setInfo may have computed a valid rowbytes if 0 were passed in
249 rowBytes = this->rowBytes();
250
Mike Reed086a4272017-07-18 10:53:11 -0400251 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(correctedInfo, rowBytes);
Hal Canary1b3387b2016-12-12 13:48:12 -0500252 if (!pr) {
reedbae704b2014-06-28 14:26:35 -0700253 return reset_return_false(this);
254 }
Hal Canary1b3387b2016-12-12 13:48:12 -0500255 this->setPixelRef(std::move(pr), 0, 0);
halcanary96fcdcc2015-08-27 07:41:13 -0700256 if (nullptr == this->getPixels()) {
reedbae704b2014-06-28 14:26:35 -0700257 return reset_return_false(this);
258 }
Mike Reedb7120892017-04-14 17:16:36 -0400259 SkDEBUGCODE(this->validate();)
reedbae704b2014-06-28 14:26:35 -0700260 return true;
261}
262
Mike Reed086a4272017-07-18 10:53:11 -0400263bool SkBitmap::tryAllocPixelsFlags(const SkImageInfo& requestedInfo, uint32_t allocFlags) {
scroggo0187dc22014-06-05 11:18:04 -0700264 if (!this->setInfo(requestedInfo)) {
reed@google.com9ebcac52014-01-24 18:53:42 +0000265 return reset_return_false(this);
266 }
267
scroggo0187dc22014-06-05 11:18:04 -0700268 // setInfo may have corrected info (e.g. 565 is always opaque).
269 const SkImageInfo& correctedInfo = this->info();
270
Mike Reed6b3155c2017-04-03 14:41:44 -0400271 sk_sp<SkPixelRef> pr = (allocFlags & kZeroPixels_AllocFlag) ?
Mike Reed086a4272017-07-18 10:53:11 -0400272 SkMallocPixelRef::MakeZeroed(correctedInfo, correctedInfo.minRowBytes()) :
273 SkMallocPixelRef::MakeAllocate(correctedInfo, correctedInfo.minRowBytes());
Hal Canary1b3387b2016-12-12 13:48:12 -0500274 if (!pr) {
reed@google.com9ebcac52014-01-24 18:53:42 +0000275 return reset_return_false(this);
276 }
Hal Canary1b3387b2016-12-12 13:48:12 -0500277 this->setPixelRef(std::move(pr), 0, 0);
halcanary96fcdcc2015-08-27 07:41:13 -0700278 if (nullptr == this->getPixels()) {
reed@google.com9ebcac52014-01-24 18:53:42 +0000279 return reset_return_false(this);
280 }
Mike Reedb7120892017-04-14 17:16:36 -0400281 SkDEBUGCODE(this->validate();)
reed@google.com9ebcac52014-01-24 18:53:42 +0000282 return true;
283}
284
reeddb74f622015-05-30 13:41:15 -0700285static void invoke_release_proc(void (*proc)(void* pixels, void* ctx), void* pixels, void* ctx) {
286 if (proc) {
287 proc(pixels, ctx);
288 }
289}
290
scroggo0187dc22014-06-05 11:18:04 -0700291bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
Mike Reed086a4272017-07-18 10:53:11 -0400292 void (*releaseProc)(void* addr, void* context), void* context) {
scroggo0187dc22014-06-05 11:18:04 -0700293 if (!this->setInfo(requestedInfo, rb)) {
reeddb74f622015-05-30 13:41:15 -0700294 invoke_release_proc(releaseProc, pixels, context);
reed@google.com9ebcac52014-01-24 18:53:42 +0000295 this->reset();
296 return false;
297 }
halcanary96fcdcc2015-08-27 07:41:13 -0700298 if (nullptr == pixels) {
reeddb74f622015-05-30 13:41:15 -0700299 invoke_release_proc(releaseProc, pixels, context);
300 return true; // we behaved as if they called setInfo()
301 }
reed@google.com9ebcac52014-01-24 18:53:42 +0000302
scroggo0187dc22014-06-05 11:18:04 -0700303 // setInfo may have corrected info (e.g. 565 is always opaque).
304 const SkImageInfo& correctedInfo = this->info();
305
Mike Reed086a4272017-07-18 10:53:11 -0400306 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeWithProc(correctedInfo, rb, pixels,
307 releaseProc, context);
reed@google.com9ebcac52014-01-24 18:53:42 +0000308 if (!pr) {
309 this->reset();
310 return false;
311 }
312
Hal Canary1b3387b2016-12-12 13:48:12 -0500313 this->setPixelRef(std::move(pr), 0, 0);
mike@reedtribe.org6e58cf32014-02-16 20:54:21 +0000314 SkDEBUGCODE(this->validate();)
reed@google.com9ebcac52014-01-24 18:53:42 +0000315 return true;
316}
317
halcanarye36ec872015-12-09 11:36:59 -0800318bool SkBitmap::installPixels(const SkPixmap& pixmap) {
Mike Reed086a4272017-07-18 10:53:11 -0400319 return this->installPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(),
halcanarye36ec872015-12-09 11:36:59 -0800320 nullptr, nullptr);
321}
322
commit-bot@chromium.orgdac52252014-02-17 21:21:46 +0000323bool SkBitmap::installMaskPixels(const SkMask& mask) {
324 if (SkMask::kA8_Format != mask.fFormat) {
325 this->reset();
326 return false;
327 }
328 return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
329 mask.fBounds.height()),
330 mask.fImage, mask.fRowBytes);
331}
332
reed@google.comeb9a46c2014-01-25 16:46:20 +0000333///////////////////////////////////////////////////////////////////////////////
334
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335void SkBitmap::freePixels() {
Mike Reedb7120892017-04-14 17:16:36 -0400336 fPixelRef = nullptr;
337 fPixelRefOrigin.setZero();
halcanary96fcdcc2015-08-27 07:41:13 -0700338 fPixels = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000339}
340
reed@android.com8a1c16f2008-12-17 15:59:43 +0000341uint32_t SkBitmap::getGenerationID() const {
Hal Canary1b3387b2016-12-12 13:48:12 -0500342 return fPixelRef ? fPixelRef->getGenerationID() : 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000343}
344
345void SkBitmap::notifyPixelsChanged() const {
junov@chromium.orgb0521292011-12-15 20:14:06 +0000346 SkASSERT(!this->isImmutable());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000347 if (fPixelRef) {
348 fPixelRef->notifyPixelsChanged();
349 }
350}
351
352///////////////////////////////////////////////////////////////////////////////
353
reed@android.com8a1c16f2008-12-17 15:59:43 +0000354/** We explicitly use the same allocator for our pixels that SkMask does,
355 so that we can freely assign memory allocated by one class to the other.
356 */
Mike Reedb7648a22017-07-19 15:45:45 -0400357bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst) {
commit-bot@chromium.org466f5f32014-05-27 21:30:37 +0000358 const SkImageInfo info = dst->info();
359 if (kUnknown_SkColorType == info.colorType()) {
reed@google.combf790232013-12-13 19:45:58 +0000360// SkDebugf("unsupported config for info %d\n", dst->config());
361 return false;
362 }
skia.committer@gmail.com96f5fa02013-12-16 07:01:40 +0000363
Mike Reed086a4272017-07-18 10:53:11 -0400364 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, dst->rowBytes());
Hal Canary1b3387b2016-12-12 13:48:12 -0500365 if (!pr) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000366 return false;
367 }
weita@google.comf9ab99a2009-05-03 18:23:30 +0000368
Hal Canary1b3387b2016-12-12 13:48:12 -0500369 dst->setPixelRef(std::move(pr), 0, 0);
Mike Reedb7120892017-04-14 17:16:36 -0400370 SkDEBUGCODE(dst->validate();)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000371 return true;
372}
373
374///////////////////////////////////////////////////////////////////////////////
375
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000376bool SkBitmap::isImmutable() const {
scroggo08470592014-07-15 19:56:48 -0700377 return fPixelRef ? fPixelRef->isImmutable() : false;
junov@chromium.orgb0521292011-12-15 20:14:06 +0000378}
379
380void SkBitmap::setImmutable() {
381 if (fPixelRef) {
382 fPixelRef->setImmutable();
junov@chromium.orgb0521292011-12-15 20:14:06 +0000383 }
384}
385
junov@google.com4ee7ae52011-06-30 17:30:49 +0000386bool SkBitmap::isVolatile() const {
387 return (fFlags & kImageIsVolatile_Flag) != 0;
388}
389
390void SkBitmap::setIsVolatile(bool isVolatile) {
391 if (isVolatile) {
392 fFlags |= kImageIsVolatile_Flag;
393 } else {
394 fFlags &= ~kImageIsVolatile_Flag;
395 }
396}
397
reed@android.com8a1c16f2008-12-17 15:59:43 +0000398void* SkBitmap::getAddr(int x, int y) const {
399 SkASSERT((unsigned)x < (unsigned)this->width());
400 SkASSERT((unsigned)y < (unsigned)this->height());
401
402 char* base = (char*)this->getPixels();
403 if (base) {
404 base += y * this->rowBytes();
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000405 switch (this->colorType()) {
mtklein7fd93e32016-07-26 13:05:30 -0700406 case kRGBA_F16_SkColorType:
407 base += x << 3;
408 break;
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000409 case kRGBA_8888_SkColorType:
410 case kBGRA_8888_SkColorType:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000411 base += x << 2;
412 break;
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000413 case kARGB_4444_SkColorType:
414 case kRGB_565_SkColorType:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000415 base += x << 1;
416 break;
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000417 case kAlpha_8_SkColorType:
reed0c9b1a82015-03-17 17:44:06 -0700418 case kGray_8_SkColorType:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000419 base += x;
420 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000421 default:
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000422 SkDEBUGFAIL("Can't return addr for config");
halcanary96fcdcc2015-08-27 07:41:13 -0700423 base = nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000424 break;
425 }
426 }
427 return base;
428}
429
430///////////////////////////////////////////////////////////////////////////////
431///////////////////////////////////////////////////////////////////////////////
432
reed7aefe032015-06-08 10:22:22 -0700433void SkBitmap::erase(SkColor c, const SkIRect& area) const {
reed92fc2ae2015-05-22 08:06:21 -0700434 SkDEBUGCODE(this->validate();)
reed92fc2ae2015-05-22 08:06:21 -0700435
436 switch (fInfo.colorType()) {
437 case kUnknown_SkColorType:
reed92fc2ae2015-05-22 08:06:21 -0700438 // TODO: can we ASSERT that we never get here?
439 return; // can't erase. Should we bzero so the memory is not uninitialized?
440 default:
441 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000442 }
weita@google.comf9ab99a2009-05-03 18:23:30 +0000443
Mike Reed4edb5d22017-04-17 11:02:51 -0400444 SkPixmap result;
445 if (!this->peekPixels(&result)) {
reed92fc2ae2015-05-22 08:06:21 -0700446 return;
447 }
448
Mike Reed4edb5d22017-04-17 11:02:51 -0400449 if (result.erase(c, area)) {
reed92fc2ae2015-05-22 08:06:21 -0700450 this->notifyPixelsChanged();
451 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000452}
453
reed7aefe032015-06-08 10:22:22 -0700454void SkBitmap::eraseColor(SkColor c) const {
455 this->erase(c, SkIRect::MakeWH(this->width(), this->height()));
reed@google.com60d32352013-06-28 19:40:50 +0000456}
457
reed@android.com8a1c16f2008-12-17 15:59:43 +0000458//////////////////////////////////////////////////////////////////////////////////////
459//////////////////////////////////////////////////////////////////////////////////////
460
reed@android.com8a1c16f2008-12-17 15:59:43 +0000461bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
462 SkDEBUGCODE(this->validate();)
463
Hal Canary1b3387b2016-12-12 13:48:12 -0500464 if (nullptr == result || !fPixelRef) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000465 return false; // no src pixels
466 }
467
468 SkIRect srcRect, r;
469 srcRect.set(0, 0, this->width(), this->height());
470 if (!r.intersect(srcRect, subset)) {
471 return false; // r is empty (i.e. no intersection)
472 }
473
scroggo@google.coma2a31922012-12-07 19:14:45 +0000474 // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
475 // exited above.
476 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
477 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
478
reed@android.com8a1c16f2008-12-17 15:59:43 +0000479 SkBitmap dst;
herbb5d74682016-04-21 08:45:39 -0700480 dst.setInfo(this->info().makeWH(r.width(), r.height()), this->rowBytes());
skyostil@google.com0eb75762012-01-16 10:45:53 +0000481 dst.setIsVolatile(this->isVolatile());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000482
483 if (fPixelRef) {
reed@google.com672588b2014-01-08 15:42:01 +0000484 SkIPoint origin = fPixelRefOrigin;
485 origin.fX += r.fLeft;
486 origin.fY += r.fTop;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000487 // share the pixelref with a custom offset
Hal Canary1b3387b2016-12-12 13:48:12 -0500488 dst.setPixelRef(fPixelRef, origin.x(), origin.y());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000489 }
490 SkDEBUGCODE(dst.validate();)
491
492 // we know we're good, so commit to result
493 result->swap(dst);
494 return true;
495}
496
497///////////////////////////////////////////////////////////////////////////////
498
reedb184f7f2014-07-13 04:32:32 -0700499bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
Matt Sarett3928ff82017-06-06 10:11:34 -0400500 int x, int y, SkTransferFunctionBehavior behavior) const {
Mike Reed4edb5d22017-04-17 11:02:51 -0400501 SkPixmap src;
502 if (!this->peekPixels(&src)) {
reedb184f7f2014-07-13 04:32:32 -0700503 return false;
504 }
Matt Sarett3928ff82017-06-06 10:11:34 -0400505 return src.readPixels(requestedDstInfo, dstPixels, dstRB, x, y, behavior);
reedb184f7f2014-07-13 04:32:32 -0700506}
507
Mike Reed68dd8d02017-01-04 16:34:31 -0500508bool SkBitmap::readPixels(const SkPixmap& dst, int srcX, int srcY) const {
509 return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
510}
511
Matt Sarettd2adc662017-03-27 15:07:35 -0400512bool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY,
513 SkTransferFunctionBehavior behavior) {
Matt Sarett03dd6d52017-01-23 12:15:09 -0500514 if (!SkImageInfoValidConversion(fInfo, src.info())) {
Mike Reed68dd8d02017-01-04 16:34:31 -0500515 return false;
516 }
517
Matt Sarett03dd6d52017-01-23 12:15:09 -0500518 SkWritePixelsRec rec(src.info(), src.addr(), src.rowBytes(), dstX, dstY);
519 if (!rec.trim(fInfo.width(), fInfo.height())) {
520 return false;
521 }
522
523 void* dstPixels = this->getAddr(rec.fX, rec.fY);
524 const SkImageInfo dstInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height());
Matt Sarett485c4992017-02-14 14:18:27 -0500525 SkConvertPixels(dstInfo, dstPixels, this->rowBytes(), rec.fInfo, rec.fPixels, rec.fRowBytes,
Mike Reed086a4272017-07-18 10:53:11 -0400526 nullptr, behavior);
Matt Sarett8572d852017-02-14 11:21:02 -0500527 return true;
Mike Reed68dd8d02017-01-04 16:34:31 -0500528}
529
reed@android.com8a1c16f2008-12-17 15:59:43 +0000530///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000531
reed92fc2ae2015-05-22 08:06:21 -0700532static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
halcanary96fcdcc2015-08-27 07:41:13 -0700533 SkASSERT(alpha != nullptr);
reed92fc2ae2015-05-22 08:06:21 -0700534 SkASSERT(alphaRowBytes >= src.width());
535
Mike Reed4edb5d22017-04-17 11:02:51 -0400536 SkPixmap pmap;
537 if (!src.peekPixels(&pmap)) {
lsalzmana2415ac2016-10-11 14:29:12 -0700538 for (int y = 0; y < src.height(); ++y) {
539 memset(alpha, 0, src.width());
540 alpha += alphaRowBytes;
541 }
reed92fc2ae2015-05-22 08:06:21 -0700542 return false;
543 }
Matt Sarett485c4992017-02-14 14:18:27 -0500544 SkConvertPixels(SkImageInfo::MakeA8(pmap.width(), pmap.height()), alpha, alphaRowBytes,
Mike Reed086a4272017-07-18 10:53:11 -0400545 pmap.info(), pmap.addr(), pmap.rowBytes(), nullptr,
Matt Sarettd2adc662017-03-27 15:07:35 -0400546 SkTransferFunctionBehavior::kRespect);
reed@android.com1cdcb512009-08-24 19:11:00 +0000547 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000548}
549
550#include "SkPaint.h"
551#include "SkMaskFilter.h"
552#include "SkMatrix.h"
553
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000554bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
djsollen@google.com57f49692011-02-23 20:46:31 +0000555 Allocator *allocator, SkIPoint* offset) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000556 SkDEBUGCODE(this->validate();)
557
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000558 SkBitmap tmpBitmap;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000559 SkMatrix identity;
560 SkMask srcM, dstM;
561
562 srcM.fBounds.set(0, 0, this->width(), this->height());
563 srcM.fRowBytes = SkAlign4(this->width());
564 srcM.fFormat = SkMask::kA8_Format;
565
halcanary96fcdcc2015-08-27 07:41:13 -0700566 SkMaskFilter* filter = paint ? paint->getMaskFilter() : nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000567
568 // compute our (larger?) dst bounds if we have a filter
bsalomon49f085d2014-09-05 13:34:00 -0700569 if (filter) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000570 identity.reset();
halcanary96fcdcc2015-08-27 07:41:13 -0700571 if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000572 goto NO_FILTER_CASE;
573 }
574 dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
575 } else {
576 NO_FILTER_CASE:
commit-bot@chromium.orga3264e52014-05-30 13:26:10 +0000577 tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
Mike Reed086a4272017-07-18 10:53:11 -0400578 if (!tmpBitmap.tryAllocPixels(allocator)) {
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000579 // Allocation of pixels for alpha bitmap failed.
580 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
581 tmpBitmap.width(), tmpBitmap.height());
582 return false;
583 }
584 GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000585 if (offset) {
586 offset->set(0, 0);
587 }
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000588 tmpBitmap.swap(*dst);
589 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590 }
bungeman@google.com02f55842011-10-04 21:25:00 +0000591 srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
592 SkAutoMaskFreeImage srcCleanup(srcM.fImage);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000593
594 GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
halcanary96fcdcc2015-08-27 07:41:13 -0700595 if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000596 goto NO_FILTER_CASE;
597 }
bungeman@google.com02f55842011-10-04 21:25:00 +0000598 SkAutoMaskFreeImage dstCleanup(dstM.fImage);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000599
commit-bot@chromium.orga3264e52014-05-30 13:26:10 +0000600 tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
601 dstM.fRowBytes);
Mike Reed086a4272017-07-18 10:53:11 -0400602 if (!tmpBitmap.tryAllocPixels(allocator)) {
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000603 // Allocation of pixels for alpha bitmap failed.
604 SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
605 tmpBitmap.width(), tmpBitmap.height());
606 return false;
607 }
608 memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000609 if (offset) {
610 offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
611 }
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000612 SkDEBUGCODE(tmpBitmap.validate();)
613
614 tmpBitmap.swap(*dst);
615 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616}
617
618///////////////////////////////////////////////////////////////////////////////
619
reed92fc2ae2015-05-22 08:06:21 -0700620static void write_raw_pixels(SkWriteBuffer* buffer, const SkPixmap& pmap) {
621 const SkImageInfo& info = pmap.info();
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000622 const size_t snugRB = info.width() * info.bytesPerPixel();
reed92fc2ae2015-05-22 08:06:21 -0700623 const char* src = (const char*)pmap.addr();
624 const size_t ramRB = pmap.rowBytes();
skia.committer@gmail.com3c134a92014-05-24 03:05:26 +0000625
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000626 buffer->write32(SkToU32(snugRB));
627 info.flatten(*buffer);
628
629 const size_t size = snugRB * info.height();
scroggo565901d2015-12-10 10:44:13 -0800630 SkAutoTMalloc<char> storage(size);
631 char* dst = storage.get();
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000632 for (int y = 0; y < info.height(); ++y) {
633 memcpy(dst, src, snugRB);
634 dst += snugRB;
635 src += ramRB;
636 }
637 buffer->writeByteArray(storage.get(), size);
Mike Reed262b3192017-07-17 10:13:58 -0400638 // no colortable
639 buffer->writeBool(false);
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000640}
641
reed92fc2ae2015-05-22 08:06:21 -0700642void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
643 const SkImageInfo info = bitmap.info();
Hal Canary1b3387b2016-12-12 13:48:12 -0500644 if (0 == info.width() || 0 == info.height() || bitmap.isNull()) {
reed92fc2ae2015-05-22 08:06:21 -0700645 buffer->writeUInt(0); // instead of snugRB, signaling no pixels
646 return;
647 }
648
Mike Reed4edb5d22017-04-17 11:02:51 -0400649 SkPixmap result;
650 if (!bitmap.peekPixels(&result)) {
reed92fc2ae2015-05-22 08:06:21 -0700651 buffer->writeUInt(0); // instead of snugRB, signaling no pixels
652 return;
653 }
654
Mike Reed4edb5d22017-04-17 11:02:51 -0400655 write_raw_pixels(buffer, result);
reed92fc2ae2015-05-22 08:06:21 -0700656}
657
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000658bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
Mike Kleind6c04d92017-09-25 13:49:49 -0400659 if (0 == buffer->readUInt()) {
660 return false; // no pixels
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000661 }
662
663 SkImageInfo info;
664 info.unflatten(*buffer);
665
Robert Phillipsb2cb5352016-12-20 12:44:41 -0500666 if (info.width() < 0 || info.height() < 0) {
667 return false;
668 }
669
mtklein58e389b2016-07-15 07:00:11 -0700670 // If there was an error reading "info" or if it is bogus,
Mike Kleind6c04d92017-09-25 13:49:49 -0400671 // don't use it to compute minRowBytes().
robertphillips74139f12016-06-28 09:04:34 -0700672 if (!buffer->validate(SkColorTypeValidateAlphaType(info.colorType(),
673 info.alphaType()))) {
sugoica95c192014-07-08 09:18:48 -0700674 return false;
675 }
676
Mike Kleind6c04d92017-09-25 13:49:49 -0400677 // write_raw_pixels() always writes snug buffers with rowBytes == minRowBytes().
Greg Danielf46633f2017-09-26 20:07:58 +0000678 size_t bytes = info.getSafeSize(info.minRowBytes());
Mike Kleind6c04d92017-09-25 13:49:49 -0400679 if (!buffer->validate(bytes != 0)) {
commit-bot@chromium.org05858432014-05-30 01:06:44 +0000680 return false;
681 }
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000682
Mike Kleind6c04d92017-09-25 13:49:49 -0400683 sk_sp<SkData> data(SkData::MakeUninitialized(bytes));
robertphillips28937842015-06-08 07:10:49 -0700684 unsigned char* dst = (unsigned char*)data->writable_data();
Mike Kleind6c04d92017-09-25 13:49:49 -0400685 if (!buffer->readByteArray(dst, bytes)) {
686 return false;
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000687 }
skia.committer@gmail.com3c134a92014-05-24 03:05:26 +0000688
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000689 if (buffer->readBool()) {
Mike Reed323ae0e2017-07-24 22:05:25 -0400690 SkColorTable::Skip(*buffer);
691 if (!buffer->isValid()) {
reedb236d1a2015-08-28 10:14:18 -0700692 return false;
693 }
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000694 }
skia.committer@gmail.com3c134a92014-05-24 03:05:26 +0000695
Mike Reed6b3155c2017-04-03 14:41:44 -0400696 sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeWithData(info, info.minRowBytes(),
Mike Reed086a4272017-07-18 10:53:11 -0400697 std::move(data));
Mike Reed6b3155c2017-04-03 14:41:44 -0400698 if (!pr) {
sugoi6af31472015-01-28 13:15:32 -0800699 return false;
700 }
Matt Sarettf7583112017-05-01 10:22:31 -0400701 bitmap->setInfo(info);
Hal Canary1b3387b2016-12-12 13:48:12 -0500702 bitmap->setPixelRef(std::move(pr), 0, 0);
commit-bot@chromium.org968edca2014-05-23 13:21:55 +0000703 return true;
704}
705
reed@android.com8a1c16f2008-12-17 15:59:43 +0000706enum {
707 SERIALIZE_PIXELTYPE_NONE,
djsollen@google.com21830d92012-08-07 19:49:41 +0000708 SERIALIZE_PIXELTYPE_REF_DATA
reed@android.com8a1c16f2008-12-17 15:59:43 +0000709};
710
reed@android.com8a1c16f2008-12-17 15:59:43 +0000711///////////////////////////////////////////////////////////////////////////////
712
reed@android.com8a1c16f2008-12-17 15:59:43 +0000713#ifdef SK_DEBUG
714void SkBitmap::validate() const {
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000715 fInfo.validate();
commit-bot@chromium.orgd5414e52014-02-13 22:30:38 +0000716
717 // ImageInfo may not require this, but Bitmap ensures that opaque-only
718 // colorTypes report opaque for their alphatype
719 if (kRGB_565_SkColorType == fInfo.colorType()) {
720 SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
721 }
722
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000723 SkASSERT(fInfo.validRowBytes(fRowBytes));
scroggo08470592014-07-15 19:56:48 -0700724 uint8_t allFlags = kImageIsVolatile_Flag;
scroggo@google.com8e990eb2013-06-14 15:55:56 +0000725#ifdef SK_BUILD_FOR_ANDROID
726 allFlags |= kHasHardwareMipMap_Flag;
727#endif
scroggo08470592014-07-15 19:56:48 -0700728 SkASSERT((~allFlags & fFlags) == 0);
Mike Reedb7120892017-04-14 17:16:36 -0400729
730 if (fPixelRef && fPixelRef->pixels()) {
731 SkASSERT(fPixels);
732 } else {
733 SkASSERT(!fPixels);
734 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000735
reed@google.com615316c2014-01-15 19:15:23 +0000736 if (fPixels) {
737 SkASSERT(fPixelRef);
reed@google.com615316c2014-01-15 19:15:23 +0000738 SkASSERT(fPixelRef->rowBytes() == fRowBytes);
739 SkASSERT(fPixelRefOrigin.fX >= 0);
740 SkASSERT(fPixelRefOrigin.fY >= 0);
Matt Sarettf7583112017-05-01 10:22:31 -0400741 SkASSERT(fPixelRef->width() >= (int)this->width() + fPixelRefOrigin.fX);
742 SkASSERT(fPixelRef->height() >= (int)this->height() + fPixelRefOrigin.fY);
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000743 SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000744 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000745}
746#endif
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000747
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000748#ifndef SK_IGNORE_TO_STRING
bungemand3ebb482015-08-05 13:57:49 -0700749#include "SkString.h"
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000750void SkBitmap::toString(SkString* str) const {
751
commit-bot@chromium.orgcba73782014-05-29 15:57:47 +0000752 static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
753 "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000754 };
755
756 str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
commit-bot@chromium.orgcba73782014-05-29 15:57:47 +0000757 gColorTypeNames[this->colorType()]);
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000758
759 str->append(" (");
760 if (this->isOpaque()) {
761 str->append("opaque");
762 } else {
763 str->append("transparent");
764 }
765 if (this->isImmutable()) {
766 str->append(", immutable");
767 } else {
768 str->append(", not-immutable");
769 }
770 str->append(")");
771
Mike Reed96d5b9a2017-04-12 22:29:00 -0400772 str->appendf(" pixelref:%p", this->pixelRef());
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000773 str->append(")");
774}
775#endif
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000776
777///////////////////////////////////////////////////////////////////////////////
778
reedcb674142015-06-05 06:58:22 -0700779bool SkBitmap::peekPixels(SkPixmap* pmap) const {
780 if (fPixels) {
781 if (pmap) {
Mike Reed086a4272017-07-18 10:53:11 -0400782 pmap->reset(fInfo, fPixels, fRowBytes);
reedcb674142015-06-05 06:58:22 -0700783 }
784 return true;
785 }
786 return false;
787}
788
reed92fc2ae2015-05-22 08:06:21 -0700789///////////////////////////////////////////////////////////////////////////////
790
commit-bot@chromium.org61e96cd2014-02-11 18:21:45 +0000791#ifdef SK_DEBUG
792void SkImageInfo::validate() const {
793 SkASSERT(fWidth >= 0);
794 SkASSERT(fHeight >= 0);
795 SkASSERT(SkColorTypeIsValid(fColorType));
796 SkASSERT(SkAlphaTypeIsValid(fAlphaType));
797}
798#endif