OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkColorPriv.h" | 8 #include "SkColorPriv.h" |
9 #include "SkSwizzler.h" | 9 #include "SkSwizzler.h" |
10 #include "SkTemplates.h" | 10 #include "SkTemplates.h" |
11 | 11 |
12 // index | |
13 | |
14 #define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT) | 12 #define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT) |
15 | 13 |
16 static bool swizzle_index_to_n32(void* SK_RESTRICT dstRow, | 14 // kIndex1, kIndex2, kIndex4 |
17 const uint8_t* SK_RESTRICT src, | 15 |
18 int width, int deltaSrc, int, const SkPMColor c table[]) { | 16 static bool swizzle_small_index_to_n32(void* SK_RESTRICT dstRow, |
17 const uint8_t* SK_RESTRICT src, | |
18 int width, int bitsPerPixel, int, | |
19 const SkPMColor ctable[], | |
20 const SkSwizzler::ColorMasks, | |
21 const SkSwizzler::AlphaOption, bool*, | |
22 bool*) { | |
19 | 23 |
20 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 24 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
21 SkPMColor cc = A32_MASK_IN_PLACE; | 25 SkPMColor cc = A32_MASK_IN_PLACE; |
26 const uint32_t pixelsPerByte = 8 / bitsPerPixel; | |
27 const uint32_t rowBytes = (width + pixelsPerByte - 1) / pixelsPerByte; | |
28 const uint8_t mask = (1 << bitsPerPixel) - 1; | |
29 | |
30 uint32_t x = 0; | |
31 for (uint32_t byte = 0; byte < rowBytes; byte++) { | |
32 uint8_t pixelData = src[byte]; | |
33 for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) { | |
34 uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask; | |
35 dst[x] = ctable[index]; | |
36 cc &= ctable[index]; | |
37 pixelData <<= bitsPerPixel; | |
38 x++; | |
39 } | |
40 } | |
41 return cc != A32_MASK_IN_PLACE; | |
42 } | |
43 | |
44 // kIndex | |
45 | |
46 static bool swizzle_index_to_n32(void* SK_RESTRICT dstRow, | |
47 const uint8_t* SK_RESTRICT src, | |
48 int width, int bitsPerPixel, int, | |
49 const SkPMColor ctable[], | |
50 const SkSwizzler::ColorMasks, | |
51 const SkSwizzler::AlphaOption, bool*, bool*) { | |
52 | |
53 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | |
54 SkPMColor cc = A32_MASK_IN_PLACE; | |
22 for (int x = 0; x < width; x++) { | 55 for (int x = 0; x < width; x++) { |
23 SkPMColor c = ctable[*src]; | 56 SkPMColor c = ctable[*src]; |
24 cc &= c; | 57 cc &= c; |
25 dst[x] = c; | 58 dst[x] = c; |
26 src += deltaSrc; | 59 src++; |
27 } | 60 } |
28 return cc != A32_MASK_IN_PLACE; | 61 return cc != A32_MASK_IN_PLACE; |
29 } | 62 } |
30 | 63 |
31 static bool swizzle_index_to_n32_skipZ(void* SK_RESTRICT dstRow, | 64 static bool swizzle_index_to_n32_skipZ(void* SK_RESTRICT dstRow, |
32 const uint8_t* SK_RESTRICT src, | 65 const uint8_t* SK_RESTRICT src, |
33 int width, int deltaSrc, int, | 66 int width, int bitsPerPixel, int, |
34 const SkPMColor ctable[]) { | 67 const SkPMColor ctable[], |
68 const SkSwizzler::ColorMasks, | |
69 const SkSwizzler::AlphaOption, bool*, | |
70 bool*) { | |
35 | 71 |
36 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 72 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
37 SkPMColor cc = A32_MASK_IN_PLACE; | 73 SkPMColor cc = A32_MASK_IN_PLACE; |
38 for (int x = 0; x < width; x++) { | 74 for (int x = 0; x < width; x++) { |
39 SkPMColor c = ctable[*src]; | 75 SkPMColor c = ctable[*src]; |
40 cc &= c; | 76 cc &= c; |
41 if (c != 0) { | 77 if (c != 0) { |
42 dst[x] = c; | 78 dst[x] = c; |
43 } | 79 } |
80 src++; | |
81 } | |
82 return cc != A32_MASK_IN_PLACE; | |
83 } | |
84 | |
85 #undef A32_MASK_IN_PLACE | |
86 | |
87 // mask | |
88 | |
89 /** | |
90 * | |
91 * Used to convert 1-7 bit color components into 8-bit color components | |
92 * | |
93 */ | |
94 const uint8_t nBitTo8BitlookupTable[] = { | |
95 // 1 bit | |
96 0, 255, | |
97 // 2 bits | |
98 0, 85, 170, 255, | |
99 // 3 bits | |
100 0, 36, 73, 109, 146, 182, 219, 255, | |
101 // 4 bits | |
102 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255, | |
103 // 5 bits | |
104 0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, | |
105 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255, | |
106 // 6 bits | |
107 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, | |
108 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, | |
109 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198, | |
110 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255, | |
111 // 7 bits | |
112 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, | |
113 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, | |
114 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, | |
115 112, 114, 116, 118, 120, 122, 124, 126, 129, 131, 133, 135, 137, 139, 141, | |
116 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, | |
117 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, | |
118 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, | |
119 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 | |
120 }; | |
121 | |
122 /* | |
123 * | |
124 * Convert an n bit component to an 8-bit component | |
125 * | |
126 */ | |
127 static uint8_t convert_n_to_8(uint32_t component, uint32_t n) { | |
128 if (0 == n) { | |
129 return 0; | |
130 } else if (8 > n) { | |
131 return nBitTo8BitlookupTable[(1 << n) - 2 + component]; | |
132 } else if (8 == n) { | |
133 return component; | |
134 } else { | |
135 SkDebugf("Error: too many bits for lookup table.\n"); | |
136 return 0; | |
137 } | |
138 } | |
139 | |
140 /* | |
141 * | |
142 * For a continuous bit mask (ex: 0011100), retrieves the size of the mask and | |
143 * the trailing zeros | |
144 * | |
145 */ | |
146 static void get_mask_info(uint32_t mask, uint32_t bPP, uint32_t* size, | |
147 uint32_t* shift) { | |
148 // For empty masks, set zeros and return | |
149 uint32_t tempMask = mask; | |
150 if (!tempMask) { | |
151 *size = 0; | |
152 *shift = 0; | |
153 return; | |
154 } | |
155 | |
156 // Count trailing zeros | |
157 int zeros = 0; | |
158 for (; !(tempMask & 1); tempMask >>= 1) { | |
159 zeros++; | |
160 } | |
161 | |
162 // Count mask size | |
163 int count = 0; | |
164 for (; tempMask & 1; tempMask >>= 1) { | |
165 count++; | |
166 } | |
167 | |
168 // We will use a maximum of 8 bits for the size, truncate some of the mask | |
169 // bits if necessary | |
170 if (count > 8) { | |
171 *shift = count - 8 + zeros; | |
172 *size = 8; | |
173 } else { | |
174 *shift = zeros; | |
175 *size = count; | |
176 } | |
177 return; | |
178 } | |
179 | |
180 /* | |
181 * | |
182 * Set the alpha channel value based on the input alpha type. The interesting | |
183 * case is kTransparentAsOpaque. We must respect the alpha channel in this | |
184 * case. However, if it is all zeros, we want to display the image as opaque | |
185 * instead of transparent. This may require reseting the loop iterator and | |
186 * reprocessing previous rows. | |
187 * | |
188 */ | |
189 static uint8_t get_alpha(uint8_t alpha, SkSwizzler::AlphaOption opt, | |
190 uint32_t* currIndex, int deltaSrc, | |
191 bool* seenNonZeroAlphaPtr, bool* zeroPrevRowsPtr) { | |
192 switch (opt) { | |
193 case SkSwizzler::kOpaque_AlphaOption: | |
194 return 0xFF; | |
195 case SkSwizzler::kNormal_AlphaOption: | |
196 return alpha; | |
197 case SkSwizzler::kTransparentAsOpaque_AlphaOption: | |
198 if (*seenNonZeroAlphaPtr) { | |
199 return alpha; | |
200 } else if(!alpha) { | |
201 return 0xFF; | |
202 } else { | |
203 *zeroPrevRowsPtr = true; | |
204 *seenNonZeroAlphaPtr = true; | |
205 *currIndex = -deltaSrc; | |
206 return alpha; | |
207 } | |
208 default: | |
209 SkASSERT(false); | |
210 return 0; | |
211 } | |
212 } | |
213 | |
214 // kMask16 | |
215 | |
216 static bool swizzle_mask16_to_n32(void* SK_RESTRICT dstRow, | |
217 const uint8_t* SK_RESTRICT src, | |
218 int width, int bitsPerPixel, int, | |
219 const SkPMColor ctable[], | |
220 const SkSwizzler::ColorMasks masks, | |
221 const SkSwizzler::AlphaOption alphaOption, | |
222 bool* seenNonZeroAlphaPtr, | |
223 bool* zeroPrevRowsPtr) { | |
224 // Load the bit masks | |
225 uint32_t redMask = masks.redMask; | |
scroggo
2015/03/04 17:10:31
Would it be possible to make a function that looks
| |
226 uint32_t greenMask = masks.greenMask; | |
227 uint32_t blueMask = masks.blueMask; | |
228 uint32_t alphaMask = masks.alphaMask; | |
229 uint32_t rBits, rShift, gBits, gShift, bBits, bShift, aBits, aShift; | |
230 get_mask_info(redMask, bitsPerPixel, &rBits, &rShift); | |
231 get_mask_info(greenMask, bitsPerPixel, &gBits, &gShift); | |
232 get_mask_info(blueMask, bitsPerPixel, &bBits, &bShift); | |
233 get_mask_info(alphaMask, bitsPerPixel, &aBits, &aShift); | |
234 | |
235 // Use the masks to decode to the destination | |
236 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | |
237 int deltaSrc = 2; | |
238 for (uint32_t p = 0; p < width * deltaSrc; p += deltaSrc) { | |
239 uint16_t pixel = src[p] | (src[p + 1] << 8); | |
240 uint8_t red = convert_n_to_8((pixel & redMask) >> rShift, rBits); | |
241 uint8_t green = convert_n_to_8((pixel & greenMask) >> gShift, gBits); | |
242 uint8_t blue = convert_n_to_8((pixel & blueMask) >> bShift, bBits); | |
243 uint8_t alpha = convert_n_to_8((pixel & alphaMask) >> aShift, aBits); | |
244 // Call to get_alpha may reset the loop iterator. | |
245 // We will get a safe result cell before this call. | |
246 SkPMColor* dstCell = &dst[p/deltaSrc]; | |
247 uint8_t trueAlpha = get_alpha(alpha, alphaOption, &p, deltaSrc, | |
248 seenNonZeroAlphaPtr, zeroPrevRowsPtr); | |
249 *dstCell = SkPreMultiplyARGB(trueAlpha, red, green, blue); | |
250 } | |
251 return *seenNonZeroAlphaPtr; | |
scroggo
2015/03/04 17:10:31
I think this is not want you want to return. The f
| |
252 } | |
253 | |
254 // kMask24 | |
255 | |
256 static bool swizzle_mask24_to_n32(void* SK_RESTRICT dstRow, | |
257 const uint8_t* SK_RESTRICT src, | |
258 int width, int bitsPerPixel, int, | |
259 const SkPMColor ctable[], | |
260 const SkSwizzler::ColorMasks masks, | |
261 const SkSwizzler::AlphaOption alphaOption, | |
262 bool* seenNonZeroAlphaPtr, | |
263 bool* zeroPrevRowsPtr) { | |
scroggo
2015/03/04 17:10:31
I'm trying to figure out how we can cut down on th
| |
264 // Load the bit masks | |
265 uint32_t redMask = masks.redMask; | |
266 uint32_t greenMask = masks.greenMask; | |
267 uint32_t blueMask = masks.blueMask; | |
268 uint32_t alphaMask = masks.alphaMask; | |
269 uint32_t rBits, rShift, gBits, gShift, bBits, bShift, aBits, aShift; | |
270 get_mask_info(redMask, bitsPerPixel, &rBits, &rShift); | |
271 get_mask_info(greenMask, bitsPerPixel, &gBits, &gShift); | |
272 get_mask_info(blueMask, bitsPerPixel, &bBits, &bShift); | |
273 get_mask_info(alphaMask, bitsPerPixel, &aBits, &aShift); | |
274 | |
275 // Use the masks to decode to the destination | |
276 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | |
277 int x = 0; | |
278 int deltaSrc = 3; | |
279 for (uint32_t p = 0; p < width * deltaSrc; p += deltaSrc) { | |
280 uint32_t pixel = src[p] | (src[p + 1] << 8) | src[p + 2] << 16; | |
281 uint8_t red = convert_n_to_8((pixel & redMask) >> rShift, rBits); | |
282 uint8_t green = convert_n_to_8((pixel & greenMask) >> gShift, gBits); | |
283 uint8_t blue = convert_n_to_8((pixel & blueMask) >> bShift, bBits); | |
284 uint8_t alpha = convert_n_to_8((pixel & alphaMask) >> aShift, aBits); | |
285 // Call to get_alpha may reset the loop iterator. | |
286 // We will get a safe result cell before this call. | |
287 SkPMColor* dstCell = &dst[p/deltaSrc]; | |
288 uint8_t trueAlpha = get_alpha(alpha, alphaOption, &p, deltaSrc, | |
289 seenNonZeroAlphaPtr, zeroPrevRowsPtr); | |
290 *dstCell = SkPreMultiplyARGB(trueAlpha, red, green, blue); | |
291 } | |
292 return *seenNonZeroAlphaPtr; | |
293 } | |
294 | |
295 // kMask32 | |
296 | |
297 static bool swizzle_mask32_to_n32(void* SK_RESTRICT dstRow, | |
298 const uint8_t* SK_RESTRICT src, | |
299 int width, int bitsPerPixel, int, | |
300 const SkPMColor ctable[], | |
301 const SkSwizzler::ColorMasks masks, | |
302 const SkSwizzler::AlphaOption alphaOption, | |
303 bool* seenNonZeroAlphaPtr, | |
304 bool* zeroPrevRowsPtr) { | |
305 // Load the bit masks | |
306 uint32_t redMask = masks.redMask; | |
307 uint32_t greenMask = masks.greenMask; | |
308 uint32_t blueMask = masks.blueMask; | |
309 uint32_t alphaMask = masks.alphaMask; | |
310 uint32_t rBits, rShift, gBits, gShift, bBits, bShift, aBits, aShift; | |
311 get_mask_info(redMask, bitsPerPixel, &rBits, &rShift); | |
312 get_mask_info(greenMask, bitsPerPixel, &gBits, &gShift); | |
313 get_mask_info(blueMask, bitsPerPixel, &bBits, &bShift); | |
314 get_mask_info(alphaMask, bitsPerPixel, &aBits, &aShift); | |
315 | |
316 // Use the masks to decode to the destination | |
317 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | |
318 int x = 0; | |
319 int deltaSrc = 4; | |
320 for (uint32_t p = 0; p < width * deltaSrc; p += deltaSrc) { | |
321 uint32_t pixel = src[p] | (src[p + 1] << 8) | src[p + 2] << 16 | | |
322 src[p + 3] << 24; | |
323 uint8_t red = convert_n_to_8((pixel & redMask) >> rShift, rBits); | |
324 uint8_t green = convert_n_to_8((pixel & greenMask) >> gShift, gBits); | |
325 uint8_t blue = convert_n_to_8((pixel & blueMask) >> bShift, bBits); | |
326 uint8_t alpha = convert_n_to_8((pixel & alphaMask) >> aShift, aBits); | |
327 // Call to get_alpha may reset the loop iterator. | |
328 // We will get a safe result cell before this call. | |
329 SkPMColor* dstCell = &dst[p/deltaSrc]; | |
330 uint8_t trueAlpha = get_alpha(alpha, alphaOption, &p, deltaSrc, | |
331 seenNonZeroAlphaPtr, zeroPrevRowsPtr); | |
332 *dstCell = SkPreMultiplyARGB(trueAlpha, red, green, blue); | |
333 } | |
334 return *seenNonZeroAlphaPtr; | |
335 } | |
336 | |
337 // kBGRX and kBGR | |
338 | |
339 static bool swizzle_bgrx_to_n32(void* SK_RESTRICT dstRow, | |
340 const uint8_t* SK_RESTRICT src, | |
341 int width, int bitsPerPixel, int, | |
342 const SkPMColor[], | |
343 const SkSwizzler::ColorMasks, | |
344 const SkSwizzler::AlphaOption, bool*, bool*) { | |
345 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | |
346 int deltaSrc = bitsPerPixel / 8; | |
347 for (int x = 0; x < width; x++) { | |
348 dst[x] = SkPackARGB32(0xFF, src[2], src[1], src[0]); | |
44 src += deltaSrc; | 349 src += deltaSrc; |
45 } | 350 } |
46 return cc != A32_MASK_IN_PLACE; | 351 return false; |
47 } | 352 } |
48 | 353 |
49 #undef A32_MASK_IN_PLACE | 354 // kBGRA |
355 | |
356 static bool swizzle_bgra_to_n32(void* SK_RESTRICT dstRow, | |
357 const uint8_t* SK_RESTRICT src, | |
358 int width, int bitsPerPixel, int, | |
359 const SkPMColor[], | |
360 const SkSwizzler::ColorMasks masks, | |
361 const SkSwizzler::AlphaOption alphaOption, | |
362 bool* seenNonZeroAlphaPtr, | |
363 bool* zeroPrevRowsPtr) { | |
364 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | |
365 uint32_t alphaMask = masks.alphaMask; | |
366 for (uint32_t x = 0; x < width; x++) { | |
367 uint8_t alpha = alphaMask & src[4*x + 3]; | |
368 SkPMColor* dstCell = &dst[x]; | |
369 uint8_t trueAlpha = get_alpha(alpha, alphaOption, &x, 1, | |
370 seenNonZeroAlphaPtr, zeroPrevRowsPtr); | |
371 dst[x] = SkPreMultiplyARGB(alpha, src[4*x + 2], src[4*x + 1], src[4*x]); | |
372 } | |
373 return *seenNonZeroAlphaPtr; | |
374 } | |
50 | 375 |
51 // n32 | 376 // n32 |
52 static bool swizzle_rgbx_to_n32(void* SK_RESTRICT dstRow, | 377 static bool swizzle_rgbx_to_n32(void* SK_RESTRICT dstRow, |
53 const uint8_t* SK_RESTRICT src, | 378 const uint8_t* SK_RESTRICT src, |
54 int width, int deltaSrc, int, const SkPMColor[]) { | 379 int width, int bitsPerPixel, int, |
55 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 380 const SkPMColor[], |
381 const SkSwizzler::ColorMasks, | |
382 const SkSwizzler::AlphaOption, bool*, bool*) { | |
383 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | |
384 int deltaSrc = bitsPerPixel / 8; | |
56 for (int x = 0; x < width; x++) { | 385 for (int x = 0; x < width; x++) { |
57 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); | 386 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); |
58 src += deltaSrc; | 387 src += deltaSrc; |
59 } | 388 } |
60 return false; | 389 return false; |
61 } | 390 } |
62 | 391 |
63 static bool swizzle_rgba_to_n32_premul(void* SK_RESTRICT dstRow, | 392 static bool swizzle_rgba_to_n32_premul(void* SK_RESTRICT dstRow, |
64 const uint8_t* SK_RESTRICT src, | 393 const uint8_t* SK_RESTRICT src, |
65 int width, int deltaSrc, int, const SkPMC olor[]) { | 394 int width, int bitsPerPixel, int, |
395 const SkPMColor[], | |
396 const SkSwizzler::ColorMasks, | |
397 const SkSwizzler::AlphaOption, bool*, | |
398 bool*) { | |
66 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 399 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
400 int deltaSrc = bitsPerPixel / 8; | |
67 unsigned alphaMask = 0xFF; | 401 unsigned alphaMask = 0xFF; |
68 for (int x = 0; x < width; x++) { | 402 for (int x = 0; x < width; x++) { |
69 unsigned alpha = src[3]; | 403 unsigned alpha = src[3]; |
70 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); | 404 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); |
71 src += deltaSrc; | 405 src += deltaSrc; |
72 alphaMask &= alpha; | 406 alphaMask &= alpha; |
73 } | 407 } |
74 return alphaMask != 0xFF; | 408 return alphaMask != 0xFF; |
75 } | 409 } |
76 | 410 |
77 static bool swizzle_rgba_to_n32_unpremul(void* SK_RESTRICT dstRow, | 411 static bool swizzle_rgba_to_n32_unpremul(void* SK_RESTRICT dstRow, |
78 const uint8_t* SK_RESTRICT src, | 412 const uint8_t* SK_RESTRICT src, |
79 int width, int deltaSrc, int, | 413 int width, int bitsPerPixel, int, |
80 const SkPMColor[]) { | 414 const SkPMColor[], |
415 const SkSwizzler::ColorMasks, | |
416 const SkSwizzler::AlphaOption, bool*, | |
417 bool*) { | |
81 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); | 418 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); |
419 int deltaSrc = bitsPerPixel / 8; | |
82 unsigned alphaMask = 0xFF; | 420 unsigned alphaMask = 0xFF; |
83 for (int x = 0; x < width; x++) { | 421 for (int x = 0; x < width; x++) { |
84 unsigned alpha = src[3]; | 422 unsigned alpha = src[3]; |
85 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); | 423 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); |
86 src += deltaSrc; | 424 src += deltaSrc; |
87 alphaMask &= alpha; | 425 alphaMask &= alpha; |
88 } | 426 } |
89 return alphaMask != 0xFF; | 427 return alphaMask != 0xFF; |
90 } | 428 } |
91 | 429 |
92 static bool swizzle_rgba_to_n32_premul_skipZ(void* SK_RESTRICT dstRow, | 430 static bool swizzle_rgba_to_n32_premul_skipZ(void* SK_RESTRICT dstRow, |
93 const uint8_t* SK_RESTRICT src, | 431 const uint8_t* SK_RESTRICT src, |
94 int width, int deltaSrc, int, | 432 int width, int bitsPerPixel, int, |
95 const SkPMColor[]) { | 433 const SkPMColor[], |
434 const SkSwizzler::ColorMasks, | |
435 const SkSwizzler::AlphaOption, | |
436 bool*, bool*) { | |
96 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 437 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
438 int deltaSrc = bitsPerPixel / 8; | |
97 unsigned alphaMask = 0xFF; | 439 unsigned alphaMask = 0xFF; |
98 for (int x = 0; x < width; x++) { | 440 for (int x = 0; x < width; x++) { |
99 unsigned alpha = src[3]; | 441 unsigned alpha = src[3]; |
100 if (0 != alpha) { | 442 if (0 != alpha) { |
101 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); | 443 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); |
102 } | 444 } |
103 src += deltaSrc; | 445 src += deltaSrc; |
104 alphaMask &= alpha; | 446 alphaMask &= alpha; |
105 } | 447 } |
106 return alphaMask != 0xFF; | 448 return alphaMask != 0xFF; |
107 } | 449 } |
108 | 450 |
109 /** | 451 /** |
110 FIXME: This was my idea to cheat in order to continue taking advantage of sk ipping zeroes. | 452 FIXME: This was my idea to cheat in order to continue taking advantage of sk ipping zeroes. |
111 This would be fine for drawing normally, but not for drawing with transfer m odes. Being | 453 This would be fine for drawing normally, but not for drawing with transfer m odes. Being |
112 honest means we can draw correctly with transfer modes, with the cost of not being able | 454 honest means we can draw correctly with transfer modes, with the cost of not being able |
113 to take advantage of Android's free unwritten pages. Something to keep in mi nd when we | 455 to take advantage of Android's free unwritten pages. Something to keep in mi nd when we |
114 decide whether to switch to unpremul default. | 456 decide whether to switch to unpremul default. |
115 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, | 457 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, |
116 const uint8_t* SK_RESTRICT src, | 458 const uint8_t* SK_RESTRICT src, |
117 int width, int deltaSrc, int, | 459 int width, int bitsPerPixel, |
118 const SkPMColor[]) { | 460 const SkPMColor[]) { |
119 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 461 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
120 unsigned alphaMask = 0xFF; | 462 unsigned alphaMask = 0xFF; |
121 for (int x = 0; x < width; x++) { | 463 for (int x = 0; x < width; x++) { |
122 unsigned alpha = src[3]; | 464 unsigned alpha = src[3]; |
123 // NOTE: We cheat here. The caller requested unpremul and skip zeroes. I t's possible | 465 // NOTE: We cheat here. The caller requested unpremul and skip zeroes. I t's possible |
124 // the color components are not zero, but we skip them anyway, meaning t hey'll remain | 466 // the color components are not zero, but we skip them anyway, meaning t hey'll remain |
125 // zero (implied by the request to skip zeroes). | 467 // zero (implied by the request to skip zeroes). |
126 if (0 != alpha) { | 468 if (0 != alpha) { |
127 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); | 469 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); |
128 } | 470 } |
129 src += deltaSrc; | 471 src += deltaSrc; |
130 alphaMask &= alpha; | 472 alphaMask &= alpha; |
131 } | 473 } |
132 return alphaMask != 0xFF; | 474 return alphaMask != 0xFF; |
133 } | 475 } |
134 */ | 476 */ |
135 | 477 |
136 SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, const SkPMColor * ctable, | 478 SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, |
479 const SkPMColor* ctable, | |
137 const SkImageInfo& info, void* dst, | 480 const SkImageInfo& info, void* dst, |
138 size_t dstRowBytes, bool skipZeroes) { | 481 size_t dstRowBytes, bool skipZeroes, |
139 if (info.colorType() == kUnknown_SkColorType) { | 482 const ColorMasks bitMasks, |
483 const AlphaOption alphaOption, | |
484 const RowOrder rowOrder) { | |
485 if (kUnknown_SkColorType == info.colorType()) { | |
140 return NULL; | 486 return NULL; |
141 } | 487 } |
142 if (info.minRowBytes() > dstRowBytes) { | 488 if (info.minRowBytes() > dstRowBytes) { |
143 return NULL; | 489 return NULL; |
144 } | 490 } |
145 if (kIndex == sc && NULL == ctable) { | 491 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc) |
492 && NULL == ctable) { | |
146 return NULL; | 493 return NULL; |
147 } | 494 } |
148 RowProc proc = NULL; | 495 RowProc proc = NULL; |
149 switch (sc) { | 496 switch (sc) { |
497 case kIndex1: | |
498 case kIndex2: | |
499 case kIndex4: | |
500 switch (info.colorType()) { | |
501 case kN32_SkColorType: | |
502 proc = &swizzle_small_index_to_n32; | |
503 break; | |
504 default: | |
505 break; | |
506 } | |
507 break; | |
150 case kIndex: | 508 case kIndex: |
151 switch (info.colorType()) { | 509 switch (info.colorType()) { |
152 case kN32_SkColorType: | 510 case kN32_SkColorType: |
153 // We assume the color premultiplied ctable (or not) as desi red. | 511 proc = &swizzle_index_to_n32; |
154 if (skipZeroes) { | |
155 proc = &swizzle_index_to_n32_skipZ; | |
156 } else { | |
157 proc = &swizzle_index_to_n32; | |
158 } | |
159 break; | 512 break; |
160 | |
161 default: | 513 default: |
162 break; | 514 break; |
163 } | 515 } |
516 break; | |
517 case kMask16: | |
518 switch (info.colorType()) { | |
519 case kN32_SkColorType: | |
520 proc = &swizzle_mask16_to_n32; | |
521 break; | |
522 default: | |
523 break; | |
524 } | |
525 break; | |
526 case kMask24: | |
527 switch (info.colorType()) { | |
528 case kN32_SkColorType: | |
529 proc = &swizzle_mask24_to_n32; | |
530 break; | |
531 default: | |
532 break; | |
533 } | |
534 break; | |
535 case kMask32: | |
536 switch (info.colorType()) { | |
537 case kN32_SkColorType: | |
538 proc = &swizzle_mask32_to_n32; | |
539 break; | |
540 default: | |
541 break; | |
542 } | |
543 break; | |
544 case kBGR: | |
545 case kBGRX: | |
546 switch (info.colorType()) { | |
547 case kN32_SkColorType: | |
548 proc = &swizzle_bgrx_to_n32; | |
549 break; | |
550 default: | |
551 break; | |
552 } | |
553 break; | |
554 case kBGRA: | |
555 switch (info.colorType()) { | |
556 case kN32_SkColorType: | |
557 proc = &swizzle_bgra_to_n32; | |
558 break; | |
559 default: | |
560 break; | |
561 } | |
164 break; | 562 break; |
165 case kRGBX: | 563 case kRGBX: |
166 // TODO: Support other swizzles. | 564 // TODO: Support other swizzles. |
167 switch (info.colorType()) { | 565 switch (info.colorType()) { |
168 case kN32_SkColorType: | 566 case kN32_SkColorType: |
169 proc = &swizzle_rgbx_to_n32; | 567 proc = &swizzle_rgbx_to_n32; |
170 break; | 568 break; |
171 default: | 569 default: |
172 break; | 570 break; |
173 } | 571 } |
174 break; | 572 break; |
175 case kRGBA: | 573 case kRGBA: |
176 switch (info.colorType()) { | 574 switch (info.colorType()) { |
177 case kN32_SkColorType: | 575 case kN32_SkColorType: |
178 if (info.alphaType() == kUnpremul_SkAlphaType) { | 576 if (info.alphaType() == kUnpremul_SkAlphaType) { |
179 // Respect skipZeroes? | 577 // Respect skipZeroes? |
180 proc = &swizzle_rgba_to_n32_unpremul; | 578 proc = &swizzle_rgba_to_n32_unpremul; |
181 } else { | 579 } else { |
182 if (skipZeroes) { | 580 if (skipZeroes) { |
183 proc = &swizzle_rgba_to_n32_premul_skipZ; | 581 proc = &swizzle_rgba_to_n32_premul_skipZ; |
184 } else { | 582 } else { |
185 proc = &swizzle_rgba_to_n32_premul; | 583 proc = &swizzle_rgba_to_n32_premul; |
186 } | 584 } |
187 } | 585 } |
188 break; | 586 break; |
189 default: | 587 default: |
190 break; | 588 break; |
191 } | 589 } |
192 break; | 590 break; |
591 case kRGB: | |
592 switch (info.colorType()) { | |
593 case kN32_SkColorType: | |
594 proc = &swizzle_rgbx_to_n32; | |
595 break; | |
596 default: | |
597 break; | |
598 } | |
599 break; | |
193 default: | 600 default: |
194 break; | 601 break; |
195 } | 602 } |
196 if (NULL == proc) { | 603 if (NULL == proc) { |
197 return NULL; | 604 return NULL; |
198 } | 605 } |
199 return SkNEW_ARGS(SkSwizzler, (proc, ctable, BytesPerPixel(sc), info, dst, d stRowBytes)); | 606 return SkNEW_ARGS(SkSwizzler, (proc, ctable, BitsPerPixel(sc), info, dst, |
607 dstRowBytes, bitMasks, alphaOption, rowOrder) ); | |
200 } | 608 } |
201 | 609 |
202 SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcBpp, | 610 SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, |
203 const SkImageInfo& info, void* dst, size_t rowBytes) | 611 int srcBitsPerPixel, const SkImageInfo& info, void* dst, |
612 size_t rowBytes, const ColorMasks bitMasks, | |
613 const AlphaOption alphaOption, const RowOrder rowOrder) | |
204 : fRowProc(proc) | 614 : fRowProc(proc) |
205 , fColorTable(ctable) | 615 , fColorTable(ctable) |
206 , fSrcPixelSize(srcBpp) | 616 , fSrcBitsPerPixel(srcBitsPerPixel) |
207 , fDstInfo(info) | 617 , fDstInfo(info) |
208 , fDstRow(dst) | 618 , fDstRow(dst) |
209 , fDstRowBytes(rowBytes) | 619 , fDstRowBytes(rowBytes) |
210 , fCurrY(0) | 620 , fCurrY(0) |
621 , fBitMasks(bitMasks) | |
622 , fAlphaOption(alphaOption) | |
623 , fRowOrder(rowOrder) | |
624 , fSeenNonZeroAlpha(false) | |
625 , fZeroPrevRows(false) | |
211 { | 626 { |
212 } | 627 } |
213 | 628 |
214 bool SkSwizzler::next(const uint8_t* SK_RESTRICT src) { | 629 bool SkSwizzler::next(const uint8_t* SK_RESTRICT src) { |
215 SkASSERT(fCurrY < fDstInfo.height()); | 630 SkASSERT(fCurrY < fDstInfo.height()); |
216 const bool hadAlpha = fRowProc(fDstRow, src, fDstInfo.width(), fSrcPixelSize , | 631 |
217 fCurrY, fColorTable); | 632 // On the first iteration, if the image is inverted, start at the bottom |
633 if (0 == fCurrY && kBottomUp_RowOrder == fRowOrder) { | |
scroggo
2015/03/04 17:10:31
I think the bottom up row order is only going to b
| |
634 fDstRow = SkTAddOffset<void>(fDstRow, | |
635 fDstRowBytes * (fDstInfo.height() - 1)); | |
636 } | |
637 | |
638 // Decode a row | |
639 const bool hadAlpha = fRowProc(fDstRow, src, fDstInfo.width(), | |
640 fSrcBitsPerPixel, fCurrY, fColorTable, fBitMasks, fAlphaOption, | |
641 &fSeenNonZeroAlpha, &fZeroPrevRows); | |
642 | |
643 // This flag indicates that we have decoded the image as opaque instead of | |
644 // transparent, and we just realized that it should have been transparent. | |
645 // To fix this, we zero the rows that have already been decoded. | |
646 if (fZeroPrevRows) { | |
scroggo
2015/03/04 17:10:31
Some thoughts:
1) I think this behavior is exclus
| |
647 void* dstRow; | |
648 if (kTopDown_RowOrder == fRowOrder) { | |
649 void* dstStart = SkTAddOffset<void>(fDstRow, -fCurrY*fDstRowBytes); | |
650 memset(dstStart, 0, fCurrY*fDstRowBytes); | |
651 } else { | |
652 void* dstStart = SkTAddOffset<void>(fDstRow, fDstRowBytes); | |
653 memset(dstStart, 0, fCurrY*fDstRowBytes); | |
654 } | |
655 fZeroPrevRows = false; | |
656 } | |
657 | |
658 // Move to the next row and return the result | |
218 fCurrY++; | 659 fCurrY++; |
219 fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes); | 660 if (kTopDown_RowOrder == fRowOrder) { |
661 fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes); | |
662 } else { | |
663 fDstRow = SkTAddOffset<void>(fDstRow, -fDstRowBytes); | |
664 } | |
220 return hadAlpha; | 665 return hadAlpha; |
221 } | 666 } |
222 | 667 |
OLD | NEW |