1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/private/SkColorData.h"
9cb93a386Sopenharmony_ci#include "include/private/SkHalf.h"
10cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h"
11cb93a386Sopenharmony_ci#include "src/codec/SkCodecPriv.h"
12cb93a386Sopenharmony_ci#include "src/codec/SkSwizzler.h"
13cb93a386Sopenharmony_ci#include "src/core/SkOpts.h"
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
16cb93a386Sopenharmony_ci    #include "include/android/SkAndroidFrameworkUtils.h"
17cb93a386Sopenharmony_ci#endif
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_cistatic void copy(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
20cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
21cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
22cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
23cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci    memcpy(dst, src + offset, width * bpp);
26cb93a386Sopenharmony_ci}
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_cistatic void sample1(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
29cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
30cb93a386Sopenharmony_ci    src += offset;
31cb93a386Sopenharmony_ci    uint8_t* dst8 = (uint8_t*) dst;
32cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
33cb93a386Sopenharmony_ci        dst8[x] = *src;
34cb93a386Sopenharmony_ci        src += deltaSrc;
35cb93a386Sopenharmony_ci    }
36cb93a386Sopenharmony_ci}
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_cistatic void sample2(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
39cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
40cb93a386Sopenharmony_ci    src += offset;
41cb93a386Sopenharmony_ci    uint16_t* dst16 = (uint16_t*) dst;
42cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
43cb93a386Sopenharmony_ci        dst16[x] = *((const uint16_t*) src);
44cb93a386Sopenharmony_ci        src += deltaSrc;
45cb93a386Sopenharmony_ci    }
46cb93a386Sopenharmony_ci}
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_cistatic void sample4(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
49cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
50cb93a386Sopenharmony_ci    src += offset;
51cb93a386Sopenharmony_ci    uint32_t* dst32 = (uint32_t*) dst;
52cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
53cb93a386Sopenharmony_ci        dst32[x] = *((const uint32_t*) src);
54cb93a386Sopenharmony_ci        src += deltaSrc;
55cb93a386Sopenharmony_ci    }
56cb93a386Sopenharmony_ci}
57cb93a386Sopenharmony_ci
58cb93a386Sopenharmony_cistatic void sample6(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
59cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
60cb93a386Sopenharmony_ci    src += offset;
61cb93a386Sopenharmony_ci    uint8_t* dst8 = (uint8_t*) dst;
62cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
63cb93a386Sopenharmony_ci        memcpy(dst8, src, 6);
64cb93a386Sopenharmony_ci        dst8 += 6;
65cb93a386Sopenharmony_ci        src += deltaSrc;
66cb93a386Sopenharmony_ci    }
67cb93a386Sopenharmony_ci}
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_cistatic void sample8(void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
70cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
71cb93a386Sopenharmony_ci    src += offset;
72cb93a386Sopenharmony_ci    uint64_t* dst64 = (uint64_t*) dst;
73cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
74cb93a386Sopenharmony_ci        dst64[x] = *((const uint64_t*) src);
75cb93a386Sopenharmony_ci        src += deltaSrc;
76cb93a386Sopenharmony_ci    }
77cb93a386Sopenharmony_ci}
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ci// kBit
80cb93a386Sopenharmony_ci// These routines exclusively choose between white and black
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_ci#define GRAYSCALE_BLACK 0
83cb93a386Sopenharmony_ci#define GRAYSCALE_WHITE 0xFF
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci// same as swizzle_bit_to_index and swizzle_bit_to_n32 except for value assigned to dst[x]
87cb93a386Sopenharmony_cistatic void swizzle_bit_to_grayscale(
88cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
89cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_ci    uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    // increment src by byte offset and bitIndex by bit offset
94cb93a386Sopenharmony_ci    src += offset / 8;
95cb93a386Sopenharmony_ci    int bitIndex = offset % 8;
96cb93a386Sopenharmony_ci    uint8_t currByte = *src;
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    dst[0] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci    for (int x = 1; x < dstWidth; x++) {
101cb93a386Sopenharmony_ci        int bitOffset = bitIndex + deltaSrc;
102cb93a386Sopenharmony_ci        bitIndex = bitOffset % 8;
103cb93a386Sopenharmony_ci        currByte = *(src += bitOffset / 8);
104cb93a386Sopenharmony_ci        dst[x] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK;
105cb93a386Sopenharmony_ci    }
106cb93a386Sopenharmony_ci}
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ci#undef GRAYSCALE_BLACK
109cb93a386Sopenharmony_ci#undef GRAYSCALE_WHITE
110cb93a386Sopenharmony_ci
111cb93a386Sopenharmony_ci// same as swizzle_bit_to_grayscale and swizzle_bit_to_index except for value assigned to dst[x]
112cb93a386Sopenharmony_cistatic void swizzle_bit_to_n32(
113cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
114cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
115cb93a386Sopenharmony_ci    SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    // increment src by byte offset and bitIndex by bit offset
118cb93a386Sopenharmony_ci    src += offset / 8;
119cb93a386Sopenharmony_ci    int bitIndex = offset % 8;
120cb93a386Sopenharmony_ci    uint8_t currByte = *src;
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci    dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    for (int x = 1; x < dstWidth; x++) {
125cb93a386Sopenharmony_ci        int bitOffset = bitIndex + deltaSrc;
126cb93a386Sopenharmony_ci        bitIndex = bitOffset % 8;
127cb93a386Sopenharmony_ci        currByte = *(src += bitOffset / 8);
128cb93a386Sopenharmony_ci        dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK;
129cb93a386Sopenharmony_ci    }
130cb93a386Sopenharmony_ci}
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ci#define RGB565_BLACK 0
133cb93a386Sopenharmony_ci#define RGB565_WHITE 0xFFFF
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_cistatic void swizzle_bit_to_565(
136cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
137cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
138cb93a386Sopenharmony_ci    uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow;
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci    // increment src by byte offset and bitIndex by bit offset
141cb93a386Sopenharmony_ci    src += offset / 8;
142cb93a386Sopenharmony_ci    int bitIndex = offset % 8;
143cb93a386Sopenharmony_ci    uint8_t currByte = *src;
144cb93a386Sopenharmony_ci
145cb93a386Sopenharmony_ci    dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK;
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ci    for (int x = 1; x < dstWidth; x++) {
148cb93a386Sopenharmony_ci        int bitOffset = bitIndex + deltaSrc;
149cb93a386Sopenharmony_ci        bitIndex = bitOffset % 8;
150cb93a386Sopenharmony_ci        currByte = *(src += bitOffset / 8);
151cb93a386Sopenharmony_ci        dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK;
152cb93a386Sopenharmony_ci    }
153cb93a386Sopenharmony_ci}
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_ci#undef RGB565_BLACK
156cb93a386Sopenharmony_ci#undef RGB565_WHITE
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_cistatic void swizzle_bit_to_f16(
159cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
160cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) {
161cb93a386Sopenharmony_ci    constexpr uint64_t kWhite = (((uint64_t) SK_Half1) <<  0) |
162cb93a386Sopenharmony_ci                                (((uint64_t) SK_Half1) << 16) |
163cb93a386Sopenharmony_ci                                (((uint64_t) SK_Half1) << 32) |
164cb93a386Sopenharmony_ci                                (((uint64_t) SK_Half1) << 48);
165cb93a386Sopenharmony_ci    constexpr uint64_t kBlack = (((uint64_t)        0) <<  0) |
166cb93a386Sopenharmony_ci                                (((uint64_t)        0) << 16) |
167cb93a386Sopenharmony_ci                                (((uint64_t)        0) << 32) |
168cb93a386Sopenharmony_ci                                (((uint64_t) SK_Half1) << 48);
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ci    uint64_t* SK_RESTRICT dst = (uint64_t*) dstRow;
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci    // increment src by byte offset and bitIndex by bit offset
173cb93a386Sopenharmony_ci    src += offset / 8;
174cb93a386Sopenharmony_ci    int bitIndex = offset % 8;
175cb93a386Sopenharmony_ci    uint8_t currByte = *src;
176cb93a386Sopenharmony_ci
177cb93a386Sopenharmony_ci    dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? kWhite : kBlack;
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_ci    for (int x = 1; x < dstWidth; x++) {
180cb93a386Sopenharmony_ci        int bitOffset = bitIndex + deltaSrc;
181cb93a386Sopenharmony_ci        bitIndex = bitOffset % 8;
182cb93a386Sopenharmony_ci        currByte = *(src += bitOffset / 8);
183cb93a386Sopenharmony_ci        dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? kWhite : kBlack;
184cb93a386Sopenharmony_ci    }
185cb93a386Sopenharmony_ci}
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ci// kIndex1, kIndex2, kIndex4
188cb93a386Sopenharmony_ci
189cb93a386Sopenharmony_cistatic void swizzle_small_index_to_565(
190cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
191cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_ci    uint16_t* dst = (uint16_t*) dstRow;
194cb93a386Sopenharmony_ci    src += offset / 8;
195cb93a386Sopenharmony_ci    int bitIndex = offset % 8;
196cb93a386Sopenharmony_ci    uint8_t currByte = *src;
197cb93a386Sopenharmony_ci    const uint8_t mask = (1 << bpp) - 1;
198cb93a386Sopenharmony_ci    uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
199cb93a386Sopenharmony_ci    dst[0] = SkPixel32ToPixel16(ctable[index]);
200cb93a386Sopenharmony_ci
201cb93a386Sopenharmony_ci    for (int x = 1; x < dstWidth; x++) {
202cb93a386Sopenharmony_ci        int bitOffset = bitIndex + deltaSrc;
203cb93a386Sopenharmony_ci        bitIndex = bitOffset % 8;
204cb93a386Sopenharmony_ci        currByte = *(src += bitOffset / 8);
205cb93a386Sopenharmony_ci        index = (currByte >> (8 - bpp - bitIndex)) & mask;
206cb93a386Sopenharmony_ci        dst[x] = SkPixel32ToPixel16(ctable[index]);
207cb93a386Sopenharmony_ci    }
208cb93a386Sopenharmony_ci}
209cb93a386Sopenharmony_ci
210cb93a386Sopenharmony_cistatic void swizzle_small_index_to_n32(
211cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
212cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
213cb93a386Sopenharmony_ci
214cb93a386Sopenharmony_ci    SkPMColor* dst = (SkPMColor*) dstRow;
215cb93a386Sopenharmony_ci    src += offset / 8;
216cb93a386Sopenharmony_ci    int bitIndex = offset % 8;
217cb93a386Sopenharmony_ci    uint8_t currByte = *src;
218cb93a386Sopenharmony_ci    const uint8_t mask = (1 << bpp) - 1;
219cb93a386Sopenharmony_ci    uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask;
220cb93a386Sopenharmony_ci    dst[0] = ctable[index];
221cb93a386Sopenharmony_ci
222cb93a386Sopenharmony_ci    for (int x = 1; x < dstWidth; x++) {
223cb93a386Sopenharmony_ci        int bitOffset = bitIndex + deltaSrc;
224cb93a386Sopenharmony_ci        bitIndex = bitOffset % 8;
225cb93a386Sopenharmony_ci        currByte = *(src += bitOffset / 8);
226cb93a386Sopenharmony_ci        index = (currByte >> (8 - bpp - bitIndex)) & mask;
227cb93a386Sopenharmony_ci        dst[x] = ctable[index];
228cb93a386Sopenharmony_ci    }
229cb93a386Sopenharmony_ci}
230cb93a386Sopenharmony_ci
231cb93a386Sopenharmony_ci// kIndex
232cb93a386Sopenharmony_ci
233cb93a386Sopenharmony_cistatic void swizzle_index_to_n32(
234cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
235cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
236cb93a386Sopenharmony_ci
237cb93a386Sopenharmony_ci    src += offset;
238cb93a386Sopenharmony_ci    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
239cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
240cb93a386Sopenharmony_ci        SkPMColor c = ctable[*src];
241cb93a386Sopenharmony_ci        dst[x] = c;
242cb93a386Sopenharmony_ci        src += deltaSrc;
243cb93a386Sopenharmony_ci    }
244cb93a386Sopenharmony_ci}
245cb93a386Sopenharmony_ci
246cb93a386Sopenharmony_cistatic void swizzle_index_to_n32_skipZ(
247cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
248cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_ci    src += offset;
251cb93a386Sopenharmony_ci    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
252cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
253cb93a386Sopenharmony_ci        SkPMColor c = ctable[*src];
254cb93a386Sopenharmony_ci        if (c != 0) {
255cb93a386Sopenharmony_ci            dst[x] = c;
256cb93a386Sopenharmony_ci        }
257cb93a386Sopenharmony_ci        src += deltaSrc;
258cb93a386Sopenharmony_ci    }
259cb93a386Sopenharmony_ci}
260cb93a386Sopenharmony_ci
261cb93a386Sopenharmony_cistatic void swizzle_index_to_565(
262cb93a386Sopenharmony_ci      void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
263cb93a386Sopenharmony_ci      int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
264cb93a386Sopenharmony_ci    src += offset;
265cb93a386Sopenharmony_ci    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
266cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
267cb93a386Sopenharmony_ci        dst[x] = SkPixel32ToPixel16(ctable[*src]);
268cb93a386Sopenharmony_ci        src += deltaSrc;
269cb93a386Sopenharmony_ci    }
270cb93a386Sopenharmony_ci}
271cb93a386Sopenharmony_ci
272cb93a386Sopenharmony_ci// kGray
273cb93a386Sopenharmony_ci
274cb93a386Sopenharmony_cistatic void swizzle_gray_to_n32(
275cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
276cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
277cb93a386Sopenharmony_ci
278cb93a386Sopenharmony_ci    src += offset;
279cb93a386Sopenharmony_ci    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
280cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
281cb93a386Sopenharmony_ci        dst[x] = SkPackARGB32NoCheck(0xFF, *src, *src, *src);
282cb93a386Sopenharmony_ci        src += deltaSrc;
283cb93a386Sopenharmony_ci    }
284cb93a386Sopenharmony_ci}
285cb93a386Sopenharmony_ci
286cb93a386Sopenharmony_cistatic void fast_swizzle_gray_to_n32(
287cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
288cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
291cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
292cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
293cb93a386Sopenharmony_ci
294cb93a386Sopenharmony_ci    // Note that there is no need to distinguish between RGB and BGR.
295cb93a386Sopenharmony_ci    // Each color channel will get the same value.
296cb93a386Sopenharmony_ci    SkOpts::gray_to_RGB1((uint32_t*) dst, src + offset, width);
297cb93a386Sopenharmony_ci}
298cb93a386Sopenharmony_ci
299cb93a386Sopenharmony_cistatic void swizzle_gray_to_565(
300cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
301cb93a386Sopenharmony_ci        int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
302cb93a386Sopenharmony_ci
303cb93a386Sopenharmony_ci    src += offset;
304cb93a386Sopenharmony_ci    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
305cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
306cb93a386Sopenharmony_ci        dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
307cb93a386Sopenharmony_ci        src += deltaSrc;
308cb93a386Sopenharmony_ci    }
309cb93a386Sopenharmony_ci}
310cb93a386Sopenharmony_ci
311cb93a386Sopenharmony_ci// kGrayAlpha
312cb93a386Sopenharmony_ci
313cb93a386Sopenharmony_cistatic void swizzle_grayalpha_to_n32_unpremul(
314cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
315cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
316cb93a386Sopenharmony_ci
317cb93a386Sopenharmony_ci    src += offset;
318cb93a386Sopenharmony_ci    SkPMColor* dst32 = (SkPMColor*) dst;
319cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
320cb93a386Sopenharmony_ci        dst32[x] = SkPackARGB32NoCheck(src[1], src[0], src[0], src[0]);
321cb93a386Sopenharmony_ci        src += deltaSrc;
322cb93a386Sopenharmony_ci    }
323cb93a386Sopenharmony_ci}
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_cistatic void fast_swizzle_grayalpha_to_n32_unpremul(
326cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
327cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
330cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
331cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
332cb93a386Sopenharmony_ci
333cb93a386Sopenharmony_ci    // Note that there is no need to distinguish between RGB and BGR.
334cb93a386Sopenharmony_ci    // Each color channel will get the same value.
335cb93a386Sopenharmony_ci    SkOpts::grayA_to_RGBA((uint32_t*) dst, src + offset, width);
336cb93a386Sopenharmony_ci}
337cb93a386Sopenharmony_ci
338cb93a386Sopenharmony_cistatic void swizzle_grayalpha_to_n32_premul(
339cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
340cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
341cb93a386Sopenharmony_ci
342cb93a386Sopenharmony_ci    src += offset;
343cb93a386Sopenharmony_ci    SkPMColor* dst32 = (SkPMColor*) dst;
344cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
345cb93a386Sopenharmony_ci        uint8_t pmgray = SkMulDiv255Round(src[1], src[0]);
346cb93a386Sopenharmony_ci        dst32[x] = SkPackARGB32NoCheck(src[1], pmgray, pmgray, pmgray);
347cb93a386Sopenharmony_ci        src += deltaSrc;
348cb93a386Sopenharmony_ci    }
349cb93a386Sopenharmony_ci}
350cb93a386Sopenharmony_ci
351cb93a386Sopenharmony_cistatic void fast_swizzle_grayalpha_to_n32_premul(
352cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
353cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
354cb93a386Sopenharmony_ci
355cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
356cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
357cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
358cb93a386Sopenharmony_ci
359cb93a386Sopenharmony_ci    // Note that there is no need to distinguish between rgb and bgr.
360cb93a386Sopenharmony_ci    // Each color channel will get the same value.
361cb93a386Sopenharmony_ci    SkOpts::grayA_to_rgbA((uint32_t*) dst, src + offset, width);
362cb93a386Sopenharmony_ci}
363cb93a386Sopenharmony_ci
364cb93a386Sopenharmony_cistatic void swizzle_grayalpha_to_a8(void* dst, const uint8_t* src, int width, int bpp,
365cb93a386Sopenharmony_ci                                    int deltaSrc, int offset, const SkPMColor[]) {
366cb93a386Sopenharmony_ci    src += offset;
367cb93a386Sopenharmony_ci    uint8_t* dst8 = (uint8_t*)dst;
368cb93a386Sopenharmony_ci    for (int x = 0; x < width; ++x) {
369cb93a386Sopenharmony_ci        dst8[x] = src[1];   // src[0] is gray, ignored
370cb93a386Sopenharmony_ci        src += deltaSrc;
371cb93a386Sopenharmony_ci    }
372cb93a386Sopenharmony_ci}
373cb93a386Sopenharmony_ci
374cb93a386Sopenharmony_ci// kBGR
375cb93a386Sopenharmony_ci
376cb93a386Sopenharmony_cistatic void swizzle_bgr_to_565(
377cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
378cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
379cb93a386Sopenharmony_ci
380cb93a386Sopenharmony_ci    src += offset;
381cb93a386Sopenharmony_ci    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
382cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
383cb93a386Sopenharmony_ci        dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]);
384cb93a386Sopenharmony_ci        src += deltaSrc;
385cb93a386Sopenharmony_ci    }
386cb93a386Sopenharmony_ci}
387cb93a386Sopenharmony_ci
388cb93a386Sopenharmony_ci// kRGB
389cb93a386Sopenharmony_ci
390cb93a386Sopenharmony_cistatic void swizzle_rgb_to_rgba(
391cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
392cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
393cb93a386Sopenharmony_ci
394cb93a386Sopenharmony_ci    src += offset;
395cb93a386Sopenharmony_ci    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
396cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
397cb93a386Sopenharmony_ci        dst[x] = SkPackARGB_as_RGBA(0xFF, src[0], src[1], src[2]);
398cb93a386Sopenharmony_ci        src += deltaSrc;
399cb93a386Sopenharmony_ci    }
400cb93a386Sopenharmony_ci}
401cb93a386Sopenharmony_ci
402cb93a386Sopenharmony_cistatic void swizzle_rgb_to_bgra(
403cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
404cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
405cb93a386Sopenharmony_ci
406cb93a386Sopenharmony_ci    src += offset;
407cb93a386Sopenharmony_ci    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
408cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
409cb93a386Sopenharmony_ci        dst[x] = SkPackARGB_as_BGRA(0xFF, src[0], src[1], src[2]);
410cb93a386Sopenharmony_ci        src += deltaSrc;
411cb93a386Sopenharmony_ci    }
412cb93a386Sopenharmony_ci}
413cb93a386Sopenharmony_ci
414cb93a386Sopenharmony_cistatic void fast_swizzle_rgb_to_rgba(
415cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
416cb93a386Sopenharmony_ci        int offset, const SkPMColor ctable[]) {
417cb93a386Sopenharmony_ci
418cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
419cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
420cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
421cb93a386Sopenharmony_ci
422cb93a386Sopenharmony_ci    SkOpts::RGB_to_RGB1((uint32_t*) dst, src + offset, width);
423cb93a386Sopenharmony_ci}
424cb93a386Sopenharmony_ci
425cb93a386Sopenharmony_cistatic void fast_swizzle_rgb_to_bgra(
426cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
427cb93a386Sopenharmony_ci        int offset, const SkPMColor ctable[]) {
428cb93a386Sopenharmony_ci
429cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
430cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
431cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_ci    SkOpts::RGB_to_BGR1((uint32_t*) dst, src + offset, width);
434cb93a386Sopenharmony_ci}
435cb93a386Sopenharmony_ci
436cb93a386Sopenharmony_cistatic void swizzle_rgb_to_565(
437cb93a386Sopenharmony_ci       void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
438cb93a386Sopenharmony_ci       int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) {
439cb93a386Sopenharmony_ci
440cb93a386Sopenharmony_ci    src += offset;
441cb93a386Sopenharmony_ci    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
442cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
443cb93a386Sopenharmony_ci        dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
444cb93a386Sopenharmony_ci        src += deltaSrc;
445cb93a386Sopenharmony_ci    }
446cb93a386Sopenharmony_ci}
447cb93a386Sopenharmony_ci
448cb93a386Sopenharmony_ci// kRGBA
449cb93a386Sopenharmony_ci
450cb93a386Sopenharmony_cistatic void swizzle_rgba_to_rgba_premul(
451cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
452cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
453cb93a386Sopenharmony_ci
454cb93a386Sopenharmony_ci    src += offset;
455cb93a386Sopenharmony_ci    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
456cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
457cb93a386Sopenharmony_ci        dst[x] = premultiply_argb_as_rgba(src[3], src[0], src[1], src[2]);
458cb93a386Sopenharmony_ci        src += deltaSrc;
459cb93a386Sopenharmony_ci    }
460cb93a386Sopenharmony_ci}
461cb93a386Sopenharmony_ci
462cb93a386Sopenharmony_cistatic void swizzle_rgba_to_bgra_premul(
463cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
464cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
465cb93a386Sopenharmony_ci
466cb93a386Sopenharmony_ci    src += offset;
467cb93a386Sopenharmony_ci    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
468cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
469cb93a386Sopenharmony_ci        dst[x] = premultiply_argb_as_bgra(src[3], src[0], src[1], src[2]);
470cb93a386Sopenharmony_ci        src += deltaSrc;
471cb93a386Sopenharmony_ci    }
472cb93a386Sopenharmony_ci}
473cb93a386Sopenharmony_ci
474cb93a386Sopenharmony_cistatic void fast_swizzle_rgba_to_rgba_premul(
475cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
476cb93a386Sopenharmony_ci        int offset, const SkPMColor ctable[]) {
477cb93a386Sopenharmony_ci
478cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
479cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
480cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
481cb93a386Sopenharmony_ci
482cb93a386Sopenharmony_ci    SkOpts::RGBA_to_rgbA((uint32_t*) dst, (const uint32_t*)(src + offset), width);
483cb93a386Sopenharmony_ci}
484cb93a386Sopenharmony_ci
485cb93a386Sopenharmony_cistatic void fast_swizzle_rgba_to_bgra_premul(
486cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc,
487cb93a386Sopenharmony_ci        int offset, const SkPMColor ctable[]) {
488cb93a386Sopenharmony_ci
489cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
490cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
491cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
492cb93a386Sopenharmony_ci
493cb93a386Sopenharmony_ci    SkOpts::RGBA_to_bgrA((uint32_t*) dst, (const uint32_t*)(src + offset), width);
494cb93a386Sopenharmony_ci}
495cb93a386Sopenharmony_ci
496cb93a386Sopenharmony_cistatic void swizzle_rgba_to_bgra_unpremul(
497cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
498cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
499cb93a386Sopenharmony_ci
500cb93a386Sopenharmony_ci    src += offset;
501cb93a386Sopenharmony_ci    uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
502cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
503cb93a386Sopenharmony_ci        unsigned alpha = src[3];
504cb93a386Sopenharmony_ci        dst[x] = SkPackARGB_as_BGRA(alpha, src[0], src[1], src[2]);
505cb93a386Sopenharmony_ci        src += deltaSrc;
506cb93a386Sopenharmony_ci    }
507cb93a386Sopenharmony_ci}
508cb93a386Sopenharmony_ci
509cb93a386Sopenharmony_cistatic void fast_swizzle_rgba_to_bgra_unpremul(
510cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
511cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
512cb93a386Sopenharmony_ci
513cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
514cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
515cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
516cb93a386Sopenharmony_ci
517cb93a386Sopenharmony_ci    SkOpts::RGBA_to_BGRA((uint32_t*) dst, (const uint32_t*)(src + offset), width);
518cb93a386Sopenharmony_ci}
519cb93a386Sopenharmony_ci
520cb93a386Sopenharmony_ci// 16-bits per component kRGB and kRGBA
521cb93a386Sopenharmony_ci
522cb93a386Sopenharmony_cistatic void swizzle_rgb16_to_rgba(
523cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
524cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
525cb93a386Sopenharmony_ci    auto strip16to8 = [](const uint8_t* ptr) {
526cb93a386Sopenharmony_ci        return 0xFF000000 | (ptr[4] << 16) | (ptr[2] << 8) | ptr[0];
527cb93a386Sopenharmony_ci    };
528cb93a386Sopenharmony_ci
529cb93a386Sopenharmony_ci    src += offset;
530cb93a386Sopenharmony_ci    uint32_t* dst32 = (uint32_t*) dst;
531cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
532cb93a386Sopenharmony_ci        dst32[x] = strip16to8(src);
533cb93a386Sopenharmony_ci        src += deltaSrc;
534cb93a386Sopenharmony_ci    }
535cb93a386Sopenharmony_ci}
536cb93a386Sopenharmony_ci
537cb93a386Sopenharmony_cistatic void swizzle_rgb16_to_bgra(
538cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
539cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
540cb93a386Sopenharmony_ci    auto strip16to8 = [](const uint8_t* ptr) {
541cb93a386Sopenharmony_ci        return 0xFF000000 | (ptr[0] << 16) | (ptr[2] << 8) | ptr[4];
542cb93a386Sopenharmony_ci    };
543cb93a386Sopenharmony_ci
544cb93a386Sopenharmony_ci    src += offset;
545cb93a386Sopenharmony_ci    uint32_t* dst32 = (uint32_t*) dst;
546cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
547cb93a386Sopenharmony_ci        dst32[x] = strip16to8(src);
548cb93a386Sopenharmony_ci        src += deltaSrc;
549cb93a386Sopenharmony_ci    }
550cb93a386Sopenharmony_ci}
551cb93a386Sopenharmony_ci
552cb93a386Sopenharmony_cistatic void swizzle_rgb16_to_565(
553cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
554cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
555cb93a386Sopenharmony_ci    auto strip16to565 = [](const uint8_t* ptr) {
556cb93a386Sopenharmony_ci        return SkPack888ToRGB16(ptr[0], ptr[2], ptr[4]);
557cb93a386Sopenharmony_ci    };
558cb93a386Sopenharmony_ci
559cb93a386Sopenharmony_ci    src += offset;
560cb93a386Sopenharmony_ci    uint16_t* dst16 = (uint16_t*) dst;
561cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
562cb93a386Sopenharmony_ci        dst16[x] = strip16to565(src);
563cb93a386Sopenharmony_ci        src += deltaSrc;
564cb93a386Sopenharmony_ci    }
565cb93a386Sopenharmony_ci}
566cb93a386Sopenharmony_ci
567cb93a386Sopenharmony_cistatic void swizzle_rgba16_to_rgba_unpremul(
568cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
569cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
570cb93a386Sopenharmony_ci    auto strip16to8 = [](const uint8_t* ptr) {
571cb93a386Sopenharmony_ci        return (ptr[6] << 24) | (ptr[4] << 16) | (ptr[2] << 8) | ptr[0];
572cb93a386Sopenharmony_ci    };
573cb93a386Sopenharmony_ci
574cb93a386Sopenharmony_ci    src += offset;
575cb93a386Sopenharmony_ci    uint32_t* dst32 = (uint32_t*) dst;
576cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
577cb93a386Sopenharmony_ci        dst32[x] = strip16to8(src);
578cb93a386Sopenharmony_ci        src += deltaSrc;
579cb93a386Sopenharmony_ci    }
580cb93a386Sopenharmony_ci}
581cb93a386Sopenharmony_ci
582cb93a386Sopenharmony_cistatic void swizzle_rgba16_to_rgba_premul(
583cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
584cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
585cb93a386Sopenharmony_ci    auto stripAndPremul16to8 = [](const uint8_t* ptr) {
586cb93a386Sopenharmony_ci        return premultiply_argb_as_rgba(ptr[6], ptr[0], ptr[2], ptr[4]);
587cb93a386Sopenharmony_ci    };
588cb93a386Sopenharmony_ci
589cb93a386Sopenharmony_ci    src += offset;
590cb93a386Sopenharmony_ci    uint32_t* dst32 = (uint32_t*) dst;
591cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
592cb93a386Sopenharmony_ci        dst32[x] = stripAndPremul16to8(src);
593cb93a386Sopenharmony_ci        src += deltaSrc;
594cb93a386Sopenharmony_ci    }
595cb93a386Sopenharmony_ci}
596cb93a386Sopenharmony_ci
597cb93a386Sopenharmony_cistatic void swizzle_rgba16_to_bgra_unpremul(
598cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
599cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
600cb93a386Sopenharmony_ci    auto strip16to8 = [](const uint8_t* ptr) {
601cb93a386Sopenharmony_ci        return (ptr[6] << 24) | (ptr[0] << 16) | (ptr[2] << 8) | ptr[4];
602cb93a386Sopenharmony_ci    };
603cb93a386Sopenharmony_ci
604cb93a386Sopenharmony_ci    src += offset;
605cb93a386Sopenharmony_ci    uint32_t* dst32 = (uint32_t*) dst;
606cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
607cb93a386Sopenharmony_ci        dst32[x] = strip16to8(src);
608cb93a386Sopenharmony_ci        src += deltaSrc;
609cb93a386Sopenharmony_ci    }
610cb93a386Sopenharmony_ci}
611cb93a386Sopenharmony_ci
612cb93a386Sopenharmony_cistatic void swizzle_rgba16_to_bgra_premul(
613cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
614cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
615cb93a386Sopenharmony_ci    auto stripAndPremul16to8 = [](const uint8_t* ptr) {
616cb93a386Sopenharmony_ci        return premultiply_argb_as_bgra(ptr[6], ptr[0], ptr[2], ptr[4]);
617cb93a386Sopenharmony_ci    };
618cb93a386Sopenharmony_ci
619cb93a386Sopenharmony_ci    src += offset;
620cb93a386Sopenharmony_ci    uint32_t* dst32 = (uint32_t*) dst;
621cb93a386Sopenharmony_ci    for (int x = 0; x < width; x++) {
622cb93a386Sopenharmony_ci        dst32[x] = stripAndPremul16to8(src);
623cb93a386Sopenharmony_ci        src += deltaSrc;
624cb93a386Sopenharmony_ci    }
625cb93a386Sopenharmony_ci}
626cb93a386Sopenharmony_ci
627cb93a386Sopenharmony_ci// kCMYK
628cb93a386Sopenharmony_ci//
629cb93a386Sopenharmony_ci// CMYK is stored as four bytes per pixel.
630cb93a386Sopenharmony_ci//
631cb93a386Sopenharmony_ci// We will implement a crude conversion from CMYK -> RGB using formulas
632cb93a386Sopenharmony_ci// from easyrgb.com.
633cb93a386Sopenharmony_ci//
634cb93a386Sopenharmony_ci// CMYK -> CMY
635cb93a386Sopenharmony_ci// C = C * (1 - K) + K
636cb93a386Sopenharmony_ci// M = M * (1 - K) + K
637cb93a386Sopenharmony_ci// Y = Y * (1 - K) + K
638cb93a386Sopenharmony_ci//
639cb93a386Sopenharmony_ci// libjpeg actually gives us inverted CMYK, so we must subtract the
640cb93a386Sopenharmony_ci// original terms from 1.
641cb93a386Sopenharmony_ci// CMYK -> CMY
642cb93a386Sopenharmony_ci// C = (1 - C) * (1 - (1 - K)) + (1 - K)
643cb93a386Sopenharmony_ci// M = (1 - M) * (1 - (1 - K)) + (1 - K)
644cb93a386Sopenharmony_ci// Y = (1 - Y) * (1 - (1 - K)) + (1 - K)
645cb93a386Sopenharmony_ci//
646cb93a386Sopenharmony_ci// Simplifying the above expression.
647cb93a386Sopenharmony_ci// CMYK -> CMY
648cb93a386Sopenharmony_ci// C = 1 - CK
649cb93a386Sopenharmony_ci// M = 1 - MK
650cb93a386Sopenharmony_ci// Y = 1 - YK
651cb93a386Sopenharmony_ci//
652cb93a386Sopenharmony_ci// CMY -> RGB
653cb93a386Sopenharmony_ci// R = (1 - C) * 255
654cb93a386Sopenharmony_ci// G = (1 - M) * 255
655cb93a386Sopenharmony_ci// B = (1 - Y) * 255
656cb93a386Sopenharmony_ci//
657cb93a386Sopenharmony_ci// Therefore the full conversion is below.  This can be verified at
658cb93a386Sopenharmony_ci// www.rapidtables.com (assuming inverted CMYK).
659cb93a386Sopenharmony_ci// CMYK -> RGB
660cb93a386Sopenharmony_ci// R = C * K * 255
661cb93a386Sopenharmony_ci// G = M * K * 255
662cb93a386Sopenharmony_ci// B = Y * K * 255
663cb93a386Sopenharmony_ci//
664cb93a386Sopenharmony_ci// As a final note, we have treated the CMYK values as if they were on
665cb93a386Sopenharmony_ci// a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255.
666cb93a386Sopenharmony_ci// We must divide each CMYK component by 255 to obtain the true conversion
667cb93a386Sopenharmony_ci// we should perform.
668cb93a386Sopenharmony_ci// CMYK -> RGB
669cb93a386Sopenharmony_ci// R = C * K / 255
670cb93a386Sopenharmony_ci// G = M * K / 255
671cb93a386Sopenharmony_ci// B = Y * K / 255
672cb93a386Sopenharmony_cistatic void swizzle_cmyk_to_rgba(
673cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
674cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
675cb93a386Sopenharmony_ci
676cb93a386Sopenharmony_ci    src += offset;
677cb93a386Sopenharmony_ci    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
678cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
679cb93a386Sopenharmony_ci        const uint8_t r = SkMulDiv255Round(src[0], src[3]);
680cb93a386Sopenharmony_ci        const uint8_t g = SkMulDiv255Round(src[1], src[3]);
681cb93a386Sopenharmony_ci        const uint8_t b = SkMulDiv255Round(src[2], src[3]);
682cb93a386Sopenharmony_ci
683cb93a386Sopenharmony_ci        dst[x] = SkPackARGB_as_RGBA(0xFF, r, g, b);
684cb93a386Sopenharmony_ci        src += deltaSrc;
685cb93a386Sopenharmony_ci    }
686cb93a386Sopenharmony_ci}
687cb93a386Sopenharmony_ci
688cb93a386Sopenharmony_cistatic void swizzle_cmyk_to_bgra(
689cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
690cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
691cb93a386Sopenharmony_ci
692cb93a386Sopenharmony_ci    src += offset;
693cb93a386Sopenharmony_ci    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
694cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
695cb93a386Sopenharmony_ci        const uint8_t r = SkMulDiv255Round(src[0], src[3]);
696cb93a386Sopenharmony_ci        const uint8_t g = SkMulDiv255Round(src[1], src[3]);
697cb93a386Sopenharmony_ci        const uint8_t b = SkMulDiv255Round(src[2], src[3]);
698cb93a386Sopenharmony_ci
699cb93a386Sopenharmony_ci        dst[x] = SkPackARGB_as_BGRA(0xFF, r, g, b);
700cb93a386Sopenharmony_ci        src += deltaSrc;
701cb93a386Sopenharmony_ci    }
702cb93a386Sopenharmony_ci}
703cb93a386Sopenharmony_ci
704cb93a386Sopenharmony_cistatic void fast_swizzle_cmyk_to_rgba(
705cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
706cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
707cb93a386Sopenharmony_ci
708cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
709cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
710cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
711cb93a386Sopenharmony_ci
712cb93a386Sopenharmony_ci    SkOpts::inverted_CMYK_to_RGB1((uint32_t*) dst, (const uint32_t*)(src + offset), width);
713cb93a386Sopenharmony_ci}
714cb93a386Sopenharmony_ci
715cb93a386Sopenharmony_cistatic void fast_swizzle_cmyk_to_bgra(
716cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width, int bpp, int deltaSrc, int offset,
717cb93a386Sopenharmony_ci        const SkPMColor ctable[]) {
718cb93a386Sopenharmony_ci
719cb93a386Sopenharmony_ci    // This function must not be called if we are sampling.  If we are not
720cb93a386Sopenharmony_ci    // sampling, deltaSrc should equal bpp.
721cb93a386Sopenharmony_ci    SkASSERT(deltaSrc == bpp);
722cb93a386Sopenharmony_ci
723cb93a386Sopenharmony_ci    SkOpts::inverted_CMYK_to_BGR1((uint32_t*) dst, (const uint32_t*)(src + offset), width);
724cb93a386Sopenharmony_ci}
725cb93a386Sopenharmony_ci
726cb93a386Sopenharmony_cistatic void swizzle_cmyk_to_565(
727cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
728cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
729cb93a386Sopenharmony_ci
730cb93a386Sopenharmony_ci    src += offset;
731cb93a386Sopenharmony_ci    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
732cb93a386Sopenharmony_ci    for (int x = 0; x < dstWidth; x++) {
733cb93a386Sopenharmony_ci        const uint8_t r = SkMulDiv255Round(src[0], src[3]);
734cb93a386Sopenharmony_ci        const uint8_t g = SkMulDiv255Round(src[1], src[3]);
735cb93a386Sopenharmony_ci        const uint8_t b = SkMulDiv255Round(src[2], src[3]);
736cb93a386Sopenharmony_ci
737cb93a386Sopenharmony_ci        dst[x] = SkPack888ToRGB16(r, g, b);
738cb93a386Sopenharmony_ci        src += deltaSrc;
739cb93a386Sopenharmony_ci    }
740cb93a386Sopenharmony_ci}
741cb93a386Sopenharmony_ci
742cb93a386Sopenharmony_citemplate <SkSwizzler::RowProc proc>
743cb93a386Sopenharmony_civoid SkSwizzler::SkipLeadingGrayAlphaZerosThen(
744cb93a386Sopenharmony_ci        void* dst, const uint8_t* src, int width,
745cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
746cb93a386Sopenharmony_ci    SkASSERT(!ctable);
747cb93a386Sopenharmony_ci
748cb93a386Sopenharmony_ci    const uint16_t* src16 = (const uint16_t*) (src + offset);
749cb93a386Sopenharmony_ci    uint32_t* dst32 = (uint32_t*) dst;
750cb93a386Sopenharmony_ci
751cb93a386Sopenharmony_ci    // This may miss opportunities to skip when the output is premultiplied,
752cb93a386Sopenharmony_ci    // e.g. for a src pixel 0x00FF which is not zero but becomes zero after premultiplication.
753cb93a386Sopenharmony_ci    while (width > 0 && *src16 == 0x0000) {
754cb93a386Sopenharmony_ci        width--;
755cb93a386Sopenharmony_ci        dst32++;
756cb93a386Sopenharmony_ci        src16 += deltaSrc / 2;
757cb93a386Sopenharmony_ci    }
758cb93a386Sopenharmony_ci    proc(dst32, (const uint8_t*)src16, width, bpp, deltaSrc, 0, ctable);
759cb93a386Sopenharmony_ci}
760cb93a386Sopenharmony_ci
761cb93a386Sopenharmony_citemplate <SkSwizzler::RowProc proc>
762cb93a386Sopenharmony_civoid SkSwizzler::SkipLeading8888ZerosThen(
763cb93a386Sopenharmony_ci        void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth,
764cb93a386Sopenharmony_ci        int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) {
765cb93a386Sopenharmony_ci    SkASSERT(!ctable);
766cb93a386Sopenharmony_ci
767cb93a386Sopenharmony_ci    auto src32 = (const uint32_t*)(src+offset);
768cb93a386Sopenharmony_ci    auto dst32 = (uint32_t*)dstRow;
769cb93a386Sopenharmony_ci
770cb93a386Sopenharmony_ci    // This may miss opportunities to skip when the output is premultiplied,
771cb93a386Sopenharmony_ci    // e.g. for a src pixel 0x00FFFFFF which is not zero but becomes zero after premultiplication.
772cb93a386Sopenharmony_ci    while (dstWidth > 0 && *src32 == 0x00000000) {
773cb93a386Sopenharmony_ci        dstWidth--;
774cb93a386Sopenharmony_ci        dst32++;
775cb93a386Sopenharmony_ci        src32 += deltaSrc/4;
776cb93a386Sopenharmony_ci    }
777cb93a386Sopenharmony_ci    proc(dst32, (const uint8_t*)src32, dstWidth, bpp, deltaSrc, 0, ctable);
778cb93a386Sopenharmony_ci}
779cb93a386Sopenharmony_ci
780cb93a386Sopenharmony_cistd::unique_ptr<SkSwizzler> SkSwizzler::MakeSimple(int srcBPP, const SkImageInfo& dstInfo,
781cb93a386Sopenharmony_ci                                                   const SkCodec::Options& options) {
782cb93a386Sopenharmony_ci    RowProc proc = nullptr;
783cb93a386Sopenharmony_ci    switch (srcBPP) {
784cb93a386Sopenharmony_ci        case 1:     // kGray_8_SkColorType
785cb93a386Sopenharmony_ci            proc = &sample1;
786cb93a386Sopenharmony_ci            break;
787cb93a386Sopenharmony_ci        case 2:     // kRGB_565_SkColorType
788cb93a386Sopenharmony_ci            proc = &sample2;
789cb93a386Sopenharmony_ci            break;
790cb93a386Sopenharmony_ci        case 4:     // kRGBA_8888_SkColorType
791cb93a386Sopenharmony_ci                    // kBGRA_8888_SkColorType
792cb93a386Sopenharmony_ci            proc = &sample4;
793cb93a386Sopenharmony_ci            break;
794cb93a386Sopenharmony_ci        case 6:     // 16 bit PNG no alpha
795cb93a386Sopenharmony_ci            proc = &sample6;
796cb93a386Sopenharmony_ci            break;
797cb93a386Sopenharmony_ci        case 8:     // 16 bit PNG with alpha
798cb93a386Sopenharmony_ci            proc = &sample8;
799cb93a386Sopenharmony_ci            break;
800cb93a386Sopenharmony_ci        default:
801cb93a386Sopenharmony_ci            return nullptr;
802cb93a386Sopenharmony_ci    }
803cb93a386Sopenharmony_ci
804cb93a386Sopenharmony_ci    return Make(dstInfo, &copy, proc, nullptr /*ctable*/, srcBPP,
805cb93a386Sopenharmony_ci                dstInfo.bytesPerPixel(), options, nullptr /*frame*/);
806cb93a386Sopenharmony_ci}
807cb93a386Sopenharmony_ci
808cb93a386Sopenharmony_cistd::unique_ptr<SkSwizzler> SkSwizzler::Make(const SkEncodedInfo& encodedInfo,
809cb93a386Sopenharmony_ci                                             const SkPMColor* ctable,
810cb93a386Sopenharmony_ci                                             const SkImageInfo& dstInfo,
811cb93a386Sopenharmony_ci                                             const SkCodec::Options& options,
812cb93a386Sopenharmony_ci                                             const SkIRect* frame) {
813cb93a386Sopenharmony_ci    if (SkEncodedInfo::kPalette_Color == encodedInfo.color() && nullptr == ctable) {
814cb93a386Sopenharmony_ci        return nullptr;
815cb93a386Sopenharmony_ci    }
816cb93a386Sopenharmony_ci
817cb93a386Sopenharmony_ci    RowProc fastProc = nullptr;
818cb93a386Sopenharmony_ci    RowProc proc = nullptr;
819cb93a386Sopenharmony_ci    SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized;
820cb93a386Sopenharmony_ci    const bool premultiply = (SkEncodedInfo::kOpaque_Alpha != encodedInfo.alpha()) &&
821cb93a386Sopenharmony_ci            (kPremul_SkAlphaType == dstInfo.alphaType());
822cb93a386Sopenharmony_ci
823cb93a386Sopenharmony_ci    switch (encodedInfo.color()) {
824cb93a386Sopenharmony_ci        case SkEncodedInfo::kGray_Color:
825cb93a386Sopenharmony_ci            switch (encodedInfo.bitsPerComponent()) {
826cb93a386Sopenharmony_ci                case 1:
827cb93a386Sopenharmony_ci                    switch (dstInfo.colorType()) {
828cb93a386Sopenharmony_ci                        case kRGBA_8888_SkColorType:
829cb93a386Sopenharmony_ci                        case kBGRA_8888_SkColorType:
830cb93a386Sopenharmony_ci                            proc = &swizzle_bit_to_n32;
831cb93a386Sopenharmony_ci                            break;
832cb93a386Sopenharmony_ci                        case kRGB_565_SkColorType:
833cb93a386Sopenharmony_ci                            proc = &swizzle_bit_to_565;
834cb93a386Sopenharmony_ci                            break;
835cb93a386Sopenharmony_ci                        case kGray_8_SkColorType:
836cb93a386Sopenharmony_ci                            proc = &swizzle_bit_to_grayscale;
837cb93a386Sopenharmony_ci                            break;
838cb93a386Sopenharmony_ci                        case kRGBA_F16_SkColorType:
839cb93a386Sopenharmony_ci                            proc = &swizzle_bit_to_f16;
840cb93a386Sopenharmony_ci                            break;
841cb93a386Sopenharmony_ci                        default:
842cb93a386Sopenharmony_ci                            return nullptr;
843cb93a386Sopenharmony_ci                    }
844cb93a386Sopenharmony_ci                    break;
845cb93a386Sopenharmony_ci                case 8:
846cb93a386Sopenharmony_ci                    switch (dstInfo.colorType()) {
847cb93a386Sopenharmony_ci                        case kRGBA_8888_SkColorType:
848cb93a386Sopenharmony_ci                        case kBGRA_8888_SkColorType:
849cb93a386Sopenharmony_ci                            proc = &swizzle_gray_to_n32;
850cb93a386Sopenharmony_ci                            fastProc = &fast_swizzle_gray_to_n32;
851cb93a386Sopenharmony_ci                            break;
852cb93a386Sopenharmony_ci                        case kGray_8_SkColorType:
853cb93a386Sopenharmony_ci                            proc = &sample1;
854cb93a386Sopenharmony_ci                            fastProc = &copy;
855cb93a386Sopenharmony_ci                            break;
856cb93a386Sopenharmony_ci                        case kRGB_565_SkColorType:
857cb93a386Sopenharmony_ci                            proc = &swizzle_gray_to_565;
858cb93a386Sopenharmony_ci                            break;
859cb93a386Sopenharmony_ci                        default:
860cb93a386Sopenharmony_ci                            return nullptr;
861cb93a386Sopenharmony_ci                    }
862cb93a386Sopenharmony_ci                    break;
863cb93a386Sopenharmony_ci                default:
864cb93a386Sopenharmony_ci                    return nullptr;
865cb93a386Sopenharmony_ci            }
866cb93a386Sopenharmony_ci            break;
867cb93a386Sopenharmony_ci        case SkEncodedInfo::kXAlpha_Color:
868cb93a386Sopenharmony_ci        case SkEncodedInfo::kGrayAlpha_Color:
869cb93a386Sopenharmony_ci            switch (dstInfo.colorType()) {
870cb93a386Sopenharmony_ci                case kRGBA_8888_SkColorType:
871cb93a386Sopenharmony_ci                case kBGRA_8888_SkColorType:
872cb93a386Sopenharmony_ci                    if (premultiply) {
873cb93a386Sopenharmony_ci                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
874cb93a386Sopenharmony_ci                            proc = &SkipLeadingGrayAlphaZerosThen
875cb93a386Sopenharmony_ci                                    <swizzle_grayalpha_to_n32_premul>;
876cb93a386Sopenharmony_ci                            fastProc = &SkipLeadingGrayAlphaZerosThen
877cb93a386Sopenharmony_ci                                    <fast_swizzle_grayalpha_to_n32_premul>;
878cb93a386Sopenharmony_ci                        } else {
879cb93a386Sopenharmony_ci                            proc = &swizzle_grayalpha_to_n32_premul;
880cb93a386Sopenharmony_ci                            fastProc = &fast_swizzle_grayalpha_to_n32_premul;
881cb93a386Sopenharmony_ci                        }
882cb93a386Sopenharmony_ci                    } else {
883cb93a386Sopenharmony_ci                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
884cb93a386Sopenharmony_ci                            proc = &SkipLeadingGrayAlphaZerosThen
885cb93a386Sopenharmony_ci                                    <swizzle_grayalpha_to_n32_unpremul>;
886cb93a386Sopenharmony_ci                            fastProc = &SkipLeadingGrayAlphaZerosThen
887cb93a386Sopenharmony_ci                                    <fast_swizzle_grayalpha_to_n32_unpremul>;
888cb93a386Sopenharmony_ci                        } else {
889cb93a386Sopenharmony_ci                            proc = &swizzle_grayalpha_to_n32_unpremul;
890cb93a386Sopenharmony_ci                            fastProc = &fast_swizzle_grayalpha_to_n32_unpremul;
891cb93a386Sopenharmony_ci                        }
892cb93a386Sopenharmony_ci                    }
893cb93a386Sopenharmony_ci                    break;
894cb93a386Sopenharmony_ci                case kAlpha_8_SkColorType:
895cb93a386Sopenharmony_ci                    proc = &swizzle_grayalpha_to_a8;
896cb93a386Sopenharmony_ci                    break;
897cb93a386Sopenharmony_ci                default:
898cb93a386Sopenharmony_ci                    return nullptr;
899cb93a386Sopenharmony_ci            }
900cb93a386Sopenharmony_ci            break;
901cb93a386Sopenharmony_ci        case SkEncodedInfo::kPalette_Color:
902cb93a386Sopenharmony_ci            // We assume that the color table is premultiplied and swizzled
903cb93a386Sopenharmony_ci            // as desired.
904cb93a386Sopenharmony_ci            switch (encodedInfo.bitsPerComponent()) {
905cb93a386Sopenharmony_ci                case 1:
906cb93a386Sopenharmony_ci                case 2:
907cb93a386Sopenharmony_ci                case 4:
908cb93a386Sopenharmony_ci                    switch (dstInfo.colorType()) {
909cb93a386Sopenharmony_ci                        case kRGBA_8888_SkColorType:
910cb93a386Sopenharmony_ci                        case kBGRA_8888_SkColorType:
911cb93a386Sopenharmony_ci                            proc = &swizzle_small_index_to_n32;
912cb93a386Sopenharmony_ci                            break;
913cb93a386Sopenharmony_ci                        case kRGB_565_SkColorType:
914cb93a386Sopenharmony_ci                            proc = &swizzle_small_index_to_565;
915cb93a386Sopenharmony_ci                            break;
916cb93a386Sopenharmony_ci                        default:
917cb93a386Sopenharmony_ci                            return nullptr;
918cb93a386Sopenharmony_ci                    }
919cb93a386Sopenharmony_ci                    break;
920cb93a386Sopenharmony_ci                case 8:
921cb93a386Sopenharmony_ci                    switch (dstInfo.colorType()) {
922cb93a386Sopenharmony_ci                        case kRGBA_8888_SkColorType:
923cb93a386Sopenharmony_ci                        case kBGRA_8888_SkColorType:
924cb93a386Sopenharmony_ci                            if (SkCodec::kYes_ZeroInitialized == zeroInit) {
925cb93a386Sopenharmony_ci                                proc = &swizzle_index_to_n32_skipZ;
926cb93a386Sopenharmony_ci                            } else {
927cb93a386Sopenharmony_ci                                proc = &swizzle_index_to_n32;
928cb93a386Sopenharmony_ci                            }
929cb93a386Sopenharmony_ci                            break;
930cb93a386Sopenharmony_ci                        case kRGB_565_SkColorType:
931cb93a386Sopenharmony_ci                            proc = &swizzle_index_to_565;
932cb93a386Sopenharmony_ci                            break;
933cb93a386Sopenharmony_ci                        default:
934cb93a386Sopenharmony_ci                            return nullptr;
935cb93a386Sopenharmony_ci                    }
936cb93a386Sopenharmony_ci                    break;
937cb93a386Sopenharmony_ci                default:
938cb93a386Sopenharmony_ci                    return nullptr;
939cb93a386Sopenharmony_ci            }
940cb93a386Sopenharmony_ci            break;
941cb93a386Sopenharmony_ci        case SkEncodedInfo::k565_Color:
942cb93a386Sopenharmony_ci            // Treat 565 exactly like RGB (since it's still encoded as 8 bits per component).
943cb93a386Sopenharmony_ci            // We just mark as 565 when we have a hint that there are only 5/6/5 "significant"
944cb93a386Sopenharmony_ci            // bits in each channel.
945cb93a386Sopenharmony_ci        case SkEncodedInfo::kRGB_Color:
946cb93a386Sopenharmony_ci            switch (dstInfo.colorType()) {
947cb93a386Sopenharmony_ci                case kRGBA_8888_SkColorType:
948cb93a386Sopenharmony_ci                    if (16 == encodedInfo.bitsPerComponent()) {
949cb93a386Sopenharmony_ci                        proc = &swizzle_rgb16_to_rgba;
950cb93a386Sopenharmony_ci                        break;
951cb93a386Sopenharmony_ci                    }
952cb93a386Sopenharmony_ci
953cb93a386Sopenharmony_ci                    SkASSERT(8 == encodedInfo.bitsPerComponent());
954cb93a386Sopenharmony_ci                    proc = &swizzle_rgb_to_rgba;
955cb93a386Sopenharmony_ci                    fastProc = &fast_swizzle_rgb_to_rgba;
956cb93a386Sopenharmony_ci                    break;
957cb93a386Sopenharmony_ci                case kBGRA_8888_SkColorType:
958cb93a386Sopenharmony_ci                    if (16 == encodedInfo.bitsPerComponent()) {
959cb93a386Sopenharmony_ci                        proc = &swizzle_rgb16_to_bgra;
960cb93a386Sopenharmony_ci                        break;
961cb93a386Sopenharmony_ci                    }
962cb93a386Sopenharmony_ci
963cb93a386Sopenharmony_ci                    SkASSERT(8 == encodedInfo.bitsPerComponent());
964cb93a386Sopenharmony_ci                    proc = &swizzle_rgb_to_bgra;
965cb93a386Sopenharmony_ci                    fastProc = &fast_swizzle_rgb_to_bgra;
966cb93a386Sopenharmony_ci                    break;
967cb93a386Sopenharmony_ci                case kRGB_565_SkColorType:
968cb93a386Sopenharmony_ci                    if (16 == encodedInfo.bitsPerComponent()) {
969cb93a386Sopenharmony_ci                        proc = &swizzle_rgb16_to_565;
970cb93a386Sopenharmony_ci                        break;
971cb93a386Sopenharmony_ci                    }
972cb93a386Sopenharmony_ci
973cb93a386Sopenharmony_ci                    proc = &swizzle_rgb_to_565;
974cb93a386Sopenharmony_ci                    break;
975cb93a386Sopenharmony_ci                default:
976cb93a386Sopenharmony_ci                    return nullptr;
977cb93a386Sopenharmony_ci            }
978cb93a386Sopenharmony_ci            break;
979cb93a386Sopenharmony_ci        case SkEncodedInfo::kRGBA_Color:
980cb93a386Sopenharmony_ci            switch (dstInfo.colorType()) {
981cb93a386Sopenharmony_ci                case kRGBA_8888_SkColorType:
982cb93a386Sopenharmony_ci                    if (16 == encodedInfo.bitsPerComponent()) {
983cb93a386Sopenharmony_ci                        proc = premultiply ? &swizzle_rgba16_to_rgba_premul :
984cb93a386Sopenharmony_ci                                             &swizzle_rgba16_to_rgba_unpremul;
985cb93a386Sopenharmony_ci                        break;
986cb93a386Sopenharmony_ci                    }
987cb93a386Sopenharmony_ci
988cb93a386Sopenharmony_ci                    SkASSERT(8 == encodedInfo.bitsPerComponent());
989cb93a386Sopenharmony_ci                    if (premultiply) {
990cb93a386Sopenharmony_ci                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
991cb93a386Sopenharmony_ci                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_rgba_premul>;
992cb93a386Sopenharmony_ci                            fastProc = &SkipLeading8888ZerosThen
993cb93a386Sopenharmony_ci                                    <fast_swizzle_rgba_to_rgba_premul>;
994cb93a386Sopenharmony_ci                        } else {
995cb93a386Sopenharmony_ci                            proc = &swizzle_rgba_to_rgba_premul;
996cb93a386Sopenharmony_ci                            fastProc = &fast_swizzle_rgba_to_rgba_premul;
997cb93a386Sopenharmony_ci                        }
998cb93a386Sopenharmony_ci                    } else {
999cb93a386Sopenharmony_ci                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1000cb93a386Sopenharmony_ci                            proc = &SkipLeading8888ZerosThen<sample4>;
1001cb93a386Sopenharmony_ci                            fastProc = &SkipLeading8888ZerosThen<copy>;
1002cb93a386Sopenharmony_ci                        } else {
1003cb93a386Sopenharmony_ci                            proc = &sample4;
1004cb93a386Sopenharmony_ci                            fastProc = &copy;
1005cb93a386Sopenharmony_ci                        }
1006cb93a386Sopenharmony_ci                    }
1007cb93a386Sopenharmony_ci                    break;
1008cb93a386Sopenharmony_ci                case kBGRA_8888_SkColorType:
1009cb93a386Sopenharmony_ci                    if (16 == encodedInfo.bitsPerComponent()) {
1010cb93a386Sopenharmony_ci                        proc = premultiply ? &swizzle_rgba16_to_bgra_premul :
1011cb93a386Sopenharmony_ci                                             &swizzle_rgba16_to_bgra_unpremul;
1012cb93a386Sopenharmony_ci                        break;
1013cb93a386Sopenharmony_ci                    }
1014cb93a386Sopenharmony_ci
1015cb93a386Sopenharmony_ci                    SkASSERT(8 == encodedInfo.bitsPerComponent());
1016cb93a386Sopenharmony_ci                    if (premultiply) {
1017cb93a386Sopenharmony_ci                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1018cb93a386Sopenharmony_ci                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_premul>;
1019cb93a386Sopenharmony_ci                            fastProc = &SkipLeading8888ZerosThen
1020cb93a386Sopenharmony_ci                                    <fast_swizzle_rgba_to_bgra_premul>;
1021cb93a386Sopenharmony_ci                        } else {
1022cb93a386Sopenharmony_ci                            proc = &swizzle_rgba_to_bgra_premul;
1023cb93a386Sopenharmony_ci                            fastProc = &fast_swizzle_rgba_to_bgra_premul;
1024cb93a386Sopenharmony_ci                        }
1025cb93a386Sopenharmony_ci                    } else {
1026cb93a386Sopenharmony_ci                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1027cb93a386Sopenharmony_ci                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_unpremul>;
1028cb93a386Sopenharmony_ci                            fastProc = &SkipLeading8888ZerosThen
1029cb93a386Sopenharmony_ci                                    <fast_swizzle_rgba_to_bgra_unpremul>;
1030cb93a386Sopenharmony_ci                        } else {
1031cb93a386Sopenharmony_ci                            proc = &swizzle_rgba_to_bgra_unpremul;
1032cb93a386Sopenharmony_ci                            fastProc = &fast_swizzle_rgba_to_bgra_unpremul;
1033cb93a386Sopenharmony_ci                        }
1034cb93a386Sopenharmony_ci                    }
1035cb93a386Sopenharmony_ci                    break;
1036cb93a386Sopenharmony_ci                default:
1037cb93a386Sopenharmony_ci                    return nullptr;
1038cb93a386Sopenharmony_ci            }
1039cb93a386Sopenharmony_ci            break;
1040cb93a386Sopenharmony_ci        case SkEncodedInfo::kBGR_Color:
1041cb93a386Sopenharmony_ci            switch (dstInfo.colorType()) {
1042cb93a386Sopenharmony_ci                case kBGRA_8888_SkColorType:
1043cb93a386Sopenharmony_ci                    proc = &swizzle_rgb_to_rgba;
1044cb93a386Sopenharmony_ci                    fastProc = &fast_swizzle_rgb_to_rgba;
1045cb93a386Sopenharmony_ci                    break;
1046cb93a386Sopenharmony_ci                case kRGBA_8888_SkColorType:
1047cb93a386Sopenharmony_ci                    proc = &swizzle_rgb_to_bgra;
1048cb93a386Sopenharmony_ci                    fastProc = &fast_swizzle_rgb_to_bgra;
1049cb93a386Sopenharmony_ci                    break;
1050cb93a386Sopenharmony_ci                case kRGB_565_SkColorType:
1051cb93a386Sopenharmony_ci                    proc = &swizzle_bgr_to_565;
1052cb93a386Sopenharmony_ci                    break;
1053cb93a386Sopenharmony_ci                default:
1054cb93a386Sopenharmony_ci                    return nullptr;
1055cb93a386Sopenharmony_ci            }
1056cb93a386Sopenharmony_ci            break;
1057cb93a386Sopenharmony_ci        case SkEncodedInfo::kBGRX_Color:
1058cb93a386Sopenharmony_ci            switch (dstInfo.colorType()) {
1059cb93a386Sopenharmony_ci                case kBGRA_8888_SkColorType:
1060cb93a386Sopenharmony_ci                    proc = &swizzle_rgb_to_rgba;
1061cb93a386Sopenharmony_ci                    break;
1062cb93a386Sopenharmony_ci                case kRGBA_8888_SkColorType:
1063cb93a386Sopenharmony_ci                    proc = &swizzle_rgb_to_bgra;
1064cb93a386Sopenharmony_ci                    break;
1065cb93a386Sopenharmony_ci                case kRGB_565_SkColorType:
1066cb93a386Sopenharmony_ci                    proc = &swizzle_bgr_to_565;
1067cb93a386Sopenharmony_ci                    break;
1068cb93a386Sopenharmony_ci                default:
1069cb93a386Sopenharmony_ci                    return nullptr;
1070cb93a386Sopenharmony_ci            }
1071cb93a386Sopenharmony_ci            break;
1072cb93a386Sopenharmony_ci        case SkEncodedInfo::kBGRA_Color:
1073cb93a386Sopenharmony_ci            switch (dstInfo.colorType()) {
1074cb93a386Sopenharmony_ci                case kBGRA_8888_SkColorType:
1075cb93a386Sopenharmony_ci                    if (premultiply) {
1076cb93a386Sopenharmony_ci                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1077cb93a386Sopenharmony_ci                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_rgba_premul>;
1078cb93a386Sopenharmony_ci                            fastProc = &SkipLeading8888ZerosThen
1079cb93a386Sopenharmony_ci                                    <fast_swizzle_rgba_to_rgba_premul>;
1080cb93a386Sopenharmony_ci                        } else {
1081cb93a386Sopenharmony_ci                            proc = &swizzle_rgba_to_rgba_premul;
1082cb93a386Sopenharmony_ci                            fastProc = &fast_swizzle_rgba_to_rgba_premul;
1083cb93a386Sopenharmony_ci                        }
1084cb93a386Sopenharmony_ci                    } else {
1085cb93a386Sopenharmony_ci                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1086cb93a386Sopenharmony_ci                            proc = &SkipLeading8888ZerosThen<sample4>;
1087cb93a386Sopenharmony_ci                            fastProc = &SkipLeading8888ZerosThen<copy>;
1088cb93a386Sopenharmony_ci                        } else {
1089cb93a386Sopenharmony_ci                            proc = &sample4;
1090cb93a386Sopenharmony_ci                            fastProc = &copy;
1091cb93a386Sopenharmony_ci                        }
1092cb93a386Sopenharmony_ci                    }
1093cb93a386Sopenharmony_ci                    break;
1094cb93a386Sopenharmony_ci                case kRGBA_8888_SkColorType:
1095cb93a386Sopenharmony_ci                    if (premultiply) {
1096cb93a386Sopenharmony_ci                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1097cb93a386Sopenharmony_ci                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_premul>;
1098cb93a386Sopenharmony_ci                            fastProc = &SkipLeading8888ZerosThen
1099cb93a386Sopenharmony_ci                                    <fast_swizzle_rgba_to_bgra_premul>;
1100cb93a386Sopenharmony_ci                        } else {
1101cb93a386Sopenharmony_ci                            proc = &swizzle_rgba_to_bgra_premul;
1102cb93a386Sopenharmony_ci                            fastProc = &fast_swizzle_rgba_to_bgra_premul;
1103cb93a386Sopenharmony_ci                        }
1104cb93a386Sopenharmony_ci                    } else {
1105cb93a386Sopenharmony_ci                        if (SkCodec::kYes_ZeroInitialized == zeroInit) {
1106cb93a386Sopenharmony_ci                            proc = &SkipLeading8888ZerosThen<swizzle_rgba_to_bgra_unpremul>;
1107cb93a386Sopenharmony_ci                            fastProc = &SkipLeading8888ZerosThen
1108cb93a386Sopenharmony_ci                                    <fast_swizzle_rgba_to_bgra_unpremul>;
1109cb93a386Sopenharmony_ci                        } else {
1110cb93a386Sopenharmony_ci                            proc = &swizzle_rgba_to_bgra_unpremul;
1111cb93a386Sopenharmony_ci                            fastProc = &fast_swizzle_rgba_to_bgra_unpremul;
1112cb93a386Sopenharmony_ci                        }
1113cb93a386Sopenharmony_ci                    }
1114cb93a386Sopenharmony_ci                    break;
1115cb93a386Sopenharmony_ci                default:
1116cb93a386Sopenharmony_ci                    return nullptr;
1117cb93a386Sopenharmony_ci            }
1118cb93a386Sopenharmony_ci            break;
1119cb93a386Sopenharmony_ci        case SkEncodedInfo::kInvertedCMYK_Color:
1120cb93a386Sopenharmony_ci            switch (dstInfo.colorType()) {
1121cb93a386Sopenharmony_ci                case kRGBA_8888_SkColorType:
1122cb93a386Sopenharmony_ci                    proc = &swizzle_cmyk_to_rgba;
1123cb93a386Sopenharmony_ci                    fastProc = &fast_swizzle_cmyk_to_rgba;
1124cb93a386Sopenharmony_ci                    break;
1125cb93a386Sopenharmony_ci                case kBGRA_8888_SkColorType:
1126cb93a386Sopenharmony_ci                    proc = &swizzle_cmyk_to_bgra;
1127cb93a386Sopenharmony_ci                    fastProc = &fast_swizzle_cmyk_to_bgra;
1128cb93a386Sopenharmony_ci                    break;
1129cb93a386Sopenharmony_ci                case kRGB_565_SkColorType:
1130cb93a386Sopenharmony_ci                    proc = &swizzle_cmyk_to_565;
1131cb93a386Sopenharmony_ci                    break;
1132cb93a386Sopenharmony_ci                default:
1133cb93a386Sopenharmony_ci                    return nullptr;
1134cb93a386Sopenharmony_ci            }
1135cb93a386Sopenharmony_ci            break;
1136cb93a386Sopenharmony_ci        default:
1137cb93a386Sopenharmony_ci            return nullptr;
1138cb93a386Sopenharmony_ci    }
1139cb93a386Sopenharmony_ci
1140cb93a386Sopenharmony_ci    // Store bpp in bytes if it is an even multiple, otherwise use bits
1141cb93a386Sopenharmony_ci    uint8_t bitsPerPixel = encodedInfo.bitsPerPixel();
1142cb93a386Sopenharmony_ci    int srcBPP = SkIsAlign8(bitsPerPixel) ? bitsPerPixel / 8 : bitsPerPixel;
1143cb93a386Sopenharmony_ci    int dstBPP = dstInfo.bytesPerPixel();
1144cb93a386Sopenharmony_ci    return Make(dstInfo, fastProc, proc, ctable, srcBPP, dstBPP, options, frame);
1145cb93a386Sopenharmony_ci}
1146cb93a386Sopenharmony_ci
1147cb93a386Sopenharmony_cistd::unique_ptr<SkSwizzler> SkSwizzler::Make(const SkImageInfo& dstInfo,
1148cb93a386Sopenharmony_ci        RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcBPP,
1149cb93a386Sopenharmony_ci        int dstBPP, const SkCodec::Options& options, const SkIRect* frame) {
1150cb93a386Sopenharmony_ci    int srcOffset = 0;
1151cb93a386Sopenharmony_ci    int srcWidth = dstInfo.width();
1152cb93a386Sopenharmony_ci    int dstOffset = 0;
1153cb93a386Sopenharmony_ci    int dstWidth = srcWidth;
1154cb93a386Sopenharmony_ci    if (options.fSubset) {
1155cb93a386Sopenharmony_ci        // We do not currently support subset decodes for image types that may have
1156cb93a386Sopenharmony_ci        // frames (gif).
1157cb93a386Sopenharmony_ci        SkASSERT(!frame);
1158cb93a386Sopenharmony_ci        srcOffset = options.fSubset->left();
1159cb93a386Sopenharmony_ci        srcWidth = options.fSubset->width();
1160cb93a386Sopenharmony_ci        dstWidth = srcWidth;
1161cb93a386Sopenharmony_ci    } else if (frame) {
1162cb93a386Sopenharmony_ci        dstOffset = frame->left();
1163cb93a386Sopenharmony_ci        srcWidth = frame->width();
1164cb93a386Sopenharmony_ci    }
1165cb93a386Sopenharmony_ci
1166cb93a386Sopenharmony_ci    return std::unique_ptr<SkSwizzler>(new SkSwizzler(fastProc, proc, ctable, srcOffset, srcWidth,
1167cb93a386Sopenharmony_ci                                                      dstOffset, dstWidth, srcBPP, dstBPP));
1168cb93a386Sopenharmony_ci}
1169cb93a386Sopenharmony_ci
1170cb93a386Sopenharmony_ciSkSwizzler::SkSwizzler(RowProc fastProc, RowProc proc, const SkPMColor* ctable, int srcOffset,
1171cb93a386Sopenharmony_ci        int srcWidth, int dstOffset, int dstWidth, int srcBPP, int dstBPP)
1172cb93a386Sopenharmony_ci    : fFastProc(fastProc)
1173cb93a386Sopenharmony_ci    , fSlowProc(proc)
1174cb93a386Sopenharmony_ci    , fActualProc(fFastProc ? fFastProc : fSlowProc)
1175cb93a386Sopenharmony_ci    , fColorTable(ctable)
1176cb93a386Sopenharmony_ci    , fSrcOffset(srcOffset)
1177cb93a386Sopenharmony_ci    , fDstOffset(dstOffset)
1178cb93a386Sopenharmony_ci    , fSrcOffsetUnits(srcOffset * srcBPP)
1179cb93a386Sopenharmony_ci    , fDstOffsetBytes(dstOffset * dstBPP)
1180cb93a386Sopenharmony_ci    , fSrcWidth(srcWidth)
1181cb93a386Sopenharmony_ci    , fDstWidth(dstWidth)
1182cb93a386Sopenharmony_ci    , fSwizzleWidth(srcWidth)
1183cb93a386Sopenharmony_ci    , fAllocatedWidth(dstWidth)
1184cb93a386Sopenharmony_ci    , fSampleX(1)
1185cb93a386Sopenharmony_ci    , fSrcBPP(srcBPP)
1186cb93a386Sopenharmony_ci    , fDstBPP(dstBPP)
1187cb93a386Sopenharmony_ci{}
1188cb93a386Sopenharmony_ci
1189cb93a386Sopenharmony_ciint SkSwizzler::onSetSampleX(int sampleX) {
1190cb93a386Sopenharmony_ci    SkASSERT(sampleX > 0);
1191cb93a386Sopenharmony_ci
1192cb93a386Sopenharmony_ci    fSampleX = sampleX;
1193cb93a386Sopenharmony_ci    fDstOffsetBytes = (fDstOffset / sampleX) * fDstBPP;
1194cb93a386Sopenharmony_ci    fSwizzleWidth = get_scaled_dimension(fSrcWidth, sampleX);
1195cb93a386Sopenharmony_ci    fAllocatedWidth = get_scaled_dimension(fDstWidth, sampleX);
1196cb93a386Sopenharmony_ci
1197cb93a386Sopenharmony_ci    int frameSampleX = sampleX;
1198cb93a386Sopenharmony_ci    if (fSrcWidth < fDstWidth) {
1199cb93a386Sopenharmony_ci        // Although SkSampledCodec adjusted sampleX so that it will never be
1200cb93a386Sopenharmony_ci        // larger than the width of the image (or subset, if applicable), it
1201cb93a386Sopenharmony_ci        // doesn't account for the width of a subset frame (i.e. gif). As a
1202cb93a386Sopenharmony_ci        // result, get_start_coord(sampleX) could result in fSrcOffsetUnits
1203cb93a386Sopenharmony_ci        // being wider than fSrcWidth. Compute a sampling rate based on the
1204cb93a386Sopenharmony_ci        // frame width to ensure that fSrcOffsetUnits is sensible.
1205cb93a386Sopenharmony_ci        frameSampleX = fSrcWidth / fSwizzleWidth;
1206cb93a386Sopenharmony_ci    }
1207cb93a386Sopenharmony_ci    fSrcOffsetUnits = (get_start_coord(frameSampleX) + fSrcOffset) * fSrcBPP;
1208cb93a386Sopenharmony_ci
1209cb93a386Sopenharmony_ci    if (fDstOffsetBytes > 0) {
1210cb93a386Sopenharmony_ci        const size_t dstSwizzleBytes   = fSwizzleWidth   * fDstBPP;
1211cb93a386Sopenharmony_ci        const size_t dstAllocatedBytes = fAllocatedWidth * fDstBPP;
1212cb93a386Sopenharmony_ci        if (fDstOffsetBytes + dstSwizzleBytes > dstAllocatedBytes) {
1213cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
1214cb93a386Sopenharmony_ci            SkAndroidFrameworkUtils::SafetyNetLog("118143775");
1215cb93a386Sopenharmony_ci#endif
1216cb93a386Sopenharmony_ci            SkASSERT(dstSwizzleBytes <= dstAllocatedBytes);
1217cb93a386Sopenharmony_ci            fDstOffsetBytes = dstAllocatedBytes - dstSwizzleBytes;
1218cb93a386Sopenharmony_ci        }
1219cb93a386Sopenharmony_ci    }
1220cb93a386Sopenharmony_ci
1221cb93a386Sopenharmony_ci    // The optimized swizzler functions do not support sampling.  Sampled swizzles
1222cb93a386Sopenharmony_ci    // are already fast because they skip pixels.  We haven't seen a situation
1223cb93a386Sopenharmony_ci    // where speeding up sampling has a significant impact on total decode time.
1224cb93a386Sopenharmony_ci    if (1 == fSampleX && fFastProc) {
1225cb93a386Sopenharmony_ci        fActualProc = fFastProc;
1226cb93a386Sopenharmony_ci    } else {
1227cb93a386Sopenharmony_ci        fActualProc = fSlowProc;
1228cb93a386Sopenharmony_ci    }
1229cb93a386Sopenharmony_ci
1230cb93a386Sopenharmony_ci    return fAllocatedWidth;
1231cb93a386Sopenharmony_ci}
1232cb93a386Sopenharmony_ci
1233cb93a386Sopenharmony_civoid SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
1234cb93a386Sopenharmony_ci    SkASSERT(nullptr != dst && nullptr != src);
1235cb93a386Sopenharmony_ci    fActualProc(SkTAddOffset<void>(dst, fDstOffsetBytes), src, fSwizzleWidth, fSrcBPP,
1236cb93a386Sopenharmony_ci            fSampleX * fSrcBPP, fSrcOffsetUnits, fColorTable);
1237cb93a386Sopenharmony_ci}
1238