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