1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 2bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/* 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2008 The Android Open Source Project 4bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com * 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 7bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 9685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBitmap.h" 11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkColorPriv.h" 12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkDither.h" 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkFlattenable.h" 14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkMallocPixelRef.h" 15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkMask.h" 169ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com#include "SkOrderedReadBuffer.h" 179ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com#include "SkOrderedWriteBuffer.h" 18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPixelRef.h" 19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkThread.h" 20ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org#include "SkUnPreMultiply.h" 21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkUtils.h" 22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPackBits.h" 23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include <new> 24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2586dbfc4180c99e8934ac930f87c569d5babbf838robertphillips@google.comSK_DEFINE_INST_COUNT(SkBitmap::Allocator) 2686dbfc4180c99e8934ac930f87c569d5babbf838robertphillips@google.com 270eee10048d23302ea663354ee7c65ce525e594e2reed@android.comstatic bool isPos32Bits(const Sk64& value) { 280eee10048d23302ea663354ee7c65ce525e594e2reed@android.com return !value.isNeg() && value.is32(); 290eee10048d23302ea663354ee7c65ce525e594e2reed@android.com} 300eee10048d23302ea663354ee7c65ce525e594e2reed@android.com 31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstruct MipLevel { 32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* fPixels; 33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t fRowBytes; 345133a0c03f39e1ede6edf628a79c726c2a30b55ereed@android.com uint32_t fWidth, fHeight; 35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstruct SkBitmap::MipMap : SkNoncopyable { 38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int32_t fRefCnt; 39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int fLevelCount; 40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// MipLevel fLevel[fLevelCount]; 41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// Pixels[] 42d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com static MipMap* Alloc(int levelCount, size_t pixelSize) { 440eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (levelCount < 0) { 450eee10048d23302ea663354ee7c65ce525e594e2reed@android.com return NULL; 460eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 470eee10048d23302ea663354ee7c65ce525e594e2reed@android.com Sk64 size; 480eee10048d23302ea663354ee7c65ce525e594e2reed@android.com size.setMul(levelCount + 1, sizeof(MipLevel)); 490eee10048d23302ea663354ee7c65ce525e594e2reed@android.com size.add(sizeof(MipMap)); 502dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com size.add(SkToS32(pixelSize)); 510eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (!isPos32Bits(size)) { 520eee10048d23302ea663354ee7c65ce525e594e2reed@android.com return NULL; 530eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 540eee10048d23302ea663354ee7c65ce525e594e2reed@android.com MipMap* mm = (MipMap*)sk_malloc_throw(size.get32()); 55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com mm->fRefCnt = 1; 56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com mm->fLevelCount = levelCount; 57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return mm; 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const MipLevel* levels() const { return (const MipLevel*)(this + 1); } 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com MipLevel* levels() { return (MipLevel*)(this + 1); } 62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const void* pixels() const { return levels() + fLevelCount; } 64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* pixels() { return levels() + fLevelCount; } 65d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 660eee10048d23302ea663354ee7c65ce525e594e2reed@android.com void ref() { 670eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (SK_MaxS32 == sk_atomic_inc(&fRefCnt)) { 680eee10048d23302ea663354ee7c65ce525e594e2reed@android.com sk_throw(); 69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 710eee10048d23302ea663354ee7c65ce525e594e2reed@android.com void unref() { 720eee10048d23302ea663354ee7c65ce525e594e2reed@android.com SkASSERT(fRefCnt > 0); 730eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (sk_atomic_dec(&fRefCnt) == 1) { 740eee10048d23302ea663354ee7c65ce525e594e2reed@android.com sk_free(this); 75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkBitmap::SkBitmap() { 835eafe260fa3574ec71eccb5519f41b8095f56562reed@android.com sk_bzero(this, sizeof(*this)); 84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkBitmap::SkBitmap(const SkBitmap& src) { 87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(src.validate();) 885eafe260fa3574ec71eccb5519f41b8095f56562reed@android.com sk_bzero(this, sizeof(*this)); 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *this = src; 90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkBitmap::~SkBitmap() { 94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->freePixels(); 96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkBitmap& SkBitmap::operator=(const SkBitmap& src) { 99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (this != &src) { 100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->freePixels(); 101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memcpy(this, &src, sizeof(src)); 102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // inc src reference counts 10471251167e61c460ad5b0be70c7131b5e5916094areed@android.com SkSafeRef(src.fPixelRef); 1050eee10048d23302ea663354ee7c65ce525e594e2reed@android.com SkSafeRef(src.fMipMap); 106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // we reset our locks if we get blown away 108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelLockCount = 0; 109d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /* The src could be in 3 states 111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1. no pixelref, in which case we just copy/ref the pixels/ctable 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2. unlocked pixelref, pixels/ctable should be null 113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 3. locked pixelref, we should lock the ref again ourselves 114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL == fPixelRef) { 116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // leave fPixels as it is 117919114813d58933c9d9433b141e0222c34b700b1reed@google.com SkSafeRef(fColorTable); // ref the user's ctable if present 118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { // we have a pixelref, so pixels/ctable reflect it 119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // ignore the values from the memcpy 120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixels = NULL; 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fColorTable = NULL; 1226c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com // Note that what to for genID is somewhat arbitrary. We have no 1236c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com // way to track changes to raw pixels across multiple SkBitmaps. 1246c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com // Would benefit from an SkRawPixelRef type created by 1256c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com // setPixels. 1266c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com // Just leave the memcpy'ed one but they'll get out of sync 1276c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com // as soon either is modified. 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return *this; 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::swap(SkBitmap& other) { 1366c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fColorTable, other.fColorTable); 1376c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fPixelRef, other.fPixelRef); 1386c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fPixelRefOffset, other.fPixelRefOffset); 1396c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fPixelLockCount, other.fPixelLockCount); 1406c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fMipMap, other.fMipMap); 1416c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fPixels, other.fPixels); 1426c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fRowBytes, other.fRowBytes); 1436c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fWidth, other.fWidth); 1446c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fHeight, other.fHeight); 1456c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fConfig, other.fConfig); 1466c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fFlags, other.fFlags); 1476c597bfae2fff2065a9291672a74e075ad256aedbsalomon@google.com SkTSwap(fBytesPerPixel, other.fBytesPerPixel); 148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::reset() { 153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->freePixels(); 1545eafe260fa3574ec71eccb5519f41b8095f56562reed@android.com sk_bzero(this, sizeof(*this)); 155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) { 158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int bpp; 159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (config) { 160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kNo_Config: 161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kA1_Config: 162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bpp = 0; // not applicable 163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kA8_Config: 165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kIndex8_Config: 166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bpp = 1; 167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kRGB_565_Config: 169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kARGB_4444_Config: 170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bpp = 2; 171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kARGB_8888_Config: 173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bpp = 4; 174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 1762d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("unknown config"); 177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bpp = 0; // error 178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return bpp; 181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1830c1d83adde8270c6d8c5eb3eecb457b6b196689bscroggo@google.comsize_t SkBitmap::ComputeRowBytes(Config c, int width) { 1840eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (width < 0) { 1850eee10048d23302ea663354ee7c65ce525e594e2reed@android.com return 0; 1860eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 1870eee10048d23302ea663354ee7c65ce525e594e2reed@android.com 1880eee10048d23302ea663354ee7c65ce525e594e2reed@android.com Sk64 rowBytes; 1890eee10048d23302ea663354ee7c65ce525e594e2reed@android.com rowBytes.setZero(); 190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (c) { 192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kNo_Config: 193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kA1_Config: 1950eee10048d23302ea663354ee7c65ce525e594e2reed@android.com rowBytes.set(width); 1960eee10048d23302ea663354ee7c65ce525e594e2reed@android.com rowBytes.add(7); 1970eee10048d23302ea663354ee7c65ce525e594e2reed@android.com rowBytes.shiftRight(3); 198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kA8_Config: 200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kIndex8_Config: 2010eee10048d23302ea663354ee7c65ce525e594e2reed@android.com rowBytes.set(width); 202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kRGB_565_Config: 204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kARGB_4444_Config: 2050eee10048d23302ea663354ee7c65ce525e594e2reed@android.com rowBytes.set(width); 2060eee10048d23302ea663354ee7c65ce525e594e2reed@android.com rowBytes.shiftLeft(1); 207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kARGB_8888_Config: 2090eee10048d23302ea663354ee7c65ce525e594e2reed@android.com rowBytes.set(width); 2100eee10048d23302ea663354ee7c65ce525e594e2reed@android.com rowBytes.shiftLeft(2); 211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 2132d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("unknown config"); 214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 2160eee10048d23302ea663354ee7c65ce525e594e2reed@android.com return isPos32Bits(rowBytes) ? rowBytes.get32() : 0; 217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSk64 SkBitmap::ComputeSize64(Config c, int width, int height) { 220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 size; 2212dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com size.setMul(SkToS32(SkBitmap::ComputeRowBytes(c, width)), height); 222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return size; 223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comsize_t SkBitmap::ComputeSize(Config c, int width, int height) { 226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 size = SkBitmap::ComputeSize64(c, width, height); 2270eee10048d23302ea663354ee7c65ce525e594e2reed@android.com return isPos32Bits(size) ? size.get32() : 0; 228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 230f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.orgSk64 SkBitmap::ComputeSafeSize64(Config config, 231f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org uint32_t width, 232f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org uint32_t height, 2330c1d83adde8270c6d8c5eb3eecb457b6b196689bscroggo@google.com size_t rowBytes) { 234f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org Sk64 safeSize; 235f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org safeSize.setZero(); 236f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org if (height > 0) { 2372dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com // TODO: Handle the case where the return value from 2382dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com // ComputeRowBytes is more than 31 bits. 2392dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com safeSize.set(SkToS32(ComputeRowBytes(config, width))); 240f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org Sk64 sizeAllButLastRow; 2412dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com sizeAllButLastRow.setMul(height - 1, SkToS32(rowBytes)); 242f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org safeSize.add(sizeAllButLastRow); 243f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org } 244f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org SkASSERT(!safeSize.isNeg()); 245f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org return safeSize; 246f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org} 247f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 248f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.orgsize_t SkBitmap::ComputeSafeSize(Config config, 249f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org uint32_t width, 250f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org uint32_t height, 2510c1d83adde8270c6d8c5eb3eecb457b6b196689bscroggo@google.com size_t rowBytes) { 252f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org Sk64 safeSize = ComputeSafeSize64(config, width, height, rowBytes); 253f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org return (safeSize.is32() ? safeSize.get32() : 0); 254f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org} 255f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 25683359275c4142b1431ed5ab3ead75f3704664a49reed@google.comvoid SkBitmap::getBounds(SkRect* bounds) const { 25783359275c4142b1431ed5ab3ead75f3704664a49reed@google.com SkASSERT(bounds); 25883359275c4142b1431ed5ab3ead75f3704664a49reed@google.com bounds->set(0, 0, 25983359275c4142b1431ed5ab3ead75f3704664a49reed@google.com SkIntToScalar(fWidth), SkIntToScalar(fHeight)); 26083359275c4142b1431ed5ab3ead75f3704664a49reed@google.com} 26183359275c4142b1431ed5ab3ead75f3704664a49reed@google.com 26288ac2872e94c4caf49ac731b3470294e52afa83breed@google.comvoid SkBitmap::getBounds(SkIRect* bounds) const { 26388ac2872e94c4caf49ac731b3470294e52afa83breed@google.com SkASSERT(bounds); 26488ac2872e94c4caf49ac731b3470294e52afa83breed@google.com bounds->set(0, 0, fWidth, fHeight); 26588ac2872e94c4caf49ac731b3470294e52afa83breed@google.com} 26688ac2872e94c4caf49ac731b3470294e52afa83breed@google.com 26783359275c4142b1431ed5ab3ead75f3704664a49reed@google.com/////////////////////////////////////////////////////////////////////////////// 26883359275c4142b1431ed5ab3ead75f3704664a49reed@google.com 2690c1d83adde8270c6d8c5eb3eecb457b6b196689bscroggo@google.comvoid SkBitmap::setConfig(Config c, int width, int height, size_t rowBytes) { 270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->freePixels(); 271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2720c1d83adde8270c6d8c5eb3eecb457b6b196689bscroggo@google.com if ((width | height) < 0) { 27346bf92525f293731be7e466e1e60c2790a976486agl@chromium.org goto err; 2740eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 2750eee10048d23302ea663354ee7c65ce525e594e2reed@android.com 276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (rowBytes == 0) { 277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rowBytes = SkBitmap::ComputeRowBytes(c, width); 2780eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (0 == rowBytes && kNo_Config != c) { 27946bf92525f293731be7e466e1e60c2790a976486agl@chromium.org goto err; 2800eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 282badeafac94730d6c53098c3d90abc05509ebd6a1reed@android.com 283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fConfig = SkToU8(c); 2845133a0c03f39e1ede6edf628a79c726c2a30b55ereed@android.com fWidth = width; 2855133a0c03f39e1ede6edf628a79c726c2a30b55ereed@android.com fHeight = height; 2862dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com fRowBytes = SkToU32(rowBytes); 287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c); 289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 29171719e434d4a201bf56304a77ab00fe11121b03creed@android.com return; 29246bf92525f293731be7e466e1e60c2790a976486agl@chromium.org 29371719e434d4a201bf56304a77ab00fe11121b03creed@android.com // if we got here, we had an error, so we reset the bitmap to empty 29446bf92525f293731be7e466e1e60c2790a976486agl@chromium.orgerr: 29546bf92525f293731be7e466e1e60c2790a976486agl@chromium.org this->reset(); 296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::updatePixelsFromRef() const { 299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL != fPixelRef) { 300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPixelLockCount > 0) { 301e0f5c7da0d07c811789773d1bd555edba3a1cf40reed@google.com SkASSERT(fPixelRef->isLocked()); 302d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* p = fPixelRef->pixels(); 304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL != p) { 305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com p = (char*)p + fPixelRefOffset; 306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixels = p; 308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkRefCnt_SafeAssign(fColorTable, fPixelRef->colorTable()); 309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(0 == fPixelLockCount); 311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixels = NULL; 3120eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (fColorTable) { 3130eee10048d23302ea663354ee7c65ce525e594e2reed@android.com fColorTable->unref(); 3140eee10048d23302ea663354ee7c65ce525e594e2reed@android.com fColorTable = NULL; 3150eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) { 321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // do this first, we that we never have a non-zero offset with a null ref 322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL == pr) { 323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com offset = 0; 324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPixelRef != pr || fPixelRefOffset != offset) { 327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPixelRef != pr) { 328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->freePixels(); 329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(NULL == fPixelRef); 330d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 331919114813d58933c9d9433b141e0222c34b700b1reed@google.com SkSafeRef(pr); 332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelRef = pr; 333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelRefOffset = offset; 335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->updatePixelsFromRef(); 336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return pr; 340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 342bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::lockPixels() const { 343391d415ebbccf6526aec96e31fa9b6f9d5b87ffadjsollen@google.com if (NULL != fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) { 344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelRef->lockPixels(); 345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->updatePixelsFromRef(); 346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::unlockPixels() const { 351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(NULL == fPixelRef || fPixelLockCount > 0); 352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 353391d415ebbccf6526aec96e31fa9b6f9d5b87ffadjsollen@google.com if (NULL != fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) { 354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelRef->unlockPixels(); 355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->updatePixelsFromRef(); 356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 360c0fcabd5182ed09e162638355c8d8d734a5a8f74reed@google.combool SkBitmap::lockPixelsAreWritable() const { 36170542e91dafb18d75d1f07f4c6e706d93ebc6883djsollen@google.com return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false; 362c0fcabd5182ed09e162638355c8d8d734a5a8f74reed@google.com} 363c0fcabd5182ed09e162638355c8d8d734a5a8f74reed@google.com 364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::setPixels(void* p, SkColorTable* ctable) { 36581fe1c51f0b3b844d5442a838999ad618ddb5f19reed@google.com if (NULL == p) { 36681fe1c51f0b3b844d5442a838999ad618ddb5f19reed@google.com this->setPixelRef(NULL, 0); 36781fe1c51f0b3b844d5442a838999ad618ddb5f19reed@google.com return; 36881fe1c51f0b3b844d5442a838999ad618ddb5f19reed@google.com } 36981fe1c51f0b3b844d5442a838999ad618ddb5f19reed@google.com 37070542e91dafb18d75d1f07f4c6e706d93ebc6883djsollen@google.com Sk64 size = this->getSize64(); 37170542e91dafb18d75d1f07f4c6e706d93ebc6883djsollen@google.com SkASSERT(!size.isNeg() && size.is32()); 372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 37370542e91dafb18d75d1f07f4c6e706d93ebc6883djsollen@google.com this->setPixelRef(new SkMallocPixelRef(p, size.get32(), ctable, false))->unref(); 37470542e91dafb18d75d1f07f4c6e706d93ebc6883djsollen@google.com // since we're already allocated, we lockPixels right away 37570542e91dafb18d75d1f07f4c6e706d93ebc6883djsollen@google.com this->lockPixels(); 376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 378bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) { 380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com HeapAllocator stdalloc; 381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL == allocator) { 383bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com allocator = &stdalloc; 384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 385bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return allocator->allocPixelRef(this, ctable); 386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::freePixels() { 389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // if we're gonna free the pixels, we certainly need to free the mipmap 390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->freeMipMap(); 391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 3920eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (fColorTable) { 3930eee10048d23302ea663354ee7c65ce525e594e2reed@android.com fColorTable->unref(); 3940eee10048d23302ea663354ee7c65ce525e594e2reed@android.com fColorTable = NULL; 3950eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 396bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL != fPixelRef) { 398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPixelLockCount > 0) { 399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelRef->unlockPixels(); 400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelRef->unref(); 402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelRef = NULL; 403bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelRefOffset = 0; 404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 405bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelLockCount = 0; 406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixels = NULL; 407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::freeMipMap() { 4100eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (fMipMap) { 4110eee10048d23302ea663354ee7c65ce525e594e2reed@android.com fMipMap->unref(); 4120eee10048d23302ea663354ee7c65ce525e594e2reed@android.com fMipMap = NULL; 4130eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 416bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comuint32_t SkBitmap::getGenerationID() const { 41770542e91dafb18d75d1f07f4c6e706d93ebc6883djsollen@google.com return (fPixelRef) ? fPixelRef->getGenerationID() : 0; 418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 420bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::notifyPixelsChanged() const { 421055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org SkASSERT(!this->isImmutable()); 422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPixelRef) { 423bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPixelRef->notifyPixelsChanged(); 424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 42787816f8e3e4e8633221d6e2c20c2ecdab3b6b6fccommit-bot@chromium.orgGrTexture* SkBitmap::getTexture() const { 428a857a062e3d616442d27ff56f3261e6afe86c1f9reed@android.com return fPixelRef ? fPixelRef->getTexture() : NULL; 429a857a062e3d616442d27ff56f3261e6afe86c1f9reed@android.com} 430a857a062e3d616442d27ff56f3261e6afe86c1f9reed@android.com 431bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 433bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/** We explicitly use the same allocator for our pixels that SkMask does, 434bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com so that we can freely assign memory allocated by one class to the other. 435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, 437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkColorTable* ctable) { 438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk64 size = dst->getSize64(); 439bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (size.isNeg() || !size.is32()) { 440bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 441bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 442d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 443bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* addr = sk_malloc_flags(size.get32(), 0); // returns NULL on failure 444bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL == addr) { 445bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 447d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->setPixelRef(new SkMallocPixelRef(addr, size.get32(), ctable))->unref(); 449bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // since we're already allocated, we lockPixels right away 450bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->lockPixels(); 451bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return true; 452bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 453bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 454bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 456f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.orgsize_t SkBitmap::getSafeSize() const { 457f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org // This is intended to be a size_t version of ComputeSafeSize64(), just 458f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org // faster. The computation is meant to be identical. 459f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org return (fHeight ? ((fHeight - 1) * fRowBytes) + 460f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org ComputeRowBytes(getConfig(), fWidth): 0); 461f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org} 462f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 463f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.orgSk64 SkBitmap::getSafeSize64() const { 464f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org return ComputeSafeSize64(getConfig(), fWidth, fHeight, fRowBytes); 465f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org} 466f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 467935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.combool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize, 4680c1d83adde8270c6d8c5eb3eecb457b6b196689bscroggo@google.com size_t dstRowBytes, bool preserveDstPad) const { 469f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 4700c1d83adde8270c6d8c5eb3eecb457b6b196689bscroggo@google.com if (0 == dstRowBytes) { 471f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org dstRowBytes = fRowBytes; 4720c1d83adde8270c6d8c5eb3eecb457b6b196689bscroggo@google.com } 473f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 4747046fabd572d913a9a02106de3b053cfeed7062freed@google.com if (dstRowBytes < ComputeRowBytes(getConfig(), fWidth) || 475f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) 476f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org return false; 477f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 4786cc3764f05b72f3064a99146c7b6d0b55a0634febsalomon@google.com if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) { 479f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org size_t safeSize = getSafeSize(); 480f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org if (safeSize > dstSize || safeSize == 0) 481f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org return false; 482f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org else { 483f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org SkAutoLockPixels lock(*this); 484f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org // This implementation will write bytes beyond the end of each row, 485f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org // excluding the last row, if the bitmap's stride is greater than 486f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org // strictly required by the current config. 487f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org memcpy(dst, getPixels(), safeSize); 488f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 489f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org return true; 490f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org } 491f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org } else { 492f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org // If destination has different stride than us, then copy line by line. 493f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org if (ComputeSafeSize(getConfig(), fWidth, fHeight, dstRowBytes) > 494f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org dstSize) 495f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org return false; 496f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org else { 497f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org // Just copy what we need on each line. 4982dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com size_t rowBytes = ComputeRowBytes(getConfig(), fWidth); 499f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org SkAutoLockPixels lock(*this); 500f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels()); 501f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org uint8_t* dstP = reinterpret_cast<uint8_t*>(dst); 502f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org for (uint32_t row = 0; row < fHeight; 503f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org row++, srcP += fRowBytes, dstP += dstRowBytes) { 504f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org memcpy(dstP, srcP, rowBytes); 505f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org } 506f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 507f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org return true; 508f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org } 509f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org } 510f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org} 511f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 512f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org/////////////////////////////////////////////////////////////////////////////// 513f924d70150ed7edbd26d6ce98ea3dcf74a962690wjmaclean@chromium.org 514935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.combool SkBitmap::isImmutable() const { 515055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org return fPixelRef ? fPixelRef->isImmutable() : 516935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com fFlags & kImageIsImmutable_Flag; 517055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org} 518055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org 519055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.orgvoid SkBitmap::setImmutable() { 520055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org if (fPixelRef) { 521055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org fPixelRef->setImmutable(); 522055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org } else { 523055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org fFlags |= kImageIsImmutable_Flag; 524055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org } 525055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org} 526055f10a51713256704416e1c6c9bf7dd69858449junov@chromium.org 527bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkBitmap::isOpaque() const { 528bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (fConfig) { 529bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kNo_Config: 530bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return true; 531bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 532bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kA1_Config: 533bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kA8_Config: 534bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kARGB_4444_Config: 535bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kARGB_8888_Config: 536bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (fFlags & kImageIsOpaque_Flag) != 0; 537bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5387046fabd572d913a9a02106de3b053cfeed7062freed@google.com case kIndex8_Config: { 5397046fabd572d913a9a02106de3b053cfeed7062freed@google.com uint32_t flags = 0; 540bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5417046fabd572d913a9a02106de3b053cfeed7062freed@google.com this->lockPixels(); 5427046fabd572d913a9a02106de3b053cfeed7062freed@google.com // if lockPixels failed, we may not have a ctable ptr 5437046fabd572d913a9a02106de3b053cfeed7062freed@google.com if (fColorTable) { 5447046fabd572d913a9a02106de3b053cfeed7062freed@google.com flags = fColorTable->getFlags(); 545bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 5467046fabd572d913a9a02106de3b053cfeed7062freed@google.com this->unlockPixels(); 5477046fabd572d913a9a02106de3b053cfeed7062freed@google.com 5487046fabd572d913a9a02106de3b053cfeed7062freed@google.com return (flags & SkColorTable::kColorsAreOpaque_Flag) != 0; 5497046fabd572d913a9a02106de3b053cfeed7062freed@google.com } 550bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 551bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kRGB_565_Config: 552bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return true; 553bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 554bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 5552d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("unknown bitmap config pased to isOpaque"); 556bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 557bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 558bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 559bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 560bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::setIsOpaque(bool isOpaque) { 561bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /* we record this regardless of fConfig, though it is ignored in 562bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com isOpaque() for configs that can't support per-pixel alpha. 563bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 564bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (isOpaque) { 565bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fFlags |= kImageIsOpaque_Flag; 566bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 567bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fFlags &= ~kImageIsOpaque_Flag; 568bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 569bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 570bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5719ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.combool SkBitmap::isVolatile() const { 5729ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.com return (fFlags & kImageIsVolatile_Flag) != 0; 5739ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.com} 5749ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.com 5759ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.comvoid SkBitmap::setIsVolatile(bool isVolatile) { 5769ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.com if (isVolatile) { 5779ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.com fFlags |= kImageIsVolatile_Flag; 5789ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.com } else { 5799ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.com fFlags &= ~kImageIsVolatile_Flag; 5809ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.com } 5819ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.com} 5829ad10ea962254748b7056318d7c74ad8de87b6c3junov@google.com 583bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid* SkBitmap::getAddr(int x, int y) const { 584bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((unsigned)x < (unsigned)this->width()); 585bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((unsigned)y < (unsigned)this->height()); 586bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 587bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com char* base = (char*)this->getPixels(); 588bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (base) { 589bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com base += y * this->rowBytes(); 590bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (this->config()) { 591bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kARGB_8888_Config: 592bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com base += x << 2; 593bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 594bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kARGB_4444_Config: 595bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kRGB_565_Config: 596bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com base += x << 1; 597bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 598bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kA8_Config: 599bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kIndex8_Config: 600bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com base += x; 601bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 602bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kA1_Config: 603bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com base += x >> 3; 604bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 605bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 6062d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("Can't return addr for config"); 607bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com base = NULL; 608bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 609bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 610bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 611bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return base; 612bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 613bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 614ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.orgSkColor SkBitmap::getColor(int x, int y) const { 615ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org SkASSERT((unsigned)x < (unsigned)this->width()); 616ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org SkASSERT((unsigned)y < (unsigned)this->height()); 617ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org 618ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org switch (this->config()) { 619ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org case SkBitmap::kA1_Config: { 620b70380d81547afa11829344822fd04adef55c9cfreed@google.com uint8_t* addr = this->getAddr1(x, y); 621ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org uint8_t mask = 1 << (7 - (x % 8)); 622ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org if (addr[0] & mask) { 623ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org return SK_ColorBLACK; 624ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org } else { 625ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org return 0; 626ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org } 627ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org } 628ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org case SkBitmap::kA8_Config: { 629b70380d81547afa11829344822fd04adef55c9cfreed@google.com uint8_t* addr = this->getAddr8(x, y); 630ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org return SkColorSetA(0, addr[0]); 631ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org } 632ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org case SkBitmap::kIndex8_Config: { 633b70380d81547afa11829344822fd04adef55c9cfreed@google.com SkPMColor c = this->getIndex8Color(x, y); 634ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org return SkUnPreMultiply::PMColorToColor(c); 635ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org } 636ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org case SkBitmap::kRGB_565_Config: { 637b70380d81547afa11829344822fd04adef55c9cfreed@google.com uint16_t* addr = this->getAddr16(x, y); 638ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org return SkPixel16ToColor(addr[0]); 639ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org } 640ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org case SkBitmap::kARGB_4444_Config: { 641b70380d81547afa11829344822fd04adef55c9cfreed@google.com uint16_t* addr = this->getAddr16(x, y); 642ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org SkPMColor c = SkPixel4444ToPixel32(addr[0]); 643ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org return SkUnPreMultiply::PMColorToColor(c); 644ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org } 645ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org case SkBitmap::kARGB_8888_Config: { 646b70380d81547afa11829344822fd04adef55c9cfreed@google.com uint32_t* addr = this->getAddr32(x, y); 647ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org return SkUnPreMultiply::PMColorToColor(addr[0]); 648ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org } 649ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org case kNo_Config: 650ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org SkASSERT(false); 651ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org return 0; 652ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org } 653ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org SkASSERT(false); // Not reached. 654ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org return 0; 655ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org} 656ce1c95c73b2a5b70cee991bfd13c1d8091316d09vandebo@chromium.org 65750f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.combool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { 65850f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com SkAutoLockPixels alp(bm); 65950f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com if (!bm.getPixels()) { 66050f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return false; 66150f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 66250f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com 66350f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com const int height = bm.height(); 66450f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com const int width = bm.width(); 66550f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com 66650f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com switch (bm.config()) { 66750f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com case SkBitmap::kA1_Config: { 66850f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com // TODO 66950f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } break; 67050f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com case SkBitmap::kA8_Config: { 67150f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com unsigned a = 0xFF; 67250f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com for (int y = 0; y < height; ++y) { 67350f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com const uint8_t* row = bm.getAddr8(0, y); 67450f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com for (int x = 0; x < width; ++x) { 67550f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com a &= row[x]; 67650f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 67750f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com if (0xFF != a) { 67850f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return false; 67950f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 68050f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 68150f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return true; 68250f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } break; 68350f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com case SkBitmap::kIndex8_Config: { 68450f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com SkAutoLockColors alc(bm); 68550f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com const SkPMColor* table = alc.colors(); 68650f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com if (!table) { 68750f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return false; 68850f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 6892fe04f3f1d09716bfb9f712d4d37a6c1229ebe31reed@google.com SkPMColor c = (SkPMColor)~0; 69050f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) { 69150f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com c &= table[i]; 69250f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 69350f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return 0xFF == SkGetPackedA32(c); 69450f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } break; 69550f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com case SkBitmap::kRGB_565_Config: 69650f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return true; 69750f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com break; 69850f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com case SkBitmap::kARGB_4444_Config: { 69950f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com unsigned c = 0xFFFF; 70050f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com for (int y = 0; y < height; ++y) { 70150f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com const SkPMColor16* row = bm.getAddr16(0, y); 70250f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com for (int x = 0; x < width; ++x) { 70350f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com c &= row[x]; 70450f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 70550f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com if (0xF != SkGetPackedA4444(c)) { 70650f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return false; 70750f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 70850f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 70950f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return true; 71050f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } break; 71150f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com case SkBitmap::kARGB_8888_Config: { 7122fe04f3f1d09716bfb9f712d4d37a6c1229ebe31reed@google.com SkPMColor c = (SkPMColor)~0; 71350f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com for (int y = 0; y < height; ++y) { 71450f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com const SkPMColor* row = bm.getAddr32(0, y); 71550f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com for (int x = 0; x < width; ++x) { 71650f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com c &= row[x]; 71750f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 71850f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com if (0xFF != SkGetPackedA32(c)) { 71950f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return false; 72050f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 72150f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 72250f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return true; 72350f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 72450f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com default: 72550f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com break; 72650f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com } 72750f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com return false; 72850f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com} 72950f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com 73050f82958b878662bcf7b7cdee6e416de91ba78b2reed@google.com 731bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 732bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 733bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 73407ffff5475ac62659ac496c58898f20918836acereed@google.comstatic uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) { 73507ffff5475ac62659ac496c58898f20918836acereed@google.com unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) | 73607ffff5475ac62659ac496c58898f20918836acereed@google.com (SkR32To4444(r) << SK_R4444_SHIFT) | 73707ffff5475ac62659ac496c58898f20918836acereed@google.com (SkG32To4444(g) << SK_G4444_SHIFT) | 73807ffff5475ac62659ac496c58898f20918836acereed@google.com (SkB32To4444(b) << SK_B4444_SHIFT); 73907ffff5475ac62659ac496c58898f20918836acereed@google.com return SkToU16(pixel); 74007ffff5475ac62659ac496c58898f20918836acereed@google.com} 74107ffff5475ac62659ac496c58898f20918836acereed@google.com 742f08d62a57fe862fce451801a7d7e01287103bff4reed@google.comvoid SkBitmap::internalErase(const SkIRect& area, 743f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 744f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com#ifdef SK_DEBUG 745bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 746f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com SkASSERT(!area.isEmpty()); 747f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com { 7485a3eebf1f4a0ecbe91e72333580c66c0587b203freed@google.com SkIRect total = { 0, 0, this->width(), this->height() }; 749f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com SkASSERT(total.contains(area)); 750f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com } 751f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com#endif 752bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 753f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com if (kNo_Config == fConfig || kIndex8_Config == fConfig) { 754bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 755bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 756bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 757bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAutoLockPixels alp(*this); 758bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // perform this check after the lock call 759bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!this->readyToDraw()) { 760bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 761bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 762bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 763f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com int height = area.height(); 764f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com const int width = area.width(); 765bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const int rowBytes = fRowBytes; 766bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 767bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // make rgb premultiplied 768bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (255 != a) { 769bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com r = SkAlphaMul(r, a); 770bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com g = SkAlphaMul(g, a); 771bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b = SkAlphaMul(b, a); 772bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 773bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 774bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (fConfig) { 775bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kA1_Config: { 776f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com uint8_t* p = this->getAddr1(area.fLeft, area.fTop); 777f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com const int left = area.fLeft >> 3; 778f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com const int right = area.fRight >> 3; 7798ee3e9b4a4d76bba3de2e5963d39f6bd2f6ec965skia.committer@gmail.com 780f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com int middle = right - left - 1; 781f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com 782f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com uint8_t leftMask = 0xFF >> (area.fLeft & 7); 783f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com uint8_t rightMask = ~(0xFF >> (area.fRight & 7)); 784f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com if (left == right) { 785f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com leftMask &= rightMask; 786f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com rightMask = 0; 787f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com } 788f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com 789bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com a = (a >> 7) ? 0xFF : 0; 790bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (--height >= 0) { 791f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com uint8_t* startP = p; 792f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com 793f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com *p = (*p & ~leftMask) | (a & leftMask); 794f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com p++; 795f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com if (middle > 0) { 796f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com memset(p, a, middle); 797f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com p += middle; 798f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com } 799f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com if (rightMask) { 800f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com *p = (*p & ~rightMask) | (a & rightMask); 801f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com } 8028ee3e9b4a4d76bba3de2e5963d39f6bd2f6ec965skia.committer@gmail.com 803f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com p = startP + rowBytes; 804bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 805bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 806bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 807bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kA8_Config: { 808f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com uint8_t* p = this->getAddr8(area.fLeft, area.fTop); 809bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (--height >= 0) { 810bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memset(p, a, width); 811bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com p += rowBytes; 812bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 813bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 814bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 81507ffff5475ac62659ac496c58898f20918836acereed@google.com case kARGB_4444_Config: 816bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kRGB_565_Config: { 817f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com uint16_t* p = this->getAddr16(area.fLeft, area.fTop);; 81807ffff5475ac62659ac496c58898f20918836acereed@google.com uint16_t v; 819d568a8073d2b1f8d8469c83f82976757274724fbskia.committer@gmail.com 82007ffff5475ac62659ac496c58898f20918836acereed@google.com if (kARGB_4444_Config == fConfig) { 82107ffff5475ac62659ac496c58898f20918836acereed@google.com v = pack_8888_to_4444(a, r, g, b); 82207ffff5475ac62659ac496c58898f20918836acereed@google.com } else { 82307ffff5475ac62659ac496c58898f20918836acereed@google.com v = SkPackRGB16(r >> (8 - SK_R16_BITS), 82407ffff5475ac62659ac496c58898f20918836acereed@google.com g >> (8 - SK_G16_BITS), 82507ffff5475ac62659ac496c58898f20918836acereed@google.com b >> (8 - SK_B16_BITS)); 82607ffff5475ac62659ac496c58898f20918836acereed@google.com } 827bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (--height >= 0) { 828bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sk_memset16(p, v, width); 829bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com p = (uint16_t*)((char*)p + rowBytes); 830bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 831bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 832bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 833bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kARGB_8888_Config: { 834f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com uint32_t* p = this->getAddr32(area.fLeft, area.fTop); 835bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t v = SkPackARGB32(a, r, g, b); 836bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 837bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (--height >= 0) { 838bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sk_memset32(p, v, width); 839bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com p = (uint32_t*)((char*)p + rowBytes); 840bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 841bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 842bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 843bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 844d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 845bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->notifyPixelsChanged(); 846bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 847bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 848f08d62a57fe862fce451801a7d7e01287103bff4reed@google.comvoid SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { 8495a3eebf1f4a0ecbe91e72333580c66c0587b203freed@google.com SkIRect area = { 0, 0, this->width(), this->height() }; 850f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com if (!area.isEmpty()) { 851f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com this->internalErase(area, a, r, g, b); 852f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com } 853f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com} 854f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com 855f08d62a57fe862fce451801a7d7e01287103bff4reed@google.comvoid SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { 8565a3eebf1f4a0ecbe91e72333580c66c0587b203freed@google.com SkIRect area = { 0, 0, this->width(), this->height() }; 857f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com if (area.intersect(rect)) { 858f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com this->internalErase(area, SkColorGetA(c), SkColorGetR(c), 859f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com SkColorGetG(c), SkColorGetB(c)); 860f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com } 861f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com} 862f08d62a57fe862fce451801a7d7e01287103bff4reed@google.com 863bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////////////////// 864bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////////////////// 865bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 866bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SUB_OFFSET_FAILURE ((size_t)-1) 867bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 8686ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com/** 8696ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com * Based on the Config and rowBytes() of bm, return the offset into an SkPixelRef of the pixel at 8706ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com * (x, y). 8716ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com * Note that the SkPixelRef does not need to be set yet. deepCopyTo takes advantage of this fact. 8726ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com * Also note that (x, y) may be outside the range of (0 - width(), 0 - height()), so long as it is 8736ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com * within the bounds of the SkPixelRef being used. 8746ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com */ 875df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.comstatic size_t get_sub_offset(const SkBitmap& bm, int x, int y) { 876bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (bm.getConfig()) { 877bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kA8_Config: 878bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap:: kIndex8_Config: 879bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // x is fine as is for the calculation 880bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 881bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 882bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kRGB_565_Config: 883bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kARGB_4444_Config: 884bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x <<= 1; 885bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 886bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 887bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kARGB_8888_Config: 888bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x <<= 2; 889bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 890bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 891bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kNo_Config: 892bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkBitmap::kA1_Config: 893bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 894bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SUB_OFFSET_FAILURE; 895bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 896bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return y * bm.rowBytes() + x; 897bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 898bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 8996ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com/** 9006ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com * Using the pixelRefOffset(), rowBytes(), and Config of bm, determine the (x, y) coordinate of the 9016ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com * upper left corner of bm relative to its SkPixelRef. 9026ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com * x and y must be non-NULL. 9036ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com */ 904df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.combool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes, 905847b6a4df3f6fc268f8ab28f4f412ef720f11046scroggo@google.com int32_t* x, int32_t* y); 906847b6a4df3f6fc268f8ab28f4f412ef720f11046scroggo@google.combool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes, 907df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com int32_t* x, int32_t* y) { 9086ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com SkASSERT(x != NULL && y != NULL); 9096ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com if (0 == offset) { 9106ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com *x = *y = 0; 9116ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com return true; 9126ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } 9136ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // Use integer division to find the correct y position. 914df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com *y = SkToS32(offset / rowBytes); 915df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com // The remainder will be the x position, after we reverse get_sub_offset. 916df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com *x = SkToS32(offset % rowBytes); 917df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com switch (config) { 9186ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com case SkBitmap::kA8_Config: 9196ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // Fall through. 9206ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com case SkBitmap::kIndex8_Config: 9216ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // x is unmodified 9226ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com break; 9236ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com 9246ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com case SkBitmap::kRGB_565_Config: 9256ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // Fall through. 9266ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com case SkBitmap::kARGB_4444_Config: 9276ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com *x >>= 1; 9286ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com break; 9296ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com 9306ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com case SkBitmap::kARGB_8888_Config: 9316ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com *x >>= 2; 9326ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com break; 9336ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com 9346ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com case SkBitmap::kNo_Config: 9356ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // Fall through. 9366ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com case SkBitmap::kA1_Config: 9376ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // Fall through. 9386ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com default: 9396ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com return false; 9406ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } 9416ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com return true; 9426ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com} 9436ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com 944df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.comstatic bool get_upper_left_from_offset(const SkBitmap& bm, int32_t* x, int32_t* y) { 945df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com return get_upper_left_from_offset(bm.config(), bm.pixelRefOffset(), bm.rowBytes(), x, y); 946df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com} 947df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com 948bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { 949bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 950bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 95170542e91dafb18d75d1f07f4c6e706d93ebc6883djsollen@google.com if (NULL == result || NULL == fPixelRef) { 952bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; // no src pixels 953bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 954bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 955bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkIRect srcRect, r; 956bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com srcRect.set(0, 0, this->width(), this->height()); 957bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!r.intersect(srcRect, subset)) { 958bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; // r is empty (i.e. no intersection) 959bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 960bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 9616ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com if (fPixelRef->getTexture() != NULL) { 9626ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // Do a deep copy 9636ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); 9646ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com if (pixelRef != NULL) { 9656ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com SkBitmap dst; 9666ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com dst.setConfig(this->config(), subset.width(), subset.height()); 9676ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com dst.setIsVolatile(this->isVolatile()); 9686ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com dst.setIsOpaque(this->isOpaque()); 9696ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com dst.setPixelRef(pixelRef)->unref(); 9706ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com SkDEBUGCODE(dst.validate()); 9716ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com result->swap(dst); 9726ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com return true; 9736ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } 9746ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } 9756ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com 9766ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have 9776ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // exited above. 9786ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); 9796ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); 9806ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com 981df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); 982bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (SUB_OFFSET_FAILURE == offset) { 983bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; // config not supported 984bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 985bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 986bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBitmap dst; 987bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes()); 9880336b57b22beef74f3394b0082f0c3011f66f050skyostil@google.com dst.setIsVolatile(this->isVolatile()); 9890dd6362de48a3dc2656a0261cd797e0249cc7b09reed@google.com dst.setIsOpaque(this->isOpaque()); 990bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 991bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPixelRef) { 992bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // share the pixelref with a custom offset 993bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); 994bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 995bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(dst.validate();) 996bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 997bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // we know we're good, so commit to result 998bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com result->swap(dst); 999bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return true; 1000bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1001bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1002bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 1003bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1004bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkCanvas.h" 1005bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPaint.h" 1006bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 100714a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.combool SkBitmap::canCopyTo(Config dstConfig) const { 100814a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com if (this->getConfig() == kNo_Config) { 1009bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 1010bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1011bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 101214a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com bool sameConfigs = (this->config() == dstConfig); 1013bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (dstConfig) { 1014bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kA8_Config: 1015bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kRGB_565_Config: 1016bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kARGB_8888_Config: 1017bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 1018d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com case kA1_Config: 1019d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com case kIndex8_Config: 1020d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com if (!sameConfigs) { 1021d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com return false; 1022d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com } 1023d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com break; 10248bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com case kARGB_4444_Config: 10258bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com return sameConfigs || kARGB_8888_Config == this->config(); 1026bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 1027bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 1028bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1029d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1030d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config 1031d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com if (this->getConfig() == kA1_Config && !sameConfigs) { 1032d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com return false; 1033d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com } 1034d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 103514a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com return true; 103614a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com} 103714a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com 103814a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.combool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { 103914a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com if (!this->canCopyTo(dstConfig)) { 104014a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com return false; 104114a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com } 104214a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com 10430029edecdfbb02376027b059642d4bf52f86b49ereed@google.com // if we have a texture, first get those pixels 10440029edecdfbb02376027b059642d4bf52f86b49ereed@google.com SkBitmap tmpSrc; 10450029edecdfbb02376027b059642d4bf52f86b49ereed@google.com const SkBitmap* src = this; 10460029edecdfbb02376027b059642d4bf52f86b49ereed@google.com 10476ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com if (fPixelRef) { 10486ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com SkIRect subset; 1049df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com if (get_upper_left_from_offset(*this, &subset.fLeft, &subset.fTop)) { 10506ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com subset.fRight = subset.fLeft + fWidth; 10516ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com subset.fBottom = subset.fTop + fHeight; 10526ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com if (fPixelRef->readPixels(&tmpSrc, &subset)) { 10536ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com SkASSERT(tmpSrc.width() == this->width()); 10546ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com SkASSERT(tmpSrc.height() == this->height()); 10556ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com 10566ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // did we get lucky and we can just return tmpSrc? 10576ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com if (tmpSrc.config() == dstConfig && NULL == alloc) { 10586ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com dst->swap(tmpSrc); 10596ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com if (dst->pixelRef() && this->config() == dstConfig) { 10606ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com dst->pixelRef()->fGenerationID = fPixelRef->getGenerationID(); 10616ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } 10626ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com return true; 10636ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } 10640029edecdfbb02376027b059642d4bf52f86b49ereed@google.com 10656ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // fall through to the raster case 10666ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com src = &tmpSrc; 10672652781c317578ba6440287d74bff8bcf28e2b28scroggo@google.com } 10680029edecdfbb02376027b059642d4bf52f86b49ereed@google.com } 10690029edecdfbb02376027b059642d4bf52f86b49ereed@google.com } 10700029edecdfbb02376027b059642d4bf52f86b49ereed@google.com 1071bf5cca92c394c436af07491310f8d0746576a781reed@android.com // we lock this now, since we may need its colortable 10720029edecdfbb02376027b059642d4bf52f86b49ereed@google.com SkAutoLockPixels srclock(*src); 10730029edecdfbb02376027b059642d4bf52f86b49ereed@google.com if (!src->readyToDraw()) { 107414a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com return false; 107514a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com } 1076935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 10770029edecdfbb02376027b059642d4bf52f86b49ereed@google.com SkBitmap tmpDst; 10780029edecdfbb02376027b059642d4bf52f86b49ereed@google.com tmpDst.setConfig(dstConfig, src->width(), src->height()); 1079935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 1080d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com // allocate colortable if srcConfig == kIndex8_Config 1081d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com SkColorTable* ctable = (dstConfig == kIndex8_Config) ? 10820029edecdfbb02376027b059642d4bf52f86b49ereed@google.com new SkColorTable(*src->getColorTable()) : NULL; 1083d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com SkAutoUnref au(ctable); 10840029edecdfbb02376027b059642d4bf52f86b49ereed@google.com if (!tmpDst.allocPixels(alloc, ctable)) { 1085bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 1086bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1087935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 10880029edecdfbb02376027b059642d4bf52f86b49ereed@google.com if (!tmpDst.readyToDraw()) { 1089bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // allocator/lock failed 1090bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 1091bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1092935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 109314a4f988d99d32b40a51e5b19b8378a49b5e1263reed@android.com /* do memcpy for the same configs cases, else use drawing 1094d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com */ 10950029edecdfbb02376027b059642d4bf52f86b49ereed@google.com if (src->config() == dstConfig) { 10960029edecdfbb02376027b059642d4bf52f86b49ereed@google.com if (tmpDst.getSize() == src->getSize()) { 10970029edecdfbb02376027b059642d4bf52f86b49ereed@google.com memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); 10982652781c317578ba6440287d74bff8bcf28e2b28scroggo@google.com SkPixelRef* pixelRef = tmpDst.pixelRef(); 10992652781c317578ba6440287d74bff8bcf28e2b28scroggo@google.com if (pixelRef != NULL) { 11002652781c317578ba6440287d74bff8bcf28e2b28scroggo@google.com pixelRef->fGenerationID = this->getGenerationID(); 11012652781c317578ba6440287d74bff8bcf28e2b28scroggo@google.com } 1102bf5cca92c394c436af07491310f8d0746576a781reed@android.com } else { 11030029edecdfbb02376027b059642d4bf52f86b49ereed@google.com const char* srcP = reinterpret_cast<const char*>(src->getPixels()); 11040029edecdfbb02376027b059642d4bf52f86b49ereed@google.com char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); 1105bf5cca92c394c436af07491310f8d0746576a781reed@android.com // to be sure we don't read too much, only copy our logical pixels 11060029edecdfbb02376027b059642d4bf52f86b49ereed@google.com size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); 11070029edecdfbb02376027b059642d4bf52f86b49ereed@google.com for (int y = 0; y < tmpDst.height(); y++) { 1108bf5cca92c394c436af07491310f8d0746576a781reed@android.com memcpy(dstP, srcP, bytesToCopy); 11090029edecdfbb02376027b059642d4bf52f86b49ereed@google.com srcP += src->rowBytes(); 11100029edecdfbb02376027b059642d4bf52f86b49ereed@google.com dstP += tmpDst.rowBytes(); 1111bf5cca92c394c436af07491310f8d0746576a781reed@android.com } 1112bf5cca92c394c436af07491310f8d0746576a781reed@android.com } 11138bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com } else if (SkBitmap::kARGB_4444_Config == dstConfig 11148bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com && SkBitmap::kARGB_8888_Config == src->config()) { 11158bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com SkASSERT(src->height() == tmpDst.height()); 11168bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com SkASSERT(src->width() == tmpDst.width()); 11178bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com for (int y = 0; y < src->height(); ++y) { 11188bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y); 11198bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); 11208bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com DITHER_4444_SCAN(y); 11218bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com for (int x = 0; x < src->width(); ++x) { 11228bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com dstRow[x] = SkDitherARGB32To4444(srcRow[x], 11238bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com DITHER_VALUE(x)); 11248bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com } 11258bfbe6c1295a0b39b731e80a6806e7678a860f8cscroggo@google.com } 1126d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com } else { 1127d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com // if the src has alpha, we have to clear the dst first 11280029edecdfbb02376027b059642d4bf52f86b49ereed@google.com if (!src->isOpaque()) { 11296d7b99540d86e79bbc47dc0904f68a96eeb21c8cjunov@google.com tmpDst.eraseColor(SK_ColorTRANSPARENT); 1130d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com } 1131d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 11320029edecdfbb02376027b059642d4bf52f86b49ereed@google.com SkCanvas canvas(tmpDst); 1133d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com SkPaint paint; 1134d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1135d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com paint.setDither(true); 11360029edecdfbb02376027b059642d4bf52f86b49ereed@google.com canvas.drawBitmap(*src, 0, 0, &paint); 1137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 11390029edecdfbb02376027b059642d4bf52f86b49ereed@google.com tmpDst.setIsOpaque(src->isOpaque()); 1140dfd96ac50bb13a4e610ea0923b6554ec3ed96774reed@android.com 11410029edecdfbb02376027b059642d4bf52f86b49ereed@google.com dst->swap(tmpDst); 1142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return true; 1143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1145425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.orgbool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { 1146425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org if (!this->canCopyTo(dstConfig)) { 1147425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org return false; 1148425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org } 1149425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org 1150425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org // If we have a PixelRef, and it supports deep copy, use it. 1151425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org // Currently supported only by texture-backed bitmaps. 1152425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org if (fPixelRef) { 1153425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig); 1154425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org if (pixelRef) { 11556ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com uint32_t rowBytes; 11562652781c317578ba6440287d74bff8bcf28e2b28scroggo@google.com if (dstConfig == fConfig) { 11572652781c317578ba6440287d74bff8bcf28e2b28scroggo@google.com pixelRef->fGenerationID = fPixelRef->getGenerationID(); 11586ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // Use the same rowBytes as the original. 11596ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com rowBytes = fRowBytes; 11606ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } else { 11616ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // With the new config, an appropriate fRowBytes will be computed by setConfig. 11626ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com rowBytes = 0; 11636ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } 11646ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com dst->setConfig(dstConfig, fWidth, fHeight, rowBytes); 11656ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com 11666ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com size_t pixelRefOffset; 11676ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com if (0 == fPixelRefOffset || dstConfig == fConfig) { 11686ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // Use the same offset as the original. 11696ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com pixelRefOffset = fPixelRefOffset; 11706ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } else { 11716ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // Find the correct offset in the new config. This needs to be done after calling 11726ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com // setConfig so dst's fConfig and fRowBytes have been set properly. 11732dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com int32_t x, y; 1174df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com if (!get_upper_left_from_offset(*this, &x, &y)) { 11756ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com return false; 11766ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } 1177df39cdf79b3542207caec9b0ab4efdf085ef7782scroggo@google.com pixelRefOffset = get_sub_offset(*dst, x, y); 11786ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com if (SUB_OFFSET_FAILURE == pixelRefOffset) { 11796ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com return false; 11806ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com } 11812652781c317578ba6440287d74bff8bcf28e2b28scroggo@google.com } 11826ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com dst->setPixelRef(pixelRef, pixelRefOffset)->unref(); 1183425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org return true; 1184425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org } 1185425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org } 1186425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org 1187425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org if (this->getTexture()) { 1188425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org return false; 1189425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org } else { 1190425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org return this->copyTo(dst, dstConfig, NULL); 1191425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org } 1192425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org} 1193425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org 1194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 1195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 1196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void downsampleby2_proc32(SkBitmap* dst, int x, int y, 1198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkBitmap& src) { 1199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x <<= 1; 1200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com y <<= 1; 1201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkPMColor* p = src.getAddr32(x, y); 1202bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com const SkPMColor* baseP = p; 1203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPMColor c, ag, rb; 1204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF; 1206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x < src.width() - 1) { 1207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com p += 1; 1208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1211bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com p = baseP; 1212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (y < src.height() - 1) { 1213bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com p += src.rowBytes() >> 2; 1214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x < src.width() - 1) { 1217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com p += 1; 1218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; 1220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *dst->getAddr32(x >> 1, y >> 1) = 1222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00); 1223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline uint32_t expand16(U16CPU c) { 1226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16); 1227bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// returns dirt in the top 16bits, but we don't care, since we only 1230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// store the low 16bits. 1231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline U16CPU pack16(uint32_t c) { 1232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE); 1233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void downsampleby2_proc16(SkBitmap* dst, int x, int y, 1236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkBitmap& src) { 1237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x <<= 1; 1238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com y <<= 1; 1239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const uint16_t* p = src.getAddr16(x, y); 1240bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com const uint16_t* baseP = p; 1241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPMColor c; 1242d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c = expand16(*p); 1244bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com if (x < src.width() - 1) { 1245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com p += 1; 1246bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c += expand16(*p); 1248d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1249bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com p = baseP; 1250bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com if (y < src.height() - 1) { 1251bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com p += src.rowBytes() >> 1; 1252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c += expand16(*p); 1254bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com if (x < src.width() - 1) { 1255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com p += 1; 1256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c += expand16(*p); 1258d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2); 1260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic uint32_t expand4444(U16CPU c) { 1263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (c & 0xF0F) | ((c & ~0xF0F) << 12); 1264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic U16CPU collaps4444(uint32_t c) { 1267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (c & 0xF0F) | ((c >> 12) & ~0xF0F); 1268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void downsampleby2_proc4444(SkBitmap* dst, int x, int y, 1271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkBitmap& src) { 1272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x <<= 1; 1273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com y <<= 1; 1274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const uint16_t* p = src.getAddr16(x, y); 1275bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com const uint16_t* baseP = p; 1276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t c; 1277d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c = expand4444(*p); 1279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x < src.width() - 1) { 1280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com p += 1; 1281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c += expand4444(*p); 1283d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1284bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com p = baseP; 1285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (y < src.height() - 1) { 1286bec814a35bfa86de9e99d5802cdf98ef18e625b6reed@android.com p += src.rowBytes() >> 1; 1287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c += expand4444(*p); 1289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x < src.width() - 1) { 1290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com p += 1; 1291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com c += expand4444(*p); 1293d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2); 1295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::buildMipMap(bool forceRebuild) { 1298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (forceRebuild) 1299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->freeMipMap(); 1300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com else if (fMipMap) 1301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; // we're already built 1302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(NULL == fMipMap); 1304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src); 1306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkBitmap::Config config = this->getConfig(); 1308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (config) { 1310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kARGB_8888_Config: 1311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com proc = downsampleby2_proc32; 1312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 1313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kRGB_565_Config: 1314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com proc = downsampleby2_proc16; 1315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 1316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kARGB_4444_Config: 1317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com proc = downsampleby2_proc4444; 1318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 1319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kIndex8_Config: 1320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kA8_Config: 1321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 1322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; // don't build mipmaps for these configs 1323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1324badeafac94730d6c53098c3d90abc05509ebd6a1reed@android.com 13250eee10048d23302ea663354ee7c65ce525e594e2reed@android.com SkAutoLockPixels alp(*this); 13260eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (!this->readyToDraw()) { 13270eee10048d23302ea663354ee7c65ce525e594e2reed@android.com return; 13280eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 1329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // whip through our loop to compute the exact size needed 1331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com size_t size = 0; 1332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int maxLevels = 0; 1333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 13340eee10048d23302ea663354ee7c65ce525e594e2reed@android.com int width = this->width(); 13350eee10048d23302ea663354ee7c65ce525e594e2reed@android.com int height = this->height(); 1336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (;;) { 1337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com width >>= 1; 1338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com height >>= 1; 1339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (0 == width || 0 == height) { 1340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 1341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1342bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com size += ComputeRowBytes(config, width) * height; 1343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com maxLevels += 1; 1344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1346badeafac94730d6c53098c3d90abc05509ebd6a1reed@android.com 13470eee10048d23302ea663354ee7c65ce525e594e2reed@android.com // nothing to build 1348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (0 == maxLevels) { 1349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 1350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 13520eee10048d23302ea663354ee7c65ce525e594e2reed@android.com SkBitmap srcBM(*this); 13530eee10048d23302ea663354ee7c65ce525e594e2reed@android.com srcBM.lockPixels(); 13540eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (!srcBM.readyToDraw()) { 13550eee10048d23302ea663354ee7c65ce525e594e2reed@android.com return; 13560eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 13570eee10048d23302ea663354ee7c65ce525e594e2reed@android.com 13580eee10048d23302ea663354ee7c65ce525e594e2reed@android.com MipMap* mm = MipMap::Alloc(maxLevels, size); 13590eee10048d23302ea663354ee7c65ce525e594e2reed@android.com if (NULL == mm) { 13600eee10048d23302ea663354ee7c65ce525e594e2reed@android.com return; 13610eee10048d23302ea663354ee7c65ce525e594e2reed@android.com } 13620eee10048d23302ea663354ee7c65ce525e594e2reed@android.com 1363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com MipLevel* level = mm->levels(); 1364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint8_t* addr = (uint8_t*)mm->pixels(); 13650eee10048d23302ea663354ee7c65ce525e594e2reed@android.com int width = this->width(); 13660eee10048d23302ea663354ee7c65ce525e594e2reed@android.com int height = this->height(); 13672dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com uint32_t rowBytes; 13680eee10048d23302ea663354ee7c65ce525e594e2reed@android.com SkBitmap dstBM; 1369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (int i = 0; i < maxLevels; i++) { 1371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com width >>= 1; 1372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com height >>= 1; 13732dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com rowBytes = SkToU32(ComputeRowBytes(config, width)); 1374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com level[i].fPixels = addr; 13765133a0c03f39e1ede6edf628a79c726c2a30b55ereed@android.com level[i].fWidth = width; 13775133a0c03f39e1ede6edf628a79c726c2a30b55ereed@android.com level[i].fHeight = height; 137898388345db8a56e12e25b02b56a5d843376cb3dbreed@android.com level[i].fRowBytes = rowBytes; 1379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dstBM.setConfig(config, width, height, rowBytes); 1381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dstBM.setPixels(addr); 1382d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 13833fb715a5ae83be2c50f4544b43f6b3d49e5b2339bungeman@google.com srcBM.lockPixels(); 13840eee10048d23302ea663354ee7c65ce525e594e2reed@android.com for (int y = 0; y < height; y++) { 13850eee10048d23302ea663354ee7c65ce525e594e2reed@android.com for (int x = 0; x < width; x++) { 1386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com proc(&dstBM, x, y, srcBM); 1387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 13893fb715a5ae83be2c50f4544b43f6b3d49e5b2339bungeman@google.com srcBM.unlockPixels(); 1390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com srcBM = dstBM; 1392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com addr += height * rowBytes; 1393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1394bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(addr == (uint8_t*)mm->pixels() + size); 1395bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMipMap = mm; 1396bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkBitmap::hasMipMap() const { 1399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return fMipMap != NULL; 1400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) { 140371251167e61c460ad5b0be70c7131b5e5916094areed@android.com if (NULL == fMipMap) { 1404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 140571251167e61c460ad5b0be70c7131b5e5916094areed@android.com } 1406d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int level = ComputeMipLevel(sx, sy) >> 16; 1408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(level >= 0); 1409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (level <= 0) { 1410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 1411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (level >= fMipMap->fLevelCount) { 1414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com level = fMipMap->fLevelCount - 1; 1415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1416bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (dst) { 1417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const MipLevel& mip = fMipMap->levels()[level - 1]; 1418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->setConfig((SkBitmap::Config)this->config(), 1419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com mip.fWidth, mip.fHeight, mip.fRowBytes); 1420bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->setPixels(mip.fPixels); 1421bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return level; 1423bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) { 1426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sx = SkAbs32(sx); 1427bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sy = SkAbs32(sy); 1428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (sx < sy) { 1429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sx = sy; 1430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1431bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (sx < SK_Fixed1) { 1432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 1433bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1434bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int clz = SkCLZ(sx); 1435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(clz >= 1 && clz <= 15); 1436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16); 1437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1439bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 1440bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 14411ccc4d318eb17bf9d24ac7d70402201408b8f085tomhudson@google.comstatic bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, 1442bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int alphaRowBytes) { 1443bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(alpha != NULL); 1444bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(alphaRowBytes >= src.width()); 1445bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBitmap::Config config = src.getConfig(); 1447bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int w = src.width(); 1448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int h = src.height(); 14492dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com size_t rb = src.rowBytes(); 1450bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1451298bc1ed7001db4fdb9f1511e18e70de306e7e2breed@android.com SkAutoLockPixels alp(src); 1452298bc1ed7001db4fdb9f1511e18e70de306e7e2breed@android.com if (!src.readyToDraw()) { 1453298bc1ed7001db4fdb9f1511e18e70de306e7e2breed@android.com // zero out the alpha buffer and return 1454298bc1ed7001db4fdb9f1511e18e70de306e7e2breed@android.com while (--h >= 0) { 1455298bc1ed7001db4fdb9f1511e18e70de306e7e2breed@android.com memset(alpha, 0, w); 1456298bc1ed7001db4fdb9f1511e18e70de306e7e2breed@android.com alpha += alphaRowBytes; 1457298bc1ed7001db4fdb9f1511e18e70de306e7e2breed@android.com } 1458298bc1ed7001db4fdb9f1511e18e70de306e7e2breed@android.com return false; 1459298bc1ed7001db4fdb9f1511e18e70de306e7e2breed@android.com } 1460919114813d58933c9d9433b141e0222c34b700b1reed@google.com 1461bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (SkBitmap::kA8_Config == config && !src.isOpaque()) { 1462bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const uint8_t* s = src.getAddr8(0, 0); 1463bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (--h >= 0) { 1464bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memcpy(alpha, s, w); 1465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com s += rb; 1466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com alpha += alphaRowBytes; 1467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1468bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) { 1469bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0); 1470bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (--h >= 0) { 1471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (int x = 0; x < w; x++) { 1472bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com alpha[x] = SkGetPackedA32(s[x]); 1473bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1474bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com s = (const SkPMColor*)((const char*)s + rb); 1475bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com alpha += alphaRowBytes; 1476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) { 1478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0); 1479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (--h >= 0) { 1480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (int x = 0; x < w; x++) { 1481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com alpha[x] = SkPacked4444ToA32(s[x]); 1482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com s = (const SkPMColor16*)((const char*)s + rb); 1484bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com alpha += alphaRowBytes; 1485bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1486bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) { 1487bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkColorTable* ct = src.getColorTable(); 1488bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (ct) { 1489bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkPMColor* SK_RESTRICT table = ct->lockColors(); 1490bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0); 1491bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (--h >= 0) { 1492bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (int x = 0; x < w; x++) { 1493bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com alpha[x] = SkGetPackedA32(table[s[x]]); 1494bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1495bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com s += rb; 1496bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com alpha += alphaRowBytes; 1497bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1498bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ct->unlockColors(false); 1499bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1500bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { // src is opaque, so just fill alpha[] with 0xFF 1501bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memset(alpha, 0xFF, h * alphaRowBytes); 1502bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1503298bc1ed7001db4fdb9f1511e18e70de306e7e2breed@android.com return true; 1504bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1505bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1506bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPaint.h" 1507bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkMaskFilter.h" 1508bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkMatrix.h" 1509bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1510d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.combool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, 1511fb9a4ea68b33af97fd279cb238d738833f24614edjsollen@google.com Allocator *allocator, SkIPoint* offset) const { 1512bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(this->validate();) 1513bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1514d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com SkBitmap tmpBitmap; 1515bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkMatrix identity; 1516bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkMask srcM, dstM; 1517bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1518bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com srcM.fBounds.set(0, 0, this->width(), this->height()); 1519bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com srcM.fRowBytes = SkAlign4(this->width()); 1520bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com srcM.fFormat = SkMask::kA8_Format; 1521bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1522bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL; 1523bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1524bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // compute our (larger?) dst bounds if we have a filter 1525bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL != filter) { 1526bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com identity.reset(); 1527bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com srcM.fImage = NULL; 1528bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1529bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com goto NO_FILTER_CASE; 1530bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1531bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dstM.fRowBytes = SkAlign4(dstM.fBounds.width()); 1532bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 1533bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com NO_FILTER_CASE: 1534d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com tmpBitmap.setConfig(SkBitmap::kA8_Config, this->width(), this->height(), 1535bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com srcM.fRowBytes); 1536d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com if (!tmpBitmap.allocPixels(allocator, NULL)) { 1537d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com // Allocation of pixels for alpha bitmap failed. 1538d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1539d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com tmpBitmap.width(), tmpBitmap.height()); 1540d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com return false; 1541d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com } 1542d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes); 1543bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (offset) { 1544bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com offset->set(0, 0); 1545bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1546d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com tmpBitmap.swap(*dst); 1547d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com return true; 1548bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 154928dbbc76d685ad49cd8620b754e69252506dad64bungeman@google.com srcM.fImage = SkMask::AllocImage(srcM.computeImageSize()); 155028dbbc76d685ad49cd8620b754e69252506dad64bungeman@google.com SkAutoMaskFreeImage srcCleanup(srcM.fImage); 1551bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1552bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes); 1553bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!filter->filterMask(&dstM, srcM, identity, NULL)) { 1554bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com goto NO_FILTER_CASE; 1555bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 155628dbbc76d685ad49cd8620b754e69252506dad64bungeman@google.com SkAutoMaskFreeImage dstCleanup(dstM.fImage); 1557bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1558d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com tmpBitmap.setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(), 1559bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dstM.fBounds.height(), dstM.fRowBytes); 1560d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com if (!tmpBitmap.allocPixels(allocator, NULL)) { 1561d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com // Allocation of pixels for alpha bitmap failed. 1562d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n", 1563d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com tmpBitmap.width(), tmpBitmap.height()); 1564d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com return false; 1565d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com } 1566d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize()); 1567bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (offset) { 1568bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop); 1569bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1570d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com SkDEBUGCODE(tmpBitmap.validate();) 1571d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com 1572d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com tmpBitmap.swap(*dst); 1573d175ac1bb2103a7e249d4fc8383cf1f2eee54c98djsollen@google.com return true; 1574bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1575bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1576bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 1577bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1578bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comenum { 1579bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SERIALIZE_PIXELTYPE_NONE, 1580a9aa73ae674668fe929a04566a17804eefe7938edjsollen@google.com SERIALIZE_PIXELTYPE_REF_DATA 1581bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 1582bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1583bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { 15849ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com buffer.writeInt(fWidth); 15859ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com buffer.writeInt(fHeight); 15869ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com buffer.writeInt(fRowBytes); 15879ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com buffer.writeInt(fConfig); 1588bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com buffer.writeBool(this->isOpaque()); 1589d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1590bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPixelRef) { 1591e365cbf42989ed40de307f8bdb0e880a316f8071djsollen@google.com if (fPixelRef->getFactory()) { 15929ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); 15932dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com buffer.writeUInt(SkToU32(fPixelRefOffset)); 1594e365cbf42989ed40de307f8bdb0e880a316f8071djsollen@google.com buffer.writeFlattenable(fPixelRef); 1595e365cbf42989ed40de307f8bdb0e880a316f8071djsollen@google.com return; 1596bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1597bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // if we get here, we can't record the pixels 15989ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1599bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 16009ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1601bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1602bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1603bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1604bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { 1605bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->reset(); 1606d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1607bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int width = buffer.readInt(); 1608bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int height = buffer.readInt(); 1609bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int rowBytes = buffer.readInt(); 16109ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com int config = buffer.readInt(); 1611d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 1612bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setConfig((Config)config, width, height, rowBytes); 1613bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->setIsOpaque(buffer.readBool()); 1614d57ea92b0fde0f6e89532203f500b4cff07a7723weita@google.com 16159ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com int reftype = buffer.readInt(); 1616bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (reftype) { 1617bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SERIALIZE_PIXELTYPE_REF_DATA: { 16189ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com size_t offset = buffer.readUInt(); 16199ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com SkPixelRef* pr = buffer.readFlattenableT<SkPixelRef>(); 1620919114813d58933c9d9433b141e0222c34b700b1reed@google.com SkSafeUnref(this->setPixelRef(pr, offset)); 1621bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 1622bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1623bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SERIALIZE_PIXELTYPE_NONE: 1624bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 1625bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 16262d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("unrecognized pixeltype in serialized data"); 1627bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sk_throw(); 1628bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1629bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1630bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1631bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 1632bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1633bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkBitmap::RLEPixels::RLEPixels(int width, int height) { 1634bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fHeight = height; 1635bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fYPtrs = (uint8_t**)sk_malloc_throw(height * sizeof(uint8_t*)); 16365eafe260fa3574ec71eccb5519f41b8095f56562reed@android.com sk_bzero(fYPtrs, height * sizeof(uint8_t*)); 1637bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1638bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1639bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkBitmap::RLEPixels::~RLEPixels() { 1640bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sk_free(fYPtrs); 1641bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1642bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1643bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 1644bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1645bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 1646bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBitmap::validate() const { 1647bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(fConfig < kConfigCount); 1648bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth)); 16497adc34192f3fe7b114a66e3fe2819b19710b6e3ascroggo@google.com uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag; 16507adc34192f3fe7b114a66e3fe2819b19710b6e3ascroggo@google.com#ifdef SK_BUILD_FOR_ANDROID 16517adc34192f3fe7b114a66e3fe2819b19710b6e3ascroggo@google.com allFlags |= kHasHardwareMipMap_Flag; 16527adc34192f3fe7b114a66e3fe2819b19710b6e3ascroggo@google.com#endif 16537adc34192f3fe7b114a66e3fe2819b19710b6e3ascroggo@google.com SkASSERT(fFlags <= allFlags); 1654bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(fPixelLockCount >= 0); 1655bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000); 1656bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel); 1657bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1658bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if 0 // these asserts are not thread-correct, so disable for now 1659bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPixelRef) { 1660bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPixelLockCount > 0) { 1661e0f5c7da0d07c811789773d1bd555edba3a1cf40reed@google.com SkASSERT(fPixelRef->isLocked()); 1662bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 1663bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(NULL == fPixels); 1664bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(NULL == fColorTable); 1665bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1666bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 1667bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 1668bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1669bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 1670bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 1671bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com#ifdef SK_DEVELOPER 1672bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.comvoid SkBitmap::toString(SkString* str) const { 1673bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 1674bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com static const char* gConfigNames[kConfigCount] = { 1675ae7971f7747f9cc64afc1f9a2198752681c0da50edisonn@google.com "NONE", "A1", "A8", "INDEX8", "565", "4444", "8888" 1676bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com }; 1677bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 1678bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), 1679bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com gConfigNames[this->config()]); 1680bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 1681bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(" ("); 1682bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com if (this->isOpaque()) { 1683bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append("opaque"); 1684bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com } else { 1685bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append("transparent"); 1686bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com } 1687bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com if (this->isImmutable()) { 1688bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(", immutable"); 1689bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com } else { 1690bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(", not-immutable"); 1691bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com } 1692bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(")"); 1693bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 1694bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com SkPixelRef* pr = this->pixelRef(); 1695bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com if (NULL == pr) { 1696bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com // show null or the explicit pixel address (rare) 1697bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->appendf(" pixels:%p", this->getPixels()); 1698bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com } else { 1699bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com const char* uri = pr->getURI(); 1700bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com if (NULL != uri) { 1701bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->appendf(" uri:\"%s\"", uri); 1702bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com } else { 1703bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->appendf(" pixelref:%p", pr); 1704bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com } 1705bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com } 1706bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 1707bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(")"); 1708bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com} 1709bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com#endif 1710