11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
211285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2009 The Android Open Source Project
411285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
711285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed */
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBitmap.h"
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFlattenable.h"
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStream.h"
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTemplates.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkColorTable::SkColorTable(int count)
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    : f16BitCache(NULL), fFlags(0)
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count < 0)
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        count = 0;
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (count > 256)
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        count = 256;
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCount = SkToU16(count);
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    memset(fColors, 0, count * sizeof(SkPMColor));
2611285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
2711285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    SkDEBUGCODE(fColorLockCount = 0;)
2811285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    SkDEBUGCODE(f16BitCacheLockCount = 0;)
2911285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed}
3011285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
31dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed// call SkRefCnt's constructor explicitly, to avoid warning
32dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike ReedSkColorTable::SkColorTable(const SkColorTable& src) : SkRefCnt() {
3311285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    f16BitCache = NULL;
3411285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    fFlags = src.fFlags;
3511285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    int count = src.count();
3611285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    fCount = SkToU16(count);
3711285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    fColors = reinterpret_cast<SkPMColor*>(
3811285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed                                    sk_malloc_throw(count * sizeof(SkPMColor)));
3911285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    memcpy(fColors, src.fColors, count * sizeof(SkPMColor));
4011285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(fColorLockCount = 0;)
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(f16BitCacheLockCount = 0;)
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkColorTable::SkColorTable(const SkPMColor colors[], int count)
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    : f16BitCache(NULL), fFlags(0)
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count < 0)
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        count = 0;
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (count > 256)
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        count = 256;
5211285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCount = SkToU16(count);
5411285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed    fColors = reinterpret_cast<SkPMColor*>(
5511285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed                                    sk_malloc_throw(count * sizeof(SkPMColor)));
5611285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (colors)
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        memcpy(fColors, colors, count * sizeof(SkPMColor));
5911285a304c143d1bdf3a1e321803cfcc8a6a938cMike Reed
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(fColorLockCount = 0;)
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(f16BitCacheLockCount = 0;)
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkColorTable::~SkColorTable()
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fColorLockCount == 0);
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(f16BitCacheLockCount == 0);
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    sk_free(fColors);
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    sk_free(f16BitCache);
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkColorTable::setFlags(unsigned flags)
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fFlags = SkToU8(flags);
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkColorTable::unlockColors(bool changed)
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fColorLockCount != 0);
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(fColorLockCount -= 1;)
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (changed)
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->inval16BitCache();
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkColorTable::inval16BitCache()
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(f16BitCacheLockCount == 0);
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (f16BitCache)
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_free(f16BitCache);
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        f16BitCache = NULL;
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColorPriv.h"
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count)
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (--count >= 0)
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst++ = SkPixel32ToPixel16_ToU16(*src++);
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst uint16_t* SkColorTable::lock16BitCache()
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fFlags & kColorsAreOpaque_Flag)
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (f16BitCache == NULL) // build the cache
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            build_16bitcache(f16BitCache, fColors, fCount);
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else    // our colors have alpha, so no cache
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->inval16BitCache();
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (f16BitCache)
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            sk_free(f16BitCache);
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            f16BitCache = NULL;
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(f16BitCacheLockCount += 1);
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return f16BitCache;
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1283026a9ec59b285412941d278a570e382088f8adaMike Reedvoid SkColorTable::setIsOpaque(bool isOpaque) {
1293026a9ec59b285412941d278a570e382088f8adaMike Reed    if (isOpaque) {
1303026a9ec59b285412941d278a570e382088f8adaMike Reed        fFlags |= kColorsAreOpaque_Flag;
1313026a9ec59b285412941d278a570e382088f8adaMike Reed    } else {
1323026a9ec59b285412941d278a570e382088f8adaMike Reed        fFlags &= ~kColorsAreOpaque_Flag;
1333026a9ec59b285412941d278a570e382088f8adaMike Reed    }
1343026a9ec59b285412941d278a570e382088f8adaMike Reed}
1353026a9ec59b285412941d278a570e382088f8adaMike Reed
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    f16BitCache = NULL;
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(fColorLockCount = 0;)
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(f16BitCacheLockCount = 0;)
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCount = buffer.readU16();
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((unsigned)fCount <= 256);
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fFlags = buffer.readU8();
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.read(fColors, fCount * sizeof(SkPMColor));
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int count = this->count();
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write16(count);
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write8(this->getFlags());
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.writeMul4(fColors, count * sizeof(SkPMColor));
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
159