SkSwizzler.cpp revision 80803ff615e4293e8af2dc5d094a1f4fa81ec396
1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkCodecPriv.h"
9#include "SkColorPriv.h"
10#include "SkScaledCodec.h"
11#include "SkSwizzler.h"
12#include "SkTemplates.h"
13
14SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha,
15                                              uint8_t maxAlpha) {
16    // In the transparent case, this returns 0x0000
17    // In the opaque case, this returns 0xFFFF
18    // If the row is neither transparent nor opaque, returns something else
19    return (((uint16_t) maxAlpha) << 8) | zeroAlpha;
20}
21
22// samples the row. Does not do anything else but sampling
23static SkSwizzler::ResultAlpha sample565(void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src,
24        int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[]){
25
26    src += offset;
27    uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow;
28    for (int x = 0; x < width; x++) {
29        dst[x] = src[1] << 8 | src[0];
30        src += deltaSrc;
31    }
32    // 565 is always opaque
33    return SkSwizzler::kOpaque_ResultAlpha;
34}
35
36// TODO (msarett): Investigate SIMD optimizations for swizzle routines.
37
38// kBit
39// These routines exclusively choose between white and black
40
41#define GRAYSCALE_BLACK 0
42#define GRAYSCALE_WHITE 0xFF
43
44
45// same as swizzle_bit_to_index and swizzle_bit_to_n32 except for value assigned to dst[x]
46static SkSwizzler::ResultAlpha swizzle_bit_to_grayscale(
47        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
48        int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
49
50    uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
51
52    // increment src by byte offset and bitIndex by bit offset
53    src += offset / 8;
54    int bitIndex = offset % 8;
55    uint8_t currByte = *src;
56
57    dst[0] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
58
59    for (int x = 1; x < dstWidth; x++) {
60        int bitOffset = bitIndex + deltaSrc;
61        bitIndex = bitOffset % 8;
62        currByte = *(src += bitOffset / 8);
63        dst[x] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
64    }
65
66    return SkSwizzler::kOpaque_ResultAlpha;
67}
68
69#undef GRAYSCALE_BLACK
70#undef GRAYSCALE_WHITE
71
72// same as swizzle_bit_to_grayscale and swizzle_bit_to_n32 except for value assigned to dst[x]
73static SkSwizzler::ResultAlpha swizzle_bit_to_index(
74        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
75        int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
76    uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
77
78    // increment src by byte offset and bitIndex by bit offset
79    src += offset / 8;
80    int bitIndex = offset % 8;
81    uint8_t currByte = *src;
82
83    dst[0] = ((currByte >> (7-bitIndex)) & 1);
84
85    for (int x = 1; x < dstWidth; x++) {
86        int bitOffset = bitIndex + deltaSrc;
87        bitIndex = bitOffset % 8;
88        currByte = *(src += bitOffset / 8);
89        dst[x] = ((currByte >> (7-bitIndex)) & 1);
90    }
91
92    return SkSwizzler::kOpaque_ResultAlpha;
93}
94
95// same as swizzle_bit_to_grayscale and swizzle_bit_to_index except for value assigned to dst[x]
96static SkSwizzler::ResultAlpha swizzle_bit_to_n32(
97        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
98        int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
99    SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
100
101    // increment src by byte offset and bitIndex by bit offset
102    src += offset / 8;
103    int bitIndex = offset % 8;
104    uint8_t currByte = *src;
105
106    dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
107
108    for (int x = 1; x < dstWidth; x++) {
109        int bitOffset = bitIndex + deltaSrc;
110        bitIndex = bitOffset % 8;
111        currByte = *(src += bitOffset / 8);
112        dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
113    }
114
115    return SkSwizzler::kOpaque_ResultAlpha;
116}
117
118#define RGB565_BLACK 0
119#define RGB565_WHITE 0xFFFF
120
121static SkSwizzler::ResultAlpha swizzle_bit_to_565(
122        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
123        int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
124    uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow;
125
126    // increment src by byte offset and bitIndex by bit offset
127    src += offset / 8;
128    int bitIndex = offset % 8;
129    uint8_t currByte = *src;
130
131    dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK;
132
133    for (int x = 1; x < dstWidth; x++) {
134        int bitOffset = bitIndex + deltaSrc;
135        bitIndex = bitOffset % 8;
136        currByte = *(src += bitOffset / 8);
137        dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK;
138    }
139
140    return SkSwizzler::kOpaque_ResultAlpha;
141}
142
143#undef RGB565_BLACK
144#undef RGB565_WHITE
145
146// kIndex1, kIndex2, kIndex4
147
148static SkSwizzler::ResultAlpha swizzle_small_index_to_index(
149        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
150        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
151
152    uint8_t* dst = (uint8_t*) dstRow;
153    INIT_RESULT_ALPHA;
154    src += offset / 8;
155    int bitIndex = offset % 8;
156    uint8_t currByte = *src;
157    const uint8_t mask = (1 << bpp) - 1;
158    uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
159    dst[0] = index;
160    UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT);
161
162    for (int x = 1; x < dstWidth; x++) {
163        int bitOffset = bitIndex + deltaSrc;
164        bitIndex = bitOffset % 8;
165        currByte = *(src += bitOffset / 8);
166        index = (currByte >> (8 - bpp - bitIndex)) & mask;
167        dst[x] = index;
168        UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT);
169    }
170    return COMPUTE_RESULT_ALPHA;
171}
172
173static SkSwizzler::ResultAlpha swizzle_small_index_to_565(
174        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
175        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
176
177    uint16_t* dst = (uint16_t*) dstRow;
178    src += offset / 8;
179    int bitIndex = offset % 8;
180    uint8_t currByte = *src;
181    const uint8_t mask = (1 << bpp) - 1;
182    uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
183    dst[0] = SkPixel32ToPixel16(ctable[index]);
184
185    for (int x = 1; x < dstWidth; x++) {
186        int bitOffset = bitIndex + deltaSrc;
187        bitIndex = bitOffset % 8;
188        currByte = *(src += bitOffset / 8);
189        index = (currByte >> (8 - bpp - bitIndex)) & mask;
190        dst[x] = SkPixel32ToPixel16(ctable[index]);
191    }
192    return SkAlphaType::kOpaque_SkAlphaType;
193}
194
195static SkSwizzler::ResultAlpha swizzle_small_index_to_n32(
196        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
197        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
198
199    SkPMColor* dst = (SkPMColor*) dstRow;
200    INIT_RESULT_ALPHA;
201    src += offset / 8;
202    int bitIndex = offset % 8;
203    uint8_t currByte = *src;
204    const uint8_t mask = (1 << bpp) - 1;
205    uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
206    dst[0] = ctable[index];
207    UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT);
208
209    for (int x = 1; x < dstWidth; x++) {
210        int bitOffset = bitIndex + deltaSrc;
211        bitIndex = bitOffset % 8;
212        currByte = *(src += bitOffset / 8);
213        index = (currByte >> (8 - bpp - bitIndex)) & mask;
214        dst[x] = ctable[index];
215        UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT);
216    }
217    return COMPUTE_RESULT_ALPHA;
218}
219
220// kIndex
221
222static SkSwizzler::ResultAlpha swizzle_index_to_index(
223        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
224        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
225
226    src += offset;
227    uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
228    INIT_RESULT_ALPHA;
229    // TODO (msarett): Should we skip the loop here and guess that the row is opaque/not opaque?
230    //                 SkScaledBitmap sampler just guesses that it is opaque.  This is dangerous
231    //                 and probably wrong since gif and bmp (rarely) may have alpha.
232    if (1 == deltaSrc) {
233        memcpy(dst, src, dstWidth);
234        for (int x = 0; x < dstWidth; x++) {
235            UPDATE_RESULT_ALPHA(ctable[src[x]] >> SK_A32_SHIFT);
236        }
237    } else {
238        for (int x = 0; x < dstWidth; x++) {
239            dst[x] = *src;
240            UPDATE_RESULT_ALPHA(ctable[*src] >> SK_A32_SHIFT);
241            src += deltaSrc;
242        }
243    }
244    return COMPUTE_RESULT_ALPHA;
245}
246
247static SkSwizzler::ResultAlpha swizzle_index_to_n32(
248        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
249        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
250
251    src += offset;
252    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
253    INIT_RESULT_ALPHA;
254    for (int x = 0; x < dstWidth; x++) {
255        SkPMColor c = ctable[*src];
256        UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
257        dst[x] = c;
258        src += deltaSrc;
259    }
260    return COMPUTE_RESULT_ALPHA;
261}
262
263static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ(
264        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
265        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
266
267    src += offset;
268    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
269    INIT_RESULT_ALPHA;
270    for (int x = 0; x < dstWidth; x++) {
271        SkPMColor c = ctable[*src];
272        UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
273        if (c != 0) {
274            dst[x] = c;
275        }
276        src += deltaSrc;
277    }
278    return COMPUTE_RESULT_ALPHA;
279}
280
281static SkSwizzler::ResultAlpha swizzle_index_to_565(
282      void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
283      int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
284    // FIXME: Support dithering? Requires knowing y, which I think is a bigger
285    // change.
286    src += offset;
287    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
288    for (int x = 0; x < dstWidth; x++) {
289        dst[x] = SkPixel32ToPixel16(ctable[*src]);
290        src += deltaSrc;
291    }
292    return SkSwizzler::kOpaque_ResultAlpha;
293}
294
295
296#undef A32_MASK_IN_PLACE
297
298// kGray
299
300static SkSwizzler::ResultAlpha swizzle_gray_to_n32(
301        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
302        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
303
304    src += offset;
305    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
306    for (int x = 0; x < dstWidth; x++) {
307        dst[x] = SkPackARGB32NoCheck(0xFF, *src, *src, *src);
308        src += deltaSrc;
309    }
310    return SkSwizzler::kOpaque_ResultAlpha;
311}
312
313static SkSwizzler::ResultAlpha swizzle_gray_to_gray(
314        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
315        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
316
317    src += offset;
318    uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
319    if (1 == deltaSrc) {
320        memcpy(dstRow, src, dstWidth);
321    } else {
322        for (int x = 0; x < dstWidth; x++) {
323            dst[x] = src[0];
324            src += deltaSrc;
325        }
326    }
327    return SkSwizzler::kOpaque_ResultAlpha;
328}
329
330static SkSwizzler::ResultAlpha swizzle_gray_to_565(
331        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
332        int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
333    // FIXME: Support dithering?
334    src += offset;
335    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
336    for (int x = 0; x < dstWidth; x++) {
337        dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
338        src += deltaSrc;
339    }
340    return SkSwizzler::kOpaque_ResultAlpha;
341}
342
343// kBGRX
344
345static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32(
346        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
347        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
348
349    src += offset;
350    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
351    for (int x = 0; x < dstWidth; x++) {
352        dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]);
353        src += deltaSrc;
354    }
355    return SkSwizzler::kOpaque_ResultAlpha;
356}
357
358static SkSwizzler::ResultAlpha swizzle_bgrx_to_565(
359        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
360        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
361    // FIXME: Support dithering?
362    src += offset;
363    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
364    for (int x = 0; x < dstWidth; x++) {
365        dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]);
366        src += deltaSrc;
367    }
368    return SkSwizzler::kOpaque_ResultAlpha;
369}
370
371// kBGRA
372
373static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_unpremul(
374        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
375        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
376
377    src += offset;
378    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
379    INIT_RESULT_ALPHA;
380    for (int x = 0; x < dstWidth; x++) {
381        uint8_t alpha = src[3];
382        UPDATE_RESULT_ALPHA(alpha);
383        dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]);
384        src += deltaSrc;
385    }
386    return COMPUTE_RESULT_ALPHA;
387}
388
389static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_premul(
390        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
391        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
392
393    src += offset;
394    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
395    INIT_RESULT_ALPHA;
396    for (int x = 0; x < dstWidth; x++) {
397        uint8_t alpha = src[3];
398        UPDATE_RESULT_ALPHA(alpha);
399        dst[x] = SkPreMultiplyARGB(alpha, src[2], src[1], src[0]);
400        src += deltaSrc;
401    }
402    return COMPUTE_RESULT_ALPHA;
403}
404
405// kRGBX
406static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32(
407        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
408        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
409
410    src += offset;
411    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
412    for (int x = 0; x < dstWidth; x++) {
413        dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
414        src += deltaSrc;
415    }
416    return SkSwizzler::kOpaque_ResultAlpha;
417}
418
419static SkSwizzler::ResultAlpha swizzle_rgbx_to_565(
420       void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
421       int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
422    // FIXME: Support dithering?
423    src += offset;
424    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
425    for (int x = 0; x < dstWidth; x++) {
426        dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
427        src += deltaSrc;
428    }
429    return SkSwizzler::kOpaque_ResultAlpha;
430}
431
432
433// kRGBA
434static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul(
435        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
436        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
437
438    src += offset;
439    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
440    INIT_RESULT_ALPHA;
441    for (int x = 0; x < dstWidth; x++) {
442        unsigned alpha = src[3];
443        UPDATE_RESULT_ALPHA(alpha);
444        dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
445        src += deltaSrc;
446    }
447    return COMPUTE_RESULT_ALPHA;
448}
449
450static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_unpremul(
451        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
452        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
453
454    src += offset;
455    uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
456    INIT_RESULT_ALPHA;
457    for (int x = 0; x < dstWidth; x++) {
458        unsigned alpha = src[3];
459        UPDATE_RESULT_ALPHA(alpha);
460        dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
461        src += deltaSrc;
462    }
463    return COMPUTE_RESULT_ALPHA;
464}
465
466static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ(
467        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
468        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
469
470    src += offset;
471    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
472    INIT_RESULT_ALPHA;
473    for (int x = 0; x < dstWidth; x++) {
474        unsigned alpha = src[3];
475        UPDATE_RESULT_ALPHA(alpha);
476        if (0 != alpha) {
477            dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
478        }
479        src += deltaSrc;
480    }
481    return COMPUTE_RESULT_ALPHA;
482}
483
484/**
485    FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes.
486    This would be fine for drawing normally, but not for drawing with transfer modes. Being
487    honest means we can draw correctly with transfer modes, with the cost of not being able
488    to take advantage of Android's free unwritten pages. Something to keep in mind when we
489    decide whether to switch to unpremul default.
490static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow,
491                                               const uint8_t* SK_RESTRICT src,
492                                               int dstWidth, int bitsPerPixel, int offset,
493                                               const SkPMColor[]) {
494    src += offset;
495    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
496    unsigned alphaMask = 0xFF;
497    for (int x = 0; x < dstWidth; x++) {
498        unsigned alpha = src[3];
499        // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible
500        // the color components are not zero, but we skip them anyway, meaning they'll remain
501        // zero (implied by the request to skip zeroes).
502        if (0 != alpha) {
503            dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
504        }
505        src += deltaSrc;
506        alphaMask &= alpha;
507    }
508    return alphaMask != 0xFF;
509}
510*/
511
512SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
513                                       const SkPMColor* ctable,
514                                       const SkImageInfo& dstInfo,
515                                       const SkCodec::Options& options) {
516    if (dstInfo.colorType() == kUnknown_SkColorType || kUnknown == sc) {
517        return nullptr;
518    }
519    if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc)
520            && nullptr == ctable) {
521        return nullptr;
522    }
523    RowProc proc = nullptr;
524    SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized;
525    switch (sc) {
526        case kBit:
527            switch (dstInfo.colorType()) {
528                case kN32_SkColorType:
529                    proc = &swizzle_bit_to_n32;
530                    break;
531                case kIndex_8_SkColorType:
532                    proc = &swizzle_bit_to_index;
533                    break;
534                case kRGB_565_SkColorType:
535                    proc = &swizzle_bit_to_565;
536                    break;
537                case kGray_8_SkColorType:
538                    proc = &swizzle_bit_to_grayscale;
539                    break;
540                default:
541                    break;
542            }
543            break;
544        case kIndex1:
545        case kIndex2:
546        case kIndex4:
547            switch (dstInfo.colorType()) {
548                case kN32_SkColorType:
549                    proc = &swizzle_small_index_to_n32;
550                    break;
551                case kRGB_565_SkColorType:
552                    proc = &swizzle_small_index_to_565;
553                    break;
554                case kIndex_8_SkColorType:
555                    proc = &swizzle_small_index_to_index;
556                    break;
557                default:
558                    break;
559            }
560            break;
561        case kIndex:
562            switch (dstInfo.colorType()) {
563                case kN32_SkColorType:
564                    // We assume the color premultiplied ctable (or not) as desired.
565                    if (SkCodec::kYes_ZeroInitialized == zeroInit) {
566                        proc = &swizzle_index_to_n32_skipZ;
567                        break;
568                    } else {
569                        proc = &swizzle_index_to_n32;
570                        break;
571                    }
572                    break;
573                case kRGB_565_SkColorType:
574                    proc = &swizzle_index_to_565;
575                    break;
576                case kIndex_8_SkColorType:
577                    proc = &swizzle_index_to_index;
578                    break;
579                default:
580                    break;
581            }
582            break;
583        case kGray:
584            switch (dstInfo.colorType()) {
585                case kN32_SkColorType:
586                    proc = &swizzle_gray_to_n32;
587                    break;
588                case kGray_8_SkColorType:
589                    proc = &swizzle_gray_to_gray;
590                    break;
591                case kRGB_565_SkColorType:
592                    proc = &swizzle_gray_to_565;
593                    break;
594                default:
595                    break;
596            }
597            break;
598        case kBGR:
599        case kBGRX:
600            switch (dstInfo.colorType()) {
601                case kN32_SkColorType:
602                    proc = &swizzle_bgrx_to_n32;
603                    break;
604                case kRGB_565_SkColorType:
605                    proc = &swizzle_bgrx_to_565;
606                    break;
607                default:
608                    break;
609            }
610            break;
611        case kBGRA:
612            switch (dstInfo.colorType()) {
613                case kN32_SkColorType:
614                    switch (dstInfo.alphaType()) {
615                        case kUnpremul_SkAlphaType:
616                            proc = &swizzle_bgra_to_n32_unpremul;
617                            break;
618                        case kPremul_SkAlphaType:
619                            proc = &swizzle_bgra_to_n32_premul;
620                            break;
621                        default:
622                            break;
623                    }
624                    break;
625                default:
626                    break;
627            }
628            break;
629        case kRGBX:
630            // TODO: Support other swizzles.
631            switch (dstInfo.colorType()) {
632                case kN32_SkColorType:
633                    proc = &swizzle_rgbx_to_n32;
634                    break;
635                case kRGB_565_SkColorType:
636                    proc = &swizzle_rgbx_to_565;
637                default:
638                    break;
639            }
640            break;
641        case kRGBA:
642            switch (dstInfo.colorType()) {
643                case kN32_SkColorType:
644                    if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
645                        // Respect zeroInit?
646                        proc = &swizzle_rgba_to_n32_unpremul;
647                    } else {
648                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
649                            proc = &swizzle_rgba_to_n32_premul_skipZ;
650                        } else {
651                            proc = &swizzle_rgba_to_n32_premul;
652                        }
653                    }
654                    break;
655                default:
656                    break;
657            }
658            break;
659        case kRGB:
660            switch (dstInfo.colorType()) {
661                case kN32_SkColorType:
662                    proc = &swizzle_rgbx_to_n32;
663                    break;
664                default:
665                    break;
666            }
667            break;
668        case kRGB_565:
669            switch (dstInfo.colorType()) {
670                case kRGB_565_SkColorType:
671                    proc = &sample565;
672                    break;
673                default:
674                    break;
675            }
676        default:
677            break;
678    }
679    if (nullptr == proc) {
680        return nullptr;
681    }
682
683    // Store bpp in bytes if it is an even multiple, otherwise use bits
684    int bpp = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc);
685
686    int srcOffset = 0;
687    int srcWidth = dstInfo.width();
688    if (options.fSubset) {
689        srcOffset = options.fSubset->left();
690        srcWidth = options.fSubset->width();
691    }
692
693    return new SkSwizzler(proc, ctable, srcOffset, srcWidth, bpp);
694}
695
696SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcOffset, int subsetWidth,
697        int bpp)
698    : fRowProc(proc)
699    , fColorTable(ctable)
700    , fSrcOffset(srcOffset)
701    , fX0(srcOffset)
702    , fSubsetWidth(subsetWidth)
703    , fDstWidth(subsetWidth)
704    , fSampleX(1)
705    , fBPP(bpp)
706{}
707
708int SkSwizzler::onSetSampleX(int sampleX) {
709    SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be
710                           // way to report failure?
711    fSampleX = sampleX;
712    fX0 = get_start_coord(sampleX) + fSrcOffset;
713    fDstWidth = get_scaled_dimension(fSubsetWidth, sampleX);
714
715    // check that fX0 is valid
716    SkASSERT(fX0 >= 0);
717    return fDstWidth;
718}
719
720SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
721    SkASSERT(nullptr != dst && nullptr != src);
722    return fRowProc(dst, src, fDstWidth, fBPP, fSampleX * fBPP, fX0 * fBPP, fColorTable);
723}
724