1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmap.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDither.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFlattenable.h"
146e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org#include "SkImagePriv.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMallocPixelRef.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMask.h"
178b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
188b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPixelRef.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkThread.h"
21112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org#include "SkUnPreMultiply.h"
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
23c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPackBits.h"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include <new>
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.orgstatic bool reset_return_false(SkBitmap* bm) {
2861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    bm->reset();
2961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    return false;
3061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org}
3161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap::SkBitmap() {
334516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com    sk_bzero(this, sizeof(*this));
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap::SkBitmap(const SkBitmap& src) {
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(src.validate();)
384516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com    sk_bzero(this, sizeof(*this));
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *this = src;
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap::~SkBitmap() {
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->freePixels();
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap& SkBitmap::operator=(const SkBitmap& src) {
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (this != &src) {
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->freePixels();
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(this, &src, sizeof(src));
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // inc src reference counts
5483f7bc30af2837c985934e14597caec332899a1creed@android.com        SkSafeRef(src.fPixelRef);
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we reset our locks if we get blown away
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelLockCount = 0;
58f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
595f62ed74342e44cb1b9671ffdac47c6a81416136reed@google.com        if (fPixelRef) {
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // ignore the values from the memcpy
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPixels = NULL;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fColorTable = NULL;
63586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com            // Note that what to for genID is somewhat arbitrary. We have no
64586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com            // way to track changes to raw pixels across multiple SkBitmaps.
65586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com            // Would benefit from an SkRawPixelRef type created by
66586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com            // setPixels.
67586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com            // Just leave the memcpy'ed one but they'll get out of sync
68586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com            // as soon either is modified.
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *this;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::swap(SkBitmap& other) {
77586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    SkTSwap(fColorTable, other.fColorTable);
78586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    SkTSwap(fPixelRef, other.fPixelRef);
79672588b684d484dce6ae251e9e163e4a46924322reed@google.com    SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin);
80586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    SkTSwap(fPixelLockCount, other.fPixelLockCount);
81586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    SkTSwap(fPixels, other.fPixels);
8261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkTSwap(fInfo, other.fInfo);
83586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    SkTSwap(fRowBytes, other.fRowBytes);
84586f48cfa8b1fa7b29d8ee8d0a028489a33866debsalomon@google.com    SkTSwap(fFlags, other.fFlags);
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::reset() {
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->freePixels();
914516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com    sk_bzero(this, sizeof(*this));
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9486b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.comvoid SkBitmap::getBounds(SkRect* bounds) const {
9586b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com    SkASSERT(bounds);
9686b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com    bounds->set(0, 0,
97e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                SkIntToScalar(fInfo.width()), SkIntToScalar(fInfo.height()));
9886b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com}
9986b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com
10080e1459c32f5f3acbc688ae4f0e046aa283e8c3areed@google.comvoid SkBitmap::getBounds(SkIRect* bounds) const {
10180e1459c32f5f3acbc688ae4f0e046aa283e8c3areed@google.com    SkASSERT(bounds);
102e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    bounds->set(0, 0, fInfo.width(), fInfo.height());
10380e1459c32f5f3acbc688ae4f0e046aa283e8c3areed@google.com}
10480e1459c32f5f3acbc688ae4f0e046aa283e8c3areed@google.com
10586b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com///////////////////////////////////////////////////////////////////////////////
10686b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com
107e5ea500d4714a7d84de2bf913e81be3b65d2de68reedbool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) {
108e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    SkAlphaType newAT = info.alphaType();
109e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) {
110d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org        return reset_return_false(this);
111d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    }
112e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    // don't look at info.alphaType(), since newAT is the real value...
11302d6f546161e2c98d69066373cec3f54f3c46252skia.committer@gmail.com
11461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    // require that rowBytes fit in 31bits
11561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    int64_t mrb = info.minRowBytes64();
11661e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if ((int32_t)mrb != mrb) {
11761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        return reset_return_false(this);
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if ((int64_t)rowBytes != (int32_t)rowBytes) {
12061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        return reset_return_false(this);
121383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    }
122383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com
12361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if (info.width() < 0 || info.height() < 0) {
12461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        return reset_return_false(this);
125169a0ed50a5e451711c341795572e7177a540a24mike@reedtribe.org    }
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if (kUnknown_SkColorType == info.colorType()) {
12861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        rowBytes = 0;
12961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    } else if (0 == rowBytes) {
13061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        rowBytes = (size_t)mrb;
131f0aed97aec3fa1c7f6460d8d6327358f3dcbabe6reed    } else if (!info.validRowBytes(rowBytes)) {
13261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        return reset_return_false(this);
13361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    }
1341195a28892d37ae9632e81e1bc2407cf644522d2mike@reedtribe.org
13561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    this->freePixels();
1361195a28892d37ae9632e81e1bc2407cf644522d2mike@reedtribe.org
137e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    fInfo = info.makeAlphaType(newAT);
13861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    fRowBytes = SkToU32(rowBytes);
139383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    return true;
140383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com}
141383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com
142e5ea500d4714a7d84de2bf913e81be3b65d2de68reedbool SkBitmap::setAlphaType(SkAlphaType newAlphaType) {
143e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    if (!SkColorTypeValidateAlphaType(fInfo.colorType(), newAlphaType, &newAlphaType)) {
144383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com        return false;
145383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    }
146e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    if (fInfo.alphaType() != newAlphaType) {
147e5ea500d4714a7d84de2bf913e81be3b65d2de68reed        fInfo = fInfo.makeAlphaType(newAlphaType);
1480e8d0d6cdc2e02946b099006d0a47e60764905e5commit-bot@chromium.org        if (fPixelRef) {
149e5ea500d4714a7d84de2bf913e81be3b65d2de68reed            fPixelRef->changeAlphaType(newAlphaType);
1500e8d0d6cdc2e02946b099006d0a47e60764905e5commit-bot@chromium.org        }
1510e8d0d6cdc2e02946b099006d0a47e60764905e5commit-bot@chromium.org    }
152383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    return true;
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::updatePixelsFromRef() const {
15649f085dddff10473b6ebf832a974288300224e60bsalomon    if (fPixelRef) {
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fPixelLockCount > 0) {
158ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com            SkASSERT(fPixelRef->isLocked());
159f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            void* p = fPixelRef->pixels();
16149f085dddff10473b6ebf832a974288300224e60bsalomon            if (p) {
162672588b684d484dce6ae251e9e163e4a46924322reed@google.com                p = (char*)p
163303c4758ec7062daf1531c3642e9c7887423ef1breed@google.com                    + fPixelRefOrigin.fY * fRowBytes
16461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                    + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPixels = p;
1675f62ed74342e44cb1b9671ffdac47c6a81416136reed@google.com            fColorTable = fPixelRef->colorTable();
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(0 == fPixelLockCount);
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPixels = NULL;
1715f62ed74342e44cb1b9671ffdac47c6a81416136reed@google.com            fColorTable = NULL;
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
176672588b684d484dce6ae251e9e163e4a46924322reed@google.comSkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
177dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com#ifdef SK_DEBUG
178672588b684d484dce6ae251e9e163e4a46924322reed@google.com    if (pr) {
179466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org        if (kUnknown_SkColorType != fInfo.colorType()) {
180dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com            const SkImageInfo& prInfo = pr->info();
181e5ea500d4714a7d84de2bf913e81be3b65d2de68reed            SkASSERT(fInfo.width() <= prInfo.width());
182e5ea500d4714a7d84de2bf913e81be3b65d2de68reed            SkASSERT(fInfo.height() <= prInfo.height());
183e5ea500d4714a7d84de2bf913e81be3b65d2de68reed            SkASSERT(fInfo.colorType() == prInfo.colorType());
184e5ea500d4714a7d84de2bf913e81be3b65d2de68reed            switch (prInfo.alphaType()) {
185dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                case kIgnore_SkAlphaType:
186e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                    SkASSERT(fInfo.alphaType() == kIgnore_SkAlphaType);
187dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                    break;
188dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                case kOpaque_SkAlphaType:
189dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                case kPremul_SkAlphaType:
190e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                    SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType ||
191e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                             fInfo.alphaType() == kPremul_SkAlphaType);
192dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                    break;
193dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                case kUnpremul_SkAlphaType:
194e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                    SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType ||
195e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                             fInfo.alphaType() == kUnpremul_SkAlphaType);
196dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                    break;
197dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com            }
198dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com        }
199dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com    }
200dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com#endif
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
202672588b684d484dce6ae251e9e163e4a46924322reed@google.com    if (pr) {
203672588b684d484dce6ae251e9e163e4a46924322reed@google.com        const SkImageInfo& info = pr->info();
204e5ea500d4714a7d84de2bf913e81be3b65d2de68reed        fPixelRefOrigin.set(SkPin32(dx, 0, info.width()), SkPin32(dy, 0, info.height()));
205672588b684d484dce6ae251e9e163e4a46924322reed@google.com    } else {
206672588b684d484dce6ae251e9e163e4a46924322reed@google.com        // ignore dx,dy if there is no pixelref
207672588b684d484dce6ae251e9e163e4a46924322reed@google.com        fPixelRefOrigin.setZero();
208672588b684d484dce6ae251e9e163e4a46924322reed@google.com    }
209672588b684d484dce6ae251e9e163e4a46924322reed@google.com
210672588b684d484dce6ae251e9e163e4a46924322reed@google.com    if (fPixelRef != pr) {
2110eb02a6abbe2964e4955863b0f82aff6a8661801piotaixr        this->freePixels();
2120eb02a6abbe2964e4955863b0f82aff6a8661801piotaixr        SkASSERT(NULL == fPixelRef);
213f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
2140eb02a6abbe2964e4955863b0f82aff6a8661801piotaixr        SkSafeRef(pr);
2150eb02a6abbe2964e4955863b0f82aff6a8661801piotaixr        fPixelRef = pr;
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->updatePixelsFromRef();
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return pr;
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::lockPixels() const {
22449f085dddff10473b6ebf832a974288300224e60bsalomon    if (fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) {
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelRef->lockPixels();
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->updatePixelsFromRef();
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::unlockPixels() const {
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(NULL == fPixelRef || fPixelLockCount > 0);
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23449f085dddff10473b6ebf832a974288300224e60bsalomon    if (fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) {
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelRef->unlockPixels();
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->updatePixelsFromRef();
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2419c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.combool SkBitmap::lockPixelsAreWritable() const {
242c84b8335ee4fd864c30a4703afc643cf4b5010d9djsollen@google.com    return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false;
2439c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com}
2449c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::setPixels(void* p, SkColorTable* ctable) {
2468e1034e9ca0e3009f65125239e21b06ec51a55a6reed@google.com    if (NULL == p) {
247672588b684d484dce6ae251e9e163e4a46924322reed@google.com        this->setPixelRef(NULL);
2488e1034e9ca0e3009f65125239e21b06ec51a55a6reed@google.com        return;
2498e1034e9ca0e3009f65125239e21b06ec51a55a6reed@google.com    }
2508e1034e9ca0e3009f65125239e21b06ec51a55a6reed@google.com
251466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    if (kUnknown_SkColorType == fInfo.colorType()) {
252672588b684d484dce6ae251e9e163e4a46924322reed@google.com        this->setPixelRef(NULL);
253bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        return;
254bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    }
255bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com
256466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    SkPixelRef* pr = SkMallocPixelRef::NewDirect(fInfo, p, fRowBytes, ctable);
257bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    if (NULL == pr) {
258672588b684d484dce6ae251e9e163e4a46924322reed@google.com        this->setPixelRef(NULL);
259bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        return;
260bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    }
261bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com
262bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    this->setPixelRef(pr)->unref();
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
264c84b8335ee4fd864c30a4703afc643cf4b5010d9djsollen@google.com    // since we're already allocated, we lockPixels right away
265c84b8335ee4fd864c30a4703afc643cf4b5010d9djsollen@google.com    this->lockPixels();
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
269848250415eddc54075f7eb8795e8db79e749c6abreedbool SkBitmap::tryAllocPixels(Allocator* allocator, SkColorTable* ctable) {
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    HeapAllocator stdalloc;
271d2ac07b64b7d46e81d00d389781f9f83810f0095skia.committer@gmail.com
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == allocator) {
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        allocator = &stdalloc;
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return allocator->allocPixelRef(this, ctable);
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2789ebcac54635cde63110d73ad7c43d70772e7872freed@google.com///////////////////////////////////////////////////////////////////////////////
2799ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
280848250415eddc54075f7eb8795e8db79e749c6abreedbool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) {
281bae704b050491a8a98c67cb23eaccb10852d2bd5reed    if (kIndex_8_SkColorType == requestedInfo.colorType()) {
282bae704b050491a8a98c67cb23eaccb10852d2bd5reed        return reset_return_false(this);
283bae704b050491a8a98c67cb23eaccb10852d2bd5reed    }
284f0aed97aec3fa1c7f6460d8d6327358f3dcbabe6reed    if (!this->setInfo(requestedInfo, rowBytes)) {
285bae704b050491a8a98c67cb23eaccb10852d2bd5reed        return reset_return_false(this);
286bae704b050491a8a98c67cb23eaccb10852d2bd5reed    }
287bae704b050491a8a98c67cb23eaccb10852d2bd5reed
288bae704b050491a8a98c67cb23eaccb10852d2bd5reed    // setInfo may have corrected info (e.g. 565 is always opaque).
289bae704b050491a8a98c67cb23eaccb10852d2bd5reed    const SkImageInfo& correctedInfo = this->info();
290f0aed97aec3fa1c7f6460d8d6327358f3dcbabe6reed    // setInfo may have computed a valid rowbytes if 0 were passed in
291f0aed97aec3fa1c7f6460d8d6327358f3dcbabe6reed    rowBytes = this->rowBytes();
292f0aed97aec3fa1c7f6460d8d6327358f3dcbabe6reed
293bae704b050491a8a98c67cb23eaccb10852d2bd5reed    SkMallocPixelRef::PRFactory defaultFactory;
294bae704b050491a8a98c67cb23eaccb10852d2bd5reed
295f0aed97aec3fa1c7f6460d8d6327358f3dcbabe6reed    SkPixelRef* pr = defaultFactory.create(correctedInfo, rowBytes, NULL);
296bae704b050491a8a98c67cb23eaccb10852d2bd5reed    if (NULL == pr) {
297bae704b050491a8a98c67cb23eaccb10852d2bd5reed        return reset_return_false(this);
298bae704b050491a8a98c67cb23eaccb10852d2bd5reed    }
299bae704b050491a8a98c67cb23eaccb10852d2bd5reed    this->setPixelRef(pr)->unref();
300bae704b050491a8a98c67cb23eaccb10852d2bd5reed
301bae704b050491a8a98c67cb23eaccb10852d2bd5reed    // TODO: lockPixels could/should return bool or void*/NULL
302bae704b050491a8a98c67cb23eaccb10852d2bd5reed    this->lockPixels();
303bae704b050491a8a98c67cb23eaccb10852d2bd5reed    if (NULL == this->getPixels()) {
304bae704b050491a8a98c67cb23eaccb10852d2bd5reed        return reset_return_false(this);
305bae704b050491a8a98c67cb23eaccb10852d2bd5reed    }
306bae704b050491a8a98c67cb23eaccb10852d2bd5reed    return true;
307bae704b050491a8a98c67cb23eaccb10852d2bd5reed}
308bae704b050491a8a98c67cb23eaccb10852d2bd5reed
309848250415eddc54075f7eb8795e8db79e749c6abreedbool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactory* factory,
310848250415eddc54075f7eb8795e8db79e749c6abreed                                SkColorTable* ctable) {
311e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    if (kIndex_8_SkColorType == requestedInfo.colorType() && NULL == ctable) {
3129ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return reset_return_false(this);
3139ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
3140187dc2155830c1ae3390d97463d5dd3971eca41scroggo    if (!this->setInfo(requestedInfo)) {
3159ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return reset_return_false(this);
3169ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
3179ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
3180187dc2155830c1ae3390d97463d5dd3971eca41scroggo    // setInfo may have corrected info (e.g. 565 is always opaque).
3190187dc2155830c1ae3390d97463d5dd3971eca41scroggo    const SkImageInfo& correctedInfo = this->info();
3200187dc2155830c1ae3390d97463d5dd3971eca41scroggo
3219ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    SkMallocPixelRef::PRFactory defaultFactory;
3229ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    if (NULL == factory) {
3239ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        factory = &defaultFactory;
3249ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
325d2ac07b64b7d46e81d00d389781f9f83810f0095skia.committer@gmail.com
326f0aed97aec3fa1c7f6460d8d6327358f3dcbabe6reed    SkPixelRef* pr = factory->create(correctedInfo, correctedInfo.minRowBytes(), ctable);
3279ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    if (NULL == pr) {
3289ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return reset_return_false(this);
3299ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
3309ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    this->setPixelRef(pr)->unref();
3319ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
3329ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    // TODO: lockPixels could/should return bool or void*/NULL
3339ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    this->lockPixels();
3349ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    if (NULL == this->getPixels()) {
3359ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return reset_return_false(this);
3369ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
3379ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    return true;
3389ebcac54635cde63110d73ad7c43d70772e7872freed@google.com}
3399ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
3400187dc2155830c1ae3390d97463d5dd3971eca41scroggobool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
3410187dc2155830c1ae3390d97463d5dd3971eca41scroggo                             SkColorTable* ct, void (*releaseProc)(void* addr, void* context),
3420187dc2155830c1ae3390d97463d5dd3971eca41scroggo                             void* context) {
3430187dc2155830c1ae3390d97463d5dd3971eca41scroggo    if (!this->setInfo(requestedInfo, rb)) {
3449ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        this->reset();
3459ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return false;
3469ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
3479ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
3480187dc2155830c1ae3390d97463d5dd3971eca41scroggo    // setInfo may have corrected info (e.g. 565 is always opaque).
3490187dc2155830c1ae3390d97463d5dd3971eca41scroggo    const SkImageInfo& correctedInfo = this->info();
3500187dc2155830c1ae3390d97463d5dd3971eca41scroggo
3510187dc2155830c1ae3390d97463d5dd3971eca41scroggo    SkPixelRef* pr = SkMallocPixelRef::NewWithProc(correctedInfo, rb, ct, pixels, releaseProc,
3520187dc2155830c1ae3390d97463d5dd3971eca41scroggo                                                   context);
3539ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    if (!pr) {
3549ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        this->reset();
3559ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return false;
3569ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
3579ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
3589ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    this->setPixelRef(pr)->unref();
3596e58cf36f0eba4b195726aa714d5487c91d06d04mike@reedtribe.org
3606e58cf36f0eba4b195726aa714d5487c91d06d04mike@reedtribe.org    // since we're already allocated, we lockPixels right away
3616e58cf36f0eba4b195726aa714d5487c91d06d04mike@reedtribe.org    this->lockPixels();
3626e58cf36f0eba4b195726aa714d5487c91d06d04mike@reedtribe.org    SkDEBUGCODE(this->validate();)
3639ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    return true;
3649ebcac54635cde63110d73ad7c43d70772e7872freed@google.com}
3659ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
366dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.orgbool SkBitmap::installMaskPixels(const SkMask& mask) {
367dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org    if (SkMask::kA8_Format != mask.fFormat) {
368dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org        this->reset();
369dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org        return false;
370dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org    }
371dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org    return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
372dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org                                                   mask.fBounds.height()),
373dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org                               mask.fImage, mask.fRowBytes);
374dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org}
375dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org
376eb9a46cbbb475e862a084aa2224ec18d4ac5e95breed@google.com///////////////////////////////////////////////////////////////////////////////
377eb9a46cbbb475e862a084aa2224ec18d4ac5e95breed@google.com
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::freePixels() {
37949f085dddff10473b6ebf832a974288300224e60bsalomon    if (fPixelRef) {
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fPixelLockCount > 0) {
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPixelRef->unlockPixels();
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelRef->unref();
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelRef = NULL;
385672588b684d484dce6ae251e9e163e4a46924322reed@google.com        fPixelRefOrigin.setZero();
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPixelLockCount = 0;
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPixels = NULL;
3895f62ed74342e44cb1b9671ffdac47c6a81416136reed@google.com    fColorTable = NULL;
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comuint32_t SkBitmap::getGenerationID() const {
393c84b8335ee4fd864c30a4703afc643cf4b5010d9djsollen@google.com    return (fPixelRef) ? fPixelRef->getGenerationID() : 0;
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::notifyPixelsChanged() const {
397b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org    SkASSERT(!this->isImmutable());
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fPixelRef) {
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelRef->notifyPixelsChanged();
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
403b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.orgGrTexture* SkBitmap::getTexture() const {
404ce4e53a2347040a3c145768c193a7a7958c0d4ecreed@android.com    return fPixelRef ? fPixelRef->getTexture() : NULL;
405ce4e53a2347040a3c145768c193a7a7958c0d4ecreed@android.com}
406ce4e53a2347040a3c145768c193a7a7958c0d4ecreed@android.com
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** We explicitly use the same allocator for our pixels that SkMask does,
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com so that we can freely assign memory allocated by one class to the other.
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            SkColorTable* ctable) {
414466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    const SkImageInfo info = dst->info();
415466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    if (kUnknown_SkColorType == info.colorType()) {
416bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com//        SkDebugf("unsupported config for info %d\n", dst->config());
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
41996f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com
420466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), ctable);
421bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    if (NULL == pr) {
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
424f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
425672588b684d484dce6ae251e9e163e4a46924322reed@google.com    dst->setPixelRef(pr)->unref();
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // since we're already allocated, we lockPixels right away
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dst->lockPixels();
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
433fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.combool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
4340ba4bf427acbd7707d04192a98c77ef194a0f25ascroggo@google.com                            size_t dstRowBytes, bool preserveDstPad) const {
43586bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
4360ba4bf427acbd7707d04192a98c77ef194a0f25ascroggo@google.com    if (0 == dstRowBytes) {
43786bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        dstRowBytes = fRowBytes;
4380ba4bf427acbd7707d04192a98c77ef194a0f25ascroggo@google.com    }
43986bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
44061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if (dstRowBytes < fInfo.minRowBytes() ||
44161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) {
44286bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        return false;
44361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    }
44486bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
445c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) {
4464469938e92d779dff05e745559e67907bbf21e78reed@google.com        size_t safeSize = this->getSafeSize();
44786bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        if (safeSize > dstSize || safeSize == 0)
44886bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            return false;
44986bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        else {
45086bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            SkAutoLockPixels lock(*this);
45186bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            // This implementation will write bytes beyond the end of each row,
45286bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            // excluding the last row, if the bitmap's stride is greater than
45386bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            // strictly required by the current config.
45486bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            memcpy(dst, getPixels(), safeSize);
45586bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
45686bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            return true;
45786bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        }
45886bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org    } else {
45986bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        // If destination has different stride than us, then copy line by line.
46061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        if (fInfo.getSafeSize(dstRowBytes) > dstSize) {
46186bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            return false;
46261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        } else {
46386bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            // Just copy what we need on each line.
46461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            size_t rowBytes = fInfo.minRowBytes();
46586bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            SkAutoLockPixels lock(*this);
46686bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels());
46786bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
468e5ea500d4714a7d84de2bf913e81be3b65d2de68reed            for (int row = 0; row < fInfo.height(); row++, srcP += fRowBytes, dstP += dstRowBytes) {
46986bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org                memcpy(dstP, srcP, rowBytes);
47086bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            }
47186bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
47286bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            return true;
47386bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        }
47486bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org    }
47586bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org}
47686bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
47786bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org///////////////////////////////////////////////////////////////////////////////
47886bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
479fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.combool SkBitmap::isImmutable() const {
4800847059fcffe11d53d4ea803ba2d51c696eb6d07scroggo    return fPixelRef ? fPixelRef->isImmutable() : false;
481b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org}
482b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org
483b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.orgvoid SkBitmap::setImmutable() {
484b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org    if (fPixelRef) {
485b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org        fPixelRef->setImmutable();
486b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org    }
487b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org}
488b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org
4894ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.combool SkBitmap::isVolatile() const {
4904ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com    return (fFlags & kImageIsVolatile_Flag) != 0;
4914ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com}
4924ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com
4934ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.comvoid SkBitmap::setIsVolatile(bool isVolatile) {
4944ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com    if (isVolatile) {
4954ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com        fFlags |= kImageIsVolatile_Flag;
4964ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com    } else {
4974ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com        fFlags &= ~kImageIsVolatile_Flag;
4984ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com    }
4994ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com}
5004ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid* SkBitmap::getAddr(int x, int y) const {
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)x < (unsigned)this->width());
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)y < (unsigned)this->height());
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char* base = (char*)this->getPixels();
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (base) {
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        base += y * this->rowBytes();
50861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        switch (this->colorType()) {
50961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kRGBA_8888_SkColorType:
51061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kBGRA_8888_SkColorType:
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                base += x << 2;
5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
51361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kARGB_4444_SkColorType:
51461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kRGB_565_SkColorType:
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                base += x << 1;
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
51761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kAlpha_8_SkColorType:
51861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kIndex_8_SkColorType:
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                base += x;
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            default:
5220c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com                SkDEBUGFAIL("Can't return addr for config");
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                base = NULL;
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return base;
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
530112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.orgSkColor SkBitmap::getColor(int x, int y) const {
531112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org    SkASSERT((unsigned)x < (unsigned)this->width());
532112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org    SkASSERT((unsigned)y < (unsigned)this->height());
533112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org
534cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    switch (this->colorType()) {
535cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kAlpha_8_SkColorType: {
5363b521d05335a1bf76be3456feb9dbfba0a51b339reed@google.com            uint8_t* addr = this->getAddr8(x, y);
537112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return SkColorSetA(0, addr[0]);
538112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org        }
539cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kIndex_8_SkColorType: {
5403b521d05335a1bf76be3456feb9dbfba0a51b339reed@google.com            SkPMColor c = this->getIndex8Color(x, y);
541112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return SkUnPreMultiply::PMColorToColor(c);
542112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org        }
543cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kRGB_565_SkColorType: {
5443b521d05335a1bf76be3456feb9dbfba0a51b339reed@google.com            uint16_t* addr = this->getAddr16(x, y);
545112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return SkPixel16ToColor(addr[0]);
546112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org        }
547cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kARGB_4444_SkColorType: {
5483b521d05335a1bf76be3456feb9dbfba0a51b339reed@google.com            uint16_t* addr = this->getAddr16(x, y);
549112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            SkPMColor c = SkPixel4444ToPixel32(addr[0]);
550112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return SkUnPreMultiply::PMColorToColor(c);
551112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org        }
552cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kBGRA_8888_SkColorType:
553cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kRGBA_8888_SkColorType: {
5543b521d05335a1bf76be3456feb9dbfba0a51b339reed@google.com            uint32_t* addr = this->getAddr32(x, y);
555112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return SkUnPreMultiply::PMColorToColor(addr[0]);
556112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org        }
557d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        default:
558112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            SkASSERT(false);
559112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return 0;
560112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org    }
561112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org    SkASSERT(false);  // Not reached.
562112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org    return 0;
563112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org}
564112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org
5652a7579d11796866b0026755ab52597d09f4509ccreed@google.combool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
5662a7579d11796866b0026755ab52597d09f4509ccreed@google.com    SkAutoLockPixels alp(bm);
5672a7579d11796866b0026755ab52597d09f4509ccreed@google.com    if (!bm.getPixels()) {
5682a7579d11796866b0026755ab52597d09f4509ccreed@google.com        return false;
5692a7579d11796866b0026755ab52597d09f4509ccreed@google.com    }
5702a7579d11796866b0026755ab52597d09f4509ccreed@google.com
5712a7579d11796866b0026755ab52597d09f4509ccreed@google.com    const int height = bm.height();
5722a7579d11796866b0026755ab52597d09f4509ccreed@google.com    const int width = bm.width();
5732a7579d11796866b0026755ab52597d09f4509ccreed@google.com
574cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    switch (bm.colorType()) {
575cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kAlpha_8_SkColorType: {
5762a7579d11796866b0026755ab52597d09f4509ccreed@google.com            unsigned a = 0xFF;
5772a7579d11796866b0026755ab52597d09f4509ccreed@google.com            for (int y = 0; y < height; ++y) {
5782a7579d11796866b0026755ab52597d09f4509ccreed@google.com                const uint8_t* row = bm.getAddr8(0, y);
5792a7579d11796866b0026755ab52597d09f4509ccreed@google.com                for (int x = 0; x < width; ++x) {
5802a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    a &= row[x];
5812a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
5822a7579d11796866b0026755ab52597d09f4509ccreed@google.com                if (0xFF != a) {
5832a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    return false;
5842a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
5852a7579d11796866b0026755ab52597d09f4509ccreed@google.com            }
5862a7579d11796866b0026755ab52597d09f4509ccreed@google.com            return true;
5872a7579d11796866b0026755ab52597d09f4509ccreed@google.com        } break;
588cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kIndex_8_SkColorType: {
5892a7579d11796866b0026755ab52597d09f4509ccreed@google.com            SkAutoLockColors alc(bm);
5902a7579d11796866b0026755ab52597d09f4509ccreed@google.com            const SkPMColor* table = alc.colors();
5912a7579d11796866b0026755ab52597d09f4509ccreed@google.com            if (!table) {
5922a7579d11796866b0026755ab52597d09f4509ccreed@google.com                return false;
5932a7579d11796866b0026755ab52597d09f4509ccreed@google.com            }
594140d7286c5a40058932696eaa28818c313bd2ddfreed@google.com            SkPMColor c = (SkPMColor)~0;
5952a7579d11796866b0026755ab52597d09f4509ccreed@google.com            for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) {
5962a7579d11796866b0026755ab52597d09f4509ccreed@google.com                c &= table[i];
5972a7579d11796866b0026755ab52597d09f4509ccreed@google.com            }
5982a7579d11796866b0026755ab52597d09f4509ccreed@google.com            return 0xFF == SkGetPackedA32(c);
5992a7579d11796866b0026755ab52597d09f4509ccreed@google.com        } break;
600cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kRGB_565_SkColorType:
6012a7579d11796866b0026755ab52597d09f4509ccreed@google.com            return true;
6022a7579d11796866b0026755ab52597d09f4509ccreed@google.com            break;
603cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kARGB_4444_SkColorType: {
6042a7579d11796866b0026755ab52597d09f4509ccreed@google.com            unsigned c = 0xFFFF;
6052a7579d11796866b0026755ab52597d09f4509ccreed@google.com            for (int y = 0; y < height; ++y) {
6062a7579d11796866b0026755ab52597d09f4509ccreed@google.com                const SkPMColor16* row = bm.getAddr16(0, y);
6072a7579d11796866b0026755ab52597d09f4509ccreed@google.com                for (int x = 0; x < width; ++x) {
6082a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    c &= row[x];
6092a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
6102a7579d11796866b0026755ab52597d09f4509ccreed@google.com                if (0xF != SkGetPackedA4444(c)) {
6112a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    return false;
6122a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
6132a7579d11796866b0026755ab52597d09f4509ccreed@google.com            }
6142a7579d11796866b0026755ab52597d09f4509ccreed@google.com            return true;
6152a7579d11796866b0026755ab52597d09f4509ccreed@google.com        } break;
616cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kBGRA_8888_SkColorType:
617cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kRGBA_8888_SkColorType: {
618140d7286c5a40058932696eaa28818c313bd2ddfreed@google.com            SkPMColor c = (SkPMColor)~0;
6192a7579d11796866b0026755ab52597d09f4509ccreed@google.com            for (int y = 0; y < height; ++y) {
6202a7579d11796866b0026755ab52597d09f4509ccreed@google.com                const SkPMColor* row = bm.getAddr32(0, y);
6212a7579d11796866b0026755ab52597d09f4509ccreed@google.com                for (int x = 0; x < width; ++x) {
6222a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    c &= row[x];
6232a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
6242a7579d11796866b0026755ab52597d09f4509ccreed@google.com                if (0xFF != SkGetPackedA32(c)) {
6252a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    return false;
6262a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
6272a7579d11796866b0026755ab52597d09f4509ccreed@google.com            }
6282a7579d11796866b0026755ab52597d09f4509ccreed@google.com            return true;
6292a7579d11796866b0026755ab52597d09f4509ccreed@google.com        }
6302a7579d11796866b0026755ab52597d09f4509ccreed@google.com        default:
6312a7579d11796866b0026755ab52597d09f4509ccreed@google.com            break;
6322a7579d11796866b0026755ab52597d09f4509ccreed@google.com    }
6332a7579d11796866b0026755ab52597d09f4509ccreed@google.com    return false;
6342a7579d11796866b0026755ab52597d09f4509ccreed@google.com}
6352a7579d11796866b0026755ab52597d09f4509ccreed@google.com
6362a7579d11796866b0026755ab52597d09f4509ccreed@google.com
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
64045f746f521d6925d22a304921f6e17196f4f8157reed@google.comstatic uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) {
64145f746f521d6925d22a304921f6e17196f4f8157reed@google.com    unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) |
64245f746f521d6925d22a304921f6e17196f4f8157reed@google.com                     (SkR32To4444(r) << SK_R4444_SHIFT) |
64345f746f521d6925d22a304921f6e17196f4f8157reed@google.com                     (SkG32To4444(g) << SK_G4444_SHIFT) |
64445f746f521d6925d22a304921f6e17196f4f8157reed@google.com                     (SkB32To4444(b) << SK_B4444_SHIFT);
64545f746f521d6925d22a304921f6e17196f4f8157reed@google.com    return SkToU16(pixel);
64645f746f521d6925d22a304921f6e17196f4f8157reed@google.com}
64745f746f521d6925d22a304921f6e17196f4f8157reed@google.com
64860d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.comvoid SkBitmap::internalErase(const SkIRect& area,
64960d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com                             U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
65060d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com#ifdef SK_DEBUG
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
65260d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    SkASSERT(!area.isEmpty());
65360d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    {
65492833f99b99f1f955c350f6f4f70acd3356a79a5reed@google.com        SkIRect total = { 0, 0, this->width(), this->height() };
65560d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com        SkASSERT(total.contains(area));
65660d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    }
65760d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com#endif
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    switch (fInfo.colorType()) {
66061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kUnknown_SkColorType:
66161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kIndex_8_SkColorType:
6627669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            return; // can't erase. Should we bzero so the memory is not uninitialized?
66361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        default:
66461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            break;
6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoLockPixels alp(*this);
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // perform this check after the lock call
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!this->readyToDraw()) {
6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
67360d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    int height = area.height();
67460d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    const int width = area.width();
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const int rowBytes = fRowBytes;
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
67761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    switch (this->colorType()) {
67861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kAlpha_8_SkColorType: {
67960d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com            uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (--height >= 0) {
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memset(p, a, width);
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                p += rowBytes;
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
68661e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kARGB_4444_SkColorType:
68761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kRGB_565_SkColorType: {
68860d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com            uint16_t* p = this->getAddr16(area.fLeft, area.fTop);;
68945f746f521d6925d22a304921f6e17196f4f8157reed@google.com            uint16_t v;
690020b25becb4a99061e8643780c887ad472eb0648skia.committer@gmail.com
6917669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            // make rgb premultiplied
6927669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            if (255 != a) {
6937669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                r = SkAlphaMul(r, a);
6947669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                g = SkAlphaMul(g, a);
6957669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                b = SkAlphaMul(b, a);
6967669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            }
6977669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org
69861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            if (kARGB_4444_SkColorType == this->colorType()) {
69945f746f521d6925d22a304921f6e17196f4f8157reed@google.com                v = pack_8888_to_4444(a, r, g, b);
70045f746f521d6925d22a304921f6e17196f4f8157reed@google.com            } else {
70145f746f521d6925d22a304921f6e17196f4f8157reed@google.com                v = SkPackRGB16(r >> (8 - SK_R16_BITS),
70245f746f521d6925d22a304921f6e17196f4f8157reed@google.com                                g >> (8 - SK_G16_BITS),
70345f746f521d6925d22a304921f6e17196f4f8157reed@google.com                                b >> (8 - SK_B16_BITS));
70445f746f521d6925d22a304921f6e17196f4f8157reed@google.com            }
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (--height >= 0) {
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_memset16(p, v, width);
7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                p = (uint16_t*)((char*)p + rowBytes);
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7117669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org        case kBGRA_8888_SkColorType:
7127669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org        case kRGBA_8888_SkColorType: {
71360d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com            uint32_t* p = this->getAddr32(area.fLeft, area.fTop);
7147669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org
7157669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            if (255 != a && kPremul_SkAlphaType == this->alphaType()) {
7167669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                r = SkAlphaMul(r, a);
7177669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                g = SkAlphaMul(g, a);
7187669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                b = SkAlphaMul(b, a);
7197669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            }
7207669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            uint32_t v = kRGBA_8888_SkColorType == this->colorType() ?
7217669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                         SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b);
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (--height >= 0) {
7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_memset32(p, v, width);
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                p = (uint32_t*)((char*)p + rowBytes);
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
72961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        default:
73061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            return; // no change, so don't call notifyPixelsChanged()
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
732f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->notifyPixelsChanged();
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
73660d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.comvoid SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
73792833f99b99f1f955c350f6f4f70acd3356a79a5reed@google.com    SkIRect area = { 0, 0, this->width(), this->height() };
73860d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    if (!area.isEmpty()) {
73960d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com        this->internalErase(area, a, r, g, b);
74060d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    }
74160d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com}
74260d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com
74360d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.comvoid SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const {
74492833f99b99f1f955c350f6f4f70acd3356a79a5reed@google.com    SkIRect area = { 0, 0, this->width(), this->height() };
74560d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    if (area.intersect(rect)) {
74660d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com        this->internalErase(area, SkColorGetA(c), SkColorGetR(c),
74760d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com                            SkColorGetG(c), SkColorGetB(c));
74860d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    }
74960d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com}
75060d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
757c84b8335ee4fd864c30a4703afc643cf4b5010d9djsollen@google.com    if (NULL == result || NULL == fPixelRef) {
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;   // no src pixels
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect srcRect, r;
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcRect.set(0, 0, this->width(), this->height());
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!r.intersect(srcRect, subset)) {
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;   // r is empty (i.e. no intersection)
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
767a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    if (fPixelRef->getTexture() != NULL) {
768a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        // Do a deep copy
769e4538f5b46d70798e34eb078f5d5e76a59d02318reed        SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), &subset);
770a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        if (pixelRef != NULL) {
771a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            SkBitmap dst;
772a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org            dst.setInfo(SkImageInfo::Make(subset.width(), subset.height(),
773a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org                                          this->colorType(), this->alphaType()));
774a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            dst.setIsVolatile(this->isVolatile());
775a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            dst.setPixelRef(pixelRef)->unref();
776a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            SkDEBUGCODE(dst.validate());
777a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            result->swap(dst);
778a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            return true;
779a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        }
780a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    }
781a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com
782a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
783a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    // exited above.
784a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
785a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
786a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBitmap dst;
788a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    dst.setInfo(SkImageInfo::Make(r.width(), r.height(), this->colorType(), this->alphaType()),
789a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org                this->rowBytes());
7900eb7576c659a165f1d73b6b7ddfd43dc3782f62bskyostil@google.com    dst.setIsVolatile(this->isVolatile());
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fPixelRef) {
793672588b684d484dce6ae251e9e163e4a46924322reed@google.com        SkIPoint origin = fPixelRefOrigin;
794672588b684d484dce6ae251e9e163e4a46924322reed@google.com        origin.fX += r.fLeft;
795672588b684d484dce6ae251e9e163e4a46924322reed@google.com        origin.fY += r.fTop;
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // share the pixelref with a custom offset
797672588b684d484dce6ae251e9e163e4a46924322reed@google.com        dst.setPixelRef(fPixelRef, origin);
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(dst.validate();)
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // we know we're good, so commit to result
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result->swap(dst);
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8118a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.orgbool SkBitmap::canCopyTo(SkColorType dstColorType) const {
812b184f7f52b2a94e95aee326a3ca37110d2e43336reed    const SkColorType srcCT = this->colorType();
813b184f7f52b2a94e95aee326a3ca37110d2e43336reed
814b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (srcCT == kUnknown_SkColorType) {
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
818b184f7f52b2a94e95aee326a3ca37110d2e43336reed    bool sameConfigs = (srcCT == dstColorType);
8198a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    switch (dstColorType) {
8208a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        case kAlpha_8_SkColorType:
8218a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        case kRGB_565_SkColorType:
82260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kRGBA_8888_SkColorType:
82360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kBGRA_8888_SkColorType:
8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
8258a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        case kIndex_8_SkColorType:
826f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com            if (!sameConfigs) {
827f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com                return false;
828f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com            }
829f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com            break;
8308a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        case kARGB_4444_SkColorType:
831b184f7f52b2a94e95aee326a3ca37110d2e43336reed            return sameConfigs || kN32_SkColorType == srcCT || kIndex_8_SkColorType == srcCT;
8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return false;
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
835fbaa88d9695347299321cbce2bf803726999fb58reed@android.com    return true;
836fbaa88d9695347299321cbce2bf803726999fb58reed@android.com}
837fbaa88d9695347299321cbce2bf803726999fb58reed@android.com
838b184f7f52b2a94e95aee326a3ca37110d2e43336reed#include "SkConfig8888.h"
839b184f7f52b2a94e95aee326a3ca37110d2e43336reed
840b184f7f52b2a94e95aee326a3ca37110d2e43336reedbool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
841b184f7f52b2a94e95aee326a3ca37110d2e43336reed                          int x, int y) const {
842b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (kUnknown_SkColorType == requestedDstInfo.colorType()) {
843b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return false;
844b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
845b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (NULL == dstPixels || dstRB < requestedDstInfo.minRowBytes()) {
846b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return false;
847b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
848b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (0 == requestedDstInfo.width() || 0 == requestedDstInfo.height()) {
849b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return false;
850b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
851b184f7f52b2a94e95aee326a3ca37110d2e43336reed
852b184f7f52b2a94e95aee326a3ca37110d2e43336reed    SkIRect srcR = SkIRect::MakeXYWH(x, y, requestedDstInfo.width(), requestedDstInfo.height());
853b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (!srcR.intersect(0, 0, this->width(), this->height())) {
854b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return false;
855b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
856b184f7f52b2a94e95aee326a3ca37110d2e43336reed
857b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // the intersect may have shrunk info's logical size
858e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo dstInfo = requestedDstInfo.makeWH(srcR.width(), srcR.height());
859b184f7f52b2a94e95aee326a3ca37110d2e43336reed
860b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // if x or y are negative, then we have to adjust pixels
861b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (x > 0) {
862b184f7f52b2a94e95aee326a3ca37110d2e43336reed        x = 0;
863b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
864b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (y > 0) {
865b184f7f52b2a94e95aee326a3ca37110d2e43336reed        y = 0;
866b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
867b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // here x,y are either 0 or negative
868b184f7f52b2a94e95aee326a3ca37110d2e43336reed    dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel());
869b184f7f52b2a94e95aee326a3ca37110d2e43336reed
870b184f7f52b2a94e95aee326a3ca37110d2e43336reed    //////////////
871b184f7f52b2a94e95aee326a3ca37110d2e43336reed
872b184f7f52b2a94e95aee326a3ca37110d2e43336reed    SkAutoLockPixels alp(*this);
873b184f7f52b2a94e95aee326a3ca37110d2e43336reed
874b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // since we don't stop creating un-pixeled devices yet, check for no pixels here
875b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (NULL == this->getPixels()) {
876b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return false;
877b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
878b184f7f52b2a94e95aee326a3ca37110d2e43336reed
879e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo srcInfo = this->info().makeWH(dstInfo.width(), dstInfo.height());
880b184f7f52b2a94e95aee326a3ca37110d2e43336reed
881b184f7f52b2a94e95aee326a3ca37110d2e43336reed    const void* srcPixels = this->getAddr(srcR.x(), srcR.y());
882b184f7f52b2a94e95aee326a3ca37110d2e43336reed    return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, this->rowBytes(),
883b184f7f52b2a94e95aee326a3ca37110d2e43336reed                                   this->getColorTable());
884b184f7f52b2a94e95aee326a3ca37110d2e43336reed}
885b184f7f52b2a94e95aee326a3ca37110d2e43336reed
886b184f7f52b2a94e95aee326a3ca37110d2e43336reedbool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc) const {
8878a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    if (!this->canCopyTo(dstColorType)) {
888fbaa88d9695347299321cbce2bf803726999fb58reed@android.com        return false;
889fbaa88d9695347299321cbce2bf803726999fb58reed@android.com    }
890fbaa88d9695347299321cbce2bf803726999fb58reed@android.com
89150dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    // if we have a texture, first get those pixels
89250dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    SkBitmap tmpSrc;
89350dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    const SkBitmap* src = this;
89450dfa0130b0705414df7ba7da9915139f6320b09reed@google.com
895a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    if (fPixelRef) {
896a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        SkIRect subset;
89761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
89861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                       fInfo.width(), fInfo.height());
899672588b684d484dce6ae251e9e163e4a46924322reed@google.com        if (fPixelRef->readPixels(&tmpSrc, &subset)) {
9000187dc2155830c1ae3390d97463d5dd3971eca41scroggo            if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) {
9010187dc2155830c1ae3390d97463d5dd3971eca41scroggo                // FIXME: The only meaningful implementation of readPixels
9020187dc2155830c1ae3390d97463d5dd3971eca41scroggo                // (GrPixelRef) assumes premultiplied pixels.
9030187dc2155830c1ae3390d97463d5dd3971eca41scroggo                return false;
9040187dc2155830c1ae3390d97463d5dd3971eca41scroggo            }
905672588b684d484dce6ae251e9e163e4a46924322reed@google.com            SkASSERT(tmpSrc.width() == this->width());
906672588b684d484dce6ae251e9e163e4a46924322reed@google.com            SkASSERT(tmpSrc.height() == this->height());
907672588b684d484dce6ae251e9e163e4a46924322reed@google.com
908672588b684d484dce6ae251e9e163e4a46924322reed@google.com            // did we get lucky and we can just return tmpSrc?
9098a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org            if (tmpSrc.colorType() == dstColorType && NULL == alloc) {
910672588b684d484dce6ae251e9e163e4a46924322reed@google.com                dst->swap(tmpSrc);
9115ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com                // If the result is an exact copy, clone the gen ID.
9125ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com                if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) {
913672588b684d484dce6ae251e9e163e4a46924322reed@google.com                    dst->pixelRef()->cloneGenID(*fPixelRef);
914a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com                }
915672588b684d484dce6ae251e9e163e4a46924322reed@google.com                return true;
916d5764e8ab731dd12df9293e52ce644eaa45333bdscroggo@google.com            }
917672588b684d484dce6ae251e9e163e4a46924322reed@google.com
918672588b684d484dce6ae251e9e163e4a46924322reed@google.com            // fall through to the raster case
919672588b684d484dce6ae251e9e163e4a46924322reed@google.com            src = &tmpSrc;
92050dfa0130b0705414df7ba7da9915139f6320b09reed@google.com        }
92150dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    }
92250dfa0130b0705414df7ba7da9915139f6320b09reed@google.com
923311c82db3115fc6810855cbcc42a6bc6fbd48265reed@android.com    // we lock this now, since we may need its colortable
92450dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    SkAutoLockPixels srclock(*src);
92550dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    if (!src->readyToDraw()) {
926fbaa88d9695347299321cbce2bf803726999fb58reed@android.com        return false;
927fbaa88d9695347299321cbce2bf803726999fb58reed@android.com    }
928fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9295ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com    // The only way to be readyToDraw is if fPixelRef is non NULL.
9305ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com    SkASSERT(fPixelRef != NULL);
9315ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com
932e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    const SkImageInfo dstInfo = src->info().makeColorType(dstColorType);
9338a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org
93450dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    SkBitmap tmpDst;
935a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    if (!tmpDst.setInfo(dstInfo)) {
9368a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        return false;
9378a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    }
938fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
939f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com    // allocate colortable if srcConfig == kIndex8_Config
9408a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    SkAutoTUnref<SkColorTable> ctable;
9418a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    if (dstColorType == kIndex_8_SkColorType) {
9428a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        // TODO: can we just ref() the src colortable? Is it reentrant-safe?
9438a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        ctable.reset(SkNEW_ARGS(SkColorTable, (*src->getColorTable())));
9448a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    }
945848250415eddc54075f7eb8795e8db79e749c6abreed    if (!tmpDst.tryAllocPixels(alloc, ctable)) {
9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
948fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
94950dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    if (!tmpDst.readyToDraw()) {
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // allocator/lock failed
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
953fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9545ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com    // pixelRef must be non NULL or tmpDst.readyToDraw() would have
9555ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com    // returned false.
9565ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com    SkASSERT(tmpDst.pixelRef() != NULL);
9575ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com
958b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (!src->readPixels(tmpDst.info(), tmpDst.getPixels(), tmpDst.rowBytes(), 0, 0)) {
959b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return false;
960b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
9610187dc2155830c1ae3390d97463d5dd3971eca41scroggo
962b184f7f52b2a94e95aee326a3ca37110d2e43336reed    //  (for BitmapHeap) Clone the pixelref genID even though we have a new pixelref.
963b184f7f52b2a94e95aee326a3ca37110d2e43336reed    //  The old copyTo impl did this, so we continue it for now.
964b184f7f52b2a94e95aee326a3ca37110d2e43336reed    //
965b184f7f52b2a94e95aee326a3ca37110d2e43336reed    //  TODO: should we ignore rowbytes (i.e. getSize)? Then it could just be
966b184f7f52b2a94e95aee326a3ca37110d2e43336reed    //      if (src_pixelref->info == dst_pixelref->info)
967b184f7f52b2a94e95aee326a3ca37110d2e43336reed    //
968b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (src->colorType() == dstColorType && tmpDst.getSize() == src->getSize()) {
969b184f7f52b2a94e95aee326a3ca37110d2e43336reed        SkPixelRef* dstPixelRef = tmpDst.pixelRef();
970b184f7f52b2a94e95aee326a3ca37110d2e43336reed        if (dstPixelRef->info() == fPixelRef->info()) {
971b184f7f52b2a94e95aee326a3ca37110d2e43336reed            dstPixelRef->cloneGenID(*fPixelRef);
972311c82db3115fc6810855cbcc42a6bc6fbd48265reed@android.com        }
9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
97550dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    dst->swap(tmpDst);
9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
979fab349c0bf3a305b7a7388b77bab13b0f7b37393commit-bot@chromium.orgbool SkBitmap::deepCopyTo(SkBitmap* dst) const {
980e4538f5b46d70798e34eb078f5d5e76a59d02318reed    const SkColorType dstCT = this->colorType();
98161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org
9828a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    if (!this->canCopyTo(dstCT)) {
983ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return false;
984ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
985ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
986ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    // If we have a PixelRef, and it supports deep copy, use it.
987ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    // Currently supported only by texture-backed bitmaps.
988ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (fPixelRef) {
989e4538f5b46d70798e34eb078f5d5e76a59d02318reed        SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, NULL);
990eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org        if (pixelRef) {
991eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            uint32_t rowBytes;
992eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            if (this->colorType() == dstCT) {
993eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                // Since there is no subset to pass to deepCopy, and deepCopy
994eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                // succeeded, the new pixel ref must be identical.
995eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                SkASSERT(fPixelRef->info() == pixelRef->info());
996eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                pixelRef->cloneGenID(*fPixelRef);
997eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                // Use the same rowBytes as the original.
998eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                rowBytes = fRowBytes;
999eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            } else {
1000a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org                // With the new config, an appropriate fRowBytes will be computed by setInfo.
1001eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                rowBytes = 0;
1002eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            }
1003eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org
1004e5ea500d4714a7d84de2bf913e81be3b65d2de68reed            const SkImageInfo info = fInfo.makeColorType(dstCT);
1005a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org            if (!dst->setInfo(info, rowBytes)) {
100661e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                return false;
100761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            }
1008eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref();
1009ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org            return true;
1010ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        }
1011ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1012ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
1013ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (this->getTexture()) {
1014ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return false;
1015ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    } else {
10168a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        return this->copyTo(dst, dstCT, NULL);
1017ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1018ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org}
1019ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1022a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comstatic bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           int alphaRowBytes) {
10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(alpha != NULL);
10258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(alphaRowBytes >= src.width());
10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1027cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    SkColorType colorType = src.colorType();
1028cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    int         w = src.width();
1029cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    int         h = src.height();
1030cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    size_t      rb = src.rowBytes();
10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10321cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    SkAutoLockPixels alp(src);
10331cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    if (!src.readyToDraw()) {
10341cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        // zero out the alpha buffer and return
10351cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        while (--h >= 0) {
10361cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com            memset(alpha, 0, w);
10371cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com            alpha += alphaRowBytes;
10381cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        }
10391cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        return false;
10401cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    }
104182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1042cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    if (kAlpha_8_SkColorType == colorType && !src.isOpaque()) {
10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t* s = src.getAddr8(0, 0);
10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--h >= 0) {
10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(alpha, s, w);
10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            s += rb;
10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += alphaRowBytes;
10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1049cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    } else if (kN32_SkColorType == colorType && !src.isOpaque()) {
10508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--h >= 0) {
10528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (int x = 0; x < w; x++) {
10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                alpha[x] = SkGetPackedA32(s[x]);
10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            s = (const SkPMColor*)((const char*)s + rb);
10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += alphaRowBytes;
10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1058cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    } else if (kARGB_4444_SkColorType == colorType && !src.isOpaque()) {
10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--h >= 0) {
10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (int x = 0; x < w; x++) {
10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                alpha[x] = SkPacked4444ToA32(s[x]);
10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            s = (const SkPMColor16*)((const char*)s + rb);
10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += alphaRowBytes;
10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1067cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    } else if (kIndex_8_SkColorType == colorType && !src.isOpaque()) {
10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkColorTable* ct = src.getColorTable();
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (ct) {
10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const SkPMColor* SK_RESTRICT table = ct->lockColors();
10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (--h >= 0) {
10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                for (int x = 0; x < w; x++) {
10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    alpha[x] = SkGetPackedA32(table[s[x]]);
10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                s += rb;
10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                alpha += alphaRowBytes;
10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10790a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com            ct->unlockColors();
10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // src is opaque, so just fill alpha[] with 0xFF
10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memset(alpha, 0xFF, h * alphaRowBytes);
10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10841cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    return true;
10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMatrix.h"
10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1091cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.combool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
109257f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com                            Allocator *allocator, SkIPoint* offset) const {
10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1095cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    SkBitmap    tmpBitmap;
10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    identity;
10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMask      srcM, dstM;
10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcM.fBounds.set(0, 0, this->width(), this->height());
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcM.fRowBytes = SkAlign4(this->width());
11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcM.fFormat = SkMask::kA8_Format;
11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL;
11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // compute our (larger?) dst bounds if we have a filter
110649f085dddff10473b6ebf832a974288300224e60bsalomon    if (filter) {
11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        identity.reset();
11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        srcM.fImage = NULL;
11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            goto NO_FILTER_CASE;
11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NO_FILTER_CASE:
1115a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
1116848250415eddc54075f7eb8795e8db79e749c6abreed        if (!tmpBitmap.tryAllocPixels(allocator, NULL)) {
1117cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com            // Allocation of pixels for alpha bitmap failed.
1118cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com            SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1119cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com                    tmpBitmap.width(), tmpBitmap.height());
1120cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com            return false;
1121cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        }
1122cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (offset) {
11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            offset->set(0, 0);
11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1126cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        tmpBitmap.swap(*dst);
1127cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        return true;
11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
112902f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com    srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
113002f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com    SkAutoMaskFreeImage srcCleanup(srcM.fImage);
11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        goto NO_FILTER_CASE;
11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
113602f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com    SkAutoMaskFreeImage dstCleanup(dstM.fImage);
11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1138a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
1139a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org                      dstM.fRowBytes);
1140848250415eddc54075f7eb8795e8db79e749c6abreed    if (!tmpBitmap.tryAllocPixels(allocator, NULL)) {
1141cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        // Allocation of pixels for alpha bitmap failed.
1142cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1143cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com                tmpBitmap.width(), tmpBitmap.height());
1144cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        return false;
1145cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    }
1146cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (offset) {
11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1150cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    SkDEBUGCODE(tmpBitmap.validate();)
1151cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com
1152cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    tmpBitmap.swap(*dst);
1153cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    return true;
11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1158968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.orgvoid SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
1159968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const SkImageInfo info = bitmap.info();
1160968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkAutoLockPixels alp(bitmap);
1161968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    if (0 == info.width() || 0 == info.height() || NULL == bitmap.getPixels()) {
1162968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        buffer->writeUInt(0); // instead of snugRB, signaling no pixels
1163968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        return;
1164968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
1165968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1166968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t snugRB = info.width() * info.bytesPerPixel();
1167968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const char* src = (const char*)bitmap.getPixels();
1168968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t ramRB = bitmap.rowBytes();
11693c134a97ed128ca95345e13619512df0f42e95f8skia.committer@gmail.com
1170968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    buffer->write32(SkToU32(snugRB));
1171968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    info.flatten(*buffer);
1172968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1173968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t size = snugRB * info.height();
1174968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkAutoMalloc storage(size);
1175968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    char* dst = (char*)storage.get();
1176968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    for (int y = 0; y < info.height(); ++y) {
1177968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        memcpy(dst, src, snugRB);
1178968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        dst += snugRB;
1179968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        src += ramRB;
1180968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
1181968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    buffer->writeByteArray(storage.get(), size);
1182968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1183968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkColorTable* ct = bitmap.getColorTable();
1184968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    if (kIndex_8_SkColorType == info.colorType() && ct) {
1185968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        buffer->writeBool(true);
1186968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        ct->writeToBuffer(*buffer);
1187968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    } else {
1188968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        buffer->writeBool(false);
1189968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
1190968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org}
1191968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1192968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.orgbool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
1193968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t snugRB = buffer->readUInt();
1194968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    if (0 == snugRB) {  // no pixels
1195968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        return false;
1196968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
1197968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1198968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkImageInfo info;
1199968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    info.unflatten(*buffer);
1200968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1201ca95c19d27b505a1ac8f57b53cb49c198bc29267sugoi    // If there was an error reading "info", don't use it to compute minRowBytes()
1202ca95c19d27b505a1ac8f57b53cb49c198bc29267sugoi    if (!buffer->validate(true)) {
1203ca95c19d27b505a1ac8f57b53cb49c198bc29267sugoi        return false;
1204ca95c19d27b505a1ac8f57b53cb49c198bc29267sugoi    }
1205ca95c19d27b505a1ac8f57b53cb49c198bc29267sugoi
1206968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t ramRB = info.minRowBytes();
1207968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const int height = info.height();
1208968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t snugSize = snugRB * height;
1209968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t ramSize = ramRB * height;
121005858435ee8744de863be7e5ade05e4fd6edfb46commit-bot@chromium.org    if (!buffer->validate(snugSize <= ramSize)) {
121105858435ee8744de863be7e5ade05e4fd6edfb46commit-bot@chromium.org        return false;
121205858435ee8744de863be7e5ade05e4fd6edfb46commit-bot@chromium.org    }
1213968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
121433a30503d76fdd989358cedd78445ba96bb809ddreed    SkAutoDataUnref data(SkData::NewUninitialized(ramSize));
121533a30503d76fdd989358cedd78445ba96bb809ddreed    char* dst = (char*)data->writable_data();
1216968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    buffer->readByteArray(dst, snugSize);
1217968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1218968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    if (snugSize != ramSize) {
1219968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        const char* srcRow = dst + snugRB * (height - 1);
1220968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        char* dstRow = dst + ramRB * (height - 1);
1221968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        for (int y = height - 1; y >= 1; --y) {
1222968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org            memmove(dstRow, srcRow, snugRB);
1223968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org            srcRow -= snugRB;
1224968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org            dstRow -= ramRB;
1225968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        }
1226968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        SkASSERT(srcRow == dstRow); // first row does not need to be moved
1227968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
12283c134a97ed128ca95345e13619512df0f42e95f8skia.committer@gmail.com
1229968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkAutoTUnref<SkColorTable> ctable;
1230968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    if (buffer->readBool()) {
1231968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        ctable.reset(SkNEW_ARGS(SkColorTable, (*buffer)));
1232968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
12333c134a97ed128ca95345e13619512df0f42e95f8skia.committer@gmail.com
1234968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewWithData(info, info.minRowBytes(),
1235968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org                                                              ctable.get(), data.get()));
1236a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    bitmap->setInfo(pr->info());
1237968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    bitmap->setPixelRef(pr, 0, 0);
1238968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    return true;
1239968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org}
1240968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comenum {
12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SERIALIZE_PIXELTYPE_NONE,
124321830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com    SERIALIZE_PIXELTYPE_REF_DATA
12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1246851155c28e18e3f5b702ef15ee7bfb12f3cbacdacommit-bot@chromium.orgvoid SkBitmap::legacyUnflatten(SkReadBuffer& buffer) {
12479a9eae21ed5235869702a66d6decddd6643792c3reed#ifdef SK_SUPPORT_LEGACY_PIXELREF_UNFLATTENABLE
12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->reset();
1249f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
125061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkImageInfo info;
125161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    info.unflatten(buffer);
125261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    size_t rowBytes = buffer.readInt();
125333fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org    if (!buffer.validate((info.width() >= 0) && (info.height() >= 0) &&
125433fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org                         SkColorTypeIsValid(info.fColorType) &&
125533fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org                         SkAlphaTypeIsValid(info.fAlphaType) &&
12562fd0d14b9be34a7a945942733c3516d97d07f516scroggo                         SkColorTypeValidateAlphaType(info.fColorType, info.fAlphaType) &&
125733fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org                         info.validRowBytes(rowBytes))) {
125833fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org        return;
125933fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org    }
1260f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
1261a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    bool configIsValid = this->setInfo(info, rowBytes);
126261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    buffer.validate(configIsValid);
1263f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
1264c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    int reftype = buffer.readInt();
1265ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) ||
1266ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                        (SERIALIZE_PIXELTYPE_NONE == reftype))) {
1267ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        switch (reftype) {
1268ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            case SERIALIZE_PIXELTYPE_REF_DATA: {
1269672588b684d484dce6ae251e9e163e4a46924322reed@google.com                SkIPoint origin;
1270672588b684d484dce6ae251e9e163e4a46924322reed@google.com                origin.fX = buffer.readInt();
1271672588b684d484dce6ae251e9e163e4a46924322reed@google.com                origin.fY = buffer.readInt();
127261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                size_t offset = origin.fY * rowBytes + origin.fX * info.bytesPerPixel();
12739a9eae21ed5235869702a66d6decddd6643792c3reed                SkPixelRef* pr = buffer.readFlattenable<SkPixelRef>();
1274cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org                if (!buffer.validate((NULL == pr) ||
1275cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org                       (pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) {
1276672588b684d484dce6ae251e9e163e4a46924322reed@google.com                    origin.setZero();
1277cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org                }
1278672588b684d484dce6ae251e9e163e4a46924322reed@google.com                SkSafeUnref(this->setPixelRef(pr, origin));
1279ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                break;
1280ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            }
1281ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            case SERIALIZE_PIXELTYPE_NONE:
1282ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                break;
1283ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            default:
1284ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                SkDEBUGFAIL("unrecognized pixeltype in serialized data");
1285ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                sk_throw();
12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12889a9eae21ed5235869702a66d6decddd6643792c3reed#else
12899a9eae21ed5235869702a66d6decddd6643792c3reed    sk_throw();
12909a9eae21ed5235869702a66d6decddd6643792c3reed#endif
12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap::RLEPixels::RLEPixels(int width, int height) {
12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fHeight = height;
1297235002fb127fc5b7564910434faed84337c08238commit-bot@chromium.org    fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*));
12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap::RLEPixels::~RLEPixels() {
13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fYPtrs);
13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::validate() const {
130861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    fInfo.validate();
1309d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org
1310d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    // ImageInfo may not require this, but Bitmap ensures that opaque-only
1311d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    // colorTypes report opaque for their alphatype
1312d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    if (kRGB_565_SkColorType == fInfo.colorType()) {
1313d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org        SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
1314d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    }
1315d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org
131661e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkASSERT(fInfo.validRowBytes(fRowBytes));
13170847059fcffe11d53d4ea803ba2d51c696eb6d07scroggo    uint8_t allFlags = kImageIsVolatile_Flag;
13188e990eb440e0f61386ba21b06b8428d5b285c341scroggo@google.com#ifdef SK_BUILD_FOR_ANDROID
13198e990eb440e0f61386ba21b06b8428d5b285c341scroggo@google.com    allFlags |= kHasHardwareMipMap_Flag;
13208e990eb440e0f61386ba21b06b8428d5b285c341scroggo@google.com#endif
13210847059fcffe11d53d4ea803ba2d51c696eb6d07scroggo    SkASSERT((~allFlags & fFlags) == 0);
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fPixelLockCount >= 0);
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1324615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com    if (fPixels) {
1325615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelRef);
1326615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelLockCount > 0);
1327615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelRef->isLocked());
1328615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelRef->rowBytes() == fRowBytes);
1329615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelRefOrigin.fX >= 0);
1330615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelRefOrigin.fY >= 0);
133161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
1332e5ea500d4714a7d84de2bf913e81be3b65d2de68reed        SkASSERT(fPixelRef->info().height() >= (int)this->height() + fPixelRefOrigin.fY);
133361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
1334615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com    } else {
1335615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(NULL == fColorTable);
13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
133976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
13400f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
134176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkBitmap::toString(SkString* str) const {
134276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
1343cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
1344cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
134576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    };
134676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
134776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
1348cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org                 gColorTypeNames[this->colorType()]);
134976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
135076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(" (");
135176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    if (this->isOpaque()) {
135276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append("opaque");
135376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    } else {
135476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append("transparent");
135576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    }
135676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    if (this->isImmutable()) {
135776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append(", immutable");
135876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    } else {
135976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append(", not-immutable");
136076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    }
136176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(")");
136276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
136376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    SkPixelRef* pr = this->pixelRef();
136476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    if (NULL == pr) {
136576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        // show null or the explicit pixel address (rare)
136676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->appendf(" pixels:%p", this->getPixels());
136776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    } else {
136876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        const char* uri = pr->getURI();
136949f085dddff10473b6ebf832a974288300224e60bsalomon        if (uri) {
137076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com            str->appendf(" uri:\"%s\"", uri);
137176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        } else {
137276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com            str->appendf(" pixelref:%p", pr);
137376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        }
137476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    }
137576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
137676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(")");
137776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com}
137876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif
137961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org
138061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
138161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org
138261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org#ifdef SK_DEBUG
138361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.orgvoid SkImageInfo::validate() const {
138461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkASSERT(fWidth >= 0);
138561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkASSERT(fHeight >= 0);
138661e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkASSERT(SkColorTypeIsValid(fColorType));
138761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkASSERT(SkAlphaTypeIsValid(fAlphaType));
138861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org}
138961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org#endif
1390