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