1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/images/SkScaledBitmapSampler.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,852 @@ 1.4 +/* 1.5 + * Copyright 2007 The Android Open Source Project 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 + 1.12 +#include "SkScaledBitmapSampler.h" 1.13 +#include "SkBitmap.h" 1.14 +#include "SkColorPriv.h" 1.15 +#include "SkDither.h" 1.16 +#include "SkTypes.h" 1.17 + 1.18 +// 8888 1.19 + 1.20 +static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow, 1.21 + const uint8_t* SK_RESTRICT src, 1.22 + int width, int deltaSrc, int, const SkPMColor[]) { 1.23 + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 1.24 + for (int x = 0; x < width; x++) { 1.25 + dst[x] = SkPackARGB32(0xFF, src[0], src[0], src[0]); 1.26 + src += deltaSrc; 1.27 + } 1.28 + return false; 1.29 +} 1.30 + 1.31 +static SkScaledBitmapSampler::RowProc get_gray_to_8888_proc(const SkImageDecoder& decoder) { 1.32 + // Dither, unpremul, and skipZeroes have no effect 1.33 + return Sample_Gray_D8888; 1.34 +} 1.35 + 1.36 +static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow, 1.37 + const uint8_t* SK_RESTRICT src, 1.38 + int width, int deltaSrc, int, const SkPMColor[]) { 1.39 + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 1.40 + for (int x = 0; x < width; x++) { 1.41 + dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); 1.42 + src += deltaSrc; 1.43 + } 1.44 + return false; 1.45 +} 1.46 + 1.47 +static SkScaledBitmapSampler::RowProc get_RGBx_to_8888_proc(const SkImageDecoder& decoder) { 1.48 + // Dither, unpremul, and skipZeroes have no effect 1.49 + return Sample_RGBx_D8888; 1.50 +} 1.51 + 1.52 +static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow, 1.53 + const uint8_t* SK_RESTRICT src, 1.54 + int width, int deltaSrc, int, const SkPMColor[]) { 1.55 + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 1.56 + unsigned alphaMask = 0xFF; 1.57 + for (int x = 0; x < width; x++) { 1.58 + unsigned alpha = src[3]; 1.59 + dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 1.60 + src += deltaSrc; 1.61 + alphaMask &= alpha; 1.62 + } 1.63 + return alphaMask != 0xFF; 1.64 +} 1.65 + 1.66 +static bool Sample_RGBA_D8888_Unpremul(void* SK_RESTRICT dstRow, 1.67 + const uint8_t* SK_RESTRICT src, 1.68 + int width, int deltaSrc, int, 1.69 + const SkPMColor[]) { 1.70 + uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); 1.71 + unsigned alphaMask = 0xFF; 1.72 + for (int x = 0; x < width; x++) { 1.73 + unsigned alpha = src[3]; 1.74 + dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); 1.75 + src += deltaSrc; 1.76 + alphaMask &= alpha; 1.77 + } 1.78 + return alphaMask != 0xFF; 1.79 +} 1.80 + 1.81 +static bool Sample_RGBA_D8888_SkipZ(void* SK_RESTRICT dstRow, 1.82 + const uint8_t* SK_RESTRICT src, 1.83 + int width, int deltaSrc, int, 1.84 + const SkPMColor[]) { 1.85 + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 1.86 + unsigned alphaMask = 0xFF; 1.87 + for (int x = 0; x < width; x++) { 1.88 + unsigned alpha = src[3]; 1.89 + if (0 != alpha) { 1.90 + dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 1.91 + } 1.92 + src += deltaSrc; 1.93 + alphaMask &= alpha; 1.94 + } 1.95 + return alphaMask != 0xFF; 1.96 +} 1.97 + 1.98 +static SkScaledBitmapSampler::RowProc get_RGBA_to_8888_proc(const SkImageDecoder& decoder) { 1.99 + // Dither has no effect. 1.100 + if (decoder.getRequireUnpremultipliedColors()) { 1.101 + // We could check each component for a zero, at the expense of extra checks. 1.102 + // For now, just return unpremul. 1.103 + return Sample_RGBA_D8888_Unpremul; 1.104 + } 1.105 + // Supply the versions that premultiply the colors 1.106 + if (decoder.getSkipWritingZeroes()) { 1.107 + return Sample_RGBA_D8888_SkipZ; 1.108 + } 1.109 + return Sample_RGBA_D8888; 1.110 +} 1.111 + 1.112 +// 565 1.113 + 1.114 +static bool Sample_Gray_D565(void* SK_RESTRICT dstRow, 1.115 + const uint8_t* SK_RESTRICT src, 1.116 + int width, int deltaSrc, int, const SkPMColor[]) { 1.117 + uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 1.118 + for (int x = 0; x < width; x++) { 1.119 + dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]); 1.120 + src += deltaSrc; 1.121 + } 1.122 + return false; 1.123 +} 1.124 + 1.125 +static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow, 1.126 + const uint8_t* SK_RESTRICT src, 1.127 + int width, int deltaSrc, int y, const SkPMColor[]) { 1.128 + uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 1.129 + DITHER_565_SCAN(y); 1.130 + for (int x = 0; x < width; x++) { 1.131 + dst[x] = SkDitherRGBTo565(src[0], src[0], src[0], DITHER_VALUE(x)); 1.132 + src += deltaSrc; 1.133 + } 1.134 + return false; 1.135 +} 1.136 + 1.137 +static SkScaledBitmapSampler::RowProc get_gray_to_565_proc(const SkImageDecoder& decoder) { 1.138 + // Unpremul and skip zeroes make no difference 1.139 + if (decoder.getDitherImage()) { 1.140 + return Sample_Gray_D565_D; 1.141 + } 1.142 + return Sample_Gray_D565; 1.143 +} 1.144 + 1.145 +static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow, 1.146 + const uint8_t* SK_RESTRICT src, 1.147 + int width, int deltaSrc, int, const SkPMColor[]) { 1.148 + uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 1.149 + for (int x = 0; x < width; x++) { 1.150 + dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]); 1.151 + src += deltaSrc; 1.152 + } 1.153 + return false; 1.154 +} 1.155 + 1.156 +static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow, 1.157 + const uint8_t* SK_RESTRICT src, 1.158 + int width, int deltaSrc, int y, 1.159 + const SkPMColor[]) { 1.160 + uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 1.161 + DITHER_565_SCAN(y); 1.162 + for (int x = 0; x < width; x++) { 1.163 + dst[x] = SkDitherRGBTo565(src[0], src[1], src[2], DITHER_VALUE(x)); 1.164 + src += deltaSrc; 1.165 + } 1.166 + return false; 1.167 +} 1.168 + 1.169 +static SkScaledBitmapSampler::RowProc get_RGBx_to_565_proc(const SkImageDecoder& decoder) { 1.170 + // Unpremul and skip zeroes make no difference 1.171 + if (decoder.getDitherImage()) { 1.172 + return Sample_RGBx_D565_D; 1.173 + } 1.174 + return Sample_RGBx_D565; 1.175 +} 1.176 + 1.177 + 1.178 +static bool Sample_D565_D565(void* SK_RESTRICT dstRow, 1.179 + const uint8_t* SK_RESTRICT src, 1.180 + int width, int deltaSrc, int, const SkPMColor[]) { 1.181 + uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 1.182 + uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src; 1.183 + for (int x = 0; x < width; x++) { 1.184 + dst[x] = castedSrc[0]; 1.185 + castedSrc += deltaSrc >> 1; 1.186 + } 1.187 + return false; 1.188 +} 1.189 + 1.190 +static SkScaledBitmapSampler::RowProc get_565_to_565_proc(const SkImageDecoder& decoder) { 1.191 + // Unpremul, dither, and skip zeroes have no effect 1.192 + return Sample_D565_D565; 1.193 +} 1.194 + 1.195 +// 4444 1.196 + 1.197 +static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow, 1.198 + const uint8_t* SK_RESTRICT src, 1.199 + int width, int deltaSrc, int, const SkPMColor[]) { 1.200 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.201 + for (int x = 0; x < width; x++) { 1.202 + unsigned gray = src[0] >> 4; 1.203 + dst[x] = SkPackARGB4444(0xF, gray, gray, gray); 1.204 + src += deltaSrc; 1.205 + } 1.206 + return false; 1.207 +} 1.208 + 1.209 +static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow, 1.210 + const uint8_t* SK_RESTRICT src, 1.211 + int width, int deltaSrc, int y, const SkPMColor[]) { 1.212 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.213 + DITHER_4444_SCAN(y); 1.214 + for (int x = 0; x < width; x++) { 1.215 + dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[0], src[0], 1.216 + DITHER_VALUE(x)); 1.217 + src += deltaSrc; 1.218 + } 1.219 + return false; 1.220 +} 1.221 + 1.222 +static SkScaledBitmapSampler::RowProc get_gray_to_4444_proc(const SkImageDecoder& decoder) { 1.223 + // Skip zeroes and unpremul make no difference 1.224 + if (decoder.getDitherImage()) { 1.225 + return Sample_Gray_D4444_D; 1.226 + } 1.227 + return Sample_Gray_D4444; 1.228 +} 1.229 + 1.230 +static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow, 1.231 + const uint8_t* SK_RESTRICT src, 1.232 + int width, int deltaSrc, int, const SkPMColor[]) { 1.233 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.234 + for (int x = 0; x < width; x++) { 1.235 + dst[x] = SkPackARGB4444(0xF, src[0] >> 4, src[1] >> 4, src[2] >> 4); 1.236 + src += deltaSrc; 1.237 + } 1.238 + return false; 1.239 +} 1.240 + 1.241 +static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow, 1.242 + const uint8_t* SK_RESTRICT src, 1.243 + int width, int deltaSrc, int y, const SkPMColor[]) { 1.244 + SkPMColor16* dst = (SkPMColor16*)dstRow; 1.245 + DITHER_4444_SCAN(y); 1.246 + 1.247 + for (int x = 0; x < width; x++) { 1.248 + dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[1], src[2], 1.249 + DITHER_VALUE(x)); 1.250 + src += deltaSrc; 1.251 + } 1.252 + return false; 1.253 +} 1.254 + 1.255 +static SkScaledBitmapSampler::RowProc get_RGBx_to_4444_proc(const SkImageDecoder& decoder) { 1.256 + // Skip zeroes and unpremul make no difference 1.257 + if (decoder.getDitherImage()) { 1.258 + return Sample_RGBx_D4444_D; 1.259 + } 1.260 + return Sample_RGBx_D4444; 1.261 +} 1.262 + 1.263 +static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow, 1.264 + const uint8_t* SK_RESTRICT src, 1.265 + int width, int deltaSrc, int, const SkPMColor[]) { 1.266 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.267 + unsigned alphaMask = 0xFF; 1.268 + 1.269 + for (int x = 0; x < width; x++) { 1.270 + unsigned alpha = src[3]; 1.271 + SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 1.272 + dst[x] = SkPixel32ToPixel4444(c); 1.273 + src += deltaSrc; 1.274 + alphaMask &= alpha; 1.275 + } 1.276 + return alphaMask != 0xFF; 1.277 +} 1.278 + 1.279 +static bool Sample_RGBA_D4444_SkipZ(void* SK_RESTRICT dstRow, 1.280 + const uint8_t* SK_RESTRICT src, 1.281 + int width, int deltaSrc, int, 1.282 + const SkPMColor[]) { 1.283 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.284 + unsigned alphaMask = 0xFF; 1.285 + 1.286 + for (int x = 0; x < width; x++) { 1.287 + unsigned alpha = src[3]; 1.288 + if (alpha != 0) { 1.289 + SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 1.290 + dst[x] = SkPixel32ToPixel4444(c); 1.291 + } 1.292 + src += deltaSrc; 1.293 + alphaMask &= alpha; 1.294 + } 1.295 + return alphaMask != 0xFF; 1.296 +} 1.297 + 1.298 + 1.299 +static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow, 1.300 + const uint8_t* SK_RESTRICT src, 1.301 + int width, int deltaSrc, int y, 1.302 + const SkPMColor[]) { 1.303 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.304 + unsigned alphaMask = 0xFF; 1.305 + DITHER_4444_SCAN(y); 1.306 + 1.307 + for (int x = 0; x < width; x++) { 1.308 + unsigned alpha = src[3]; 1.309 + SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 1.310 + dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x)); 1.311 + src += deltaSrc; 1.312 + alphaMask &= alpha; 1.313 + } 1.314 + return alphaMask != 0xFF; 1.315 +} 1.316 + 1.317 +static bool Sample_RGBA_D4444_D_SkipZ(void* SK_RESTRICT dstRow, 1.318 + const uint8_t* SK_RESTRICT src, 1.319 + int width, int deltaSrc, int y, 1.320 + const SkPMColor[]) { 1.321 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.322 + unsigned alphaMask = 0xFF; 1.323 + DITHER_4444_SCAN(y); 1.324 + 1.325 + for (int x = 0; x < width; x++) { 1.326 + unsigned alpha = src[3]; 1.327 + if (alpha != 0) { 1.328 + SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 1.329 + dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x)); 1.330 + } 1.331 + src += deltaSrc; 1.332 + alphaMask &= alpha; 1.333 + } 1.334 + return alphaMask != 0xFF; 1.335 +} 1.336 + 1.337 +static SkScaledBitmapSampler::RowProc get_RGBA_to_4444_proc(const SkImageDecoder& decoder) { 1.338 + if (decoder.getRequireUnpremultipliedColors()) { 1.339 + // Unpremultiplied is not supported for 4444 1.340 + return NULL; 1.341 + } 1.342 + const bool dither = decoder.getDitherImage(); 1.343 + if (decoder.getSkipWritingZeroes()) { 1.344 + if (dither) { 1.345 + return Sample_RGBA_D4444_D_SkipZ; 1.346 + } 1.347 + return Sample_RGBA_D4444_SkipZ; 1.348 + } 1.349 + if (dither) { 1.350 + return Sample_RGBA_D4444_D; 1.351 + } 1.352 + return Sample_RGBA_D4444; 1.353 +} 1.354 + 1.355 +// Index 1.356 + 1.357 +#define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT) 1.358 + 1.359 +static bool Sample_Index_D8888(void* SK_RESTRICT dstRow, 1.360 + const uint8_t* SK_RESTRICT src, 1.361 + int width, int deltaSrc, int, const SkPMColor ctable[]) { 1.362 + 1.363 + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 1.364 + SkPMColor cc = A32_MASK_IN_PLACE; 1.365 + for (int x = 0; x < width; x++) { 1.366 + SkPMColor c = ctable[*src]; 1.367 + cc &= c; 1.368 + dst[x] = c; 1.369 + src += deltaSrc; 1.370 + } 1.371 + return cc != A32_MASK_IN_PLACE; 1.372 +} 1.373 + 1.374 +static bool Sample_Index_D8888_SkipZ(void* SK_RESTRICT dstRow, 1.375 + const uint8_t* SK_RESTRICT src, 1.376 + int width, int deltaSrc, int, 1.377 + const SkPMColor ctable[]) { 1.378 + 1.379 + SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 1.380 + SkPMColor cc = A32_MASK_IN_PLACE; 1.381 + for (int x = 0; x < width; x++) { 1.382 + SkPMColor c = ctable[*src]; 1.383 + cc &= c; 1.384 + if (c != 0) { 1.385 + dst[x] = c; 1.386 + } 1.387 + src += deltaSrc; 1.388 + } 1.389 + return cc != A32_MASK_IN_PLACE; 1.390 +} 1.391 + 1.392 +static SkScaledBitmapSampler::RowProc get_index_to_8888_proc(const SkImageDecoder& decoder) { 1.393 + if (decoder.getRequireUnpremultipliedColors()) { 1.394 + // Unpremultiplied is not supported for an index source. 1.395 + return NULL; 1.396 + } 1.397 + // Dither makes no difference 1.398 + if (decoder.getSkipWritingZeroes()) { 1.399 + return Sample_Index_D8888_SkipZ; 1.400 + } 1.401 + return Sample_Index_D8888; 1.402 +} 1.403 + 1.404 +static bool Sample_Index_D565(void* SK_RESTRICT dstRow, 1.405 + const uint8_t* SK_RESTRICT src, 1.406 + int width, int deltaSrc, int, const SkPMColor ctable[]) { 1.407 + 1.408 + uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 1.409 + for (int x = 0; x < width; x++) { 1.410 + dst[x] = SkPixel32ToPixel16(ctable[*src]); 1.411 + src += deltaSrc; 1.412 + } 1.413 + return false; 1.414 +} 1.415 + 1.416 +static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow, 1.417 + const uint8_t* SK_RESTRICT src, int width, 1.418 + int deltaSrc, int y, const SkPMColor ctable[]) { 1.419 + 1.420 + uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 1.421 + DITHER_565_SCAN(y); 1.422 + 1.423 + for (int x = 0; x < width; x++) { 1.424 + SkPMColor c = ctable[*src]; 1.425 + dst[x] = SkDitherRGBTo565(SkGetPackedR32(c), SkGetPackedG32(c), 1.426 + SkGetPackedB32(c), DITHER_VALUE(x)); 1.427 + src += deltaSrc; 1.428 + } 1.429 + return false; 1.430 +} 1.431 + 1.432 +static SkScaledBitmapSampler::RowProc get_index_to_565_proc(const SkImageDecoder& decoder) { 1.433 + // Unpremultiplied and skip zeroes make no difference 1.434 + if (decoder.getDitherImage()) { 1.435 + return Sample_Index_D565_D; 1.436 + } 1.437 + return Sample_Index_D565; 1.438 +} 1.439 + 1.440 +static bool Sample_Index_D4444(void* SK_RESTRICT dstRow, 1.441 + const uint8_t* SK_RESTRICT src, int width, 1.442 + int deltaSrc, int y, const SkPMColor ctable[]) { 1.443 + 1.444 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.445 + SkPMColor cc = A32_MASK_IN_PLACE; 1.446 + for (int x = 0; x < width; x++) { 1.447 + SkPMColor c = ctable[*src]; 1.448 + cc &= c; 1.449 + dst[x] = SkPixel32ToPixel4444(c); 1.450 + src += deltaSrc; 1.451 + } 1.452 + return cc != A32_MASK_IN_PLACE; 1.453 +} 1.454 + 1.455 +static bool Sample_Index_D4444_D(void* SK_RESTRICT dstRow, 1.456 + const uint8_t* SK_RESTRICT src, int width, 1.457 + int deltaSrc, int y, const SkPMColor ctable[]) { 1.458 + 1.459 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.460 + SkPMColor cc = A32_MASK_IN_PLACE; 1.461 + DITHER_4444_SCAN(y); 1.462 + 1.463 + for (int x = 0; x < width; x++) { 1.464 + SkPMColor c = ctable[*src]; 1.465 + cc &= c; 1.466 + dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x)); 1.467 + src += deltaSrc; 1.468 + } 1.469 + return cc != A32_MASK_IN_PLACE; 1.470 +} 1.471 + 1.472 +static bool Sample_Index_D4444_SkipZ(void* SK_RESTRICT dstRow, 1.473 + const uint8_t* SK_RESTRICT src, int width, 1.474 + int deltaSrc, int y, const SkPMColor ctable[]) { 1.475 + 1.476 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.477 + SkPMColor cc = A32_MASK_IN_PLACE; 1.478 + for (int x = 0; x < width; x++) { 1.479 + SkPMColor c = ctable[*src]; 1.480 + cc &= c; 1.481 + if (c != 0) { 1.482 + dst[x] = SkPixel32ToPixel4444(c); 1.483 + } 1.484 + src += deltaSrc; 1.485 + } 1.486 + return cc != A32_MASK_IN_PLACE; 1.487 +} 1.488 + 1.489 +static bool Sample_Index_D4444_D_SkipZ(void* SK_RESTRICT dstRow, 1.490 + const uint8_t* SK_RESTRICT src, int width, 1.491 + int deltaSrc, int y, const SkPMColor ctable[]) { 1.492 + 1.493 + SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; 1.494 + SkPMColor cc = A32_MASK_IN_PLACE; 1.495 + DITHER_4444_SCAN(y); 1.496 + 1.497 + for (int x = 0; x < width; x++) { 1.498 + SkPMColor c = ctable[*src]; 1.499 + cc &= c; 1.500 + if (c != 0) { 1.501 + dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x)); 1.502 + } 1.503 + src += deltaSrc; 1.504 + } 1.505 + return cc != A32_MASK_IN_PLACE; 1.506 +} 1.507 + 1.508 +static SkScaledBitmapSampler::RowProc get_index_to_4444_proc(const SkImageDecoder& decoder) { 1.509 + // Unpremul not allowed 1.510 + if (decoder.getRequireUnpremultipliedColors()) { 1.511 + return NULL; 1.512 + } 1.513 + const bool dither = decoder.getDitherImage(); 1.514 + if (decoder.getSkipWritingZeroes()) { 1.515 + if (dither) { 1.516 + return Sample_Index_D4444_D_SkipZ; 1.517 + } 1.518 + return Sample_Index_D4444_SkipZ; 1.519 + } 1.520 + if (dither) { 1.521 + return Sample_Index_D4444_D; 1.522 + } 1.523 + return Sample_Index_D4444; 1.524 +} 1.525 + 1.526 +static bool Sample_Index_DI(void* SK_RESTRICT dstRow, 1.527 + const uint8_t* SK_RESTRICT src, 1.528 + int width, int deltaSrc, int, const SkPMColor[]) { 1.529 + if (1 == deltaSrc) { 1.530 + memcpy(dstRow, src, width); 1.531 + } else { 1.532 + uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow; 1.533 + for (int x = 0; x < width; x++) { 1.534 + dst[x] = src[0]; 1.535 + src += deltaSrc; 1.536 + } 1.537 + } 1.538 + return false; 1.539 +} 1.540 + 1.541 +static SkScaledBitmapSampler::RowProc get_index_to_index_proc(const SkImageDecoder& decoder) { 1.542 + // Unpremul not allowed 1.543 + if (decoder.getRequireUnpremultipliedColors()) { 1.544 + return NULL; 1.545 + } 1.546 + // Ignore dither and skip zeroes 1.547 + return Sample_Index_DI; 1.548 +} 1.549 + 1.550 +// A8 1.551 +static bool Sample_Gray_DA8(void* SK_RESTRICT dstRow, 1.552 + const uint8_t* SK_RESTRICT src, 1.553 + int width, int deltaSrc, int, 1.554 + const SkPMColor[]) { 1.555 + // Sampling Gray to A8 uses the same function as Index to Index8, 1.556 + // except we assume that there is alpha for speed, since an A8 1.557 + // bitmap with no alpha is not interesting. 1.558 + (void) Sample_Index_DI(dstRow, src, width, deltaSrc, /* y unused */ 0, 1.559 + /* ctable unused */ NULL); 1.560 + return true; 1.561 +} 1.562 + 1.563 +static SkScaledBitmapSampler::RowProc get_gray_to_A8_proc(const SkImageDecoder& decoder) { 1.564 + if (decoder.getRequireUnpremultipliedColors()) { 1.565 + return NULL; 1.566 + } 1.567 + // Ignore skip and dither. 1.568 + return Sample_Gray_DA8; 1.569 +} 1.570 + 1.571 +typedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkImageDecoder& decoder); 1.572 +/////////////////////////////////////////////////////////////////////////////// 1.573 + 1.574 +#include "SkScaledBitmapSampler.h" 1.575 + 1.576 +SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height, 1.577 + int sampleSize) { 1.578 + fCTable = NULL; 1.579 + fDstRow = NULL; 1.580 + fRowProc = NULL; 1.581 + 1.582 + if (width <= 0 || height <= 0) { 1.583 + sk_throw(); 1.584 + } 1.585 + 1.586 + SkDEBUGCODE(fSampleMode = kUninitialized_SampleMode); 1.587 + 1.588 + if (sampleSize <= 1) { 1.589 + fScaledWidth = width; 1.590 + fScaledHeight = height; 1.591 + fX0 = fY0 = 0; 1.592 + fDX = fDY = 1; 1.593 + return; 1.594 + } 1.595 + 1.596 + int dx = SkMin32(sampleSize, width); 1.597 + int dy = SkMin32(sampleSize, height); 1.598 + 1.599 + fScaledWidth = width / dx; 1.600 + fScaledHeight = height / dy; 1.601 + 1.602 + SkASSERT(fScaledWidth > 0); 1.603 + SkASSERT(fScaledHeight > 0); 1.604 + 1.605 + fX0 = dx >> 1; 1.606 + fY0 = dy >> 1; 1.607 + 1.608 + SkASSERT(fX0 >= 0 && fX0 < width); 1.609 + SkASSERT(fY0 >= 0 && fY0 < height); 1.610 + 1.611 + fDX = dx; 1.612 + fDY = dy; 1.613 + 1.614 + SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width); 1.615 + SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height); 1.616 +} 1.617 + 1.618 +bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, 1.619 + const SkImageDecoder& decoder, 1.620 + const SkPMColor ctable[]) { 1.621 + static const RowProcChooser gProcChoosers[] = { 1.622 + get_gray_to_8888_proc, 1.623 + get_RGBx_to_8888_proc, 1.624 + get_RGBA_to_8888_proc, 1.625 + get_index_to_8888_proc, 1.626 + NULL, // 565 to 8888 1.627 + 1.628 + get_gray_to_565_proc, 1.629 + get_RGBx_to_565_proc, 1.630 + get_RGBx_to_565_proc, // The source alpha will be ignored. 1.631 + get_index_to_565_proc, 1.632 + get_565_to_565_proc, 1.633 + 1.634 + get_gray_to_4444_proc, 1.635 + get_RGBx_to_4444_proc, 1.636 + get_RGBA_to_4444_proc, 1.637 + get_index_to_4444_proc, 1.638 + NULL, // 565 to 4444 1.639 + 1.640 + NULL, // gray to index 1.641 + NULL, // rgbx to index 1.642 + NULL, // rgba to index 1.643 + get_index_to_index_proc, 1.644 + NULL, // 565 to index 1.645 + 1.646 + get_gray_to_A8_proc, 1.647 + NULL, // rgbx to a8 1.648 + NULL, // rgba to a8 1.649 + NULL, // index to a8 1.650 + NULL, // 565 to a8 1.651 + }; 1.652 + 1.653 + // The jump between dst configs in the table 1.654 + static const int gProcDstConfigSpan = 5; 1.655 + SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gProcChoosers) == 5 * gProcDstConfigSpan, 1.656 + gProcs_has_the_wrong_number_of_entries); 1.657 + 1.658 + fCTable = ctable; 1.659 + 1.660 + int index = 0; 1.661 + switch (sc) { 1.662 + case SkScaledBitmapSampler::kGray: 1.663 + fSrcPixelSize = 1; 1.664 + index += 0; 1.665 + break; 1.666 + case SkScaledBitmapSampler::kRGB: 1.667 + fSrcPixelSize = 3; 1.668 + index += 1; 1.669 + break; 1.670 + case SkScaledBitmapSampler::kRGBX: 1.671 + fSrcPixelSize = 4; 1.672 + index += 1; 1.673 + break; 1.674 + case SkScaledBitmapSampler::kRGBA: 1.675 + fSrcPixelSize = 4; 1.676 + index += 2; 1.677 + break; 1.678 + case SkScaledBitmapSampler::kIndex: 1.679 + fSrcPixelSize = 1; 1.680 + index += 3; 1.681 + break; 1.682 + case SkScaledBitmapSampler::kRGB_565: 1.683 + fSrcPixelSize = 2; 1.684 + index += 4; 1.685 + break; 1.686 + default: 1.687 + return false; 1.688 + } 1.689 + 1.690 + switch (dst->config()) { 1.691 + case SkBitmap::kARGB_8888_Config: 1.692 + index += 0 * gProcDstConfigSpan; 1.693 + break; 1.694 + case SkBitmap::kRGB_565_Config: 1.695 + index += 1 * gProcDstConfigSpan; 1.696 + break; 1.697 + case SkBitmap::kARGB_4444_Config: 1.698 + index += 2 * gProcDstConfigSpan; 1.699 + break; 1.700 + case SkBitmap::kIndex8_Config: 1.701 + index += 3 * gProcDstConfigSpan; 1.702 + break; 1.703 + case SkBitmap::kA8_Config: 1.704 + index += 4 * gProcDstConfigSpan; 1.705 + break; 1.706 + default: 1.707 + return false; 1.708 + } 1.709 + 1.710 + RowProcChooser chooser = gProcChoosers[index]; 1.711 + if (NULL == chooser) { 1.712 + fRowProc = NULL; 1.713 + } else { 1.714 + fRowProc = chooser(decoder); 1.715 + } 1.716 + fDstRow = (char*)dst->getPixels(); 1.717 + fDstRowBytes = dst->rowBytes(); 1.718 + fCurrY = 0; 1.719 + return fRowProc != NULL; 1.720 +} 1.721 + 1.722 +bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) { 1.723 + SkASSERT(kInterlaced_SampleMode != fSampleMode); 1.724 + SkDEBUGCODE(fSampleMode = kConsecutive_SampleMode); 1.725 + SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight); 1.726 + 1.727 + bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth, 1.728 + fDX * fSrcPixelSize, fCurrY, fCTable); 1.729 + fDstRow += fDstRowBytes; 1.730 + fCurrY += 1; 1.731 + return hadAlpha; 1.732 +} 1.733 + 1.734 +bool SkScaledBitmapSampler::sampleInterlaced(const uint8_t* SK_RESTRICT src, int srcY) { 1.735 + SkASSERT(kConsecutive_SampleMode != fSampleMode); 1.736 + SkDEBUGCODE(fSampleMode = kInterlaced_SampleMode); 1.737 + // Any line that should be a part of the destination can be created by the formula: 1.738 + // fY0 + (some multiplier) * fDY 1.739 + // so if srcY - fY0 is not an integer multiple of fDY that srcY will be skipped. 1.740 + const int srcYMinusY0 = srcY - fY0; 1.741 + if (srcYMinusY0 % fDY != 0) { 1.742 + // This line is not part of the output, so return false for alpha, since we have 1.743 + // not added an alpha to the output. 1.744 + return false; 1.745 + } 1.746 + // Unlike in next(), where the data is used sequentially, this function skips around, 1.747 + // so fDstRow and fCurrY are never updated. fDstRow must always be the starting point 1.748 + // of the destination bitmap's pixels, which is used to calculate the destination row 1.749 + // each time this function is called. 1.750 + const int dstY = srcYMinusY0 / fDY; 1.751 + SkASSERT(dstY < fScaledHeight); 1.752 + char* dstRow = fDstRow + dstY * fDstRowBytes; 1.753 + return fRowProc(dstRow, src + fX0 * fSrcPixelSize, fScaledWidth, 1.754 + fDX * fSrcPixelSize, dstY, fCTable); 1.755 +} 1.756 + 1.757 +#ifdef SK_DEBUG 1.758 +// The following code is for a test to ensure that changing the method to get the right row proc 1.759 +// did not change the row proc unintentionally. Tested by ImageDecodingTest.cpp 1.760 + 1.761 +// friend of SkScaledBitmapSampler solely for the purpose of accessing fRowProc. 1.762 +class RowProcTester { 1.763 +public: 1.764 + static SkScaledBitmapSampler::RowProc getRowProc(const SkScaledBitmapSampler& sampler) { 1.765 + return sampler.fRowProc; 1.766 + } 1.767 +}; 1.768 + 1.769 + 1.770 +// Table showing the expected RowProc for each combination of inputs. 1.771 +// Table formated as follows: 1.772 +// Each group of 5 consecutive rows represents sampling from a single 1.773 +// SkScaledBitmapSampler::SrcConfig. 1.774 +// Within each set, each row represents a different destination SkBitmap::Config 1.775 +// Each column represents a different combination of dither and unpremul. 1.776 +// D = dither ~D = no dither 1.777 +// U = unpremul ~U = no unpremul 1.778 +// ~D~U D~U ~DU DU 1.779 +SkScaledBitmapSampler::RowProc gTestProcs[] = { 1.780 + // Gray 1.781 + Sample_Gray_DA8, Sample_Gray_DA8, NULL, NULL, // to A8 1.782 + NULL, NULL, NULL, NULL, // to Index8 1.783 + Sample_Gray_D565, Sample_Gray_D565_D, Sample_Gray_D565, Sample_Gray_D565_D, // to 565 1.784 + Sample_Gray_D4444, Sample_Gray_D4444_D, Sample_Gray_D4444, Sample_Gray_D4444_D, // to 4444 1.785 + Sample_Gray_D8888, Sample_Gray_D8888, Sample_Gray_D8888, Sample_Gray_D8888, // to 8888 1.786 + // Index 1.787 + NULL, NULL, NULL, NULL, // to A8 1.788 + Sample_Index_DI, Sample_Index_DI, NULL, NULL, // to Index8 1.789 + Sample_Index_D565, Sample_Index_D565_D, Sample_Index_D565, Sample_Index_D565_D, // to 565 1.790 + Sample_Index_D4444, Sample_Index_D4444_D, NULL, NULL, // to 4444 1.791 + Sample_Index_D8888, Sample_Index_D8888, NULL, NULL, // to 8888 1.792 + // RGB 1.793 + NULL, NULL, NULL, NULL, // to A8 1.794 + NULL, NULL, NULL, NULL, // to Index8 1.795 + Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565 1.796 + Sample_RGBx_D4444, Sample_RGBx_D4444_D, Sample_RGBx_D4444, Sample_RGBx_D4444_D, // to 4444 1.797 + Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, // to 8888 1.798 + // RGBx is the same as RGB 1.799 + NULL, NULL, NULL, NULL, // to A8 1.800 + NULL, NULL, NULL, NULL, // to Index8 1.801 + Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565 1.802 + Sample_RGBx_D4444, Sample_RGBx_D4444_D, Sample_RGBx_D4444, Sample_RGBx_D4444_D, // to 4444 1.803 + Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, // to 8888 1.804 + // RGBA 1.805 + NULL, NULL, NULL, NULL, // to A8 1.806 + NULL, NULL, NULL, NULL, // to Index8 1.807 + Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565 1.808 + Sample_RGBA_D4444, Sample_RGBA_D4444_D, NULL, NULL, // to 4444 1.809 + Sample_RGBA_D8888, Sample_RGBA_D8888, Sample_RGBA_D8888_Unpremul, Sample_RGBA_D8888_Unpremul, // to 8888 1.810 + // RGB_565 1.811 + NULL, NULL, NULL, NULL, // to A8 1.812 + NULL, NULL, NULL, NULL, // to Index8 1.813 + Sample_D565_D565, Sample_D565_D565, Sample_D565_D565, Sample_D565_D565, // to 565 1.814 + NULL, NULL, NULL, NULL, // to 4444 1.815 + NULL, NULL, NULL, NULL, // to 8888 1.816 +}; 1.817 + 1.818 +// Dummy class that allows instantiation of an ImageDecoder, so begin can query its fields. 1.819 +class DummyDecoder : public SkImageDecoder { 1.820 +public: 1.821 + DummyDecoder() {} 1.822 +protected: 1.823 + virtual bool onDecode(SkStream*, SkBitmap*, SkImageDecoder::Mode) SK_OVERRIDE { 1.824 + return false; 1.825 + } 1.826 +}; 1.827 + 1.828 +void test_row_proc_choice(); 1.829 +void test_row_proc_choice() { 1.830 + SkBitmap dummyBitmap; 1.831 + DummyDecoder dummyDecoder; 1.832 + size_t procCounter = 0; 1.833 + for (int sc = SkScaledBitmapSampler::kGray; sc <= SkScaledBitmapSampler::kRGB_565; ++sc) { 1.834 + for (int c = SkBitmap::kA8_Config; c <= SkBitmap::kARGB_8888_Config; ++c) { 1.835 + for (int unpremul = 0; unpremul <= 1; ++unpremul) { 1.836 + for (int dither = 0; dither <= 1; ++dither) { 1.837 + // Arbitrary width/height/sampleSize to allow SkScaledBitmapSampler to 1.838 + // be considered valid. 1.839 + SkScaledBitmapSampler sampler(10, 10, 1); 1.840 + dummyBitmap.setConfig((SkBitmap::Config) c, 10, 10); 1.841 + dummyDecoder.setDitherImage(SkToBool(dither)); 1.842 + dummyDecoder.setRequireUnpremultipliedColors(SkToBool(unpremul)); 1.843 + sampler.begin(&dummyBitmap, (SkScaledBitmapSampler::SrcConfig) sc, 1.844 + dummyDecoder); 1.845 + SkScaledBitmapSampler::RowProc expected = gTestProcs[procCounter]; 1.846 + SkScaledBitmapSampler::RowProc actual = RowProcTester::getRowProc(sampler); 1.847 + SkASSERT(expected == actual); 1.848 + procCounter++; 1.849 + } 1.850 + } 1.851 + } 1.852 + } 1.853 + SkASSERT(SK_ARRAY_COUNT(gTestProcs) == procCounter); 1.854 +} 1.855 +#endif // SK_DEBUG