1 2 /* 3 * Copyright 2009 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkBitmap.h" 11 #include "SkFlattenable.h" 12 #include "SkStream.h" 13 #include "SkTemplates.h" 14 15 SkColorTable::SkColorTable(int count) 16 : f16BitCache(NULL), fFlags(0) 17 { 18 if (count < 0) 19 count = 0; 20 else if (count > 256) 21 count = 256; 22 23 fCount = SkToU16(count); 24 fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor)); 25 memset(fColors, 0, count * sizeof(SkPMColor)); 26 27 SkDEBUGCODE(fColorLockCount = 0;) 28 SkDEBUGCODE(f16BitCacheLockCount = 0;) 29 } 30 31 // call SkRefCnt's constructor explicitly, to avoid warning 32 SkColorTable::SkColorTable(const SkColorTable& src) : SkRefCnt() { 33 f16BitCache = NULL; 34 fFlags = src.fFlags; 35 int count = src.count(); 36 fCount = SkToU16(count); 37 fColors = reinterpret_cast<SkPMColor*>( 38 sk_malloc_throw(count * sizeof(SkPMColor))); 39 memcpy(fColors, src.fColors, count * sizeof(SkPMColor)); 40 41 SkDEBUGCODE(fColorLockCount = 0;) 42 SkDEBUGCODE(f16BitCacheLockCount = 0;) 43 } 44 45 SkColorTable::SkColorTable(const SkPMColor colors[], int count) 46 : f16BitCache(NULL), fFlags(0) 47 { 48 if (count < 0) 49 count = 0; 50 else if (count > 256) 51 count = 256; 52 53 fCount = SkToU16(count); 54 fColors = reinterpret_cast<SkPMColor*>( 55 sk_malloc_throw(count * sizeof(SkPMColor))); 56 57 if (colors) 58 memcpy(fColors, colors, count * sizeof(SkPMColor)); 59 60 SkDEBUGCODE(fColorLockCount = 0;) 61 SkDEBUGCODE(f16BitCacheLockCount = 0;) 62 } 63 64 SkColorTable::~SkColorTable() 65 { 66 SkASSERT(fColorLockCount == 0); 67 SkASSERT(f16BitCacheLockCount == 0); 68 69 sk_free(fColors); 70 sk_free(f16BitCache); 71 } 72 73 void SkColorTable::setFlags(unsigned flags) 74 { 75 fFlags = SkToU8(flags); 76 } 77 78 void SkColorTable::unlockColors(bool changed) 79 { 80 SkASSERT(fColorLockCount != 0); 81 SkDEBUGCODE(fColorLockCount -= 1;) 82 if (changed) 83 this->inval16BitCache(); 84 } 85 86 void SkColorTable::inval16BitCache() 87 { 88 SkASSERT(f16BitCacheLockCount == 0); 89 if (f16BitCache) 90 { 91 sk_free(f16BitCache); 92 f16BitCache = NULL; 93 } 94 } 95 96 #include "SkColorPriv.h" 97 98 static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count) 99 { 100 while (--count >= 0) 101 *dst++ = SkPixel32ToPixel16_ToU16(*src++); 102 } 103 104 const uint16_t* SkColorTable::lock16BitCache() 105 { 106 if (fFlags & kColorsAreOpaque_Flag) 107 { 108 if (f16BitCache == NULL) // build the cache 109 { 110 f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t)); 111 build_16bitcache(f16BitCache, fColors, fCount); 112 } 113 } 114 else // our colors have alpha, so no cache 115 { 116 this->inval16BitCache(); 117 if (f16BitCache) 118 { 119 sk_free(f16BitCache); 120 f16BitCache = NULL; 121 } 122 } 123 124 SkDEBUGCODE(f16BitCacheLockCount += 1); 125 return f16BitCache; 126 } 127 128 void SkColorTable::setIsOpaque(bool isOpaque) { 129 if (isOpaque) { 130 fFlags |= kColorsAreOpaque_Flag; 131 } else { 132 fFlags &= ~kColorsAreOpaque_Flag; 133 } 134 } 135 136 /////////////////////////////////////////////////////////////////////////////// 137 138 SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) { 139 f16BitCache = NULL; 140 SkDEBUGCODE(fColorLockCount = 0;) 141 SkDEBUGCODE(f16BitCacheLockCount = 0;) 142 143 fCount = buffer.readU16(); 144 SkASSERT((unsigned)fCount <= 256); 145 146 fFlags = buffer.readU8(); 147 148 fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor)); 149 buffer.read(fColors, fCount * sizeof(SkPMColor)); 150 } 151 152 void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const { 153 int count = this->count(); 154 buffer.write16(count); 155 buffer.write8(this->getFlags()); 156 buffer.writeMul4(fColors, count * sizeof(SkPMColor)); 157 } 158 159