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 "SkColorTable.h" 11 #include "SkFlattenableBuffers.h" 12 #include "SkStream.h" 13 #include "SkTemplates.h" 14 15 SK_DEFINE_INST_COUNT(SkColorTable) 16 17 SkColorTable::SkColorTable(int count) 18 : f16BitCache(NULL), fFlags(0) 19 { 20 if (count < 0) 21 count = 0; 22 else if (count > 256) 23 count = 256; 24 25 fCount = SkToU16(count); 26 fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor)); 27 memset(fColors, 0, count * sizeof(SkPMColor)); 28 29 SkDEBUGCODE(fColorLockCount = 0;) 30 SkDEBUGCODE(f16BitCacheLockCount = 0;) 31 } 32 33 // As copy constructor is hidden in the class hierarchy, we need to call 34 // default constructor explicitly to suppress a compiler warning. 35 SkColorTable::SkColorTable(const SkColorTable& src) : INHERITED() { 36 f16BitCache = NULL; 37 fFlags = src.fFlags; 38 int count = src.count(); 39 fCount = SkToU16(count); 40 fColors = reinterpret_cast<SkPMColor*>( 41 sk_malloc_throw(count * sizeof(SkPMColor))); 42 memcpy(fColors, src.fColors, count * sizeof(SkPMColor)); 43 44 SkDEBUGCODE(fColorLockCount = 0;) 45 SkDEBUGCODE(f16BitCacheLockCount = 0;) 46 } 47 48 SkColorTable::SkColorTable(const SkPMColor colors[], int count) 49 : f16BitCache(NULL), fFlags(0) 50 { 51 if (count < 0) 52 count = 0; 53 else if (count > 256) 54 count = 256; 55 56 fCount = SkToU16(count); 57 fColors = reinterpret_cast<SkPMColor*>( 58 sk_malloc_throw(count * sizeof(SkPMColor))); 59 60 if (colors) 61 memcpy(fColors, colors, count * sizeof(SkPMColor)); 62 63 SkDEBUGCODE(fColorLockCount = 0;) 64 SkDEBUGCODE(f16BitCacheLockCount = 0;) 65 } 66 67 SkColorTable::~SkColorTable() 68 { 69 SkASSERT(fColorLockCount == 0); 70 SkASSERT(f16BitCacheLockCount == 0); 71 72 sk_free(fColors); 73 sk_free(f16BitCache); 74 } 75 76 void SkColorTable::setFlags(unsigned flags) 77 { 78 fFlags = SkToU8(flags); 79 } 80 81 void SkColorTable::unlockColors(bool changed) 82 { 83 SkASSERT(fColorLockCount != 0); 84 SkDEBUGCODE(sk_atomic_dec(&fColorLockCount);) 85 if (changed) 86 this->inval16BitCache(); 87 } 88 89 void SkColorTable::inval16BitCache() 90 { 91 SkASSERT(f16BitCacheLockCount == 0); 92 if (f16BitCache) 93 { 94 sk_free(f16BitCache); 95 f16BitCache = NULL; 96 } 97 } 98 99 #include "SkColorPriv.h" 100 101 static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count) 102 { 103 while (--count >= 0) 104 *dst++ = SkPixel32ToPixel16_ToU16(*src++); 105 } 106 107 const uint16_t* SkColorTable::lock16BitCache() 108 { 109 if (fFlags & kColorsAreOpaque_Flag) 110 { 111 if (f16BitCache == NULL) // build the cache 112 { 113 f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t)); 114 build_16bitcache(f16BitCache, fColors, fCount); 115 } 116 } 117 else // our colors have alpha, so no cache 118 { 119 this->inval16BitCache(); 120 if (f16BitCache) 121 { 122 sk_free(f16BitCache); 123 f16BitCache = NULL; 124 } 125 } 126 127 SkDEBUGCODE(f16BitCacheLockCount += 1); 128 return f16BitCache; 129 } 130 131 void SkColorTable::setIsOpaque(bool isOpaque) { 132 if (isOpaque) { 133 fFlags |= kColorsAreOpaque_Flag; 134 } else { 135 fFlags &= ~kColorsAreOpaque_Flag; 136 } 137 } 138 139 /////////////////////////////////////////////////////////////////////////////// 140 141 SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) { 142 f16BitCache = NULL; 143 SkDEBUGCODE(fColorLockCount = 0;) 144 SkDEBUGCODE(f16BitCacheLockCount = 0;) 145 146 fFlags = buffer.readUInt(); 147 fCount = buffer.getArrayCount(); 148 fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor)); 149 SkDEBUGCODE(const uint32_t countRead =) buffer.readColorArray(fColors); 150 #ifdef SK_DEBUG 151 SkASSERT((unsigned)fCount <= 256); 152 SkASSERT(countRead == fCount); 153 #endif 154 } 155 156 void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const { 157 buffer.writeUInt(fFlags); 158 buffer.writeColorArray(fColors, fCount); 159 } 160