1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2009 The Android Open Source Project
4a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@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.
7a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
1064a0ec36555352ec31aa7c5a7630a5d042b010badjsollen@google.com#include "SkColorTable.h"
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
162999f789c7e66a31066414f4b8fffb3148b677c5reed@google.com// As copy constructor is hidden in the class hierarchy, we need to call
172999f789c7e66a31066414f4b8fffb3148b677c5reed@google.com// default constructor explicitly to suppress a compiler warning.
182999f789c7e66a31066414f4b8fffb3148b677c5reed@google.comSkColorTable::SkColorTable(const SkColorTable& src) : INHERITED() {
19f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com    f16BitCache = NULL;
200a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    fAlphaType = src.fAlphaType;
21f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com    int count = src.count();
22f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com    fCount = SkToU16(count);
23a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com    fColors = reinterpret_cast<SkPMColor*>(
24a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com                                    sk_malloc_throw(count * sizeof(SkPMColor)));
25f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com    memcpy(fColors, src.fColors, count * sizeof(SkPMColor));
26f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(fColorLockCount = 0;)
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(f16BitCacheLockCount = 0;)
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
310a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comSkColorTable::SkColorTable(const SkPMColor colors[], int count, SkAlphaType at)
320a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    : f16BitCache(NULL), fAlphaType(SkToU8(at))
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
3449f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(0 == count || colors);
350a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com
360a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    if (count < 0) {
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count = 0;
380a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    } else if (count > 256) {
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count = 256;
400a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    }
41f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fCount = SkToU16(count);
43a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com    fColors = reinterpret_cast<SkPMColor*>(
44a6260ff5696e3ae45f295463eaeada2cd75a8b85reed@android.com                                    sk_malloc_throw(count * sizeof(SkPMColor)));
45f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
460a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    memcpy(fColors, colors, count * sizeof(SkPMColor));
47f9ab99aaade8c451c0e9309b4c61a448373019e3weita@google.com
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(fColorLockCount = 0;)
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(f16BitCacheLockCount = 0;)
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkColorTable::~SkColorTable()
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fColorLockCount == 0);
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(f16BitCacheLockCount == 0);
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fColors);
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(f16BitCache);
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
610a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comvoid SkColorTable::unlockColors() {
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fColorLockCount != 0);
63c9ab987efcb7e8b69237d565f73c28c137610232djsollen@google.com    SkDEBUGCODE(sk_atomic_dec(&fColorLockCount);)
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
680a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comstatic inline void build_16bitcache(uint16_t dst[], const SkPMColor src[],
690a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com                                    int count) {
700a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    while (--count >= 0) {
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst++ = SkPixel32ToPixel16_ToU16(*src++);
720a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    }
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
750a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.comconst uint16_t* SkColorTable::lock16BitCache() {
760a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    if (this->isOpaque() && NULL == f16BitCache) {
770a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com        f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
780a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com        build_16bitcache(f16BitCache, fColors, fCount);
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(f16BitCacheLockCount += 1);
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return f16BitCache;
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
878b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkColorTable::SkColorTable(SkReadBuffer& buffer) {
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    f16BitCache = NULL;
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(fColorLockCount = 0;)
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(f16BitCacheLockCount = 0;)
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
920a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    fAlphaType = SkToU8(buffer.readUInt());
93c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    fCount = buffer.getArrayCount();
94ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org    size_t allocSize = fCount * sizeof(SkPMColor);
95ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org    SkDEBUGCODE(bool success = false;)
96ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org    if (buffer.validateAvailable(allocSize)) {
97ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org        fColors = (SkPMColor*)sk_malloc_throw(allocSize);
98ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org        SkDEBUGCODE(success =) buffer.readColorArray(fColors, fCount);
99ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org    } else {
100ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org        fCount = 0;
101ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org        fColors = NULL;
102ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org    }
10357313f6472684b14570562e43e84f5e2d6fcf278bsalomon@google.com#ifdef SK_DEBUG
104c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    SkASSERT((unsigned)fCount <= 256);
105025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    SkASSERT(success);
10657313f6472684b14570562e43e84f5e2d6fcf278bsalomon@google.com#endif
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1098b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkColorTable::writeToBuffer(SkWriteBuffer& buffer) const {
1100a6151d66cc32d91eca037c91e557158cf8a2be2reed@google.com    buffer.writeUInt(fAlphaType);
111c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    buffer.writeColorArray(fColors, fCount);
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
113