Chromium Code Reviews| 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 |