SkBitmap.cpp 20 KB

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