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