blob: 5ffd64889396b57ac8b5bf893f7f106212be00f1 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2007 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
epoger@google.comec3ed6a2011-07-28 14:26:00 +00008
reed@android.com8a1c16f2008-12-17 15:59:43 +00009#include "SkScaledBitmapSampler.h"
10#include "SkBitmap.h"
11#include "SkColorPriv.h"
12#include "SkDither.h"
scroggo@google.com2bbc2c92013-06-14 15:33:20 +000013#include "SkTypes.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014
15// 8888
16
17static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow,
18 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +000019 int width, int deltaSrc, int, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000020 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]);
23 src += deltaSrc;
24 }
25 return false;
26}
27
krajcevski407d7c92014-06-09 14:29:11 -070028static SkScaledBitmapSampler::RowProc
29get_gray_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +000030 // Dither, unpremul, and skipZeroes have no effect
31 return Sample_Gray_D8888;
32}
33
reed@android.com8a1c16f2008-12-17 15:59:43 +000034static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow,
35 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +000036 int width, int deltaSrc, int, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000037 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]);
40 src += deltaSrc;
41 }
42 return false;
43}
44
krajcevski407d7c92014-06-09 14:29:11 -070045static SkScaledBitmapSampler::RowProc
46get_RGBx_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +000047 // Dither, unpremul, and skipZeroes have no effect
48 return Sample_RGBx_D8888;
49}
50
reed@android.com8a1c16f2008-12-17 15:59:43 +000051static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow,
52 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +000053 int width, int deltaSrc, int, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000054 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]);
59 src += deltaSrc;
60 alphaMask &= alpha;
61 }
62 return alphaMask != 0xFF;
63}
64
scroggo@google.com8d239242013-10-01 17:27:15 +000065static bool Sample_RGBA_D8888_Unpremul(void* SK_RESTRICT dstRow,
66 const uint8_t* SK_RESTRICT src,
67 int width, int deltaSrc, int,
68 const SkPMColor[]) {
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]);
74 src += deltaSrc;
75 alphaMask &= alpha;
76 }
77 return alphaMask != 0xFF;
78}
79
80static bool Sample_RGBA_D8888_SkipZ(void* SK_RESTRICT dstRow,
81 const uint8_t* SK_RESTRICT src,
82 int width, int deltaSrc, int,
83 const SkPMColor[]) {
84 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
85 unsigned alphaMask = 0xFF;
86 for (int x = 0; x < width; x++) {
87 unsigned alpha = src[3];
88 if (0 != alpha) {
89 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
90 }
91 src += deltaSrc;
92 alphaMask &= alpha;
93 }
94 return alphaMask != 0xFF;
95}
96
krajcevski407d7c92014-06-09 14:29:11 -070097static SkScaledBitmapSampler::RowProc
98get_RGBA_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +000099 // Dither has no effect.
krajcevski407d7c92014-06-09 14:29:11 -0700100 if (!opts.fPremultiplyAlpha) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000101 // 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;
104 }
105 // Supply the versions that premultiply the colors
krajcevski407d7c92014-06-09 14:29:11 -0700106 if (opts.fSkipZeros) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000107 return Sample_RGBA_D8888_SkipZ;
108 }
109 return Sample_RGBA_D8888;
110}
111
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112// 565
113
114static bool Sample_Gray_D565(void* SK_RESTRICT dstRow,
115 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +0000116 int width, int deltaSrc, int, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000117 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]);
120 src += deltaSrc;
121 }
122 return false;
123}
124
125static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow,
126 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +0000127 int width, int deltaSrc, int y, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
129 DITHER_565_SCAN(y);
130 for (int x = 0; x < width; x++) {
131 dst[x] = SkDitherRGBTo565(src[0], src[0], src[0], DITHER_VALUE(x));
132 src += deltaSrc;
133 }
134 return false;
135}
136
krajcevski407d7c92014-06-09 14:29:11 -0700137static SkScaledBitmapSampler::RowProc
138get_gray_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000139 // Unpremul and skip zeroes make no difference
krajcevski407d7c92014-06-09 14:29:11 -0700140 if (opts.fDither) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000141 return Sample_Gray_D565_D;
142 }
143 return Sample_Gray_D565;
144}
145
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
147 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +0000148 int width, int deltaSrc, int, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149 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]);
152 src += deltaSrc;
153 }
154 return false;
155}
156
scroggo@google.com8d239242013-10-01 17:27:15 +0000157static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
158 const uint8_t* SK_RESTRICT src,
159 int width, int deltaSrc, int y,
160 const SkPMColor[]) {
161 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
162 DITHER_565_SCAN(y);
163 for (int x = 0; x < width; x++) {
164 dst[x] = SkDitherRGBTo565(src[0], src[1], src[2], DITHER_VALUE(x));
165 src += deltaSrc;
166 }
167 return false;
168}
169
krajcevski407d7c92014-06-09 14:29:11 -0700170static SkScaledBitmapSampler::RowProc
171get_RGBx_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000172 // Unpremul and skip zeroes make no difference
krajcevski407d7c92014-06-09 14:29:11 -0700173 if (opts.fDither) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000174 return Sample_RGBx_D565_D;
175 }
176 return Sample_RGBx_D565;
177}
178
179
djsollen@google.com57f49692011-02-23 20:46:31 +0000180static 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;
188 }
189 return false;
190}
191
krajcevski407d7c92014-06-09 14:29:11 -0700192static SkScaledBitmapSampler::RowProc
193get_565_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000194 // Unpremul, dither, and skip zeroes have no effect
195 return Sample_D565_D565;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000196}
197
198// 4444
199
200static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow,
201 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +0000202 int width, int deltaSrc, int, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000203 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);
207 src += deltaSrc;
208 }
209 return false;
210}
211
212static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow,
213 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +0000214 int width, int deltaSrc, int y, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000215 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
216 DITHER_4444_SCAN(y);
217 for (int x = 0; x < width; x++) {
218 dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[0], src[0],
219 DITHER_VALUE(x));
220 src += deltaSrc;
221 }
222 return false;
223}
224
krajcevski407d7c92014-06-09 14:29:11 -0700225static SkScaledBitmapSampler::RowProc
226get_gray_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000227 // Skip zeroes and unpremul make no difference
krajcevski407d7c92014-06-09 14:29:11 -0700228 if (opts.fDither) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000229 return Sample_Gray_D4444_D;
230 }
231 return Sample_Gray_D4444;
232}
233
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow,
235 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +0000236 int width, int deltaSrc, int, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000237 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);
240 src += deltaSrc;
241 }
242 return false;
243}
244
245static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow,
246 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +0000247 int width, int deltaSrc, int y, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000248 SkPMColor16* dst = (SkPMColor16*)dstRow;
249 DITHER_4444_SCAN(y);
250
251 for (int x = 0; x < width; x++) {
252 dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[1], src[2],
253 DITHER_VALUE(x));
254 src += deltaSrc;
255 }
256 return false;
257}
258
krajcevski407d7c92014-06-09 14:29:11 -0700259static SkScaledBitmapSampler::RowProc
260get_RGBx_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000261 // Skip zeroes and unpremul make no difference
krajcevski407d7c92014-06-09 14:29:11 -0700262 if (opts.fDither) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000263 return Sample_RGBx_D4444_D;
264 }
265 return Sample_RGBx_D4444;
266}
267
reed@android.com8a1c16f2008-12-17 15:59:43 +0000268static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow,
269 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +0000270 int width, int deltaSrc, int, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000271 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
272 unsigned alphaMask = 0xFF;
273
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);
278 src += deltaSrc;
279 alphaMask &= alpha;
280 }
281 return alphaMask != 0xFF;
282}
283
scroggo@google.com8d239242013-10-01 17:27:15 +0000284static bool Sample_RGBA_D4444_SkipZ(void* SK_RESTRICT dstRow,
285 const uint8_t* SK_RESTRICT src,
286 int width, int deltaSrc, int,
287 const SkPMColor[]) {
288 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
289 unsigned alphaMask = 0xFF;
290
291 for (int x = 0; x < width; x++) {
292 unsigned alpha = src[3];
293 if (alpha != 0) {
294 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
295 dst[x] = SkPixel32ToPixel4444(c);
296 }
297 src += deltaSrc;
298 alphaMask &= alpha;
299 }
300 return alphaMask != 0xFF;
301}
302
303
reed@android.com8a1c16f2008-12-17 15:59:43 +0000304static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow,
305 const uint8_t* SK_RESTRICT src,
scroggo@google.com8d239242013-10-01 17:27:15 +0000306 int width, int deltaSrc, int y,
307 const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000308 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
309 unsigned alphaMask = 0xFF;
310 DITHER_4444_SCAN(y);
311
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));
316 src += deltaSrc;
317 alphaMask &= alpha;
318 }
319 return alphaMask != 0xFF;
320}
321
scroggo@google.com8d239242013-10-01 17:27:15 +0000322static bool Sample_RGBA_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
323 const uint8_t* SK_RESTRICT src,
324 int width, int deltaSrc, int y,
325 const SkPMColor[]) {
326 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
327 unsigned alphaMask = 0xFF;
328 DITHER_4444_SCAN(y);
329
330 for (int x = 0; x < width; x++) {
331 unsigned alpha = src[3];
332 if (alpha != 0) {
333 SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
334 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
335 }
336 src += deltaSrc;
337 alphaMask &= alpha;
338 }
339 return alphaMask != 0xFF;
340}
341
krajcevski407d7c92014-06-09 14:29:11 -0700342static SkScaledBitmapSampler::RowProc
343get_RGBA_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
344 if (!opts.fPremultiplyAlpha) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000345 // Unpremultiplied is not supported for 4444
Tom Hudson2880df22015-10-29 09:55:42 -0400346 return nullptr;
scroggo@google.com8d239242013-10-01 17:27:15 +0000347 }
krajcevski407d7c92014-06-09 14:29:11 -0700348 if (opts.fSkipZeros) {
349 if (opts.fDither) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000350 return Sample_RGBA_D4444_D_SkipZ;
351 }
352 return Sample_RGBA_D4444_SkipZ;
353 }
krajcevski407d7c92014-06-09 14:29:11 -0700354 if (opts.fDither) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000355 return Sample_RGBA_D4444_D;
356 }
357 return Sample_RGBA_D4444;
358}
359
reed@android.com8a1c16f2008-12-17 15:59:43 +0000360// Index
361
reed@android.com1cdcb512009-08-24 19:11:00 +0000362#define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT)
reed@android.com11344262009-07-08 20:09:23 +0000363
364static bool Sample_Index_D8888(void* SK_RESTRICT dstRow,
365 const uint8_t* SK_RESTRICT src,
366 int width, int deltaSrc, int, const SkPMColor ctable[]) {
367
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];
372 cc &= c;
373 dst[x] = c;
374 src += deltaSrc;
375 }
376 return cc != A32_MASK_IN_PLACE;
377}
378
scroggo@google.com8d239242013-10-01 17:27:15 +0000379static 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[]) {
383
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];
388 cc &= c;
389 if (c != 0) {
390 dst[x] = c;
391 }
392 src += deltaSrc;
393 }
394 return cc != A32_MASK_IN_PLACE;
395}
396
krajcevski407d7c92014-06-09 14:29:11 -0700397static SkScaledBitmapSampler::RowProc
398get_index_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo13f701a2014-10-27 08:43:12 -0700399 // The caller is expected to have created the source colortable
400 // properly with respect to opts.fPremultiplyAlpha, so premul makes
401 // no difference here.
scroggo@google.com8d239242013-10-01 17:27:15 +0000402 // Dither makes no difference
krajcevski407d7c92014-06-09 14:29:11 -0700403 if (opts.fSkipZeros) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000404 return Sample_Index_D8888_SkipZ;
405 }
406 return Sample_Index_D8888;
407}
408
reed@android.com11344262009-07-08 20:09:23 +0000409static bool Sample_Index_D565(void* SK_RESTRICT dstRow,
410 const uint8_t* SK_RESTRICT src,
411 int width, int deltaSrc, int, const SkPMColor ctable[]) {
412
413 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
414 for (int x = 0; x < width; x++) {
415 dst[x] = SkPixel32ToPixel16(ctable[*src]);
416 src += deltaSrc;
417 }
418 return false;
419}
420
421static 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[]) {
424
425 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
426 DITHER_565_SCAN(y);
427
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));
432 src += deltaSrc;
433 }
434 return false;
435}
436
krajcevski407d7c92014-06-09 14:29:11 -0700437static SkScaledBitmapSampler::RowProc
438get_index_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000439 // Unpremultiplied and skip zeroes make no difference
krajcevski407d7c92014-06-09 14:29:11 -0700440 if (opts.fDither) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000441 return Sample_Index_D565_D;
442 }
443 return Sample_Index_D565;
444}
445
reed@android.com11344262009-07-08 20:09:23 +0000446static 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[]) {
449
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];
454 cc &= c;
455 dst[x] = SkPixel32ToPixel4444(c);
456 src += deltaSrc;
457 }
458 return cc != A32_MASK_IN_PLACE;
459}
460
461static 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[]) {
464
465 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
466 SkPMColor cc = A32_MASK_IN_PLACE;
467 DITHER_4444_SCAN(y);
468
469 for (int x = 0; x < width; x++) {
470 SkPMColor c = ctable[*src];
471 cc &= c;
472 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
473 src += deltaSrc;
474 }
475 return cc != A32_MASK_IN_PLACE;
476}
477
scroggo@google.com8d239242013-10-01 17:27:15 +0000478static 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[]) {
481
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];
486 cc &= c;
487 if (c != 0) {
488 dst[x] = SkPixel32ToPixel4444(c);
489 }
490 src += deltaSrc;
491 }
492 return cc != A32_MASK_IN_PLACE;
493}
494
495static 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[]) {
498
499 SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
500 SkPMColor cc = A32_MASK_IN_PLACE;
501 DITHER_4444_SCAN(y);
502
503 for (int x = 0; x < width; x++) {
504 SkPMColor c = ctable[*src];
505 cc &= c;
506 if (c != 0) {
507 dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
508 }
509 src += deltaSrc;
510 }
511 return cc != A32_MASK_IN_PLACE;
512}
513
krajcevski407d7c92014-06-09 14:29:11 -0700514static SkScaledBitmapSampler::RowProc
515get_index_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000516 // Unpremul not allowed
krajcevski407d7c92014-06-09 14:29:11 -0700517 if (!opts.fPremultiplyAlpha) {
Tom Hudson2880df22015-10-29 09:55:42 -0400518 return nullptr;
scroggo@google.com8d239242013-10-01 17:27:15 +0000519 }
krajcevski407d7c92014-06-09 14:29:11 -0700520 if (opts.fSkipZeros) {
521 if (opts.fDither) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000522 return Sample_Index_D4444_D_SkipZ;
523 }
524 return Sample_Index_D4444_SkipZ;
525 }
krajcevski407d7c92014-06-09 14:29:11 -0700526 if (opts.fDither) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000527 return Sample_Index_D4444_D;
528 }
529 return Sample_Index_D4444;
530}
531
reed@android.com8a1c16f2008-12-17 15:59:43 +0000532static bool Sample_Index_DI(void* SK_RESTRICT dstRow,
533 const uint8_t* SK_RESTRICT src,
reed@android.com11344262009-07-08 20:09:23 +0000534 int width, int deltaSrc, int, const SkPMColor[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000535 if (1 == deltaSrc) {
536 memcpy(dstRow, src, width);
537 } else {
538 uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow;
539 for (int x = 0; x < width; x++) {
540 dst[x] = src[0];
541 src += deltaSrc;
542 }
543 }
544 return false;
545}
546
krajcevski407d7c92014-06-09 14:29:11 -0700547static SkScaledBitmapSampler::RowProc
548get_index_to_index_proc(const SkScaledBitmapSampler::Options& opts) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000549 // Unpremul not allowed
krajcevski407d7c92014-06-09 14:29:11 -0700550 if (!opts.fPremultiplyAlpha) {
Tom Hudson2880df22015-10-29 09:55:42 -0400551 return nullptr;
scroggo@google.com8d239242013-10-01 17:27:15 +0000552 }
553 // Ignore dither and skip zeroes
554 return Sample_Index_DI;
555}
556
scroggo@google.comf698c822013-07-18 19:34:49 +0000557// A8
558static bool Sample_Gray_DA8(void* SK_RESTRICT dstRow,
559 const uint8_t* SK_RESTRICT src,
560 int width, int deltaSrc, int,
561 const SkPMColor[]) {
scroggo@google.com5ee18dd2013-10-21 20:47:31 +0000562 // 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,
Tom Hudson2880df22015-10-29 09:55:42 -0400566 /* ctable unused */ nullptr);
scroggo@google.comf698c822013-07-18 19:34:49 +0000567 return true;
568}
569
krajcevski407d7c92014-06-09 14:29:11 -0700570static SkScaledBitmapSampler::RowProc
571get_gray_to_A8_proc(const SkScaledBitmapSampler::Options& opts) {
572 if (!opts.fPremultiplyAlpha) {
Tom Hudson2880df22015-10-29 09:55:42 -0400573 return nullptr;
scroggo@google.com2bbc2c92013-06-14 15:33:20 +0000574 }
scroggo@google.com8d239242013-10-01 17:27:15 +0000575 // Ignore skip and dither.
576 return Sample_Gray_DA8;
scroggo@google.com2bbc2c92013-06-14 15:33:20 +0000577}
578
krajcevski407d7c92014-06-09 14:29:11 -0700579typedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkScaledBitmapSampler::Options&);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000580///////////////////////////////////////////////////////////////////////////////
581
582#include "SkScaledBitmapSampler.h"
583
584SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height,
585 int sampleSize) {
Tom Hudson2880df22015-10-29 09:55:42 -0400586 fCTable = nullptr;
587 fDstRow = nullptr;
588 fRowProc = nullptr;
vandebo@chromium.orga728e352012-03-28 20:29:38 +0000589
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590 if (width <= 0 || height <= 0) {
591 sk_throw();
592 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000593
commit-bot@chromium.orgdac4a1d2013-10-08 19:40:18 +0000594 SkDEBUGCODE(fSampleMode = kUninitialized_SampleMode);
595
reed@android.com8a1c16f2008-12-17 15:59:43 +0000596 if (sampleSize <= 1) {
597 fScaledWidth = width;
598 fScaledHeight = height;
599 fX0 = fY0 = 0;
600 fDX = fDY = 1;
601 return;
602 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000603
reed@android.com8a1c16f2008-12-17 15:59:43 +0000604 int dx = SkMin32(sampleSize, width);
605 int dy = SkMin32(sampleSize, height);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000606
reed@android.com8a1c16f2008-12-17 15:59:43 +0000607 fScaledWidth = width / dx;
608 fScaledHeight = height / dy;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000609
reed@android.com8a1c16f2008-12-17 15:59:43 +0000610 SkASSERT(fScaledWidth > 0);
611 SkASSERT(fScaledHeight > 0);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000612
reed@android.com8a1c16f2008-12-17 15:59:43 +0000613 fX0 = dx >> 1;
614 fY0 = dy >> 1;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000615
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616 SkASSERT(fX0 >= 0 && fX0 < width);
617 SkASSERT(fY0 >= 0 && fY0 < height);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000618
reed@android.com8a1c16f2008-12-17 15:59:43 +0000619 fDX = dx;
620 fDY = dy;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000621
reed@android.com8a1c16f2008-12-17 15:59:43 +0000622 SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width);
623 SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000624}
625
scroggo@google.com8d239242013-10-01 17:27:15 +0000626bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
krajcevski407d7c92014-06-09 14:29:11 -0700627 const Options& opts,
scroggo@google.com8d239242013-10-01 17:27:15 +0000628 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,
Tom Hudson2880df22015-10-29 09:55:42 -0400634 nullptr, // 565 to 8888
scroggo@google.com8d239242013-10-01 17:27:15 +0000635
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,
640 get_565_to_565_proc,
641
642 get_gray_to_4444_proc,
643 get_RGBx_to_4444_proc,
644 get_RGBA_to_4444_proc,
645 get_index_to_4444_proc,
Tom Hudson2880df22015-10-29 09:55:42 -0400646 nullptr, // 565 to 4444
scroggo@google.com8d239242013-10-01 17:27:15 +0000647
Tom Hudson2880df22015-10-29 09:55:42 -0400648 nullptr, // gray to index
649 nullptr, // rgbx to index
650 nullptr, // rgba to index
scroggo@google.com8d239242013-10-01 17:27:15 +0000651 get_index_to_index_proc,
Tom Hudson2880df22015-10-29 09:55:42 -0400652 nullptr, // 565 to index
scroggo@google.com8d239242013-10-01 17:27:15 +0000653
654 get_gray_to_A8_proc,
Tom Hudson2880df22015-10-29 09:55:42 -0400655 nullptr, // rgbx to a8
656 nullptr, // rgba to a8
657 nullptr, // index to a8
658 nullptr, // 565 to a8
reed@android.com8a1c16f2008-12-17 15:59:43 +0000659 };
scroggo@google.com8d239242013-10-01 17:27:15 +0000660
scroggo@google.com2bbc2c92013-06-14 15:33:20 +0000661 // The jump between dst configs in the table
scroggo@google.com8d239242013-10-01 17:27:15 +0000662 static const int gProcDstConfigSpan = 5;
Tom Hudson2880df22015-10-29 09:55:42 -0400663 static_assert(SK_ARRAY_COUNT(gProcChoosers) == 5 * gProcDstConfigSpan,
664 "gProcs_has_the_wrong_number_of_entries");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000665
reed@android.com11344262009-07-08 20:09:23 +0000666 fCTable = ctable;
667
reed@android.com8a1c16f2008-12-17 15:59:43 +0000668 int index = 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000669 switch (sc) {
670 case SkScaledBitmapSampler::kGray:
671 fSrcPixelSize = 1;
672 index += 0;
673 break;
674 case SkScaledBitmapSampler::kRGB:
675 fSrcPixelSize = 3;
scroggo@google.com8d239242013-10-01 17:27:15 +0000676 index += 1;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000677 break;
678 case SkScaledBitmapSampler::kRGBX:
679 fSrcPixelSize = 4;
scroggo@google.com8d239242013-10-01 17:27:15 +0000680 index += 1;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000681 break;
682 case SkScaledBitmapSampler::kRGBA:
683 fSrcPixelSize = 4;
scroggo@google.com8d239242013-10-01 17:27:15 +0000684 index += 2;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000685 break;
686 case SkScaledBitmapSampler::kIndex:
687 fSrcPixelSize = 1;
scroggo@google.com8d239242013-10-01 17:27:15 +0000688 index += 3;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000689 break;
djsollen@google.com57f49692011-02-23 20:46:31 +0000690 case SkScaledBitmapSampler::kRGB_565:
691 fSrcPixelSize = 2;
scroggo@google.com8d239242013-10-01 17:27:15 +0000692 index += 4;
djsollen@google.com57f49692011-02-23 20:46:31 +0000693 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000694 default:
695 return false;
696 }
697
reed0689d7b2014-06-14 05:30:20 -0700698 switch (dst->colorType()) {
699 case kN32_SkColorType:
scroggo@google.com2bbc2c92013-06-14 15:33:20 +0000700 index += 0 * gProcDstConfigSpan;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000701 break;
reed0689d7b2014-06-14 05:30:20 -0700702 case kRGB_565_SkColorType:
scroggo@google.com2bbc2c92013-06-14 15:33:20 +0000703 index += 1 * gProcDstConfigSpan;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000704 break;
reed0689d7b2014-06-14 05:30:20 -0700705 case kARGB_4444_SkColorType:
scroggo@google.com2bbc2c92013-06-14 15:33:20 +0000706 index += 2 * gProcDstConfigSpan;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000707 break;
reed0689d7b2014-06-14 05:30:20 -0700708 case kIndex_8_SkColorType:
scroggo@google.com2bbc2c92013-06-14 15:33:20 +0000709 index += 3 * gProcDstConfigSpan;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000710 break;
reed0689d7b2014-06-14 05:30:20 -0700711 case kAlpha_8_SkColorType:
scroggo@google.comf698c822013-07-18 19:34:49 +0000712 index += 4 * gProcDstConfigSpan;
713 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000714 default:
715 return false;
716 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000717
scroggo@google.com8d239242013-10-01 17:27:15 +0000718 RowProcChooser chooser = gProcChoosers[index];
Tom Hudson2880df22015-10-29 09:55:42 -0400719 if (nullptr == chooser) {
720 fRowProc = nullptr;
scroggo@google.com8d239242013-10-01 17:27:15 +0000721 } else {
krajcevski407d7c92014-06-09 14:29:11 -0700722 fRowProc = chooser(opts);
scroggo@google.com2bbc2c92013-06-14 15:33:20 +0000723 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000724 fDstRow = (char*)dst->getPixels();
725 fDstRowBytes = dst->rowBytes();
726 fCurrY = 0;
Tom Hudson2880df22015-10-29 09:55:42 -0400727 return fRowProc != nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000728}
729
krajcevski407d7c92014-06-09 14:29:11 -0700730bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
731 const SkImageDecoder& decoder,
732 const SkPMColor ctable[]) {
733 return this->begin(dst, sc, Options(decoder), ctable);
734}
735
reed@android.com8a1c16f2008-12-17 15:59:43 +0000736bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) {
commit-bot@chromium.orgdac4a1d2013-10-08 19:40:18 +0000737 SkASSERT(kInterlaced_SampleMode != fSampleMode);
738 SkDEBUGCODE(fSampleMode = kConsecutive_SampleMode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000739 SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight);
740
741 bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
reed@android.com11344262009-07-08 20:09:23 +0000742 fDX * fSrcPixelSize, fCurrY, fCTable);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000743 fDstRow += fDstRowBytes;
744 fCurrY += 1;
745 return hadAlpha;
746}
scroggo@google.com8d239242013-10-01 17:27:15 +0000747
commit-bot@chromium.orgdac4a1d2013-10-08 19:40:18 +0000748bool 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.
758 return false;
759 }
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;
zoran.jovanovic9c798202015-04-16 11:03:16 -0700765 if (dstY >= fScaledHeight) {
766 return false;
767 }
commit-bot@chromium.orgdac4a1d2013-10-08 19:40:18 +0000768 char* dstRow = fDstRow + dstY * fDstRowBytes;
769 return fRowProc(dstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
770 fDX * fSrcPixelSize, dstY, fCTable);
771}
772
scroggo@google.com8d239242013-10-01 17:27:15 +0000773#ifdef SK_DEBUG
774// The following code is for a test to ensure that changing the method to get the right row proc
775// did not change the row proc unintentionally. Tested by ImageDecodingTest.cpp
776
777// friend of SkScaledBitmapSampler solely for the purpose of accessing fRowProc.
778class RowProcTester {
779public:
780 static SkScaledBitmapSampler::RowProc getRowProc(const SkScaledBitmapSampler& sampler) {
781 return sampler.fRowProc;
782 }
783};
784
785
786// Table showing the expected RowProc for each combination of inputs.
787// Table formated as follows:
788// Each group of 5 consecutive rows represents sampling from a single
789// SkScaledBitmapSampler::SrcConfig.
790// Within each set, each row represents a different destination SkBitmap::Config
791// Each column represents a different combination of dither and unpremul.
792// D = dither ~D = no dither
793// U = unpremul ~U = no unpremul
794// ~D~U D~U ~DU DU
795SkScaledBitmapSampler::RowProc gTestProcs[] = {
796 // Gray
Tom Hudson2880df22015-10-29 09:55:42 -0400797 Sample_Gray_DA8, Sample_Gray_DA8, nullptr, nullptr, // to A8
798 nullptr, nullptr, nullptr, nullptr, // to Index8
scroggo@google.com8d239242013-10-01 17:27:15 +0000799 Sample_Gray_D565, Sample_Gray_D565_D, Sample_Gray_D565, Sample_Gray_D565_D, // to 565
800 Sample_Gray_D4444, Sample_Gray_D4444_D, Sample_Gray_D4444, Sample_Gray_D4444_D, // to 4444
801 Sample_Gray_D8888, Sample_Gray_D8888, Sample_Gray_D8888, Sample_Gray_D8888, // to 8888
802 // Index
Tom Hudson2880df22015-10-29 09:55:42 -0400803 nullptr, nullptr, nullptr, nullptr, // to A8
804 Sample_Index_DI, Sample_Index_DI, nullptr, nullptr, // to Index8
scroggo@google.com8d239242013-10-01 17:27:15 +0000805 Sample_Index_D565, Sample_Index_D565_D, Sample_Index_D565, Sample_Index_D565_D, // to 565
Tom Hudson2880df22015-10-29 09:55:42 -0400806 Sample_Index_D4444, Sample_Index_D4444_D, nullptr, nullptr, // to 4444
scroggo13f701a2014-10-27 08:43:12 -0700807 Sample_Index_D8888, Sample_Index_D8888, Sample_Index_D8888, Sample_Index_D8888, // to 8888
scroggo@google.com8d239242013-10-01 17:27:15 +0000808 // RGB
Tom Hudson2880df22015-10-29 09:55:42 -0400809 nullptr, nullptr, nullptr, nullptr, // to A8
810 nullptr, nullptr, nullptr, nullptr, // to Index8
scroggo@google.com8d239242013-10-01 17:27:15 +0000811 Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565
812 Sample_RGBx_D4444, Sample_RGBx_D4444_D, Sample_RGBx_D4444, Sample_RGBx_D4444_D, // to 4444
813 Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, // to 8888
814 // RGBx is the same as RGB
Tom Hudson2880df22015-10-29 09:55:42 -0400815 nullptr, nullptr, nullptr, nullptr, // to A8
816 nullptr, nullptr, nullptr, nullptr, // to Index8
scroggo@google.com8d239242013-10-01 17:27:15 +0000817 Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565
818 Sample_RGBx_D4444, Sample_RGBx_D4444_D, Sample_RGBx_D4444, Sample_RGBx_D4444_D, // to 4444
819 Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, Sample_RGBx_D8888, // to 8888
820 // RGBA
Tom Hudson2880df22015-10-29 09:55:42 -0400821 nullptr, nullptr, nullptr, nullptr, // to A8
822 nullptr, nullptr, nullptr, nullptr, // to Index8
scroggo@google.com8d239242013-10-01 17:27:15 +0000823 Sample_RGBx_D565, Sample_RGBx_D565_D, Sample_RGBx_D565, Sample_RGBx_D565_D, // to 565
Tom Hudson2880df22015-10-29 09:55:42 -0400824 Sample_RGBA_D4444, Sample_RGBA_D4444_D, nullptr, nullptr, // to 4444
scroggo@google.com8d239242013-10-01 17:27:15 +0000825 Sample_RGBA_D8888, Sample_RGBA_D8888, Sample_RGBA_D8888_Unpremul, Sample_RGBA_D8888_Unpremul, // to 8888
826 // RGB_565
Tom Hudson2880df22015-10-29 09:55:42 -0400827 nullptr, nullptr, nullptr, nullptr, // to A8
828 nullptr, nullptr, nullptr, nullptr, // to Index8
scroggo@google.com8d239242013-10-01 17:27:15 +0000829 Sample_D565_D565, Sample_D565_D565, Sample_D565_D565, Sample_D565_D565, // to 565
Tom Hudson2880df22015-10-29 09:55:42 -0400830 nullptr, nullptr, nullptr, nullptr, // to 4444
831 nullptr, nullptr, nullptr, nullptr, // to 8888
scroggo@google.com8d239242013-10-01 17:27:15 +0000832};
833
834// Dummy class that allows instantiation of an ImageDecoder, so begin can query its fields.
835class DummyDecoder : public SkImageDecoder {
836public:
837 DummyDecoder() {}
838protected:
mtklein36352bf2015-03-25 18:17:31 -0700839 Result onDecode(SkStream*, SkBitmap*, SkImageDecoder::Mode) override {
scroggo2a120802014-10-22 12:07:00 -0700840 return kFailure;
scroggo@google.com8d239242013-10-01 17:27:15 +0000841 }
842};
843
scroggo@google.com1d069992013-10-01 17:46:35 +0000844void test_row_proc_choice();
scroggo@google.com8d239242013-10-01 17:27:15 +0000845void test_row_proc_choice() {
reed6c225732014-06-09 19:52:07 -0700846 const SkColorType colorTypes[] = {
847 kAlpha_8_SkColorType, kIndex_8_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType,
848 kN32_SkColorType
849 };
850
scroggo@google.com8d239242013-10-01 17:27:15 +0000851 SkBitmap dummyBitmap;
852 DummyDecoder dummyDecoder;
853 size_t procCounter = 0;
854 for (int sc = SkScaledBitmapSampler::kGray; sc <= SkScaledBitmapSampler::kRGB_565; ++sc) {
reed6c225732014-06-09 19:52:07 -0700855 for (size_t c = 0; c < SK_ARRAY_COUNT(colorTypes); ++c) {
scroggo@google.com8d239242013-10-01 17:27:15 +0000856 for (int unpremul = 0; unpremul <= 1; ++unpremul) {
857 for (int dither = 0; dither <= 1; ++dither) {
858 // Arbitrary width/height/sampleSize to allow SkScaledBitmapSampler to
859 // be considered valid.
860 SkScaledBitmapSampler sampler(10, 10, 1);
reed6c225732014-06-09 19:52:07 -0700861 dummyBitmap.setInfo(SkImageInfo::Make(10, 10,
862 colorTypes[c], kPremul_SkAlphaType));
scroggo@google.com8d239242013-10-01 17:27:15 +0000863 dummyDecoder.setDitherImage(SkToBool(dither));
864 dummyDecoder.setRequireUnpremultipliedColors(SkToBool(unpremul));
865 sampler.begin(&dummyBitmap, (SkScaledBitmapSampler::SrcConfig) sc,
866 dummyDecoder);
867 SkScaledBitmapSampler::RowProc expected = gTestProcs[procCounter];
868 SkScaledBitmapSampler::RowProc actual = RowProcTester::getRowProc(sampler);
869 SkASSERT(expected == actual);
870 procCounter++;
871 }
872 }
873 }
874 }
875 SkASSERT(SK_ARRAY_COUNT(gTestProcs) == procCounter);
876}
877#endif // SK_DEBUG