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 "SkMaskSwizzler.h"
11 
swizzle_mask16_to_n32_opaque(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks)12 static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_opaque(
13         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
14 
15     // Use the masks to decode to the destination
16     uint16_t* srcPtr = (uint16_t*) srcRow;
17     SkPMColor* dstPtr = (SkPMColor*) dstRow;
18     for (int i = 0; i < width; i++) {
19         uint16_t p = srcPtr[i];
20         uint8_t red = masks->getRed(p);
21         uint8_t green = masks->getGreen(p);
22         uint8_t blue = masks->getBlue(p);
23         dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
24     }
25     return SkSwizzler::kOpaque_ResultAlpha;
26 }
27 
swizzle_mask16_to_n32_unpremul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks)28 static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_unpremul(
29         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
30 
31     // Use the masks to decode to the destination
32     uint16_t* srcPtr = (uint16_t*) srcRow;
33     SkPMColor* dstPtr = (SkPMColor*) dstRow;
34     INIT_RESULT_ALPHA;
35     for (int i = 0; i < width; i++) {
36         uint16_t p = srcPtr[i];
37         uint8_t red = masks->getRed(p);
38         uint8_t green = masks->getGreen(p);
39         uint8_t blue = masks->getBlue(p);
40         uint8_t alpha = masks->getAlpha(p);
41         UPDATE_RESULT_ALPHA(alpha);
42         dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
43     }
44     return COMPUTE_RESULT_ALPHA;
45 }
46 
swizzle_mask16_to_n32_premul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks)47 static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_premul(
48         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
49 
50     // Use the masks to decode to the destination
51     uint16_t* srcPtr = (uint16_t*) srcRow;
52     SkPMColor* dstPtr = (SkPMColor*) dstRow;
53     INIT_RESULT_ALPHA;
54     for (int i = 0; i < width; i++) {
55         uint16_t p = srcPtr[i];
56         uint8_t red = masks->getRed(p);
57         uint8_t green = masks->getGreen(p);
58         uint8_t blue = masks->getBlue(p);
59         uint8_t alpha = masks->getAlpha(p);
60         UPDATE_RESULT_ALPHA(alpha);
61         dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
62     }
63     return COMPUTE_RESULT_ALPHA;
64 }
65 
swizzle_mask24_to_n32_opaque(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks)66 static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_opaque(
67         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
68 
69     // Use the masks to decode to the destination
70     SkPMColor* dstPtr = (SkPMColor*) dstRow;
71     for (int i = 0; i < 3*width; i += 3) {
72         uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
73         uint8_t red = masks->getRed(p);
74         uint8_t green = masks->getGreen(p);
75         uint8_t blue = masks->getBlue(p);
76         dstPtr[i/3] = SkPackARGB32NoCheck(0xFF, red, green, blue);
77     }
78     return SkSwizzler::kOpaque_ResultAlpha;
79 }
80 
swizzle_mask24_to_n32_unpremul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks)81 static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_unpremul(
82         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
83 
84     // Use the masks to decode to the destination
85     SkPMColor* dstPtr = (SkPMColor*) dstRow;
86     INIT_RESULT_ALPHA;
87     for (int i = 0; i < 3*width; i += 3) {
88         uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
89         uint8_t red = masks->getRed(p);
90         uint8_t green = masks->getGreen(p);
91         uint8_t blue = masks->getBlue(p);
92         uint8_t alpha = masks->getAlpha(p);
93         UPDATE_RESULT_ALPHA(alpha);
94         dstPtr[i/3] = SkPackARGB32NoCheck(alpha, red, green, blue);
95     }
96     return COMPUTE_RESULT_ALPHA;
97 }
98 
swizzle_mask24_to_n32_premul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks)99 static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul(
100         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
101 
102     // Use the masks to decode to the destination
103     SkPMColor* dstPtr = (SkPMColor*) dstRow;
104     INIT_RESULT_ALPHA;
105     for (int i = 0; i < 3*width; i += 3) {
106         uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
107         uint8_t red = masks->getRed(p);
108         uint8_t green = masks->getGreen(p);
109         uint8_t blue = masks->getBlue(p);
110         uint8_t alpha = masks->getAlpha(p);
111         UPDATE_RESULT_ALPHA(alpha);
112         dstPtr[i/3] = SkPreMultiplyARGB(alpha, red, green, blue);
113     }
114     return COMPUTE_RESULT_ALPHA;
115 }
116 
swizzle_mask32_to_n32_opaque(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks)117 static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque(
118         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
119 
120     // Use the masks to decode to the destination
121     uint32_t* srcPtr = (uint32_t*) srcRow;
122     SkPMColor* dstPtr = (SkPMColor*) dstRow;
123     for (int i = 0; i < width; i++) {
124         uint32_t p = srcPtr[i];
125         uint8_t red = masks->getRed(p);
126         uint8_t green = masks->getGreen(p);
127         uint8_t blue = masks->getBlue(p);
128         dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
129     }
130     return SkSwizzler::kOpaque_ResultAlpha;
131 }
132 
swizzle_mask32_to_n32_unpremul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks)133 static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul(
134         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
135 
136     // Use the masks to decode to the destination
137     uint32_t* srcPtr = (uint32_t*) srcRow;
138     SkPMColor* dstPtr = (SkPMColor*) dstRow;
139     INIT_RESULT_ALPHA;
140     for (int i = 0; i < width; i++) {
141         uint32_t p = srcPtr[i];
142         uint8_t red = masks->getRed(p);
143         uint8_t green = masks->getGreen(p);
144         uint8_t blue = masks->getBlue(p);
145         uint8_t alpha = masks->getAlpha(p);
146         UPDATE_RESULT_ALPHA(alpha);
147         dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
148     }
149     return COMPUTE_RESULT_ALPHA;
150 }
151 
swizzle_mask32_to_n32_premul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks)152 static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul(
153         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
154 
155     // Use the masks to decode to the destination
156     uint32_t* srcPtr = (uint32_t*) srcRow;
157     SkPMColor* dstPtr = (SkPMColor*) dstRow;
158     INIT_RESULT_ALPHA;
159     for (int i = 0; i < width; i++) {
160         uint32_t p = srcPtr[i];
161         uint8_t red = masks->getRed(p);
162         uint8_t green = masks->getGreen(p);
163         uint8_t blue = masks->getBlue(p);
164         uint8_t alpha = masks->getAlpha(p);
165         UPDATE_RESULT_ALPHA(alpha);
166         dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
167     }
168     return COMPUTE_RESULT_ALPHA;
169 }
170 
171 /*
172  *
173  * Create a new mask swizzler
174  *
175  */
CreateMaskSwizzler(const SkImageInfo & info,void * dst,size_t dstRowBytes,SkMasks * masks,uint32_t bitsPerPixel)176 SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(
177         const SkImageInfo& info, void* dst, size_t dstRowBytes, SkMasks* masks,
178         uint32_t bitsPerPixel) {
179 
180     // Choose the appropriate row procedure
181     RowProc proc = NULL;
182     switch (bitsPerPixel) {
183         case 16:
184             switch (info.colorType()) {
185                 case kN32_SkColorType:
186                     switch (info.alphaType()) {
187                         case kUnpremul_SkAlphaType:
188                             proc = &swizzle_mask16_to_n32_unpremul;
189                             break;
190                         case kPremul_SkAlphaType:
191                             proc = &swizzle_mask16_to_n32_premul;
192                             break;
193                         case kOpaque_SkAlphaType:
194                             proc = &swizzle_mask16_to_n32_opaque;
195                             break;
196                         default:
197                             break;
198                     }
199                     break;
200                 default:
201                     break;
202             }
203             break;
204         case 24:
205             switch (info.colorType()) {
206                 case kN32_SkColorType:
207                     switch (info.alphaType()) {
208                         case kUnpremul_SkAlphaType:
209                             proc = &swizzle_mask24_to_n32_unpremul;
210                             break;
211                         case kPremul_SkAlphaType:
212                             proc = &swizzle_mask24_to_n32_premul;
213                             break;
214                         case kOpaque_SkAlphaType:
215                             proc = &swizzle_mask24_to_n32_opaque;
216                             break;
217                         default:
218                             break;
219                     }
220                     break;
221                 default:
222                     break;
223             }
224             break;
225         case 32:
226             switch (info.colorType()) {
227                 case kN32_SkColorType:
228                     switch (info.alphaType()) {
229                         case kUnpremul_SkAlphaType:
230                             proc = &swizzle_mask32_to_n32_unpremul;
231                             break;
232                         case kPremul_SkAlphaType:
233                             proc = &swizzle_mask32_to_n32_premul;
234                             break;
235                         case kOpaque_SkAlphaType:
236                             proc = &swizzle_mask32_to_n32_opaque;
237                             break;
238                         default:
239                             break;
240                     }
241                     break;
242                 default:
243                     break;
244             }
245             break;
246         default:
247             SkASSERT(false);
248             return NULL;
249     }
250     return SkNEW_ARGS(SkMaskSwizzler, (info, dst, dstRowBytes, masks, proc));
251 }
252 
253 /*
254  *
255  * Constructor for mask swizzler
256  *
257  */
SkMaskSwizzler(const SkImageInfo & dstInfo,void * dst,size_t dstRowBytes,SkMasks * masks,RowProc proc)258 SkMaskSwizzler::SkMaskSwizzler(const SkImageInfo& dstInfo, void* dst,
259                                size_t dstRowBytes, SkMasks* masks, RowProc proc)
260     : fDstInfo(dstInfo)
261     , fDst(dst)
262     , fDstRowBytes(dstRowBytes)
263     , fMasks(masks)
264     , fRowProc(proc)
265 {}
266 
267 /*
268  *
269  * Swizzle the specified row
270  *
271  */
next(const uint8_t * SK_RESTRICT src,int y)272 SkSwizzler::ResultAlpha SkMaskSwizzler::next(const uint8_t* SK_RESTRICT src,
273         int y) {
274     // Choose the row
275     void* row = SkTAddOffset<void>(fDst, y*fDstRowBytes);
276 
277     // Decode the row
278     return fRowProc(row, src, fDstInfo.width(), fMasks);
279 }
280