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
SkColorTable(int count)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
SkColorTable(const SkColorTable & src)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
SkColorTable(const SkPMColor colors[],int count)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
~SkColorTable()64 SkColorTable::~SkColorTable()
65 {
66 SkASSERT(fColorLockCount == 0);
67 SkASSERT(f16BitCacheLockCount == 0);
68
69 sk_free(fColors);
70 sk_free(f16BitCache);
71 }
72
setFlags(unsigned flags)73 void SkColorTable::setFlags(unsigned flags)
74 {
75 fFlags = SkToU8(flags);
76 }
77
unlockColors(bool changed)78 void SkColorTable::unlockColors(bool changed)
79 {
80 SkASSERT(fColorLockCount != 0);
81 SkDEBUGCODE(fColorLockCount -= 1;)
82 if (changed)
83 this->inval16BitCache();
84 }
85
inval16BitCache()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
build_16bitcache(uint16_t dst[],const SkPMColor src[],int count)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
lock16BitCache()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
setIsOpaque(bool isOpaque)128 void SkColorTable::setIsOpaque(bool isOpaque) {
129 if (isOpaque) {
130 fFlags |= kColorsAreOpaque_Flag;
131 } else {
132 fFlags &= ~kColorsAreOpaque_Flag;
133 }
134 }
135
136 ///////////////////////////////////////////////////////////////////////////////
137
SkColorTable(SkFlattenableReadBuffer & buffer)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
flatten(SkFlattenableWriteBuffer & buffer) const152 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