SkColorTable.cpp revision 3026a9ec59b285412941d278a570e382088f8ada
111285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed/*
211285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed * Copyright (C) 2006-2009 The Android Open Source Project
311285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed *
411285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed * Licensed under the Apache License, Version 2.0 (the "License");
511285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed * you may not use this file except in compliance with the License.
611285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed * You may obtain a copy of the License at
711285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed *
811285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed *      http://www.apache.org/licenses/LICENSE-2.0
911285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed *
1011285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed * Unless required by applicable law or agreed to in writing, software
1111285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed * distributed under the License is distributed on an "AS IS" BASIS,
1211285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1311285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed * See the License for the specific language governing permissions and
1411285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed * limitations under the License.
1511285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed */
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBitmap.h"
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFlattenable.h"
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStream.h"
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTemplates.h"
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkColorTable::SkColorTable(int count)
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    : f16BitCache(NULL), fFlags(0)
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count < 0)
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        count = 0;
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (count > 256)
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        count = 256;
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCount = SkToU16(count);
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    memset(fColors, 0, count * sizeof(SkPMColor));
3311285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
3411285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    SkDEBUGCODE(fColorLockCount = 0;)
3511285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    SkDEBUGCODE(f16BitCacheLockCount = 0;)
3611285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed}
3711285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
38dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed// call SkRefCnt's constructor explicitly, to avoid warning
39dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike ReedSkColorTable::SkColorTable(const SkColorTable& src) : SkRefCnt() {
4011285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    f16BitCache = NULL;
4111285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    fFlags = src.fFlags;
4211285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    int count = src.count();
4311285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    fCount = SkToU16(count);
4411285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    fColors = reinterpret_cast<SkPMColor*>(
4511285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed                                    sk_malloc_throw(count * sizeof(SkPMColor)));
4611285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    memcpy(fColors, src.fColors, count * sizeof(SkPMColor));
4711285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(fColorLockCount = 0;)
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(f16BitCacheLockCount = 0;)
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkColorTable::SkColorTable(const SkPMColor colors[], int count)
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    : f16BitCache(NULL), fFlags(0)
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count < 0)
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        count = 0;
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (count > 256)
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        count = 256;
5911285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCount = SkToU16(count);
6111285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    fColors = reinterpret_cast<SkPMColor*>(
6211285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed                                    sk_malloc_throw(count * sizeof(SkPMColor)));
6311285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (colors)
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        memcpy(fColors, colors, count * sizeof(SkPMColor));
6611285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(fColorLockCount = 0;)
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(f16BitCacheLockCount = 0;)
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkColorTable::~SkColorTable()
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fColorLockCount == 0);
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(f16BitCacheLockCount == 0);
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    sk_free(fColors);
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    sk_free(f16BitCache);
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkColorTable::setFlags(unsigned flags)
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fFlags = SkToU8(flags);
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkColorTable::unlockColors(bool changed)
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fColorLockCount != 0);
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(fColorLockCount -= 1;)
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (changed)
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->inval16BitCache();
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkColorTable::inval16BitCache()
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(f16BitCacheLockCount == 0);
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (f16BitCache)
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_free(f16BitCache);
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        f16BitCache = NULL;
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColorPriv.h"
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count)
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (--count >= 0)
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst++ = SkPixel32ToPixel16_ToU16(*src++);
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst uint16_t* SkColorTable::lock16BitCache()
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fFlags & kColorsAreOpaque_Flag)
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (f16BitCache == NULL) // build the cache
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            build_16bitcache(f16BitCache, fColors, fCount);
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else    // our colors have alpha, so no cache
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->inval16BitCache();
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (f16BitCache)
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            sk_free(f16BitCache);
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            f16BitCache = NULL;
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(f16BitCacheLockCount += 1);
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return f16BitCache;
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1353026a9ec59b285412941d278a570e382088f8adaMike Reedvoid SkColorTable::setIsOpaque(bool isOpaque) {
1363026a9ec59b285412941d278a570e382088f8adaMike Reed    if (isOpaque) {
1373026a9ec59b285412941d278a570e382088f8adaMike Reed        fFlags |= kColorsAreOpaque_Flag;
1383026a9ec59b285412941d278a570e382088f8adaMike Reed    } else {
1393026a9ec59b285412941d278a570e382088f8adaMike Reed        fFlags &= ~kColorsAreOpaque_Flag;
1403026a9ec59b285412941d278a570e382088f8adaMike Reed    }
1413026a9ec59b285412941d278a570e382088f8adaMike Reed}
1423026a9ec59b285412941d278a570e382088f8adaMike Reed
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    f16BitCache = NULL;
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(fColorLockCount = 0;)
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(f16BitCacheLockCount = 0;)
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCount = buffer.readU16();
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((unsigned)fCount <= 256);
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fFlags = buffer.readU8();
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.read(fColors, fCount * sizeof(SkPMColor));
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int count = this->count();
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write16(count);
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write8(this->getFlags());
1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeMul4(fColors, count * sizeof(SkPMColor));
1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
166