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
SkColorTable(int count)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
SkColorTable(const SkColorTable & src)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
SkColorTable(const SkPMColor colors[],int count)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
~SkColorTable()71 SkColorTable::~SkColorTable()
72 {
73 SkASSERT(fColorLockCount == 0);
74 SkASSERT(f16BitCacheLockCount == 0);
75
76 sk_free(fColors);
77 sk_free(f16BitCache);
78 }
79
setFlags(unsigned flags)80 void SkColorTable::setFlags(unsigned flags)
81 {
82 fFlags = SkToU8(flags);
83 }
84
unlockColors(bool changed)85 void SkColorTable::unlockColors(bool changed)
86 {
87 SkASSERT(fColorLockCount != 0);
88 SkDEBUGCODE(fColorLockCount -= 1;)
89 if (changed)
90 this->inval16BitCache();
91 }
92
inval16BitCache()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
build_16bitcache(uint16_t dst[],const SkPMColor src[],int count)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
lock16BitCache()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
setIsOpaque(bool isOpaque)135 void SkColorTable::setIsOpaque(bool isOpaque) {
136 if (isOpaque) {
137 fFlags |= kColorsAreOpaque_Flag;
138 } else {
139 fFlags &= ~kColorsAreOpaque_Flag;
140 }
141 }
142
143 ///////////////////////////////////////////////////////////////////////////////
144
SkColorTable(SkFlattenableReadBuffer & buffer)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
flatten(SkFlattenableWriteBuffer & buffer) const159 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