1 /* 2 * Copyright (C) 2006-2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "SkBitmap.h" 18 #include "SkFlattenable.h" 19 #include "SkStream.h" 20 #include "SkTemplates.h" 21 22 SkColorTable::SkColorTable(int count) 23 : f16BitCache(NULL), fFlags(0) 24 { 25 if (count < 0) 26 count = 0; 27 else if (count > 256) 28 count = 256; 29 30 fCount = SkToU16(count); 31 fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor)); 32 memset(fColors, 0, count * sizeof(SkPMColor)); 33 34 SkDEBUGCODE(fColorLockCount = 0;) 35 SkDEBUGCODE(f16BitCacheLockCount = 0;) 36 } 37 38 // call SkRefCnt's constructor explicitly, to avoid warning 39 SkColorTable::SkColorTable(const SkColorTable& src) : SkRefCnt() { 40 f16BitCache = NULL; 41 fFlags = src.fFlags; 42 int count = src.count(); 43 fCount = SkToU16(count); 44 fColors = reinterpret_cast<SkPMColor*>( 45 sk_malloc_throw(count * sizeof(SkPMColor))); 46 memcpy(fColors, src.fColors, count * sizeof(SkPMColor)); 47 48 SkDEBUGCODE(fColorLockCount = 0;) 49 SkDEBUGCODE(f16BitCacheLockCount = 0;) 50 } 51 52 SkColorTable::SkColorTable(const SkPMColor colors[], int count) 53 : f16BitCache(NULL), fFlags(0) 54 { 55 if (count < 0) 56 count = 0; 57 else if (count > 256) 58 count = 256; 59 60 fCount = SkToU16(count); 61 fColors = reinterpret_cast<SkPMColor*>( 62 sk_malloc_throw(count * sizeof(SkPMColor))); 63 64 if (colors) 65 memcpy(fColors, colors, count * sizeof(SkPMColor)); 66 67 SkDEBUGCODE(fColorLockCount = 0;) 68 SkDEBUGCODE(f16BitCacheLockCount = 0;) 69 } 70 71 SkColorTable::~SkColorTable() 72 { 73 SkASSERT(fColorLockCount == 0); 74 SkASSERT(f16BitCacheLockCount == 0); 75 76 sk_free(fColors); 77 sk_free(f16BitCache); 78 } 79 80 void SkColorTable::setFlags(unsigned flags) 81 { 82 fFlags = SkToU8(flags); 83 } 84 85 void SkColorTable::unlockColors(bool changed) 86 { 87 SkASSERT(fColorLockCount != 0); 88 SkDEBUGCODE(fColorLockCount -= 1;) 89 if (changed) 90 this->inval16BitCache(); 91 } 92 93 void SkColorTable::inval16BitCache() 94 { 95 SkASSERT(f16BitCacheLockCount == 0); 96 if (f16BitCache) 97 { 98 sk_free(f16BitCache); 99 f16BitCache = NULL; 100 } 101 } 102 103 #include "SkColorPriv.h" 104 105 static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count) 106 { 107 while (--count >= 0) 108 *dst++ = SkPixel32ToPixel16_ToU16(*src++); 109 } 110 111 const uint16_t* SkColorTable::lock16BitCache() 112 { 113 if (fFlags & kColorsAreOpaque_Flag) 114 { 115 if (f16BitCache == NULL) // build the cache 116 { 117 f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t)); 118 build_16bitcache(f16BitCache, fColors, fCount); 119 } 120 } 121 else // our colors have alpha, so no cache 122 { 123 this->inval16BitCache(); 124 if (f16BitCache) 125 { 126 sk_free(f16BitCache); 127 f16BitCache = NULL; 128 } 129 } 130 131 SkDEBUGCODE(f16BitCacheLockCount += 1); 132 return f16BitCache; 133 } 134 135 void SkColorTable::setIsOpaque(bool isOpaque) { 136 if (isOpaque) { 137 fFlags |= kColorsAreOpaque_Flag; 138 } else { 139 fFlags &= ~kColorsAreOpaque_Flag; 140 } 141 } 142 143 /////////////////////////////////////////////////////////////////////////////// 144 145 SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) { 146 f16BitCache = NULL; 147 SkDEBUGCODE(fColorLockCount = 0;) 148 SkDEBUGCODE(f16BitCacheLockCount = 0;) 149 150 fCount = buffer.readU16(); 151 SkASSERT((unsigned)fCount <= 256); 152 153 fFlags = buffer.readU8(); 154 155 fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor)); 156 buffer.read(fColors, fCount * sizeof(SkPMColor)); 157 } 158 159 void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const { 160 int count = this->count(); 161 buffer.write16(count); 162 buffer.write8(this->getFlags()); 163 buffer.writeMul4(fColors, count * sizeof(SkPMColor)); 164 } 165 166