2 * Copyright 2007 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "SkScaledBitmapSampler.h"
11 #include "SkColorPriv.h"
17 static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow,
18 const uint8_t* SK_RESTRICT src,
19 int width, int deltaSrc, int, const SkPMColor[]) {
20 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
21 for (int x = 0; x < width; x++) {
22 dst[x] = SkPackARGB32(0xFF, src[0], src[0], src[0]);
28 static SkScaledBitmapSampler::RowProc
29 get_gray_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
30 // Dither, unpremul, and skipZeroes have no effect
31 return Sample_Gray_D8888;
34 static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow,
35 const uint8_t* SK_RESTRICT src,
36 int width, int deltaSrc, int, const SkPMColor[]) {
37 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
38 for (int x = 0; x < width; x++) {
39 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
45 static SkScaledBitmapSampler::RowProc
46 get_RGBx_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
47 // Dither, unpremul, and skipZeroes have no effect
48 return Sample_RGBx_D8888;
51 static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow,
52 const uint8_t* SK_RESTRICT src,
53 int width, int deltaSrc, int, const SkPMColor[]) {
54 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
55 unsigned alphaMask = 0xFF;
56 for (int x = 0; x < width; x++) {
57 unsigned alpha = src[3];
58 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
62 return alphaMask != 0xFF;
65 static bool Sample_RGBA_D8888_Unpremul(void* SK_RESTRICT dstRow,
66 const uint8_t* SK_RESTRICT src,
67 int width, int deltaSrc, int,
69 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
70 unsigned alphaMask = 0xFF;
71 for (int x = 0; x < width; x++) {
72 unsigned alpha = src[3];
73 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
77 return alphaMask != 0xFF;
80 static bool Sample_RGBA_D8888_SkipZ(void* SK_RESTRICT dstRow,
81 const uint8_t* SK_RESTRICT src,
82 int width, int deltaSrc, int,
84 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
85 unsigned alphaMask = 0xFF;
86 for (int x = 0; x < width; x++) {
87 unsigned alpha = src[3];
89 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
94 return alphaMask != 0xFF;
97 static SkScaledBitmapSampler::RowProc
98 get_RGBA_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
99 // Dither has no effect.
100 if (!opts.fPremultiplyAlpha) {
101 // We could check each component for a zero, at the expense of extra checks.
102 // For now, just return unpremul.
103 return Sample_RGBA_D8888_Unpremul;
105 // Supply the versions that premultiply the colors
106 if (opts.fSkipZeros) {
107 return Sample_RGBA_D8888_SkipZ;
109 return Sample_RGBA_D8888;
114 static bool Sample_Gray_D565(void* SK_RESTRICT dstRow,
115 const uint8_t* SK_RESTRICT src,
116 int width, int deltaSrc, int, const SkPMColor[]) {
117 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
118 for (int x = 0; x < width; x++) {
119 dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
125 static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow,
126 const uint8_t* SK_RESTRICT src,
127 int width, int deltaSrc, int y, const SkPMColor[]) {
128 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
130 for (int x = 0; x < width; x++) {
131 dst[x] = SkDitherRGBTo565(src[0], src[0], src[0], DITHER_VALUE(x));
137 static SkScaledBitmapSampler::RowProc
138 get_gray_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
139 // Unpremul and skip zeroes make no difference
141 return Sample_Gray_D565_D;
143 return Sample_Gray_D565;
146 static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
147 const uint8_t* SK_RESTRICT src,
148 int width, int deltaSrc, int, const SkPMColor[]) {
149 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
150 for (int x = 0; x < width; x++) {
151 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
157 static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
158 const uint8_t* SK_RESTRICT src,
159 int width, int deltaSrc, int y,
161 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
163 for (int x = 0; x < width; x++) {
164 dst[x] = SkDitherRGBTo565(src[0], src[1], src[2], DITHER_VALUE(x));
170 static SkScaledBitmapSampler::RowProc
171 get_RGBx_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
172 // Unpremul and skip zeroes make no difference
174 return Sample_RGBx_D565_D;
176 return Sample_RGBx_D565;
180 static bool Sample_D565_D565(void* SK_RESTRICT dstRow,
181 const uint8_t* SK_RESTRICT src,
182 int width, int deltaSrc, int, const SkPMColor[]) {
183 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
184 uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src;
185 for (int x = 0; x < width; x++) {
186 dst[x] = castedSrc[0];
187 castedSrc += deltaSrc >> 1;
192 static SkScaledBitmapSampler::RowProc
193 get_565_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
194 // Unpremul, dither, and skip zeroes have no effect
195 return Sample_D565_D565;
200 static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow,
201 const uint8_t* SK_RESTRICT src,
202 int width, int deltaSrc, int, const SkPMColor[]) {
203 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
204 for (int x = 0; x < width; x++) {
205 unsigned gray = src[0] >> 4;
206 dst[x] = SkPackARGB4444(0xF, gray, gray, gray);
212 static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow,
213 const uint8_t* SK_RESTRICT src,
214 int width, int deltaSrc, int y, const SkPMColor[]) {
215 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
217 for (int x = 0; x < width; x++) {
218 dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[0], src[0],
225 static SkScaledBitmapSampler::RowProc
226 get_gray_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
227 // Skip zeroes and unpremul make no difference
229 return Sample_Gray_D4444_D;
231 return Sample_Gray_D4444;
234 static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow,
235 const uint8_t* SK_RESTRICT src,
236 int width, int deltaSrc, int, const SkPMColor[]) {
237 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
238 for (int x = 0; x < width; x++) {
239 dst[x] = SkPackARGB4444(0xF, src[0] >> 4, src[1] >> 4, src[2] >> 4);
245 static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow,
246 const uint8_t* SK_RESTRICT src,
247 int width, int deltaSrc, int y, const SkPMColor[]) {
248 SkPMColor16* dst = (SkPMColor16*)dstRow;
251 for (int x = 0; x < width; x++) {
252 dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[1], src[2],
259 static SkScaledBitmapSampler::RowProc
260 get_RGBx_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
261 // Skip zeroes and unpremul make no difference
263 return Sample_RGBx_D4444_D;
265 return Sample_RGBx_D4444;
268 static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow,
269 const uint8_t* SK_RESTRICT src,
270 int width, int deltaSrc, int, const SkPMColor[]) {
271 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
272 unsigned alphaMask = 0xFF;
274 for (int x = 0; x < width; x++) {
275 unsigned alpha = src[3];
276 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
277 dst[x] = SkPixel32ToPixel4444(c);
281 return alphaMask != 0xFF;
284 static bool Sample_RGBA_D4444_SkipZ(void* SK_RESTRICT dstRow,
285 const uint8_t* SK_RESTRICT src,
286 int width, int deltaSrc, int,
288 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
289 unsigned alphaMask = 0xFF;
291 for (int x = 0; x < width; x++) {
292 unsigned alpha = src[3];
294 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
295 dst[x] = SkPixel32ToPixel4444(c);
300 return alphaMask != 0xFF;
304 static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow,
305 const uint8_t* SK_RESTRICT src,
306 int width, int deltaSrc, int y,
308 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
309 unsigned alphaMask = 0xFF;
312 for (int x = 0; x < width; x++) {
313 unsigned alpha = src[3];
314 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
315 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
319 return alphaMask != 0xFF;
322 static bool Sample_RGBA_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
323 const uint8_t* SK_RESTRICT src,
324 int width, int deltaSrc, int y,
326 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
327 unsigned alphaMask = 0xFF;
330 for (int x = 0; x < width; x++) {
331 unsigned alpha = src[3];
333 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
334 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
339 return alphaMask != 0xFF;
342 static SkScaledBitmapSampler::RowProc
343 get_RGBA_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
344 if (!opts.fPremultiplyAlpha) {
345 // Unpremultiplied is not supported for 4444
348 if (opts.fSkipZeros) {
350 return Sample_RGBA_D4444_D_SkipZ;
352 return Sample_RGBA_D4444_SkipZ;
355 return Sample_RGBA_D4444_D;
357 return Sample_RGBA_D4444;
362 #define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT)
364 static bool Sample_Index_D8888(void* SK_RESTRICT dstRow,
365 const uint8_t* SK_RESTRICT src,
366 int width, int deltaSrc, int, const SkPMColor ctable[]) {
368 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
369 SkPMColor cc = A32_MASK_IN_PLACE;
370 for (int x = 0; x < width; x++) {
371 SkPMColor c = ctable[*src];
376 return cc != A32_MASK_IN_PLACE;
379 static bool Sample_Index_D8888_SkipZ(void* SK_RESTRICT dstRow,
380 const uint8_t* SK_RESTRICT src,
381 int width, int deltaSrc, int,
382 const SkPMColor ctable[]) {
384 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
385 SkPMColor cc = A32_MASK_IN_PLACE;
386 for (int x = 0; x < width; x++) {
387 SkPMColor c = ctable[*src];
394 return cc != A32_MASK_IN_PLACE;
397 static SkScaledBitmapSampler::RowProc
398 get_index_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
399 // The caller is expected to have created the source colortable
400 // properly with respect to opts.fPremultiplyAlpha, so premul makes
401 // no difference here.
402 // Dither makes no difference
403 if (opts.fSkipZeros) {
404 return Sample_Index_D8888_SkipZ;
406 return Sample_Index_D8888;
409 static bool Sample_Index_D565(void* SK_RESTRICT dstRow,
410 const uint8_t* SK_RESTRICT src,
411 int width, int deltaSrc, int, const SkPMColor ctable[]) {
413 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
414 for (int x = 0; x < width; x++) {
415 dst[x] = SkPixel32ToPixel16(ctable[*src]);
421 static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow,
422 const uint8_t* SK_RESTRICT src, int width,
423 int deltaSrc, int y, const SkPMColor ctable[]) {
425 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
428 for (int x = 0; x < width; x++) {
429 SkPMColor c = ctable[*src];
430 dst[x] = SkDitherRGBTo565(SkGetPackedR32(c), SkGetPackedG32(c),
431 SkGetPackedB32(c), DITHER_VALUE(x));
437 static SkScaledBitmapSampler::RowProc
438 get_index_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
439 // Unpremultiplied and skip zeroes make no difference
441 return Sample_Index_D565_D;
443 return Sample_Index_D565;
446 static bool Sample_Index_D4444(void* SK_RESTRICT dstRow,
447 const uint8_t* SK_RESTRICT src, int width,
448 int deltaSrc, int y, const SkPMColor ctable[]) {
450 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
451 SkPMColor cc = A32_MASK_IN_PLACE;
452 for (int x = 0; x < width; x++) {
453 SkPMColor c = ctable[*src];
455 dst[x] = SkPixel32ToPixel4444(c);
458 return cc != A32_MASK_IN_PLACE;
461 static bool Sample_Index_D4444_D(void* SK_RESTRICT dstRow,
462 const uint8_t* SK_RESTRICT src, int width,
463 int deltaSrc, int y, const SkPMColor ctable[]) {
465 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
466 SkPMColor cc = A32_MASK_IN_PLACE;
469 for (int x = 0; x < width; x++) {
470 SkPMColor c = ctable[*src];
472 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
475 return cc != A32_MASK_IN_PLACE;
478 static bool Sample_Index_D4444_SkipZ(void* SK_RESTRICT dstRow,
479 const uint8_t* SK_RESTRICT src, int width,
480 int deltaSrc, int y, const SkPMColor ctable[]) {
482 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
483 SkPMColor cc = A32_MASK_IN_PLACE;
484 for (int x = 0; x < width; x++) {
485 SkPMColor c = ctable[*src];
488 dst[x] = SkPixel32ToPixel4444(c);
492 return cc != A32_MASK_IN_PLACE;
495 static bool Sample_Index_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
496 const uint8_t* SK_RESTRICT src, int width,
497 int deltaSrc, int y, const SkPMColor ctable[]) {
499 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
500 SkPMColor cc = A32_MASK_IN_PLACE;
503 for (int x = 0; x < width; x++) {
504 SkPMColor c = ctable[*src];
507 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
511 return cc != A32_MASK_IN_PLACE;
514 static SkScaledBitmapSampler::RowProc
515 get_index_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
516 // Unpremul not allowed
517 if (!opts.fPremultiplyAlpha) {
520 if (opts.fSkipZeros) {
522 return Sample_Index_D4444_D_SkipZ;
524 return Sample_Index_D4444_SkipZ;
527 return Sample_Index_D4444_D;
529 return Sample_Index_D4444;
532 static bool Sample_Index_DI(void* SK_RESTRICT dstRow,
533 const uint8_t* SK_RESTRICT src,
534 int width, int deltaSrc, int, const SkPMColor[]) {
536 memcpy(dstRow, src, width);
538 uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow;
539 for (int x = 0; x < width; x++) {
547 static SkScaledBitmapSampler::RowProc
548 get_index_to_index_proc(const SkScaledBitmapSampler::Options& opts) {
549 // Unpremul not allowed
550 if (!opts.fPremultiplyAlpha) {
553 // Ignore dither and skip zeroes
554 return Sample_Index_DI;
558 static bool Sample_Gray_DA8(void* SK_RESTRICT dstRow,
559 const uint8_t* SK_RESTRICT src,
560 int width, int deltaSrc, int,
562 // Sampling Gray to A8 uses the same function as Index to Index8,
563 // except we assume that there is alpha for speed, since an A8
564 // bitmap with no alpha is not interesting.
565 (void) Sample_Index_DI(dstRow, src, width, deltaSrc, /* y unused */ 0,
566 /* ctable unused */ NULL);
570 static SkScaledBitmapSampler::RowProc
571 get_gray_to_A8_proc(const SkScaledBitmapSampler::Options& opts) {
572 if (!opts.fPremultiplyAlpha) {
575 // Ignore skip and dither.
576 return Sample_Gray_DA8;
579 typedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkScaledBitmapSampler::Options&);
580 ///////////////////////////////////////////////////////////////////////////////
582 #include "SkScaledBitmapSampler.h"
584 SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height,
590 if (width <= 0 || height <= 0) {
594 SkDEBUGCODE(fSampleMode = kUninitialized_SampleMode);
596 if (sampleSize <= 1) {
597 fScaledWidth = width;
598 fScaledHeight = height;
604 int dx = SkMin32(sampleSize, width);
605 int dy = SkMin32(sampleSize, height);
607 fScaledWidth = width / dx;
608 fScaledHeight = height / dy;
610 SkASSERT(fScaledWidth > 0);
611 SkASSERT(fScaledHeight > 0);
616 SkASSERT(fX0 >= 0 && fX0 < width);
617 SkASSERT(fY0 >= 0 && fY0 < height);
622 SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width);
623 SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height);
626 bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
628 const SkPMColor ctable[]) {
629 static const RowProcChooser gProcChoosers[] = {
630 get_gray_to_8888_proc,
631 get_RGBx_to_8888_proc,
632 get_RGBA_to_8888_proc,
633 get_index_to_8888_proc,
636 get_gray_to_565_proc,
637 get_RGBx_to_565_proc,
638 get_RGBx_to_565_proc, // The source alpha will be ignored.
639 get_index_to_565_proc,
642 get_gray_to_4444_proc,
643 get_RGBx_to_4444_proc,
644 get_RGBA_to_4444_proc,
645 get_index_to_4444_proc,
648 NULL, // gray to index
649 NULL, // rgbx to index
650 NULL, // rgba to index
651 get_index_to_index_proc,
652 NULL, // 565 to index
661 // The jump between dst configs in the table
662 static const int gProcDstConfigSpan = 5;
663 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gProcChoosers) == 5 * gProcDstConfigSpan,
664 gProcs_has_the_wrong_number_of_entries);
670 case SkScaledBitmapSampler::kGray:
674 case SkScaledBitmapSampler::kRGB:
678 case SkScaledBitmapSampler::kRGBX:
682 case SkScaledBitmapSampler::kRGBA:
686 case SkScaledBitmapSampler::kIndex:
690 case SkScaledBitmapSampler::kRGB_565:
698 switch (dst->colorType()) {
699 case kN32_SkColorType:
700 index += 0 * gProcDstConfigSpan;
702 case kRGB_565_SkColorType:
703 index += 1 * gProcDstConfigSpan;
705 case kARGB_4444_SkColorType:
706 index += 2 * gProcDstConfigSpan;
708 case kIndex_8_SkColorType:
709 index += 3 * gProcDstConfigSpan;
711 case kAlpha_8_SkColorType:
712 index += 4 * gProcDstConfigSpan;
718 RowProcChooser chooser = gProcChoosers[index];
719 if (NULL == chooser) {
722 fRowProc = chooser(opts);
724 fDstRow = (char*)dst->getPixels();
725 fDstRowBytes = dst->rowBytes();
727 return fRowProc != NULL;
730 bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
731 const SkImageDecoder& decoder,
732 const SkPMColor ctable[]) {
733 return this->begin(dst, sc, Options(decoder), ctable);
736 bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) {
737 SkASSERT(kInterlaced_SampleMode != fSampleMode);
738 SkDEBUGCODE(fSampleMode = kConsecutive_SampleMode);
739 SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight);
741 bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
742 fDX * fSrcPixelSize, fCurrY, fCTable);
743 fDstRow += fDstRowBytes;
748 bool SkScaledBitmapSampler::sampleInterlaced(const uint8_t* SK_RESTRICT src, int srcY) {
749 SkASSERT(kConsecutive_SampleMode != fSampleMode);
750 SkDEBUGCODE(fSampleMode = kInterlaced_SampleMode);
751 // Any line that should be a part of the destination can be created by the formula:
752 // fY0 + (some multiplier) * fDY
753 // so if srcY - fY0 is not an integer multiple of fDY that srcY will be skipped.
754 const int srcYMinusY0 = srcY - fY0;
755 if (srcYMinusY0 % fDY != 0) {
756 // This line is not part of the output, so return false for alpha, since we have
757 // not added an alpha to the output.
760 // Unlike in next(), where the data is used sequentially, this function skips around,
761 // so fDstRow and fCurrY are never updated. fDstRow must always be the starting point
762 // of the destination bitmap's pixels, which is used to calculate the destination row
763 // each time this function is called.
764 const int dstY = srcYMinusY0 / fDY;
765 SkASSERT(dstY < fScaledHeight);
766 char* dstRow = fDstRow + dstY * fDstRowBytes;
767 return fRowProc(dstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
768 fDX * fSrcPixelSize, dstY, fCTable);
772 // The following code is for a test to ensure that changing the method to get the right row proc
773 // did not change the row proc unintentionally. Tested by ImageDecodingTest.cpp
775 // friend of SkScaledBitmapSampler solely for the purpose of accessing fRowProc.
776 class RowProcTester {
778 static SkScaledBitmapSampler::RowProc getRowProc(const SkScaledBitmapSampler& sampler) {
779 return sampler.fRowProc;
784 // Table showing the expected RowProc for each combination of inputs.
785 // Table formated as follows:
786 // Each group of 5 consecutive rows represents sampling from a single
787 // SkScaledBitmapSampler::SrcConfig.
788 // Within each set, each row represents a different destination SkBitmap::Config
789 // Each column represents a different combination of dither and unpremul.
790 // D = dither ~D = no dither
791 // U = unpremul ~U = no unpremul
793 SkScaledBitmapSampler::RowProc gTestProcs[] = {
795 Sample_Gray_DA8, Sample_Gray_DA8, NULL, NULL, // to A8
796 NULL, NULL, NULL, NULL, // to Index8
797 Sample_Gray_D565, Sample_Gray_D565_D, Sample_Gray_D565, Sample_Gray_D565_D, // to 565
798 Sample_Gray_D4444, Sample_Gray_D4444_D, Sample_Gray_D4444, Sample_Gray_D4444_D, // to 4444
799 Sample_Gray_D8888, Sample_Gray_D8888, Sample_Gray_D8888, Sample_Gray_D8888, // to 8888
801 NULL, NULL, NULL, NULL, // to A8
802 Sample_Index_DI, Sample_Index_DI, NULL, NULL, // to Index8
803 Sample_Index_D565, Sample_Index_D565_D, Sample_Index_D565, Sample_Index_D565_D, // to 565
804 Sample_Index_D4444, Sample_Index_D4444_D, NULL, NULL, // to 4444
805 Sample_Index_D8888, Sample_Index_D8888, Sample_Index_D8888, Sample_Index_D8888, // to 8888
807 NULL, NULL, NULL, NULL, // to A8
808 NULL, NULL, NULL, NULL, // to Index8
809 Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565
810 Sample_RGBx_D4444, Sample_RGBx_D4444_D, Sample_RGBx_D4444, Sample_RGBx_D4444_D, // to 4444
811 Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, // to 8888
812 // RGBx is the same as RGB
813 NULL, NULL, NULL, NULL, // to A8
814 NULL, NULL, NULL, NULL, // to Index8
815 Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565
816 Sample_RGBx_D4444, Sample_RGBx_D4444_D, Sample_RGBx_D4444, Sample_RGBx_D4444_D, // to 4444
817 Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, // to 8888
819 NULL, NULL, NULL, NULL, // to A8
820 NULL, NULL, NULL, NULL, // to Index8
821 Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565
822 Sample_RGBA_D4444, Sample_RGBA_D4444_D, NULL, NULL, // to 4444
823 Sample_RGBA_D8888, Sample_RGBA_D8888, Sample_RGBA_D8888_Unpremul, Sample_RGBA_D8888_Unpremul, // to 8888
825 NULL, NULL, NULL, NULL, // to A8
826 NULL, NULL, NULL, NULL, // to Index8
827 Sample_D565_D565, Sample_D565_D565, Sample_D565_D565, Sample_D565_D565, // to 565
828 NULL, NULL, NULL, NULL, // to 4444
829 NULL, NULL, NULL, NULL, // to 8888
832 // Dummy class that allows instantiation of an ImageDecoder, so begin can query its fields.
833 class DummyDecoder : public SkImageDecoder {
837 virtual Result onDecode(SkStream*, SkBitmap*, SkImageDecoder::Mode) SK_OVERRIDE {
842 void test_row_proc_choice();
843 void test_row_proc_choice() {
844 const SkColorType colorTypes[] = {
845 kAlpha_8_SkColorType, kIndex_8_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType,
849 SkBitmap dummyBitmap;
850 DummyDecoder dummyDecoder;
851 size_t procCounter = 0;
852 for (int sc = SkScaledBitmapSampler::kGray; sc <= SkScaledBitmapSampler::kRGB_565; ++sc) {
853 for (size_t c = 0; c < SK_ARRAY_COUNT(colorTypes); ++c) {
854 for (int unpremul = 0; unpremul <= 1; ++unpremul) {
855 for (int dither = 0; dither <= 1; ++dither) {
856 // Arbitrary width/height/sampleSize to allow SkScaledBitmapSampler to
857 // be considered valid.
858 SkScaledBitmapSampler sampler(10, 10, 1);
859 dummyBitmap.setInfo(SkImageInfo::Make(10, 10,
860 colorTypes[c], kPremul_SkAlphaType));
861 dummyDecoder.setDitherImage(SkToBool(dither));
862 dummyDecoder.setRequireUnpremultipliedColors(SkToBool(unpremul));
863 sampler.begin(&dummyBitmap, (SkScaledBitmapSampler::SrcConfig) sc,
865 SkScaledBitmapSampler::RowProc expected = gTestProcs[procCounter];
866 SkScaledBitmapSampler::RowProc actual = RowProcTester::getRowProc(sampler);
867 SkASSERT(expected == actual);
873 SkASSERT(SK_ARRAY_COUNT(gTestProcs) == procCounter);