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
94c3b3266b7db2f1a41d41ecac010c766b7ad8eebcreed#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG
9561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.orgSkBitmap::Config SkBitmap::config() const {
9661e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    return SkColorTypeToBitmapConfig(fInfo.colorType());
9761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org}
98c3b3266b7db2f1a41d41ecac010c766b7ad8eebcreed#endif
9961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org
100ddd014e65264e3f18b2d4305dd2fbc81549f5180reed#ifdef SK_SUPPORT_LEGACY_COMPUTE_CONFIG_SIZE
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int bpp;
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (config) {
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kNo_Config:
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            bpp = 0;   // not applicable
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kA8_Config:
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kIndex8_Config:
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            bpp = 1;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kRGB_565_Config:
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kARGB_4444_Config:
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            bpp = 2;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kARGB_8888_Config:
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            bpp = 4;
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
1190c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown config");
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            bpp = 0;   // error
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return bpp;
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1260ba4bf427acbd7707d04192a98c77ef194a0f25ascroggo@google.comsize_t SkBitmap::ComputeRowBytes(Config c, int width) {
12761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    return SkColorTypeMinRowBytes(SkBitmapConfigToColorType(c), width);
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13057212f9469c8056bab3c85243dbb904e386eab95reed@google.comint64_t SkBitmap::ComputeSize64(Config config, int width, int height) {
13161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkColorType ct = SkBitmapConfigToColorType(config);
13261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    int64_t rowBytes = sk_64_mul(SkColorTypeBytesPerPixel(ct), width);
13357212f9469c8056bab3c85243dbb904e386eab95reed@google.com    return rowBytes * height;
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comsize_t SkBitmap::ComputeSize(Config c, int width, int height) {
13757212f9469c8056bab3c85243dbb904e386eab95reed@google.com    int64_t size = SkBitmap::ComputeSize64(c, width, height);
13857212f9469c8056bab3c85243dbb904e386eab95reed@google.com    return sk_64_isS32(size) ? sk_64_asS32(size) : 0;
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
140ddd014e65264e3f18b2d4305dd2fbc81549f5180reed#endif
14186bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
14286b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.comvoid SkBitmap::getBounds(SkRect* bounds) const {
14386b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com    SkASSERT(bounds);
14486b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com    bounds->set(0, 0,
14561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                SkIntToScalar(fInfo.fWidth), SkIntToScalar(fInfo.fHeight));
14686b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com}
14786b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com
14880e1459c32f5f3acbc688ae4f0e046aa283e8c3areed@google.comvoid SkBitmap::getBounds(SkIRect* bounds) const {
14980e1459c32f5f3acbc688ae4f0e046aa283e8c3areed@google.com    SkASSERT(bounds);
15061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    bounds->set(0, 0, fInfo.fWidth, fInfo.fHeight);
15180e1459c32f5f3acbc688ae4f0e046aa283e8c3areed@google.com}
15280e1459c32f5f3acbc688ae4f0e046aa283e8c3areed@google.com
15386b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com///////////////////////////////////////////////////////////////////////////////
15486b2e43a33c486a0b150aa14fadf7af8323a11f5reed@google.com
15561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.orgstatic bool validate_alphaType(SkColorType colorType, SkAlphaType alphaType,
156c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                               SkAlphaType* canonical = NULL) {
15761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    switch (colorType) {
15861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kUnknown_SkColorType:
159383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            alphaType = kIgnore_SkAlphaType;
160383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            break;
16161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kAlpha_8_SkColorType:
162383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            if (kUnpremul_SkAlphaType == alphaType) {
163383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com                alphaType = kPremul_SkAlphaType;
164383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            }
165383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            // fall-through
16661e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kIndex_8_SkColorType:
16761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kARGB_4444_SkColorType:
16861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kRGBA_8888_SkColorType:
16961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kBGRA_8888_SkColorType:
170383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            if (kIgnore_SkAlphaType == alphaType) {
171383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com                return false;
172383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            }
173383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            break;
17461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kRGB_565_SkColorType:
175383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            alphaType = kOpaque_SkAlphaType;
176383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            break;
177d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        default:
178d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com            return false;
179383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    }
180383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    if (canonical) {
181383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com        *canonical = alphaType;
182383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    }
183383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    return true;
184383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com}
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
186a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.orgbool SkBitmap::setInfo(const SkImageInfo& origInfo, size_t rowBytes) {
187d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    SkImageInfo info = origInfo;
188d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org
189d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    if (!validate_alphaType(info.fColorType, info.fAlphaType,
190d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org                            &info.fAlphaType)) {
191d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org        return reset_return_false(this);
192d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    }
19302d6f546161e2c98d69066373cec3f54f3c46252skia.committer@gmail.com
19461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    // require that rowBytes fit in 31bits
19561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    int64_t mrb = info.minRowBytes64();
19661e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if ((int32_t)mrb != mrb) {
19761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        return reset_return_false(this);
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if ((int64_t)rowBytes != (int32_t)rowBytes) {
20061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        return reset_return_false(this);
201383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    }
202383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com
20361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if (info.width() < 0 || info.height() < 0) {
20461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        return reset_return_false(this);
205169a0ed50a5e451711c341795572e7177a540a24mike@reedtribe.org    }
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if (kUnknown_SkColorType == info.colorType()) {
20861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        rowBytes = 0;
20961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    } else if (0 == rowBytes) {
21061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        rowBytes = (size_t)mrb;
21161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    } else if (rowBytes < info.minRowBytes()) {
21261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        return reset_return_false(this);
21361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    }
2141195a28892d37ae9632e81e1bc2407cf644522d2mike@reedtribe.org
21561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    this->freePixels();
2161195a28892d37ae9632e81e1bc2407cf644522d2mike@reedtribe.org
21761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    fInfo = info;
21861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    fRowBytes = SkToU32(rowBytes);
219383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    return true;
220383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com}
221383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com
2226c22573edb234ad14df947278cfed010669a39a7reed#ifdef SK_SUPPORT_LEGACY_SETCONFIG
22361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.orgbool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
22461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                         SkAlphaType alphaType) {
22561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkColorType ct = SkBitmapConfigToColorType(config);
226a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    return this->setInfo(SkImageInfo::Make(width, height, ct, alphaType), rowBytes);
2276e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org}
2286c22573edb234ad14df947278cfed010669a39a7reed#endif
2296e3e42296b0d7a93325146d9c9a7e23ef90760fecommit-bot@chromium.org
230383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.combool SkBitmap::setAlphaType(SkAlphaType alphaType) {
23161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if (!validate_alphaType(fInfo.fColorType, alphaType, &alphaType)) {
232383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com        return false;
233383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    }
23461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if (fInfo.fAlphaType != alphaType) {
23561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        fInfo.fAlphaType = alphaType;
2360e8d0d6cdc2e02946b099006d0a47e60764905e5commit-bot@chromium.org        if (fPixelRef) {
237c1587f94a77eaafe257a6ecf504364d40362c66areed@google.com            fPixelRef->changeAlphaType(alphaType);
2380e8d0d6cdc2e02946b099006d0a47e60764905e5commit-bot@chromium.org        }
2390e8d0d6cdc2e02946b099006d0a47e60764905e5commit-bot@chromium.org    }
240383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com    return true;
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::updatePixelsFromRef() const {
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != fPixelRef) {
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fPixelLockCount > 0) {
246ff0da4ff483ba7b4468b862949ffb3de505cba14reed@google.com            SkASSERT(fPixelRef->isLocked());
247f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            void* p = fPixelRef->pixels();
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (NULL != p) {
250672588b684d484dce6ae251e9e163e4a46924322reed@google.com                p = (char*)p
251303c4758ec7062daf1531c3642e9c7887423ef1breed@google.com                    + fPixelRefOrigin.fY * fRowBytes
25261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                    + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPixels = p;
2555f62ed74342e44cb1b9671ffdac47c6a81416136reed@google.com            fColorTable = fPixelRef->colorTable();
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(0 == fPixelLockCount);
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPixels = NULL;
2595f62ed74342e44cb1b9671ffdac47c6a81416136reed@google.com            fColorTable = NULL;
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
264672588b684d484dce6ae251e9e163e4a46924322reed@google.comSkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
265dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com#ifdef SK_DEBUG
266672588b684d484dce6ae251e9e163e4a46924322reed@google.com    if (pr) {
267466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org        if (kUnknown_SkColorType != fInfo.colorType()) {
268dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com            const SkImageInfo& prInfo = pr->info();
269466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org            SkASSERT(fInfo.fWidth <= prInfo.fWidth);
270466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org            SkASSERT(fInfo.fHeight <= prInfo.fHeight);
271466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org            SkASSERT(fInfo.fColorType == prInfo.fColorType);
272dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com            switch (prInfo.fAlphaType) {
273dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                case kIgnore_SkAlphaType:
27461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                    SkASSERT(fInfo.fAlphaType == kIgnore_SkAlphaType);
275dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                    break;
276dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                case kOpaque_SkAlphaType:
277dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                case kPremul_SkAlphaType:
278466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org                    SkASSERT(fInfo.fAlphaType == kOpaque_SkAlphaType ||
279466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org                             fInfo.fAlphaType == kPremul_SkAlphaType);
280dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                    break;
281dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                case kUnpremul_SkAlphaType:
282466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org                    SkASSERT(fInfo.fAlphaType == kOpaque_SkAlphaType ||
283466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org                             fInfo.fAlphaType == kUnpremul_SkAlphaType);
284dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com                    break;
285dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com            }
286dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com        }
287dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com    }
288dcea5300dc028b5ea210d778b9e34a7504fee6d2reed@google.com#endif
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
290672588b684d484dce6ae251e9e163e4a46924322reed@google.com    if (pr) {
291672588b684d484dce6ae251e9e163e4a46924322reed@google.com        const SkImageInfo& info = pr->info();
292672588b684d484dce6ae251e9e163e4a46924322reed@google.com        fPixelRefOrigin.set(SkPin32(dx, 0, info.fWidth),
293672588b684d484dce6ae251e9e163e4a46924322reed@google.com                            SkPin32(dy, 0, info.fHeight));
294672588b684d484dce6ae251e9e163e4a46924322reed@google.com    } else {
295672588b684d484dce6ae251e9e163e4a46924322reed@google.com        // ignore dx,dy if there is no pixelref
296672588b684d484dce6ae251e9e163e4a46924322reed@google.com        fPixelRefOrigin.setZero();
297672588b684d484dce6ae251e9e163e4a46924322reed@google.com    }
298672588b684d484dce6ae251e9e163e4a46924322reed@google.com
299672588b684d484dce6ae251e9e163e4a46924322reed@google.com    if (fPixelRef != pr) {
3000eb02a6abbe2964e4955863b0f82aff6a8661801piotaixr        this->freePixels();
3010eb02a6abbe2964e4955863b0f82aff6a8661801piotaixr        SkASSERT(NULL == fPixelRef);
302f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
3030eb02a6abbe2964e4955863b0f82aff6a8661801piotaixr        SkSafeRef(pr);
3040eb02a6abbe2964e4955863b0f82aff6a8661801piotaixr        fPixelRef = pr;
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->updatePixelsFromRef();
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return pr;
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::lockPixels() const {
3137c6d26420d80275bb92f6d9ed86190554b0a6c13djsollen@google.com    if (NULL != fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) {
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelRef->lockPixels();
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->updatePixelsFromRef();
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::unlockPixels() const {
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(NULL == fPixelRef || fPixelLockCount > 0);
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3237c6d26420d80275bb92f6d9ed86190554b0a6c13djsollen@google.com    if (NULL != fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) {
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelRef->unlockPixels();
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->updatePixelsFromRef();
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3309c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.combool SkBitmap::lockPixelsAreWritable() const {
331c84b8335ee4fd864c30a4703afc643cf4b5010d9djsollen@google.com    return (fPixelRef) ? fPixelRef->lockPixelsAreWritable() : false;
3329c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com}
3339c49bc3e643c435677727c1c0904c4a7cb7a6907reed@google.com
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::setPixels(void* p, SkColorTable* ctable) {
3358e1034e9ca0e3009f65125239e21b06ec51a55a6reed@google.com    if (NULL == p) {
336672588b684d484dce6ae251e9e163e4a46924322reed@google.com        this->setPixelRef(NULL);
3378e1034e9ca0e3009f65125239e21b06ec51a55a6reed@google.com        return;
3388e1034e9ca0e3009f65125239e21b06ec51a55a6reed@google.com    }
3398e1034e9ca0e3009f65125239e21b06ec51a55a6reed@google.com
340466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    if (kUnknown_SkColorType == fInfo.colorType()) {
341672588b684d484dce6ae251e9e163e4a46924322reed@google.com        this->setPixelRef(NULL);
342bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        return;
343bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    }
344bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com
345466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    SkPixelRef* pr = SkMallocPixelRef::NewDirect(fInfo, p, fRowBytes, ctable);
346bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    if (NULL == pr) {
347672588b684d484dce6ae251e9e163e4a46924322reed@google.com        this->setPixelRef(NULL);
348bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com        return;
349bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    }
350bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com
351bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    this->setPixelRef(pr)->unref();
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
353c84b8335ee4fd864c30a4703afc643cf4b5010d9djsollen@google.com    // since we're already allocated, we lockPixels right away
354c84b8335ee4fd864c30a4703afc643cf4b5010d9djsollen@google.com    this->lockPixels();
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) {
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    HeapAllocator stdalloc;
360d2ac07b64b7d46e81d00d389781f9f83810f0095skia.committer@gmail.com
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == allocator) {
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        allocator = &stdalloc;
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return allocator->allocPixelRef(this, ctable);
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3679ebcac54635cde63110d73ad7c43d70772e7872freed@google.com///////////////////////////////////////////////////////////////////////////////
3689ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
3690187dc2155830c1ae3390d97463d5dd3971eca41scroggobool SkBitmap::allocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactory* factory,
3709ebcac54635cde63110d73ad7c43d70772e7872freed@google.com                           SkColorTable* ctable) {
3710187dc2155830c1ae3390d97463d5dd3971eca41scroggo    if (kIndex_8_SkColorType == requestedInfo.fColorType && NULL == ctable) {
3729ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return reset_return_false(this);
3739ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
3740187dc2155830c1ae3390d97463d5dd3971eca41scroggo    if (!this->setInfo(requestedInfo)) {
3759ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return reset_return_false(this);
3769ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
3779ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
3780187dc2155830c1ae3390d97463d5dd3971eca41scroggo    // setInfo may have corrected info (e.g. 565 is always opaque).
3790187dc2155830c1ae3390d97463d5dd3971eca41scroggo    const SkImageInfo& correctedInfo = this->info();
3800187dc2155830c1ae3390d97463d5dd3971eca41scroggo
3819ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    SkMallocPixelRef::PRFactory defaultFactory;
3829ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    if (NULL == factory) {
3839ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        factory = &defaultFactory;
3849ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
385d2ac07b64b7d46e81d00d389781f9f83810f0095skia.committer@gmail.com
3860187dc2155830c1ae3390d97463d5dd3971eca41scroggo    SkPixelRef* pr = factory->create(correctedInfo, ctable);
3879ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    if (NULL == pr) {
3889ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return reset_return_false(this);
3899ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
3909ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    this->setPixelRef(pr)->unref();
3919ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
3929ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    // TODO: lockPixels could/should return bool or void*/NULL
3939ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    this->lockPixels();
3949ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    if (NULL == this->getPixels()) {
3959ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return reset_return_false(this);
3969ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
3979ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    return true;
3989ebcac54635cde63110d73ad7c43d70772e7872freed@google.com}
3999ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
4000187dc2155830c1ae3390d97463d5dd3971eca41scroggobool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
4010187dc2155830c1ae3390d97463d5dd3971eca41scroggo                             SkColorTable* ct, void (*releaseProc)(void* addr, void* context),
4020187dc2155830c1ae3390d97463d5dd3971eca41scroggo                             void* context) {
4030187dc2155830c1ae3390d97463d5dd3971eca41scroggo    if (!this->setInfo(requestedInfo, rb)) {
4049ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        this->reset();
4059ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return false;
4069ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
4079ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
4080187dc2155830c1ae3390d97463d5dd3971eca41scroggo    // setInfo may have corrected info (e.g. 565 is always opaque).
4090187dc2155830c1ae3390d97463d5dd3971eca41scroggo    const SkImageInfo& correctedInfo = this->info();
4100187dc2155830c1ae3390d97463d5dd3971eca41scroggo
4110187dc2155830c1ae3390d97463d5dd3971eca41scroggo    SkPixelRef* pr = SkMallocPixelRef::NewWithProc(correctedInfo, rb, ct, pixels, releaseProc,
4120187dc2155830c1ae3390d97463d5dd3971eca41scroggo                                                   context);
4139ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    if (!pr) {
4149ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        this->reset();
4159ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return false;
4169ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
4179ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
4189ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    this->setPixelRef(pr)->unref();
4196e58cf36f0eba4b195726aa714d5487c91d06d04mike@reedtribe.org
4206e58cf36f0eba4b195726aa714d5487c91d06d04mike@reedtribe.org    // since we're already allocated, we lockPixels right away
4216e58cf36f0eba4b195726aa714d5487c91d06d04mike@reedtribe.org    this->lockPixels();
4226e58cf36f0eba4b195726aa714d5487c91d06d04mike@reedtribe.org    SkDEBUGCODE(this->validate();)
4239ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    return true;
4249ebcac54635cde63110d73ad7c43d70772e7872freed@google.com}
4259ebcac54635cde63110d73ad7c43d70772e7872freed@google.com
426dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.orgbool SkBitmap::installMaskPixels(const SkMask& mask) {
427dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org    if (SkMask::kA8_Format != mask.fFormat) {
428dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org        this->reset();
429dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org        return false;
430dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org    }
431dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org    return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
432dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org                                                   mask.fBounds.height()),
433dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org                               mask.fImage, mask.fRowBytes);
434dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org}
435dac522589e9395b4654a1a708f1bd971f37f95a5commit-bot@chromium.org
436eb9a46cbbb475e862a084aa2224ec18d4ac5e95breed@google.com///////////////////////////////////////////////////////////////////////////////
437eb9a46cbbb475e862a084aa2224ec18d4ac5e95breed@google.com
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::freePixels() {
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != fPixelRef) {
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fPixelLockCount > 0) {
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPixelRef->unlockPixels();
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelRef->unref();
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelRef = NULL;
445672588b684d484dce6ae251e9e163e4a46924322reed@google.com        fPixelRefOrigin.setZero();
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPixelLockCount = 0;
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPixels = NULL;
4495f62ed74342e44cb1b9671ffdac47c6a81416136reed@google.com    fColorTable = NULL;
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comuint32_t SkBitmap::getGenerationID() const {
453c84b8335ee4fd864c30a4703afc643cf4b5010d9djsollen@google.com    return (fPixelRef) ? fPixelRef->getGenerationID() : 0;
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::notifyPixelsChanged() const {
457b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org    SkASSERT(!this->isImmutable());
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fPixelRef) {
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPixelRef->notifyPixelsChanged();
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
463b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.orgGrTexture* SkBitmap::getTexture() const {
464ce4e53a2347040a3c145768c193a7a7958c0d4ecreed@android.com    return fPixelRef ? fPixelRef->getTexture() : NULL;
465ce4e53a2347040a3c145768c193a7a7958c0d4ecreed@android.com}
466ce4e53a2347040a3c145768c193a7a7958c0d4ecreed@android.com
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** We explicitly use the same allocator for our pixels that SkMask does,
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com so that we can freely assign memory allocated by one class to the other.
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            SkColorTable* ctable) {
474466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    const SkImageInfo info = dst->info();
475466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    if (kUnknown_SkColorType == info.colorType()) {
476bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com//        SkDebugf("unsupported config for info %d\n", dst->config());
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
47996f5fa02e996e39179f2eb88d57e8ed6114b06c5skia.committer@gmail.com
480466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), ctable);
481bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    if (NULL == pr) {
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
484f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
485672588b684d484dce6ae251e9e163e4a46924322reed@google.com    dst->setPixelRef(pr)->unref();
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // since we're already allocated, we lockPixels right away
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dst->lockPixels();
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
493fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.combool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
4940ba4bf427acbd7707d04192a98c77ef194a0f25ascroggo@google.com                            size_t dstRowBytes, bool preserveDstPad) const {
49586bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
4960ba4bf427acbd7707d04192a98c77ef194a0f25ascroggo@google.com    if (0 == dstRowBytes) {
49786bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        dstRowBytes = fRowBytes;
4980ba4bf427acbd7707d04192a98c77ef194a0f25ascroggo@google.com    }
49986bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
50061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    if (dstRowBytes < fInfo.minRowBytes() ||
50161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) {
50286bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        return false;
50361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    }
50486bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
505c69809745e6496564639e42ef998ad39adf7dfb8bsalomon@google.com    if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) {
5064469938e92d779dff05e745559e67907bbf21e78reed@google.com        size_t safeSize = this->getSafeSize();
50786bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        if (safeSize > dstSize || safeSize == 0)
50886bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            return false;
50986bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        else {
51086bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            SkAutoLockPixels lock(*this);
51186bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            // This implementation will write bytes beyond the end of each row,
51286bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            // excluding the last row, if the bitmap's stride is greater than
51386bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            // strictly required by the current config.
51486bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            memcpy(dst, getPixels(), safeSize);
51586bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
51686bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            return true;
51786bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        }
51886bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org    } else {
51986bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        // If destination has different stride than us, then copy line by line.
52061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        if (fInfo.getSafeSize(dstRowBytes) > dstSize) {
52186bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            return false;
52261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        } else {
52386bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            // Just copy what we need on each line.
52461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            size_t rowBytes = fInfo.minRowBytes();
52586bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            SkAutoLockPixels lock(*this);
52686bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels());
52786bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
52861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            for (int row = 0; row < fInfo.fHeight;
52986bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org                 row++, srcP += fRowBytes, dstP += dstRowBytes) {
53086bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org                memcpy(dstP, srcP, rowBytes);
53186bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            }
53286bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
53386bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org            return true;
53486bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org        }
53586bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org    }
53686bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org}
53786bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
53886bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org///////////////////////////////////////////////////////////////////////////////
53986bff1f008308267c4ff75456b202a9cf60c6193wjmaclean@chromium.org
540fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.combool SkBitmap::isImmutable() const {
541b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org    return fPixelRef ? fPixelRef->isImmutable() :
542fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        fFlags & kImageIsImmutable_Flag;
543b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org}
544b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org
545b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.orgvoid SkBitmap::setImmutable() {
546b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org    if (fPixelRef) {
547b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org        fPixelRef->setImmutable();
548b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org    } else {
549b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org        fFlags |= kImageIsImmutable_Flag;
550b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org    }
551b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org}
552b052129a4121c1e3f051e374541a93d3d7a98064junov@chromium.org
5534ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.combool SkBitmap::isVolatile() const {
5544ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com    return (fFlags & kImageIsVolatile_Flag) != 0;
5554ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com}
5564ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com
5574ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.comvoid SkBitmap::setIsVolatile(bool isVolatile) {
5584ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com    if (isVolatile) {
5594ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com        fFlags |= kImageIsVolatile_Flag;
5604ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com    } else {
5614ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com        fFlags &= ~kImageIsVolatile_Flag;
5624ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com    }
5634ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com}
5644ee7ae5dcfe2055cfcfc21bf2cec1d790330eb4ajunov@google.com
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid* SkBitmap::getAddr(int x, int y) const {
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)x < (unsigned)this->width());
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)y < (unsigned)this->height());
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char* base = (char*)this->getPixels();
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (base) {
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        base += y * this->rowBytes();
57261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        switch (this->colorType()) {
57361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kRGBA_8888_SkColorType:
57461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kBGRA_8888_SkColorType:
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                base += x << 2;
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
57761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kARGB_4444_SkColorType:
57861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kRGB_565_SkColorType:
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                base += x << 1;
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
58161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kAlpha_8_SkColorType:
58261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            case kIndex_8_SkColorType:
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                base += x;
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            default:
5860c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com                SkDEBUGFAIL("Can't return addr for config");
5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                base = NULL;
5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return base;
5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
594112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.orgSkColor SkBitmap::getColor(int x, int y) const {
595112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org    SkASSERT((unsigned)x < (unsigned)this->width());
596112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org    SkASSERT((unsigned)y < (unsigned)this->height());
597112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org
598cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    switch (this->colorType()) {
599cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kAlpha_8_SkColorType: {
6003b521d05335a1bf76be3456feb9dbfba0a51b339reed@google.com            uint8_t* addr = this->getAddr8(x, y);
601112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return SkColorSetA(0, addr[0]);
602112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org        }
603cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kIndex_8_SkColorType: {
6043b521d05335a1bf76be3456feb9dbfba0a51b339reed@google.com            SkPMColor c = this->getIndex8Color(x, y);
605112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return SkUnPreMultiply::PMColorToColor(c);
606112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org        }
607cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kRGB_565_SkColorType: {
6083b521d05335a1bf76be3456feb9dbfba0a51b339reed@google.com            uint16_t* addr = this->getAddr16(x, y);
609112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return SkPixel16ToColor(addr[0]);
610112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org        }
611cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kARGB_4444_SkColorType: {
6123b521d05335a1bf76be3456feb9dbfba0a51b339reed@google.com            uint16_t* addr = this->getAddr16(x, y);
613112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            SkPMColor c = SkPixel4444ToPixel32(addr[0]);
614112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return SkUnPreMultiply::PMColorToColor(c);
615112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org        }
616cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kBGRA_8888_SkColorType:
617cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kRGBA_8888_SkColorType: {
6183b521d05335a1bf76be3456feb9dbfba0a51b339reed@google.com            uint32_t* addr = this->getAddr32(x, y);
619112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return SkUnPreMultiply::PMColorToColor(addr[0]);
620112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org        }
621d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        default:
622112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            SkASSERT(false);
623112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org            return 0;
624112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org    }
625112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org    SkASSERT(false);  // Not reached.
626112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org    return 0;
627112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org}
628112706d4c566e283890322bb246b4b86d59837e1vandebo@chromium.org
6292a7579d11796866b0026755ab52597d09f4509ccreed@google.combool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
6302a7579d11796866b0026755ab52597d09f4509ccreed@google.com    SkAutoLockPixels alp(bm);
6312a7579d11796866b0026755ab52597d09f4509ccreed@google.com    if (!bm.getPixels()) {
6322a7579d11796866b0026755ab52597d09f4509ccreed@google.com        return false;
6332a7579d11796866b0026755ab52597d09f4509ccreed@google.com    }
6342a7579d11796866b0026755ab52597d09f4509ccreed@google.com
6352a7579d11796866b0026755ab52597d09f4509ccreed@google.com    const int height = bm.height();
6362a7579d11796866b0026755ab52597d09f4509ccreed@google.com    const int width = bm.width();
6372a7579d11796866b0026755ab52597d09f4509ccreed@google.com
638cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    switch (bm.colorType()) {
639cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kAlpha_8_SkColorType: {
6402a7579d11796866b0026755ab52597d09f4509ccreed@google.com            unsigned a = 0xFF;
6412a7579d11796866b0026755ab52597d09f4509ccreed@google.com            for (int y = 0; y < height; ++y) {
6422a7579d11796866b0026755ab52597d09f4509ccreed@google.com                const uint8_t* row = bm.getAddr8(0, y);
6432a7579d11796866b0026755ab52597d09f4509ccreed@google.com                for (int x = 0; x < width; ++x) {
6442a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    a &= row[x];
6452a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
6462a7579d11796866b0026755ab52597d09f4509ccreed@google.com                if (0xFF != a) {
6472a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    return false;
6482a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
6492a7579d11796866b0026755ab52597d09f4509ccreed@google.com            }
6502a7579d11796866b0026755ab52597d09f4509ccreed@google.com            return true;
6512a7579d11796866b0026755ab52597d09f4509ccreed@google.com        } break;
652cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kIndex_8_SkColorType: {
6532a7579d11796866b0026755ab52597d09f4509ccreed@google.com            SkAutoLockColors alc(bm);
6542a7579d11796866b0026755ab52597d09f4509ccreed@google.com            const SkPMColor* table = alc.colors();
6552a7579d11796866b0026755ab52597d09f4509ccreed@google.com            if (!table) {
6562a7579d11796866b0026755ab52597d09f4509ccreed@google.com                return false;
6572a7579d11796866b0026755ab52597d09f4509ccreed@google.com            }
658140d7286c5a40058932696eaa28818c313bd2ddfreed@google.com            SkPMColor c = (SkPMColor)~0;
6592a7579d11796866b0026755ab52597d09f4509ccreed@google.com            for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) {
6602a7579d11796866b0026755ab52597d09f4509ccreed@google.com                c &= table[i];
6612a7579d11796866b0026755ab52597d09f4509ccreed@google.com            }
6622a7579d11796866b0026755ab52597d09f4509ccreed@google.com            return 0xFF == SkGetPackedA32(c);
6632a7579d11796866b0026755ab52597d09f4509ccreed@google.com        } break;
664cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kRGB_565_SkColorType:
6652a7579d11796866b0026755ab52597d09f4509ccreed@google.com            return true;
6662a7579d11796866b0026755ab52597d09f4509ccreed@google.com            break;
667cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kARGB_4444_SkColorType: {
6682a7579d11796866b0026755ab52597d09f4509ccreed@google.com            unsigned c = 0xFFFF;
6692a7579d11796866b0026755ab52597d09f4509ccreed@google.com            for (int y = 0; y < height; ++y) {
6702a7579d11796866b0026755ab52597d09f4509ccreed@google.com                const SkPMColor16* row = bm.getAddr16(0, y);
6712a7579d11796866b0026755ab52597d09f4509ccreed@google.com                for (int x = 0; x < width; ++x) {
6722a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    c &= row[x];
6732a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
6742a7579d11796866b0026755ab52597d09f4509ccreed@google.com                if (0xF != SkGetPackedA4444(c)) {
6752a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    return false;
6762a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
6772a7579d11796866b0026755ab52597d09f4509ccreed@google.com            }
6782a7579d11796866b0026755ab52597d09f4509ccreed@google.com            return true;
6792a7579d11796866b0026755ab52597d09f4509ccreed@google.com        } break;
680cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kBGRA_8888_SkColorType:
681cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        case kRGBA_8888_SkColorType: {
682140d7286c5a40058932696eaa28818c313bd2ddfreed@google.com            SkPMColor c = (SkPMColor)~0;
6832a7579d11796866b0026755ab52597d09f4509ccreed@google.com            for (int y = 0; y < height; ++y) {
6842a7579d11796866b0026755ab52597d09f4509ccreed@google.com                const SkPMColor* row = bm.getAddr32(0, y);
6852a7579d11796866b0026755ab52597d09f4509ccreed@google.com                for (int x = 0; x < width; ++x) {
6862a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    c &= row[x];
6872a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
6882a7579d11796866b0026755ab52597d09f4509ccreed@google.com                if (0xFF != SkGetPackedA32(c)) {
6892a7579d11796866b0026755ab52597d09f4509ccreed@google.com                    return false;
6902a7579d11796866b0026755ab52597d09f4509ccreed@google.com                }
6912a7579d11796866b0026755ab52597d09f4509ccreed@google.com            }
6922a7579d11796866b0026755ab52597d09f4509ccreed@google.com            return true;
6932a7579d11796866b0026755ab52597d09f4509ccreed@google.com        }
6942a7579d11796866b0026755ab52597d09f4509ccreed@google.com        default:
6952a7579d11796866b0026755ab52597d09f4509ccreed@google.com            break;
6962a7579d11796866b0026755ab52597d09f4509ccreed@google.com    }
6972a7579d11796866b0026755ab52597d09f4509ccreed@google.com    return false;
6982a7579d11796866b0026755ab52597d09f4509ccreed@google.com}
6992a7579d11796866b0026755ab52597d09f4509ccreed@google.com
7002a7579d11796866b0026755ab52597d09f4509ccreed@google.com
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
70445f746f521d6925d22a304921f6e17196f4f8157reed@google.comstatic uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) {
70545f746f521d6925d22a304921f6e17196f4f8157reed@google.com    unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) |
70645f746f521d6925d22a304921f6e17196f4f8157reed@google.com                     (SkR32To4444(r) << SK_R4444_SHIFT) |
70745f746f521d6925d22a304921f6e17196f4f8157reed@google.com                     (SkG32To4444(g) << SK_G4444_SHIFT) |
70845f746f521d6925d22a304921f6e17196f4f8157reed@google.com                     (SkB32To4444(b) << SK_B4444_SHIFT);
70945f746f521d6925d22a304921f6e17196f4f8157reed@google.com    return SkToU16(pixel);
71045f746f521d6925d22a304921f6e17196f4f8157reed@google.com}
71145f746f521d6925d22a304921f6e17196f4f8157reed@google.com
71260d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.comvoid SkBitmap::internalErase(const SkIRect& area,
71360d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com                             U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
71460d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com#ifdef SK_DEBUG
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
71660d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    SkASSERT(!area.isEmpty());
71760d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    {
71892833f99b99f1f955c350f6f4f70acd3356a79a5reed@google.com        SkIRect total = { 0, 0, this->width(), this->height() };
71960d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com        SkASSERT(total.contains(area));
72060d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    }
72160d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com#endif
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
72361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    switch (fInfo.colorType()) {
72461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kUnknown_SkColorType:
72561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kIndex_8_SkColorType:
7267669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            return; // can't erase. Should we bzero so the memory is not uninitialized?
72761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        default:
72861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            break;
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoLockPixels alp(*this);
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // perform this check after the lock call
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!this->readyToDraw()) {
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
73760d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    int height = area.height();
73860d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    const int width = area.width();
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const int rowBytes = fRowBytes;
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
74161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    switch (this->colorType()) {
74261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kAlpha_8_SkColorType: {
74360d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com            uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (--height >= 0) {
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memset(p, a, width);
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                p += rowBytes;
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
75061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kARGB_4444_SkColorType:
75161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        case kRGB_565_SkColorType: {
75260d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com            uint16_t* p = this->getAddr16(area.fLeft, area.fTop);;
75345f746f521d6925d22a304921f6e17196f4f8157reed@google.com            uint16_t v;
754020b25becb4a99061e8643780c887ad472eb0648skia.committer@gmail.com
7557669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            // make rgb premultiplied
7567669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            if (255 != a) {
7577669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                r = SkAlphaMul(r, a);
7587669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                g = SkAlphaMul(g, a);
7597669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                b = SkAlphaMul(b, a);
7607669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            }
7617669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org
76261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            if (kARGB_4444_SkColorType == this->colorType()) {
76345f746f521d6925d22a304921f6e17196f4f8157reed@google.com                v = pack_8888_to_4444(a, r, g, b);
76445f746f521d6925d22a304921f6e17196f4f8157reed@google.com            } else {
76545f746f521d6925d22a304921f6e17196f4f8157reed@google.com                v = SkPackRGB16(r >> (8 - SK_R16_BITS),
76645f746f521d6925d22a304921f6e17196f4f8157reed@google.com                                g >> (8 - SK_G16_BITS),
76745f746f521d6925d22a304921f6e17196f4f8157reed@google.com                                b >> (8 - SK_B16_BITS));
76845f746f521d6925d22a304921f6e17196f4f8157reed@google.com            }
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (--height >= 0) {
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_memset16(p, v, width);
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                p = (uint16_t*)((char*)p + rowBytes);
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7757669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org        case kBGRA_8888_SkColorType:
7767669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org        case kRGBA_8888_SkColorType: {
77760d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com            uint32_t* p = this->getAddr32(area.fLeft, area.fTop);
7787669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org
7797669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            if (255 != a && kPremul_SkAlphaType == this->alphaType()) {
7807669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                r = SkAlphaMul(r, a);
7817669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                g = SkAlphaMul(g, a);
7827669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                b = SkAlphaMul(b, a);
7837669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            }
7847669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org            uint32_t v = kRGBA_8888_SkColorType == this->colorType() ?
7857669a77cd16fbab3618ca1f1a03bcfa05a93c447commit-bot@chromium.org                         SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b);
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (--height >= 0) {
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_memset32(p, v, width);
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                p = (uint32_t*)((char*)p + rowBytes);
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
79361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        default:
79461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            return; // no change, so don't call notifyPixelsChanged()
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
796f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->notifyPixelsChanged();
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
80060d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.comvoid SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
80192833f99b99f1f955c350f6f4f70acd3356a79a5reed@google.com    SkIRect area = { 0, 0, this->width(), this->height() };
80260d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    if (!area.isEmpty()) {
80360d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com        this->internalErase(area, a, r, g, b);
80460d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    }
80560d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com}
80660d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com
80760d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.comvoid SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const {
80892833f99b99f1f955c350f6f4f70acd3356a79a5reed@google.com    SkIRect area = { 0, 0, this->width(), this->height() };
80960d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    if (area.intersect(rect)) {
81060d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com        this->internalErase(area, SkColorGetA(c), SkColorGetR(c),
81160d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com                            SkColorGetG(c), SkColorGetB(c));
81260d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com    }
81360d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com}
81460d3235ab42bd1d32a070695ee30d6e3ec2fa222reed@google.com
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
821c84b8335ee4fd864c30a4703afc643cf4b5010d9djsollen@google.com    if (NULL == result || NULL == fPixelRef) {
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;   // no src pixels
8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect srcRect, r;
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcRect.set(0, 0, this->width(), this->height());
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!r.intersect(srcRect, subset)) {
8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;   // r is empty (i.e. no intersection)
8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
831a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    if (fPixelRef->getTexture() != NULL) {
832a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        // Do a deep copy
833e4538f5b46d70798e34eb078f5d5e76a59d02318reed        SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), &subset);
834a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        if (pixelRef != NULL) {
835a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            SkBitmap dst;
836a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org            dst.setInfo(SkImageInfo::Make(subset.width(), subset.height(),
837a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org                                          this->colorType(), this->alphaType()));
838a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            dst.setIsVolatile(this->isVolatile());
839a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            dst.setPixelRef(pixelRef)->unref();
840a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            SkDEBUGCODE(dst.validate());
841a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            result->swap(dst);
842a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com            return true;
843a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        }
844a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    }
845a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com
846a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
847a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    // exited above.
848a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
849a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
850a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com
8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBitmap dst;
852a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    dst.setInfo(SkImageInfo::Make(r.width(), r.height(), this->colorType(), this->alphaType()),
853a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org                this->rowBytes());
8540eb7576c659a165f1d73b6b7ddfd43dc3782f62bskyostil@google.com    dst.setIsVolatile(this->isVolatile());
8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fPixelRef) {
857672588b684d484dce6ae251e9e163e4a46924322reed@google.com        SkIPoint origin = fPixelRefOrigin;
858672588b684d484dce6ae251e9e163e4a46924322reed@google.com        origin.fX += r.fLeft;
859672588b684d484dce6ae251e9e163e4a46924322reed@google.com        origin.fY += r.fTop;
8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // share the pixelref with a custom offset
861672588b684d484dce6ae251e9e163e4a46924322reed@google.com        dst.setPixelRef(fPixelRef, origin);
8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(dst.validate();)
8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // we know we're good, so commit to result
8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result->swap(dst);
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8758a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.orgbool SkBitmap::canCopyTo(SkColorType dstColorType) const {
8768a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    if (this->colorType() == kUnknown_SkColorType) {
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8808a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    bool sameConfigs = (this->colorType() == dstColorType);
8818a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    switch (dstColorType) {
8828a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        case kAlpha_8_SkColorType:
8838a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        case kRGB_565_SkColorType:
88460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kRGBA_8888_SkColorType:
88560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kBGRA_8888_SkColorType:
8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
8878a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        case kIndex_8_SkColorType:
888f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com            if (!sameConfigs) {
889f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com                return false;
890f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com            }
891f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com            break;
8928a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        case kARGB_4444_SkColorType:
89328fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org            return sameConfigs || kN32_SkColorType == this->colorType();
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return false;
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
897fbaa88d9695347299321cbce2bf803726999fb58reed@android.com    return true;
898fbaa88d9695347299321cbce2bf803726999fb58reed@android.com}
899fbaa88d9695347299321cbce2bf803726999fb58reed@android.com
9008a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.orgbool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType,
9018a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org                      Allocator* alloc) const {
9028a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    if (!this->canCopyTo(dstColorType)) {
903fbaa88d9695347299321cbce2bf803726999fb58reed@android.com        return false;
904fbaa88d9695347299321cbce2bf803726999fb58reed@android.com    }
905fbaa88d9695347299321cbce2bf803726999fb58reed@android.com
90650dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    // if we have a texture, first get those pixels
90750dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    SkBitmap tmpSrc;
90850dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    const SkBitmap* src = this;
90950dfa0130b0705414df7ba7da9915139f6320b09reed@google.com
910a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    if (fPixelRef) {
911a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        SkIRect subset;
91261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
91361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                       fInfo.width(), fInfo.height());
914672588b684d484dce6ae251e9e163e4a46924322reed@google.com        if (fPixelRef->readPixels(&tmpSrc, &subset)) {
9150187dc2155830c1ae3390d97463d5dd3971eca41scroggo            if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) {
9160187dc2155830c1ae3390d97463d5dd3971eca41scroggo                // FIXME: The only meaningful implementation of readPixels
9170187dc2155830c1ae3390d97463d5dd3971eca41scroggo                // (GrPixelRef) assumes premultiplied pixels.
9180187dc2155830c1ae3390d97463d5dd3971eca41scroggo                return false;
9190187dc2155830c1ae3390d97463d5dd3971eca41scroggo            }
920672588b684d484dce6ae251e9e163e4a46924322reed@google.com            SkASSERT(tmpSrc.width() == this->width());
921672588b684d484dce6ae251e9e163e4a46924322reed@google.com            SkASSERT(tmpSrc.height() == this->height());
922672588b684d484dce6ae251e9e163e4a46924322reed@google.com
923672588b684d484dce6ae251e9e163e4a46924322reed@google.com            // did we get lucky and we can just return tmpSrc?
9248a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org            if (tmpSrc.colorType() == dstColorType && NULL == alloc) {
925672588b684d484dce6ae251e9e163e4a46924322reed@google.com                dst->swap(tmpSrc);
9265ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com                // If the result is an exact copy, clone the gen ID.
9275ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com                if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) {
928672588b684d484dce6ae251e9e163e4a46924322reed@google.com                    dst->pixelRef()->cloneGenID(*fPixelRef);
929a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com                }
930672588b684d484dce6ae251e9e163e4a46924322reed@google.com                return true;
931d5764e8ab731dd12df9293e52ce644eaa45333bdscroggo@google.com            }
932672588b684d484dce6ae251e9e163e4a46924322reed@google.com
933672588b684d484dce6ae251e9e163e4a46924322reed@google.com            // fall through to the raster case
934672588b684d484dce6ae251e9e163e4a46924322reed@google.com            src = &tmpSrc;
93550dfa0130b0705414df7ba7da9915139f6320b09reed@google.com        }
93650dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    }
93750dfa0130b0705414df7ba7da9915139f6320b09reed@google.com
938311c82db3115fc6810855cbcc42a6bc6fbd48265reed@android.com    // we lock this now, since we may need its colortable
93950dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    SkAutoLockPixels srclock(*src);
94050dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    if (!src->readyToDraw()) {
941fbaa88d9695347299321cbce2bf803726999fb58reed@android.com        return false;
942fbaa88d9695347299321cbce2bf803726999fb58reed@android.com    }
943fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9445ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com    // The only way to be readyToDraw is if fPixelRef is non NULL.
9455ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com    SkASSERT(fPixelRef != NULL);
9465ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com
9478a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    SkImageInfo dstInfo = src->info();
9488a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    dstInfo.fColorType = dstColorType;
9498a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org
95050dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    SkBitmap tmpDst;
951a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    if (!tmpDst.setInfo(dstInfo)) {
9528a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        return false;
9538a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    }
954fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
955f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com    // allocate colortable if srcConfig == kIndex8_Config
9568a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    SkAutoTUnref<SkColorTable> ctable;
9578a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    if (dstColorType == kIndex_8_SkColorType) {
9588a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        // TODO: can we just ref() the src colortable? Is it reentrant-safe?
9598a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        ctable.reset(SkNEW_ARGS(SkColorTable, (*src->getColorTable())));
9608a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    }
96150dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    if (!tmpDst.allocPixels(alloc, ctable)) {
9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
964fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
96550dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    if (!tmpDst.readyToDraw()) {
9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // allocator/lock failed
9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
969fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9705ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com    // pixelRef must be non NULL or tmpDst.readyToDraw() would have
9715ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com    // returned false.
9725ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com    SkASSERT(tmpDst.pixelRef() != NULL);
9735ccae2c5b134d1b971c188215433305e88491aecscroggo@google.com
974fbaa88d9695347299321cbce2bf803726999fb58reed@android.com    /* do memcpy for the same configs cases, else use drawing
975f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com    */
9768a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    if (src->colorType() == dstColorType) {
97750dfa0130b0705414df7ba7da9915139f6320b09reed@google.com        if (tmpDst.getSize() == src->getSize()) {
97850dfa0130b0705414df7ba7da9915139f6320b09reed@google.com            memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize());
9790187dc2155830c1ae3390d97463d5dd3971eca41scroggo
9800187dc2155830c1ae3390d97463d5dd3971eca41scroggo            SkPixelRef* dstPixelRef = tmpDst.pixelRef();
9810187dc2155830c1ae3390d97463d5dd3971eca41scroggo            if (dstPixelRef->info() == fPixelRef->info()) {
9820187dc2155830c1ae3390d97463d5dd3971eca41scroggo                dstPixelRef->cloneGenID(*fPixelRef);
983d5764e8ab731dd12df9293e52ce644eaa45333bdscroggo@google.com            }
984311c82db3115fc6810855cbcc42a6bc6fbd48265reed@android.com        } else {
98550dfa0130b0705414df7ba7da9915139f6320b09reed@google.com            const char* srcP = reinterpret_cast<const char*>(src->getPixels());
98650dfa0130b0705414df7ba7da9915139f6320b09reed@google.com            char* dstP = reinterpret_cast<char*>(tmpDst.getPixels());
987311c82db3115fc6810855cbcc42a6bc6fbd48265reed@android.com            // to be sure we don't read too much, only copy our logical pixels
98850dfa0130b0705414df7ba7da9915139f6320b09reed@google.com            size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel();
98950dfa0130b0705414df7ba7da9915139f6320b09reed@google.com            for (int y = 0; y < tmpDst.height(); y++) {
990311c82db3115fc6810855cbcc42a6bc6fbd48265reed@android.com                memcpy(dstP, srcP, bytesToCopy);
99150dfa0130b0705414df7ba7da9915139f6320b09reed@google.com                srcP += src->rowBytes();
99250dfa0130b0705414df7ba7da9915139f6320b09reed@google.com                dstP += tmpDst.rowBytes();
993311c82db3115fc6810855cbcc42a6bc6fbd48265reed@android.com            }
994311c82db3115fc6810855cbcc42a6bc6fbd48265reed@android.com        }
9958a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    } else if (kARGB_4444_SkColorType == dstColorType
99628fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org               && kN32_SkColorType == src->colorType()) {
9970187dc2155830c1ae3390d97463d5dd3971eca41scroggo        if (src->alphaType() == kUnpremul_SkAlphaType) {
9980187dc2155830c1ae3390d97463d5dd3971eca41scroggo            // Our method for converting to 4444 assumes premultiplied.
9990187dc2155830c1ae3390d97463d5dd3971eca41scroggo            return false;
10000187dc2155830c1ae3390d97463d5dd3971eca41scroggo        }
10018dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com        SkASSERT(src->height() == tmpDst.height());
10028dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com        SkASSERT(src->width() == tmpDst.width());
10038dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com        for (int y = 0; y < src->height(); ++y) {
10048dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com            SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y);
10058dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com            SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y);
10068dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com            DITHER_4444_SCAN(y);
10078dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com            for (int x = 0; x < src->width(); ++x) {
10088dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com                dstRow[x] = SkDitherARGB32To4444(srcRow[x],
10098dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com                                                 DITHER_VALUE(x));
10108dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com            }
10118dc8bc55479eb7895b3f0cf4fb42d9d917b21ee1scroggo@google.com        }
1012f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com    } else {
10130187dc2155830c1ae3390d97463d5dd3971eca41scroggo        if (tmpDst.alphaType() == kUnpremul_SkAlphaType) {
10140187dc2155830c1ae3390d97463d5dd3971eca41scroggo            // We do not support drawing to unpremultiplied bitmaps.
10150187dc2155830c1ae3390d97463d5dd3971eca41scroggo            return false;
10160187dc2155830c1ae3390d97463d5dd3971eca41scroggo        }
10170187dc2155830c1ae3390d97463d5dd3971eca41scroggo
10180197b32bfb98c793c8104cefde26ca62562d1f0erobertphillips@google.com        // Always clear the dest in case one of the blitters accesses it
10190197b32bfb98c793c8104cefde26ca62562d1f0erobertphillips@google.com        // TODO: switch the allocation of tmpDst to call sk_calloc_throw
10200197b32bfb98c793c8104cefde26ca62562d1f0erobertphillips@google.com        tmpDst.eraseColor(SK_ColorTRANSPARENT);
1021f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
102250dfa0130b0705414df7ba7da9915139f6320b09reed@google.com        SkCanvas canvas(tmpDst);
1023f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com        SkPaint  paint;
1024f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
1025f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com        paint.setDither(true);
102650dfa0130b0705414df7ba7da9915139f6320b09reed@google.com        canvas.drawBitmap(*src, 0, 0, &paint);
10278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
102950dfa0130b0705414df7ba7da9915139f6320b09reed@google.com    dst->swap(tmpDst);
10308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1033fab349c0bf3a305b7a7388b77bab13b0f7b37393commit-bot@chromium.orgbool SkBitmap::deepCopyTo(SkBitmap* dst) const {
1034e4538f5b46d70798e34eb078f5d5e76a59d02318reed    const SkColorType dstCT = this->colorType();
103561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org
10368a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    if (!this->canCopyTo(dstCT)) {
1037ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return false;
1038ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1039ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
1040ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    // If we have a PixelRef, and it supports deep copy, use it.
1041ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    // Currently supported only by texture-backed bitmaps.
1042ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (fPixelRef) {
1043e4538f5b46d70798e34eb078f5d5e76a59d02318reed        SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, NULL);
1044eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org        if (pixelRef) {
1045eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            uint32_t rowBytes;
1046eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            if (this->colorType() == dstCT) {
1047eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                // Since there is no subset to pass to deepCopy, and deepCopy
1048eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                // succeeded, the new pixel ref must be identical.
1049eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                SkASSERT(fPixelRef->info() == pixelRef->info());
1050eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                pixelRef->cloneGenID(*fPixelRef);
1051eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                // Use the same rowBytes as the original.
1052eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                rowBytes = fRowBytes;
1053eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            } else {
1054a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org                // With the new config, an appropriate fRowBytes will be computed by setInfo.
1055eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org                rowBytes = 0;
1056eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            }
1057eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org
1058eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            SkImageInfo info = fInfo;
1059eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            info.fColorType = dstCT;
1060a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org            if (!dst->setInfo(info, rowBytes)) {
106161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                return false;
106261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org            }
1063eeef0cc49bf71e8b5e044d6a73b79cfe2b2c87b3commit-bot@chromium.org            dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref();
1064ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org            return true;
1065ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        }
1066ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1067ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
1068ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (this->getTexture()) {
1069ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return false;
1070ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    } else {
10718a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        return this->copyTo(dst, dstCT, NULL);
1072ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1073ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org}
1074ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1077a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comstatic bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                           int alphaRowBytes) {
10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(alpha != NULL);
10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(alphaRowBytes >= src.width());
10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1082cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    SkColorType colorType = src.colorType();
1083cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    int         w = src.width();
1084cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    int         h = src.height();
1085cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    size_t      rb = src.rowBytes();
10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10871cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    SkAutoLockPixels alp(src);
10881cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    if (!src.readyToDraw()) {
10891cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        // zero out the alpha buffer and return
10901cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        while (--h >= 0) {
10911cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com            memset(alpha, 0, w);
10921cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com            alpha += alphaRowBytes;
10931cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        }
10941cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        return false;
10951cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    }
109682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1097cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    if (kAlpha_8_SkColorType == colorType && !src.isOpaque()) {
10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t* s = src.getAddr8(0, 0);
10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--h >= 0) {
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(alpha, s, w);
11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            s += rb;
11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += alphaRowBytes;
11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1104cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    } else if (kN32_SkColorType == colorType && !src.isOpaque()) {
11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--h >= 0) {
11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (int x = 0; x < w; x++) {
11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                alpha[x] = SkGetPackedA32(s[x]);
11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            s = (const SkPMColor*)((const char*)s + rb);
11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += alphaRowBytes;
11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1113cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    } else if (kARGB_4444_SkColorType == colorType && !src.isOpaque()) {
11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        while (--h >= 0) {
11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (int x = 0; x < w; x++) {
11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                alpha[x] = SkPacked4444ToA32(s[x]);
11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            s = (const SkPMColor16*)((const char*)s + rb);
11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            alpha += alphaRowBytes;
11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1122cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    } else if (kIndex_8_SkColorType == colorType && !src.isOpaque()) {
11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkColorTable* ct = src.getColorTable();
11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (ct) {
11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const SkPMColor* SK_RESTRICT table = ct->lockColors();
11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0);
11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (--h >= 0) {
11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                for (int x = 0; x < w; x++) {
11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    alpha[x] = SkGetPackedA32(table[s[x]]);
11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                s += rb;
11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                alpha += alphaRowBytes;
11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11340a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com            ct->unlockColors();
11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // src is opaque, so just fill alpha[] with 0xFF
11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memset(alpha, 0xFF, h * alphaRowBytes);
11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11391cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    return true;
11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMatrix.h"
11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1146cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.combool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
114757f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com                            Allocator *allocator, SkIPoint* offset) const {
11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1150cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    SkBitmap    tmpBitmap;
11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    identity;
11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMask      srcM, dstM;
11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcM.fBounds.set(0, 0, this->width(), this->height());
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcM.fRowBytes = SkAlign4(this->width());
11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcM.fFormat = SkMask::kA8_Format;
11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMaskFilter* filter = paint ? paint->getMaskFilter() : NULL;
11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // compute our (larger?) dst bounds if we have a filter
11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL != filter) {
11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        identity.reset();
11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        srcM.fImage = NULL;
11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            goto NO_FILTER_CASE;
11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NO_FILTER_CASE:
1170a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
1171cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        if (!tmpBitmap.allocPixels(allocator, NULL)) {
1172cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com            // Allocation of pixels for alpha bitmap failed.
1173cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com            SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1174cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com                    tmpBitmap.width(), tmpBitmap.height());
1175cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com            return false;
1176cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        }
1177cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (offset) {
11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            offset->set(0, 0);
11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1181cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        tmpBitmap.swap(*dst);
1182cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        return true;
11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
118402f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com    srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
118502f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com    SkAutoMaskFreeImage srcCleanup(srcM.fImage);
11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!filter->filterMask(&dstM, srcM, identity, NULL)) {
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        goto NO_FILTER_CASE;
11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
119102f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com    SkAutoMaskFreeImage dstCleanup(dstM.fImage);
11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1193a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
1194a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org                      dstM.fRowBytes);
1195cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    if (!tmpBitmap.allocPixels(allocator, NULL)) {
1196cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        // Allocation of pixels for alpha bitmap failed.
1197cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
1198cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com                tmpBitmap.width(), tmpBitmap.height());
1199cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        return false;
1200cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    }
1201cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (offset) {
12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1205cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    SkDEBUGCODE(tmpBitmap.validate();)
1206cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com
1207cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    tmpBitmap.swap(*dst);
1208cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    return true;
12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1213968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.orgvoid SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
1214968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const SkImageInfo info = bitmap.info();
1215968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkAutoLockPixels alp(bitmap);
1216968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    if (0 == info.width() || 0 == info.height() || NULL == bitmap.getPixels()) {
1217968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        buffer->writeUInt(0); // instead of snugRB, signaling no pixels
1218968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        return;
1219968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
1220968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1221968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t snugRB = info.width() * info.bytesPerPixel();
1222968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const char* src = (const char*)bitmap.getPixels();
1223968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t ramRB = bitmap.rowBytes();
12243c134a97ed128ca95345e13619512df0f42e95f8skia.committer@gmail.com
1225968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    buffer->write32(SkToU32(snugRB));
1226968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    info.flatten(*buffer);
1227968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1228968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t size = snugRB * info.height();
1229968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkAutoMalloc storage(size);
1230968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    char* dst = (char*)storage.get();
1231968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    for (int y = 0; y < info.height(); ++y) {
1232968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        memcpy(dst, src, snugRB);
1233968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        dst += snugRB;
1234968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        src += ramRB;
1235968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
1236968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    buffer->writeByteArray(storage.get(), size);
1237968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1238968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkColorTable* ct = bitmap.getColorTable();
1239968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    if (kIndex_8_SkColorType == info.colorType() && ct) {
1240968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        buffer->writeBool(true);
1241968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        ct->writeToBuffer(*buffer);
1242968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    } else {
1243968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        buffer->writeBool(false);
1244968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
1245968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org}
1246968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1247968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.orgbool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
1248968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t snugRB = buffer->readUInt();
1249968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    if (0 == snugRB) {  // no pixels
1250968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        return false;
1251968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
1252968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1253968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkImageInfo info;
1254968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    info.unflatten(*buffer);
1255968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1256968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t ramRB = info.minRowBytes();
1257968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const int height = info.height();
1258968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t snugSize = snugRB * height;
1259968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    const size_t ramSize = ramRB * height;
126005858435ee8744de863be7e5ade05e4fd6edfb46commit-bot@chromium.org    if (!buffer->validate(snugSize <= ramSize)) {
126105858435ee8744de863be7e5ade05e4fd6edfb46commit-bot@chromium.org        return false;
126205858435ee8744de863be7e5ade05e4fd6edfb46commit-bot@chromium.org    }
1263968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1264968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    char* dst = (char*)sk_malloc_throw(ramSize);
1265968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    buffer->readByteArray(dst, snugSize);
1266968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkAutoDataUnref data(SkData::NewFromMalloc(dst, ramSize));
1267968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
1268968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    if (snugSize != ramSize) {
1269968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        const char* srcRow = dst + snugRB * (height - 1);
1270968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        char* dstRow = dst + ramRB * (height - 1);
1271968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        for (int y = height - 1; y >= 1; --y) {
1272968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org            memmove(dstRow, srcRow, snugRB);
1273968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org            srcRow -= snugRB;
1274968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org            dstRow -= ramRB;
1275968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        }
1276968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        SkASSERT(srcRow == dstRow); // first row does not need to be moved
1277968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
12783c134a97ed128ca95345e13619512df0f42e95f8skia.committer@gmail.com
1279968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkAutoTUnref<SkColorTable> ctable;
1280968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    if (buffer->readBool()) {
1281968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org        ctable.reset(SkNEW_ARGS(SkColorTable, (*buffer)));
1282968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    }
12833c134a97ed128ca95345e13619512df0f42e95f8skia.committer@gmail.com
1284968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewWithData(info, info.minRowBytes(),
1285968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org                                                              ctable.get(), data.get()));
1286a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    bitmap->setInfo(pr->info());
1287968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    bitmap->setPixelRef(pr, 0, 0);
1288968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org    return true;
1289968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org}
1290968edcafa61442dc4f7f8ed8f89523d0f353e9fbcommit-bot@chromium.org
12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comenum {
12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SERIALIZE_PIXELTYPE_NONE,
129321830d90096d2dccc4168d99a427e78035ce942adjsollen@google.com    SERIALIZE_PIXELTYPE_REF_DATA
12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1296851155c28e18e3f5b702ef15ee7bfb12f3cbacdacommit-bot@chromium.orgvoid SkBitmap::legacyUnflatten(SkReadBuffer& buffer) {
12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->reset();
1298f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
129961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkImageInfo info;
130061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    info.unflatten(buffer);
130161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    size_t rowBytes = buffer.readInt();
130233fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org    if (!buffer.validate((info.width() >= 0) && (info.height() >= 0) &&
130333fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org                         SkColorTypeIsValid(info.fColorType) &&
130433fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org                         SkAlphaTypeIsValid(info.fAlphaType) &&
130533fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org                         validate_alphaType(info.fColorType, info.fAlphaType) &&
130633fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org                         info.validRowBytes(rowBytes))) {
130733fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org        return;
130833fed14b1d4867015ac518874013e0b3e06ea982commit-bot@chromium.org    }
1309f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
1310a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    bool configIsValid = this->setInfo(info, rowBytes);
131161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    buffer.validate(configIsValid);
1312f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
1313c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    int reftype = buffer.readInt();
1314ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) ||
1315ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                        (SERIALIZE_PIXELTYPE_NONE == reftype))) {
1316ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        switch (reftype) {
1317ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            case SERIALIZE_PIXELTYPE_REF_DATA: {
1318672588b684d484dce6ae251e9e163e4a46924322reed@google.com                SkIPoint origin;
1319672588b684d484dce6ae251e9e163e4a46924322reed@google.com                origin.fX = buffer.readInt();
1320672588b684d484dce6ae251e9e163e4a46924322reed@google.com                origin.fY = buffer.readInt();
132161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org                size_t offset = origin.fY * rowBytes + origin.fX * info.bytesPerPixel();
1322ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                SkPixelRef* pr = buffer.readPixelRef();
1323cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org                if (!buffer.validate((NULL == pr) ||
1324cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org                       (pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) {
1325672588b684d484dce6ae251e9e163e4a46924322reed@google.com                    origin.setZero();
1326cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org                }
1327672588b684d484dce6ae251e9e163e4a46924322reed@google.com                SkSafeUnref(this->setPixelRef(pr, origin));
1328ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                break;
1329ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            }
1330ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            case SERIALIZE_PIXELTYPE_NONE:
1331ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                break;
1332ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            default:
1333ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                SkDEBUGFAIL("unrecognized pixeltype in serialized data");
1334ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                sk_throw();
13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap::RLEPixels::RLEPixels(int width, int height) {
13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fHeight = height;
1343235002fb127fc5b7564910434faed84337c08238commit-bot@chromium.org    fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*));
13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBitmap::RLEPixels::~RLEPixels() {
13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fYPtrs);
13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBitmap::validate() const {
135461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    fInfo.validate();
1355d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org
1356d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    // ImageInfo may not require this, but Bitmap ensures that opaque-only
1357d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    // colorTypes report opaque for their alphatype
1358d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    if (kRGB_565_SkColorType == fInfo.colorType()) {
1359d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org        SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
1360d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org    }
1361d5414e5efe0a6a0bce0b5499e2358e2be4cb9b61commit-bot@chromium.org
136261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkASSERT(fInfo.validRowBytes(fRowBytes));
13638e990eb440e0f61386ba21b06b8428d5b285c341scroggo@google.com    uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag;
13648e990eb440e0f61386ba21b06b8428d5b285c341scroggo@google.com#ifdef SK_BUILD_FOR_ANDROID
13658e990eb440e0f61386ba21b06b8428d5b285c341scroggo@google.com    allFlags |= kHasHardwareMipMap_Flag;
13668e990eb440e0f61386ba21b06b8428d5b285c341scroggo@google.com#endif
13678e990eb440e0f61386ba21b06b8428d5b285c341scroggo@google.com    SkASSERT(fFlags <= allFlags);
13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fPixelLockCount >= 0);
13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1370615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com    if (fPixels) {
1371615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelRef);
1372615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelLockCount > 0);
1373615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelRef->isLocked());
1374615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelRef->rowBytes() == fRowBytes);
1375615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelRefOrigin.fX >= 0);
1376615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(fPixelRefOrigin.fY >= 0);
137761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
137861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        SkASSERT(fPixelRef->info().fHeight >= (int)this->height() + fPixelRefOrigin.fY);
137961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org        SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
1380615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com    } else {
1381615316cefbf16382f6a99c72d88a13d2be1d2408reed@google.com        SkASSERT(NULL == fColorTable);
13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
138576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
13860f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
138776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkBitmap::toString(SkString* str) const {
138876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
1389cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org    static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
1390cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org        "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
139176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    };
139276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
139376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
1394cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org                 gColorTypeNames[this->colorType()]);
139576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
139676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(" (");
139776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    if (this->isOpaque()) {
139876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append("opaque");
139976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    } else {
140076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append("transparent");
140176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    }
140276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    if (this->isImmutable()) {
140376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append(", immutable");
140476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    } else {
140576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append(", not-immutable");
140676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    }
140776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(")");
140876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
140976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    SkPixelRef* pr = this->pixelRef();
141076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    if (NULL == pr) {
141176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        // show null or the explicit pixel address (rare)
141276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->appendf(" pixels:%p", this->getPixels());
141376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    } else {
141476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        const char* uri = pr->getURI();
141576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        if (NULL != uri) {
141676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com            str->appendf(" uri:\"%s\"", uri);
141776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        } else {
141876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com            str->appendf(" pixelref:%p", pr);
141976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        }
142076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    }
142176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
142276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    str->append(")");
142376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com}
142476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif
142561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org
142661e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
142761e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org
142861e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org#ifdef SK_DEBUG
142961e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.orgvoid SkImageInfo::validate() const {
143061e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkASSERT(fWidth >= 0);
143161e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkASSERT(fHeight >= 0);
143261e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkASSERT(SkColorTypeIsValid(fColorType));
143361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkASSERT(SkAlphaTypeIsValid(fAlphaType));
143461e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org}
143561e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org#endif
1436