180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2009 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorTable.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFlattenableBuffers.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkStream.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTemplates.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkColorTable)
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkColorTable::SkColorTable(int count)
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : f16BitCache(NULL), fFlags(0)
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count < 0)
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        count = 0;
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else if (count > 256)
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        count = 256;
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCount = SkToU16(count);
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    memset(fColors, 0, count * sizeof(SkPMColor));
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(fColorLockCount = 0;)
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(f16BitCacheLockCount = 0;)
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// As copy constructor is hidden in the class hierarchy, we need to call
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// default constructor explicitly to suppress a compiler warning.
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkColorTable::SkColorTable(const SkColorTable& src) : INHERITED() {
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    f16BitCache = NULL;
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fFlags = src.fFlags;
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int count = src.count();
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCount = SkToU16(count);
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fColors = reinterpret_cast<SkPMColor*>(
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    sk_malloc_throw(count * sizeof(SkPMColor)));
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    memcpy(fColors, src.fColors, count * sizeof(SkPMColor));
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(fColorLockCount = 0;)
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(f16BitCacheLockCount = 0;)
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkColorTable::SkColorTable(const SkPMColor colors[], int count)
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : f16BitCache(NULL), fFlags(0)
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count < 0)
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        count = 0;
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else if (count > 256)
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        count = 256;
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCount = SkToU16(count);
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fColors = reinterpret_cast<SkPMColor*>(
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    sk_malloc_throw(count * sizeof(SkPMColor)));
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (colors)
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(fColors, colors, count * sizeof(SkPMColor));
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(fColorLockCount = 0;)
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(f16BitCacheLockCount = 0;)
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkColorTable::~SkColorTable()
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fColorLockCount == 0);
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(f16BitCacheLockCount == 0);
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sk_free(fColors);
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sk_free(f16BitCache);
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkColorTable::setFlags(unsigned flags)
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fFlags = SkToU8(flags);
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkColorTable::unlockColors(bool changed)
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fColorLockCount != 0);
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(sk_atomic_dec(&fColorLockCount);)
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (changed)
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->inval16BitCache();
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkColorTable::inval16BitCache()
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(f16BitCacheLockCount == 0);
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (f16BitCache)
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_free(f16BitCache);
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        f16BitCache = NULL;
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h"
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count)
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (--count >= 0)
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *dst++ = SkPixel32ToPixel16_ToU16(*src++);
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst uint16_t* SkColorTable::lock16BitCache()
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fFlags & kColorsAreOpaque_Flag)
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (f16BitCache == NULL) // build the cache
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            build_16bitcache(f16BitCache, fColors, fCount);
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else    // our colors have alpha, so no cache
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->inval16BitCache();
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (f16BitCache)
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            sk_free(f16BitCache);
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            f16BitCache = NULL;
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(f16BitCacheLockCount += 1);
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return f16BitCache;
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkColorTable::setIsOpaque(bool isOpaque) {
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (isOpaque) {
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fFlags |= kColorsAreOpaque_Flag;
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fFlags &= ~kColorsAreOpaque_Flag;
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    f16BitCache = NULL;
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(fColorLockCount = 0;)
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(f16BitCacheLockCount = 0;)
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fFlags = buffer.readUInt();
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCount = buffer.getArrayCount();
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
149d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SkDEBUGCODE(const uint32_t countRead =) buffer.readColorArray(fColors);
150d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEBUG
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((unsigned)fCount <= 256);
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(countRead == fCount);
153d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    buffer.writeUInt(fFlags);
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    buffer.writeColorArray(fColors, fCount);
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
160