blob: fcfb444a3f93b8757083c26d0af947e4955b114b [file] [log] [blame]
djsollen@google.comc73dd5c2012-08-07 15:54:32 +00001
reed@google.com02f65f22012-08-06 21:20:05 +00002#include "SkBitmap.h"
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +00003#include "SkTableColorFilter.h"
djsollen@google.comc73dd5c2012-08-07 15:54:32 +00004#include "SkColorPriv.h"
5#include "SkFlattenableBuffers.h"
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +00006#include "SkUnPreMultiply.h"
7
8class SkTable_ColorFilter : public SkColorFilter {
9public:
10 SkTable_ColorFilter(const uint8_t tableA[], const uint8_t tableR[],
11 const uint8_t tableG[], const uint8_t tableB[]) {
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +000012 fBitmap = NULL;
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000013 fFlags = 0;
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +000014
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000015 uint8_t* dst = fStorage;
16 if (tableA) {
17 memcpy(dst, tableA, 256);
18 dst += 256;
19 fFlags |= kA_Flag;
20 }
21 if (tableR) {
22 memcpy(dst, tableR, 256);
23 dst += 256;
24 fFlags |= kR_Flag;
25 }
26 if (tableG) {
27 memcpy(dst, tableG, 256);
28 dst += 256;
29 fFlags |= kG_Flag;
30 }
31 if (tableB) {
32 memcpy(dst, tableB, 256);
33 fFlags |= kB_Flag;
34 }
35 }
36
tomhudson@google.com1bb4be22012-07-24 17:24:21 +000037 virtual ~SkTable_ColorFilter() {
38 SkDELETE(fBitmap);
39 }
40
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +000041 virtual bool asComponentTable(SkBitmap* table) SK_OVERRIDE;
42
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000043 virtual void filterSpan(const SkPMColor src[], int count,
44 SkPMColor dst[]) SK_OVERRIDE;
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000045
djsollen@google.comba28d032012-03-26 17:57:35 +000046 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTable_ColorFilter)
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +000047
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000048protected:
49 SkTable_ColorFilter(SkFlattenableReadBuffer& buffer);
djsollen@google.com54924242012-03-29 15:18:04 +000050 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000051
52private:
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +000053 SkBitmap* fBitmap;
54
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000055 enum {
56 kA_Flag = 1 << 0,
57 kR_Flag = 1 << 1,
58 kG_Flag = 1 << 2,
59 kB_Flag = 1 << 3,
60 };
61 uint8_t fStorage[256 * 4];
62 unsigned fFlags;
63
64 typedef SkColorFilter INHERITED;
65};
66
67static const uint8_t gIdentityTable[] = {
rmistry@google.comfbfcd562012-08-23 18:09:54 +000068 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
69 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
70 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
71 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
72 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
73 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
74 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
75 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
76 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
77 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
78 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
79 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
80 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
81 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
82 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
83 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
84 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
85 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
86 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
87 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
88 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
89 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
90 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
91 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
92 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
93 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
94 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
95 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
96 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
97 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
98 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +000099 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
100};
101
102void SkTable_ColorFilter::filterSpan(const SkPMColor src[], int count,
103 SkPMColor dst[]) {
104 const uint8_t* table = fStorage;
105 const uint8_t* tableA = gIdentityTable;
106 const uint8_t* tableR = gIdentityTable;
107 const uint8_t* tableG = gIdentityTable;
108 const uint8_t* tableB = gIdentityTable;
109 if (fFlags & kA_Flag) {
110 tableA = table; table += 256;
111 }
112 if (fFlags & kR_Flag) {
113 tableR = table; table += 256;
114 }
115 if (fFlags & kG_Flag) {
116 tableG = table; table += 256;
117 }
118 if (fFlags & kB_Flag) {
119 tableB = table;
120 }
121
122 const SkUnPreMultiply::Scale* scaleTable = SkUnPreMultiply::GetScaleTable();
123 for (int i = 0; i < count; ++i) {
124 SkPMColor c = src[i];
125 unsigned a, r, g, b;
126 if (0 == c) {
127 a = r = g = b = 0;
128 } else {
129 a = SkGetPackedA32(c);
130 r = SkGetPackedR32(c);
131 g = SkGetPackedG32(c);
132 b = SkGetPackedB32(c);
133
134 if (a < 255) {
135 SkUnPreMultiply::Scale scale = scaleTable[a];
136 r = SkUnPreMultiply::ApplyScale(scale, r);
137 g = SkUnPreMultiply::ApplyScale(scale, g);
138 b = SkUnPreMultiply::ApplyScale(scale, b);
139 }
140 }
141 dst[i] = SkPremultiplyARGBInline(tableA[a], tableR[r],
142 tableG[g], tableB[b]);
143 }
144}
145
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000146static const uint8_t gCountNibBits[] = {
147 0, 1, 1, 2,
148 1, 2, 2, 3,
149 1, 2, 2, 3,
150 2, 3, 3, 4
151};
152
153#include "SkPackBits.h"
154
djsollen@google.com54924242012-03-29 15:18:04 +0000155void SkTable_ColorFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000156 this->INHERITED::flatten(buffer);
157
158 uint8_t storage[5*256];
159 int count = gCountNibBits[fFlags & 0xF];
160 size_t size = SkPackBits::Pack8(fStorage, count * 256, storage);
161 SkASSERT(size <= sizeof(storage));
162
163// SkDebugf("raw %d packed %d\n", count * 256, size);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000164
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000165 buffer.writeInt(fFlags);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000166 buffer.writeByteArray(storage, size);
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000167}
168
169SkTable_ColorFilter::SkTable_ColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +0000170 fBitmap = NULL;
171
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000172 uint8_t storage[5*256];
173
174 fFlags = buffer.readInt();
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000175
176 size_t size = buffer.getArrayCount();
177 SkASSERT(size <= sizeof(storage));
178 buffer.readByteArray(storage);
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000179
180 size_t raw = SkPackBits::Unpack8(storage, size, fStorage);
181
182 SkASSERT(raw <= sizeof(fStorage));
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000183 size_t count = gCountNibBits[fFlags & 0xF];
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000184 SkASSERT(raw == count * 256);
185}
186
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +0000187bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) {
188 if (table) {
189 if (NULL == fBitmap) {
tomhudson@google.com060ef182012-07-24 12:22:40 +0000190 fBitmap = SkNEW(SkBitmap);
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +0000191 fBitmap->setConfig(SkBitmap::kA8_Config, 256, 4, 256);
192 fBitmap->allocPixels();
twiz@google.com58071162012-07-18 21:41:50 +0000193 uint8_t* bitmapPixels = fBitmap->getAddr8(0, 0);
194 int offset = 0;
195 static const unsigned kFlags[] = { kA_Flag, kR_Flag, kG_Flag, kB_Flag };
196
197 for (int x = 0; x < 4; ++x) {
198 if (!(fFlags & kFlags[x])) {
199 memcpy(bitmapPixels, gIdentityTable, sizeof(gIdentityTable));
200 } else {
201 memcpy(bitmapPixels, fStorage + offset, 256);
202 offset += 256;
203 }
204 bitmapPixels += 256;
205 }
mike@reedtribe.orgf23f5f72012-01-07 03:48:45 +0000206 }
207 *table = *fBitmap;
208 }
209 return true;
210}
211
mike@reedtribe.orga69b48c2011-12-28 20:31:00 +0000212///////////////////////////////////////////////////////////////////////////////
213
214#ifdef SK_CPU_BENDIAN
215#else
216 #define SK_A32_INDEX (3 - (SK_A32_SHIFT >> 3))
217 #define SK_R32_INDEX (3 - (SK_R32_SHIFT >> 3))
218 #define SK_G32_INDEX (3 - (SK_G32_SHIFT >> 3))
219 #define SK_B32_INDEX (3 - (SK_B32_SHIFT >> 3))
220#endif
221
222///////////////////////////////////////////////////////////////////////////////
223
224SkColorFilter* SkTableColorFilter::Create(const uint8_t table[256]) {
225 return SkNEW_ARGS(SkTable_ColorFilter, (table, table, table, table));
226}
227
228SkColorFilter* SkTableColorFilter::CreateARGB(const uint8_t tableA[256],
229 const uint8_t tableR[256],
230 const uint8_t tableG[256],
231 const uint8_t tableB[256]) {
232 return SkNEW_ARGS(SkTable_ColorFilter, (tableA, tableR, tableG, tableB));
233}
djsollen@google.coma2ca41e2012-03-23 19:00:34 +0000234
235SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkTableColorFilter)
236 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTable_ColorFilter)
237SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END