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::ZeroAlpha, 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::ZeroAlpha, 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::ZeroAlpha, 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 convertNTo8(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 getMaskInfo(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 // kMask16 |
| 181 |
| 182 static bool swizzle_mask16_to_n32(void* SK_RESTRICT dstRow, |
| 183 const uint8_t* SK_RESTRICT src, |
| 184 int width, int bitsPerPixel, int, |
| 185 const SkPMColor ctable[], |
| 186 const SkSwizzler::ColorMasks* masks, |
| 187 const SkSwizzler::ZeroAlpha zeroAlpha, |
| 188 bool* seenNonZeroAlphaPtr, |
| 189 bool* zeroPrevRowsPtr) { |
| 190 // Load the bit masks |
| 191 uint32_t redMask = masks->redMask; |
| 192 uint32_t greenMask = masks->greenMask; |
| 193 uint32_t blueMask = masks->blueMask; |
| 194 uint32_t alphaMask = masks->alphaMask; |
| 195 uint32_t rBits, rShift, gBits, gShift, bBits, bShift, aBits, aShift; |
| 196 getMaskInfo(redMask, bitsPerPixel, &rBits, &rShift); |
| 197 getMaskInfo(greenMask, bitsPerPixel, &gBits, &gShift); |
| 198 getMaskInfo(blueMask, bitsPerPixel, &bBits, &bShift); |
| 199 getMaskInfo(alphaMask, bitsPerPixel, &aBits, &aShift); |
| 200 |
| 201 // Use the masks to decode to the destination |
| 202 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
| 203 int x = 0; |
| 204 for (uint32_t p = 0; p < width * 2; p += 2) { |
| 205 uint16_t pixel = src[p] | (src[p + 1] << 8); |
| 206 uint8_t red = convertNTo8((pixel & redMask) >> rShift, rBits); |
| 207 uint8_t green = convertNTo8((pixel & greenMask) >> gShift, gBits); |
| 208 uint8_t blue = convertNTo8((pixel & blueMask) >> bShift, bBits); |
| 209 uint8_t alpha = convertNTo8((pixel & alphaMask) >> aShift, aBits); |
| 210 |
| 211 // We must respect the alpha channel for bmp V4+. However, if it is |
| 212 // all zeros, we will display the image as opaque rather than |
| 213 // transparent. This may require redoing some of the processing. |
| 214 if (SkSwizzler::kTransparentAsOpaque == zeroAlpha && |
| 215 *seenNonZeroAlphaPtr) { |
| 216 dst[x] = SkPackARGB32(alpha, red, blue, green); |
| 217 x++; |
| 218 } else if (!alpha) { |
| 219 dst[x] = SkPackARGB32(0xFF, red, blue, green); |
| 220 x++; |
| 221 } else { |
| 222 *zeroPrevRowsPtr = true; |
| 223 *seenNonZeroAlphaPtr = true; |
| 224 x = 0; |
| 225 p = -1; |
| 226 } |
| 227 } |
| 228 return *seenNonZeroAlphaPtr; |
| 229 } |
| 230 |
| 231 // kMask24 |
| 232 |
| 233 static bool swizzle_mask24_to_n32(void* SK_RESTRICT dstRow, |
| 234 const uint8_t* SK_RESTRICT src, |
| 235 int width, int bitsPerPixel, int, |
| 236 const SkPMColor ctable[], |
| 237 const SkSwizzler::ColorMasks* masks, |
| 238 const SkSwizzler::ZeroAlpha zeroAlpha, |
| 239 bool* seenNonZeroAlphaPtr, |
| 240 bool* zeroPrevRowsPtr) { |
| 241 // Load the bit masks |
| 242 uint32_t redMask = masks->redMask; |
| 243 uint32_t greenMask = masks->greenMask; |
| 244 uint32_t blueMask = masks->blueMask; |
| 245 uint32_t alphaMask = masks->alphaMask; |
| 246 uint32_t rBits, rShift, gBits, gShift, bBits, bShift, aBits, aShift; |
| 247 getMaskInfo(redMask, bitsPerPixel, &rBits, &rShift); |
| 248 getMaskInfo(greenMask, bitsPerPixel, &gBits, &gShift); |
| 249 getMaskInfo(blueMask, bitsPerPixel, &bBits, &bShift); |
| 250 getMaskInfo(alphaMask, bitsPerPixel, &aBits, &aShift); |
| 251 |
| 252 // Use the masks to decode to the destination |
| 253 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
| 254 int x = 0; |
| 255 for (uint32_t p = 0; p < width * 3; p += 3) { |
| 256 uint32_t pixel = src[p] | (src[p + 1] << 8) | src[p + 2] << 16; |
| 257 uint8_t red = convertNTo8((pixel & redMask) >> rShift, rBits); |
| 258 uint8_t green = convertNTo8((pixel & greenMask) >> gShift, gBits); |
| 259 uint8_t blue = convertNTo8((pixel & blueMask) >> bShift, bBits); |
| 260 uint8_t alpha = convertNTo8((pixel & alphaMask) >> aShift, aBits); |
| 261 |
| 262 // We must respect the alpha channel for bmp V4+. However, if it is |
| 263 // all zeros, we will display the image as opaque rather than |
| 264 // transparent. This may require redoing some of the processing. |
| 265 if (SkSwizzler::kTransparentAsOpaque == zeroAlpha && |
| 266 *seenNonZeroAlphaPtr) { |
| 267 dst[x] = SkPackARGB32(alpha, red, blue, green); |
| 268 x++; |
| 269 } else if (!alpha) { |
| 270 dst[x] = SkPackARGB32(0xFF, red, blue, green); |
| 271 x++; |
| 272 } else { |
| 273 *zeroPrevRowsPtr = true; |
| 274 *seenNonZeroAlphaPtr = true; |
| 275 x = 0; |
| 276 p = -1; |
| 277 } |
| 278 } |
| 279 return *seenNonZeroAlphaPtr; |
| 280 } |
| 281 |
| 282 // kMask32 |
| 283 |
| 284 static bool swizzle_mask32_to_n32(void* SK_RESTRICT dstRow, |
| 285 const uint8_t* SK_RESTRICT src, |
| 286 int width, int bitsPerPixel, int, |
| 287 const SkPMColor ctable[], |
| 288 const SkSwizzler::ColorMasks* masks, |
| 289 const SkSwizzler::ZeroAlpha zeroAlpha, |
| 290 bool* seenNonZeroAlphaPtr, |
| 291 bool* zeroPrevRowsPtr) { |
| 292 // Load the bit masks |
| 293 uint32_t redMask = masks->redMask; |
| 294 uint32_t greenMask = masks->greenMask; |
| 295 uint32_t blueMask = masks->blueMask; |
| 296 uint32_t alphaMask = masks->alphaMask; |
| 297 uint32_t rBits, rShift, gBits, gShift, bBits, bShift, aBits, aShift; |
| 298 getMaskInfo(redMask, bitsPerPixel, &rBits, &rShift); |
| 299 getMaskInfo(greenMask, bitsPerPixel, &gBits, &gShift); |
| 300 getMaskInfo(blueMask, bitsPerPixel, &bBits, &bShift); |
| 301 getMaskInfo(alphaMask, bitsPerPixel, &aBits, &aShift); |
| 302 |
| 303 // Use the masks to decode to the destination |
| 304 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
| 305 int x = 0; |
| 306 for (uint32_t p = 0; p < width * 4; p += 4) { |
| 307 uint32_t pixel = src[p] | (src[p + 1] << 8) | src[p + 2] << 16 | |
| 308 src[p + 3] << 24; |
| 309 uint8_t red = convertNTo8((pixel & redMask) >> rShift, rBits); |
| 310 uint8_t green = convertNTo8((pixel & greenMask) >> gShift, gBits); |
| 311 uint8_t blue = convertNTo8((pixel & blueMask) >> bShift, bBits); |
| 312 uint8_t alpha = convertNTo8((pixel & alphaMask) >> aShift, aBits); |
| 313 |
| 314 // We must respect the alpha channel for bmp V4+. However, if it is |
| 315 // all zeros, we will display the image as opaque rather than |
| 316 // transparent. This may require redoing some of the processing. |
| 317 if (SkSwizzler::kTransparentAsOpaque == zeroAlpha && |
| 318 *seenNonZeroAlphaPtr) { |
| 319 dst[x] = SkPackARGB32(alpha, red, blue, green); |
| 320 x++; |
| 321 } else if (!alpha) { |
| 322 dst[x] = SkPackARGB32(0xFF, red, blue, green); |
| 323 x++; |
| 324 } else { |
| 325 *zeroPrevRowsPtr = true; |
| 326 *seenNonZeroAlphaPtr = true; |
| 327 x = 0; |
| 328 p = -1; |
| 329 } |
| 330 } |
| 331 return *seenNonZeroAlphaPtr; |
| 332 } |
| 333 |
| 334 // kBGRX and kBGR |
| 335 |
| 336 static bool swizzle_bgrx_to_n32(void* SK_RESTRICT dstRow, |
| 337 const uint8_t* SK_RESTRICT src, |
| 338 int width, int bitsPerPixel, int, |
| 339 const SkPMColor[], |
| 340 const SkSwizzler::ColorMasks*, |
| 341 const SkSwizzler::ZeroAlpha, bool*, bool*) { |
| 342 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
| 343 int deltaSrc = bitsPerPixel / 8; |
| 344 for (int x = 0; x < width; x++) { |
| 345 dst[x] = SkPackARGB32(0xFF, src[2], src[1], src[0]); |
44 src += deltaSrc; | 346 src += deltaSrc; |
45 } | 347 } |
46 return cc != A32_MASK_IN_PLACE; | 348 return false; |
47 } | 349 } |
48 | 350 |
49 #undef A32_MASK_IN_PLACE | 351 // kBGRA |
| 352 |
| 353 static bool swizzle_bgra_to_n32(void* SK_RESTRICT dstRow, |
| 354 const uint8_t* SK_RESTRICT src, |
| 355 int width, int bitsPerPixel, int, |
| 356 const SkPMColor[], |
| 357 const SkSwizzler::ColorMasks* masks, |
| 358 const SkSwizzler::ZeroAlpha zeroAlpha, |
| 359 bool* seenNonZeroAlphaPtr, |
| 360 bool* zeroPrevRowsPtr) { |
| 361 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
| 362 uint32_t alphaMask = masks->alphaMask; |
| 363 int deltaSrc = bitsPerPixel / 8; |
| 364 const uint8_t* srcStart = src; |
| 365 for (int x = 0; x < width; x++) { |
| 366 uint8_t alpha = alphaMask & src[3]; |
| 367 // We must respect the alpha channel for bmp V4+. However, if it is |
| 368 // all zeros, we will display the image as opaque rather than |
| 369 // transparent. This may require redoing some of the processing. |
| 370 if (SkSwizzler::kNormal == zeroAlpha || *seenNonZeroAlphaPtr) { |
| 371 dst[x] = SkPackARGB32(alpha, src[2], src[1], src[0]); |
| 372 src += deltaSrc; |
| 373 } else if (!alpha) { |
| 374 dst[x] = SkPackARGB32(0xFF, src[2], src[1], src[0]); |
| 375 src += deltaSrc; |
| 376 } else { |
| 377 *zeroPrevRowsPtr = true; |
| 378 *seenNonZeroAlphaPtr = true; |
| 379 int x = -1; |
| 380 src = srcStart; |
| 381 } |
| 382 } |
| 383 return *seenNonZeroAlphaPtr; |
| 384 } |
50 | 385 |
51 // n32 | 386 // n32 |
52 static bool swizzle_rgbx_to_n32(void* SK_RESTRICT dstRow, | 387 static bool swizzle_rgbx_to_n32(void* SK_RESTRICT dstRow, |
53 const uint8_t* SK_RESTRICT src, | 388 const uint8_t* SK_RESTRICT src, |
54 int width, int deltaSrc, int, const SkPMColor[])
{ | 389 int width, int bitsPerPixel, int, |
55 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 390 const SkPMColor[], |
| 391 const SkSwizzler::ColorMasks*, |
| 392 const SkSwizzler::ZeroAlpha, bool*, bool*) { |
| 393 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
| 394 int deltaSrc = bitsPerPixel / 8; |
56 for (int x = 0; x < width; x++) { | 395 for (int x = 0; x < width; x++) { |
57 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); | 396 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); |
58 src += deltaSrc; | 397 src += deltaSrc; |
59 } | 398 } |
60 return false; | 399 return false; |
61 } | 400 } |
62 | 401 |
63 static bool swizzle_rgba_to_n32_premul(void* SK_RESTRICT dstRow, | 402 static bool swizzle_rgba_to_n32_premul(void* SK_RESTRICT dstRow, |
64 const uint8_t* SK_RESTRICT src, | 403 const uint8_t* SK_RESTRICT src, |
65 int width, int deltaSrc, int, const SkPMC
olor[]) { | 404 int width, int bitsPerPixel, int, |
| 405 const SkPMColor[], const SkSwizzler::Colo
rMasks*, |
| 406 const SkSwizzler::ZeroAlpha, bool*, |
| 407 bool*) { |
66 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 408 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
| 409 int deltaSrc = bitsPerPixel / 8; |
67 unsigned alphaMask = 0xFF; | 410 unsigned alphaMask = 0xFF; |
68 for (int x = 0; x < width; x++) { | 411 for (int x = 0; x < width; x++) { |
69 unsigned alpha = src[3]; | 412 unsigned alpha = src[3]; |
70 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); | 413 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); |
71 src += deltaSrc; | 414 src += deltaSrc; |
72 alphaMask &= alpha; | 415 alphaMask &= alpha; |
73 } | 416 } |
74 return alphaMask != 0xFF; | 417 return alphaMask != 0xFF; |
75 } | 418 } |
76 | 419 |
77 static bool swizzle_rgba_to_n32_unpremul(void* SK_RESTRICT dstRow, | 420 static bool swizzle_rgba_to_n32_unpremul(void* SK_RESTRICT dstRow, |
78 const uint8_t* SK_RESTRICT src, | 421 const uint8_t* SK_RESTRICT src, |
79 int width, int deltaSrc, int, | 422 int width, int bitsPerPixel, int, |
80 const SkPMColor[]) { | 423 const SkPMColor[], const SkSwizzler::Co
lorMasks*, |
| 424 const SkSwizzler::ZeroAlpha, bool*, |
| 425 bool*) { |
81 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); | 426 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); |
| 427 int deltaSrc = bitsPerPixel / 8; |
82 unsigned alphaMask = 0xFF; | 428 unsigned alphaMask = 0xFF; |
83 for (int x = 0; x < width; x++) { | 429 for (int x = 0; x < width; x++) { |
84 unsigned alpha = src[3]; | 430 unsigned alpha = src[3]; |
85 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); | 431 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); |
86 src += deltaSrc; | 432 src += deltaSrc; |
87 alphaMask &= alpha; | 433 alphaMask &= alpha; |
88 } | 434 } |
89 return alphaMask != 0xFF; | 435 return alphaMask != 0xFF; |
90 } | 436 } |
91 | 437 |
92 static bool swizzle_rgba_to_n32_premul_skipZ(void* SK_RESTRICT dstRow, | 438 static bool swizzle_rgba_to_n32_premul_skipZ(void* SK_RESTRICT dstRow, |
93 const uint8_t* SK_RESTRICT src, | 439 const uint8_t* SK_RESTRICT src, |
94 int width, int deltaSrc, int, | 440 int width, int bitsPerPixel, int, |
95 const SkPMColor[]) { | 441 const SkPMColor[], |
| 442 const SkSwizzler::ColorMasks*, |
| 443 const SkSwizzler::ZeroAlpha, |
| 444 bool*, bool*) { |
96 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 445 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
| 446 int deltaSrc = bitsPerPixel / 8; |
97 unsigned alphaMask = 0xFF; | 447 unsigned alphaMask = 0xFF; |
98 for (int x = 0; x < width; x++) { | 448 for (int x = 0; x < width; x++) { |
99 unsigned alpha = src[3]; | 449 unsigned alpha = src[3]; |
100 if (0 != alpha) { | 450 if (0 != alpha) { |
101 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); | 451 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); |
102 } | 452 } |
103 src += deltaSrc; | 453 src += deltaSrc; |
104 alphaMask &= alpha; | 454 alphaMask &= alpha; |
105 } | 455 } |
106 return alphaMask != 0xFF; | 456 return alphaMask != 0xFF; |
107 } | 457 } |
108 | 458 |
109 /** | 459 /** |
110 FIXME: This was my idea to cheat in order to continue taking advantage of sk
ipping zeroes. | 460 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 | 461 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 | 462 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 | 463 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. | 464 decide whether to switch to unpremul default. |
115 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, | 465 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, |
116 const uint8_t* SK_RESTRICT src, | 466 const uint8_t* SK_RESTRICT src, |
117 int width, int deltaSrc, int, | 467 int width, int bitsPerPixel, |
118 const SkPMColor[]) { | 468 const SkPMColor[]) { |
119 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; | 469 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
120 unsigned alphaMask = 0xFF; | 470 unsigned alphaMask = 0xFF; |
121 for (int x = 0; x < width; x++) { | 471 for (int x = 0; x < width; x++) { |
122 unsigned alpha = src[3]; | 472 unsigned alpha = src[3]; |
123 // NOTE: We cheat here. The caller requested unpremul and skip zeroes. I
t's possible | 473 // 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 | 474 // 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). | 475 // zero (implied by the request to skip zeroes). |
126 if (0 != alpha) { | 476 if (0 != alpha) { |
127 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); | 477 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); |
128 } | 478 } |
129 src += deltaSrc; | 479 src += deltaSrc; |
130 alphaMask &= alpha; | 480 alphaMask &= alpha; |
131 } | 481 } |
132 return alphaMask != 0xFF; | 482 return alphaMask != 0xFF; |
133 } | 483 } |
134 */ | 484 */ |
135 | 485 |
136 SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, const SkPMColor
* ctable, | 486 SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, |
| 487 const SkPMColor* ctable, |
137 const SkImageInfo& info, void* dst, | 488 const SkImageInfo& info, void* dst, |
138 size_t dstRowBytes, bool skipZeroes) { | 489 size_t dstRowBytes, bool skipZeroes, |
139 if (info.colorType() == kUnknown_SkColorType) { | 490 const ColorMasks* bitMasks, |
| 491 const ZeroAlpha zeroAlpha, |
| 492 const RowOrder rowOrder) { |
| 493 if (kUnknown_SkColorType == info.colorType()) { |
140 return NULL; | 494 return NULL; |
141 } | 495 } |
142 if (info.minRowBytes() > dstRowBytes) { | 496 if (info.minRowBytes() > dstRowBytes) { |
143 return NULL; | 497 return NULL; |
144 } | 498 } |
145 if (kIndex == sc && NULL == ctable) { | 499 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc) |
| 500 && NULL == ctable) { |
146 return NULL; | 501 return NULL; |
147 } | 502 } |
148 RowProc proc = NULL; | 503 RowProc proc = NULL; |
149 switch (sc) { | 504 switch (sc) { |
| 505 case kIndex1: |
| 506 case kIndex2: |
| 507 case kIndex4: |
| 508 switch (info.colorType()) { |
| 509 case kN32_SkColorType: |
| 510 proc = &swizzle_small_index_to_n32; |
| 511 break; |
| 512 default: |
| 513 break; |
| 514 } |
| 515 break; |
150 case kIndex: | 516 case kIndex: |
151 switch (info.colorType()) { | 517 switch (info.colorType()) { |
152 case kN32_SkColorType: | 518 case kN32_SkColorType: |
153 // We assume the color premultiplied ctable (or not) as desi
red. | 519 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; | 520 break; |
160 | |
161 default: | 521 default: |
162 break; | 522 break; |
163 } | 523 } |
| 524 break; |
| 525 case kMask16: |
| 526 switch (info.colorType()) { |
| 527 case kN32_SkColorType: |
| 528 proc = &swizzle_mask16_to_n32; |
| 529 break; |
| 530 default: |
| 531 break; |
| 532 } |
| 533 break; |
| 534 case kMask24: |
| 535 switch (info.colorType()) { |
| 536 case kN32_SkColorType: |
| 537 proc = &swizzle_mask24_to_n32; |
| 538 break; |
| 539 default: |
| 540 break; |
| 541 } |
| 542 break; |
| 543 case kMask32: |
| 544 switch (info.colorType()) { |
| 545 case kN32_SkColorType: |
| 546 proc = &swizzle_mask32_to_n32; |
| 547 break; |
| 548 default: |
| 549 break; |
| 550 } |
| 551 break; |
| 552 case kBGR: |
| 553 case kBGRX: |
| 554 switch (info.colorType()) { |
| 555 case kN32_SkColorType: |
| 556 proc = &swizzle_bgrx_to_n32; |
| 557 break; |
| 558 default: |
| 559 break; |
| 560 } |
| 561 break; |
| 562 case kBGRA: |
| 563 switch (info.colorType()) { |
| 564 case kN32_SkColorType: |
| 565 proc = &swizzle_bgra_to_n32; |
| 566 break; |
| 567 default: |
| 568 break; |
| 569 } |
164 break; | 570 break; |
165 case kRGBX: | 571 case kRGBX: |
166 // TODO: Support other swizzles. | 572 // TODO: Support other swizzles. |
167 switch (info.colorType()) { | 573 switch (info.colorType()) { |
168 case kN32_SkColorType: | 574 case kN32_SkColorType: |
169 proc = &swizzle_rgbx_to_n32; | 575 proc = &swizzle_rgbx_to_n32; |
170 break; | 576 break; |
171 default: | 577 default: |
172 break; | 578 break; |
173 } | 579 } |
174 break; | 580 break; |
175 case kRGBA: | 581 case kRGBA: |
176 switch (info.colorType()) { | 582 switch (info.colorType()) { |
177 case kN32_SkColorType: | 583 case kN32_SkColorType: |
178 if (info.alphaType() == kUnpremul_SkAlphaType) { | 584 if (info.alphaType() == kUnpremul_SkAlphaType) { |
179 // Respect skipZeroes? | 585 // Respect skipZeroes? |
180 proc = &swizzle_rgba_to_n32_unpremul; | 586 proc = &swizzle_rgba_to_n32_unpremul; |
181 } else { | 587 } else { |
182 if (skipZeroes) { | 588 if (skipZeroes) { |
183 proc = &swizzle_rgba_to_n32_premul_skipZ; | 589 proc = &swizzle_rgba_to_n32_premul_skipZ; |
184 } else { | 590 } else { |
185 proc = &swizzle_rgba_to_n32_premul; | 591 proc = &swizzle_rgba_to_n32_premul; |
186 } | 592 } |
187 } | 593 } |
188 break; | 594 break; |
189 default: | 595 default: |
190 break; | 596 break; |
191 } | 597 } |
192 break; | 598 break; |
| 599 case kRGB: |
| 600 switch (info.colorType()) { |
| 601 case kN32_SkColorType: |
| 602 proc = &swizzle_rgbx_to_n32; |
| 603 break; |
| 604 default: |
| 605 break; |
| 606 } |
| 607 break; |
193 default: | 608 default: |
194 break; | 609 break; |
195 } | 610 } |
196 if (NULL == proc) { | 611 if (NULL == proc) { |
197 return NULL; | 612 return NULL; |
198 } | 613 } |
199 return SkNEW_ARGS(SkSwizzler, (proc, ctable, BytesPerPixel(sc), info, dst, d
stRowBytes)); | 614 return SkNEW_ARGS(SkSwizzler, (proc, ctable, BitsPerPixel(sc), info, dst, |
| 615 dstRowBytes, bitMasks, zeroAlpha, rowOrder)); |
200 } | 616 } |
201 | 617 |
202 SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcBpp, | 618 SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, |
203 const SkImageInfo& info, void* dst, size_t rowBytes) | 619 int srcBitsPerPixel, const SkImageInfo& info, void* dst, |
| 620 size_t rowBytes, const ColorMasks* bitMasks, |
| 621 const ZeroAlpha zeroAlpha, const RowOrder rowOrder) |
204 : fRowProc(proc) | 622 : fRowProc(proc) |
205 , fColorTable(ctable) | 623 , fColorTable(ctable) |
206 , fSrcPixelSize(srcBpp) | 624 , fSrcBitsPerPixel(srcBitsPerPixel) |
207 , fDstInfo(info) | 625 , fDstInfo(info) |
208 , fDstRow(dst) | 626 , fDstRow(dst) |
209 , fDstRowBytes(rowBytes) | 627 , fDstRowBytes(rowBytes) |
210 , fCurrY(0) | 628 , fCurrY(0) |
| 629 , fBitMasks(bitMasks) |
| 630 , fZeroAlpha(zeroAlpha) |
| 631 , fRowOrder(rowOrder) |
| 632 , fSeenNonZeroAlpha(false) |
| 633 , fZeroPrevRows(false) |
211 { | 634 { |
212 } | 635 } |
213 | 636 |
214 bool SkSwizzler::next(const uint8_t* SK_RESTRICT src) { | 637 bool SkSwizzler::next(const uint8_t* SK_RESTRICT src) { |
215 SkASSERT(fCurrY < fDstInfo.height()); | 638 SkASSERT(fCurrY < fDstInfo.height()); |
216 const bool hadAlpha = fRowProc(fDstRow, src, fDstInfo.width(), fSrcPixelSize
, | 639 |
217 fCurrY, fColorTable); | 640 // On the first iteration, if the image is inverted, start at the bottom |
| 641 if (0 == fCurrY && kBottomUp == fRowOrder) { |
| 642 fDstRow = SkTAddOffset<void>(fDstRow, |
| 643 fDstRowBytes * (fDstInfo.height() - 1)); |
| 644 } |
| 645 |
| 646 // Decode a row |
| 647 const bool hadAlpha = fRowProc(fDstRow, src, fDstInfo.width(), |
| 648 fSrcBitsPerPixel, fCurrY, fColorTable, fBitMasks, fZeroAlpha, |
| 649 &fSeenNonZeroAlpha, &fZeroPrevRows); |
| 650 |
| 651 // This flag indicates that we have decoded the image as opaque instead of |
| 652 // transparent, and we just realized that it should have been transparent. |
| 653 // To fix this, we zero the rows that have already been decoded. |
| 654 if (fZeroPrevRows) { |
| 655 SkDebugf("TESTING ZERO ALPHA DECODE\n"); |
| 656 void* dstRow; |
| 657 if (kTopDown == fRowOrder) { |
| 658 void* dstStart = SkTAddOffset<void>(fDstRow, -fCurrY*fDstRowBytes); |
| 659 memset(dstStart, 0, fCurrY*fDstRowBytes); |
| 660 } else { |
| 661 void* dstStart = SkTAddOffset<void>(fDstRow, fDstRowBytes); |
| 662 memset(dstStart, 0, fCurrY*fDstRowBytes); |
| 663 } |
| 664 fZeroPrevRows = false; |
| 665 } |
| 666 |
| 667 // Move to the next row and return the result |
218 fCurrY++; | 668 fCurrY++; |
219 fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes); | 669 if (kTopDown == fRowOrder) { |
| 670 fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes); |
| 671 } else { |
| 672 fDstRow = SkTAddOffset<void>(fDstRow, -fDstRowBytes); |
| 673 } |
220 return hadAlpha; | 674 return hadAlpha; |
221 } | 675 } |
222 | 676 |
OLD | NEW |