/* * Copyright 2009 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkBitmap.h" #include "SkFlattenable.h" #include "SkStream.h" #include "SkTemplates.h" SkColorTable::SkColorTable(int count) : f16BitCache(NULL), fFlags(0) { if (count < 0) count = 0; else if (count > 256) count = 256; fCount = SkToU16(count); fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor)); memset(fColors, 0, count * sizeof(SkPMColor)); SkDEBUGCODE(fColorLockCount = 0;) SkDEBUGCODE(f16BitCacheLockCount = 0;) } // call SkRefCnt's constructor explicitly, to avoid warning SkColorTable::SkColorTable(const SkColorTable& src) : SkRefCnt() { f16BitCache = NULL; fFlags = src.fFlags; int count = src.count(); fCount = SkToU16(count); fColors = reinterpret_cast( sk_malloc_throw(count * sizeof(SkPMColor))); memcpy(fColors, src.fColors, count * sizeof(SkPMColor)); SkDEBUGCODE(fColorLockCount = 0;) SkDEBUGCODE(f16BitCacheLockCount = 0;) } SkColorTable::SkColorTable(const SkPMColor colors[], int count) : f16BitCache(NULL), fFlags(0) { if (count < 0) count = 0; else if (count > 256) count = 256; fCount = SkToU16(count); fColors = reinterpret_cast( sk_malloc_throw(count * sizeof(SkPMColor))); if (colors) memcpy(fColors, colors, count * sizeof(SkPMColor)); SkDEBUGCODE(fColorLockCount = 0;) SkDEBUGCODE(f16BitCacheLockCount = 0;) } SkColorTable::~SkColorTable() { SkASSERT(fColorLockCount == 0); SkASSERT(f16BitCacheLockCount == 0); sk_free(fColors); sk_free(f16BitCache); } void SkColorTable::setFlags(unsigned flags) { fFlags = SkToU8(flags); } void SkColorTable::unlockColors(bool changed) { SkASSERT(fColorLockCount != 0); SkDEBUGCODE(fColorLockCount -= 1;) if (changed) this->inval16BitCache(); } void SkColorTable::inval16BitCache() { SkASSERT(f16BitCacheLockCount == 0); if (f16BitCache) { sk_free(f16BitCache); f16BitCache = NULL; } } #include "SkColorPriv.h" static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count) { while (--count >= 0) *dst++ = SkPixel32ToPixel16_ToU16(*src++); } const uint16_t* SkColorTable::lock16BitCache() { if (fFlags & kColorsAreOpaque_Flag) { if (f16BitCache == NULL) // build the cache { f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t)); build_16bitcache(f16BitCache, fColors, fCount); } } else // our colors have alpha, so no cache { this->inval16BitCache(); if (f16BitCache) { sk_free(f16BitCache); f16BitCache = NULL; } } SkDEBUGCODE(f16BitCacheLockCount += 1); return f16BitCache; } void SkColorTable::setIsOpaque(bool isOpaque) { if (isOpaque) { fFlags |= kColorsAreOpaque_Flag; } else { fFlags &= ~kColorsAreOpaque_Flag; } } /////////////////////////////////////////////////////////////////////////////// SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) { f16BitCache = NULL; SkDEBUGCODE(fColorLockCount = 0;) SkDEBUGCODE(f16BitCacheLockCount = 0;) fCount = buffer.readU16(); SkASSERT((unsigned)fCount <= 256); fFlags = buffer.readU8(); fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor)); buffer.read(fColors, fCount * sizeof(SkPMColor)); } void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const { int count = this->count(); buffer.write16(count); buffer.write8(this->getFlags()); buffer.writeMul4(fColors, count * sizeof(SkPMColor)); }