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,uint32_t startX,uint32_t sampleX)12 static void swizzle_mask16_to_n32_opaque(
13         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
14         uint32_t startX, uint32_t sampleX) {
15 
16     // Use the masks to decode to the destination
17     uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
18     SkPMColor* dstPtr = (SkPMColor*) dstRow;
19     for (int i = 0; i < width; i++) {
20         uint16_t p = srcPtr[0];
21         uint8_t red = masks->getRed(p);
22         uint8_t green = masks->getGreen(p);
23         uint8_t blue = masks->getBlue(p);
24         dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
25         srcPtr += sampleX;
26     }
27 }
28 
swizzle_mask16_to_n32_unpremul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)29 static void swizzle_mask16_to_n32_unpremul(
30         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
31         uint32_t startX, uint32_t sampleX) {
32 
33     // Use the masks to decode to the destination
34     uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
35     SkPMColor* dstPtr = (SkPMColor*) dstRow;
36     for (int i = 0; i < width; i++) {
37         uint16_t p = srcPtr[0];
38         uint8_t red = masks->getRed(p);
39         uint8_t green = masks->getGreen(p);
40         uint8_t blue = masks->getBlue(p);
41         uint8_t alpha = masks->getAlpha(p);
42         dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
43         srcPtr += sampleX;
44     }
45 }
46 
swizzle_mask16_to_n32_premul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)47 static void swizzle_mask16_to_n32_premul(
48         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
49         uint32_t startX, uint32_t sampleX) {
50 
51     // Use the masks to decode to the destination
52     uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
53     SkPMColor* dstPtr = (SkPMColor*) dstRow;
54     for (int i = 0; i < width; i++) {
55         uint16_t p = srcPtr[0];
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         dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
61         srcPtr += sampleX;
62     }
63 }
64 
65 // TODO (msarett): We have promoted a two byte per pixel image to 8888, only to
66 // convert it back to 565. Instead, we should swizzle to 565 directly.
swizzle_mask16_to_565(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)67 static void swizzle_mask16_to_565(
68         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
69         uint32_t startX, uint32_t sampleX) {
70 
71     // Use the masks to decode to the destination
72     uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
73     uint16_t* dstPtr = (uint16_t*) dstRow;
74     for (int i = 0; i < width; i++) {
75         uint16_t p = srcPtr[0];
76         uint8_t red = masks->getRed(p);
77         uint8_t green = masks->getGreen(p);
78         uint8_t blue = masks->getBlue(p);
79         dstPtr[i] = SkPack888ToRGB16(red, green, blue);
80         srcPtr += sampleX;
81     }
82 }
83 
swizzle_mask24_to_n32_opaque(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)84 static void swizzle_mask24_to_n32_opaque(
85         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
86         uint32_t startX, uint32_t sampleX) {
87 
88     // Use the masks to decode to the destination
89     srcRow += 3 * startX;
90     SkPMColor* dstPtr = (SkPMColor*) dstRow;
91     for (int i = 0; i < width; i++) {
92         uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
93         uint8_t red = masks->getRed(p);
94         uint8_t green = masks->getGreen(p);
95         uint8_t blue = masks->getBlue(p);
96         dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
97         srcRow += 3 * sampleX;
98     }
99 }
100 
swizzle_mask24_to_n32_unpremul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)101 static void swizzle_mask24_to_n32_unpremul(
102         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
103         uint32_t startX, uint32_t sampleX) {
104 
105     // Use the masks to decode to the destination
106     srcRow += 3 * startX;
107     SkPMColor* dstPtr = (SkPMColor*) dstRow;
108     for (int i = 0; i < width; i++) {
109         uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
110         uint8_t red = masks->getRed(p);
111         uint8_t green = masks->getGreen(p);
112         uint8_t blue = masks->getBlue(p);
113         uint8_t alpha = masks->getAlpha(p);
114         dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
115         srcRow += 3 * sampleX;
116     }
117 }
118 
swizzle_mask24_to_n32_premul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)119 static void swizzle_mask24_to_n32_premul(
120         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
121         uint32_t startX, uint32_t sampleX) {
122 
123     // Use the masks to decode to the destination
124     srcRow += 3 * startX;
125     SkPMColor* dstPtr = (SkPMColor*) dstRow;
126     for (int i = 0; i < width; i++) {
127         uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
128         uint8_t red = masks->getRed(p);
129         uint8_t green = masks->getGreen(p);
130         uint8_t blue = masks->getBlue(p);
131         uint8_t alpha = masks->getAlpha(p);
132         dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
133         srcRow += 3 * sampleX;
134     }
135 }
136 
swizzle_mask24_to_565(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)137 static void swizzle_mask24_to_565(
138         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
139         uint32_t startX, uint32_t sampleX) {
140 
141     // Use the masks to decode to the destination
142     srcRow += 3 * startX;
143     uint16_t* dstPtr = (uint16_t*) dstRow;
144     for (int i = 0; i < width; i++) {
145         uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
146         uint8_t red = masks->getRed(p);
147         uint8_t green = masks->getGreen(p);
148         uint8_t blue = masks->getBlue(p);
149         dstPtr[i] = SkPack888ToRGB16(red, green, blue);
150         srcRow += 3 * sampleX;
151     }
152 }
153 
swizzle_mask32_to_n32_opaque(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)154 static void swizzle_mask32_to_n32_opaque(
155         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
156         uint32_t startX, uint32_t sampleX) {
157 
158     // Use the masks to decode to the destination
159     uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
160     SkPMColor* dstPtr = (SkPMColor*) dstRow;
161     for (int i = 0; i < width; i++) {
162         uint32_t p = srcPtr[0];
163         uint8_t red = masks->getRed(p);
164         uint8_t green = masks->getGreen(p);
165         uint8_t blue = masks->getBlue(p);
166         dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
167         srcPtr += sampleX;
168     }
169 }
170 
swizzle_mask32_to_n32_unpremul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)171 static void swizzle_mask32_to_n32_unpremul(
172         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
173         uint32_t startX, uint32_t sampleX) {
174 
175     // Use the masks to decode to the destination
176     uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
177     SkPMColor* dstPtr = (SkPMColor*) dstRow;
178     for (int i = 0; i < width; i++) {
179         uint32_t p = srcPtr[0];
180         uint8_t red = masks->getRed(p);
181         uint8_t green = masks->getGreen(p);
182         uint8_t blue = masks->getBlue(p);
183         uint8_t alpha = masks->getAlpha(p);
184         dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
185         srcPtr += sampleX;
186     }
187 }
188 
swizzle_mask32_to_n32_premul(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)189 static void swizzle_mask32_to_n32_premul(
190         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
191         uint32_t startX, uint32_t sampleX) {
192 
193     // Use the masks to decode to the destination
194     uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
195     SkPMColor* dstPtr = (SkPMColor*) dstRow;
196     for (int i = 0; i < width; i++) {
197         uint32_t p = srcPtr[0];
198         uint8_t red = masks->getRed(p);
199         uint8_t green = masks->getGreen(p);
200         uint8_t blue = masks->getBlue(p);
201         uint8_t alpha = masks->getAlpha(p);
202         dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
203         srcPtr += sampleX;
204     }
205 }
206 
swizzle_mask32_to_565(void * dstRow,const uint8_t * srcRow,int width,SkMasks * masks,uint32_t startX,uint32_t sampleX)207 static void swizzle_mask32_to_565(
208         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
209         uint32_t startX, uint32_t sampleX) {
210     // Use the masks to decode to the destination
211     uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
212     uint16_t* dstPtr = (uint16_t*) dstRow;
213     for (int i = 0; i < width; i++) {
214         uint32_t p = srcPtr[0];
215         uint8_t red = masks->getRed(p);
216         uint8_t green = masks->getGreen(p);
217         uint8_t blue = masks->getBlue(p);
218         dstPtr[i] = SkPack888ToRGB16(red, green, blue);
219         srcPtr += sampleX;
220     }
221 }
222 
223 /*
224  *
225  * Create a new mask swizzler
226  *
227  */
CreateMaskSwizzler(const SkImageInfo & dstInfo,const SkImageInfo & srcInfo,SkMasks * masks,uint32_t bitsPerPixel,const SkCodec::Options & options)228 SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(const SkImageInfo& dstInfo,
229         const SkImageInfo& srcInfo, SkMasks* masks, uint32_t bitsPerPixel,
230         const SkCodec::Options& options) {
231 
232     // Choose the appropriate row procedure
233     RowProc proc = nullptr;
234     switch (bitsPerPixel) {
235         case 16:
236             switch (dstInfo.colorType()) {
237                 case kN32_SkColorType:
238                     if (kOpaque_SkAlphaType == srcInfo.alphaType()) {
239                         proc = &swizzle_mask16_to_n32_opaque;
240                     } else {
241                         switch (dstInfo.alphaType()) {
242                             case kUnpremul_SkAlphaType:
243                                 proc = &swizzle_mask16_to_n32_unpremul;
244                                 break;
245                             case kPremul_SkAlphaType:
246                                 proc = &swizzle_mask16_to_n32_premul;
247                                 break;
248                             default:
249                                 break;
250                         }
251                     }
252                     break;
253                 case kRGB_565_SkColorType:
254                     proc = &swizzle_mask16_to_565;
255                     break;
256                 default:
257                     break;
258             }
259             break;
260         case 24:
261             switch (dstInfo.colorType()) {
262                 case kN32_SkColorType:
263                     if (kOpaque_SkAlphaType == srcInfo.alphaType()) {
264                         proc = &swizzle_mask24_to_n32_opaque;
265                     } else {
266                         switch (dstInfo.alphaType()) {
267                             case kUnpremul_SkAlphaType:
268                                 proc = &swizzle_mask24_to_n32_unpremul;
269                                 break;
270                             case kPremul_SkAlphaType:
271                                 proc = &swizzle_mask24_to_n32_premul;
272                                 break;
273                             default:
274                                 break;
275                         }
276                     }
277                     break;
278                 case kRGB_565_SkColorType:
279                     proc = &swizzle_mask24_to_565;
280                     break;
281                 default:
282                     break;
283             }
284             break;
285         case 32:
286             switch (dstInfo.colorType()) {
287                 case kN32_SkColorType:
288                     if (kOpaque_SkAlphaType == srcInfo.alphaType()) {
289                         proc = &swizzle_mask32_to_n32_opaque;
290                     } else {
291                         switch (dstInfo.alphaType()) {
292                             case kUnpremul_SkAlphaType:
293                                 proc = &swizzle_mask32_to_n32_unpremul;
294                                 break;
295                             case kPremul_SkAlphaType:
296                                 proc = &swizzle_mask32_to_n32_premul;
297                                 break;
298                             default:
299                                 break;
300                         }
301                     }
302                     break;
303                 case kRGB_565_SkColorType:
304                     proc = &swizzle_mask32_to_565;
305                     break;
306                 default:
307                     break;
308             }
309             break;
310         default:
311             SkASSERT(false);
312             return nullptr;
313     }
314 
315     int srcOffset = 0;
316     int srcWidth = dstInfo.width();
317     if (options.fSubset) {
318         srcOffset = options.fSubset->left();
319         srcWidth = options.fSubset->width();
320     }
321 
322     return new SkMaskSwizzler(masks, proc, srcOffset, srcWidth);
323 }
324 
325 /*
326  *
327  * Constructor for mask swizzler
328  *
329  */
SkMaskSwizzler(SkMasks * masks,RowProc proc,int srcOffset,int subsetWidth)330 SkMaskSwizzler::SkMaskSwizzler(SkMasks* masks, RowProc proc, int srcOffset, int subsetWidth)
331     : fMasks(masks)
332     , fRowProc(proc)
333     , fSubsetWidth(subsetWidth)
334     , fDstWidth(subsetWidth)
335     , fSampleX(1)
336     , fSrcOffset(srcOffset)
337     , fX0(srcOffset)
338 {}
339 
onSetSampleX(int sampleX)340 int SkMaskSwizzler::onSetSampleX(int sampleX) {
341     // FIXME: Share this function with SkSwizzler?
342     SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be
343                            // way to report failure?
344     fSampleX = sampleX;
345     fX0 = get_start_coord(sampleX) + fSrcOffset;
346     fDstWidth = get_scaled_dimension(fSubsetWidth, sampleX);
347 
348     // check that fX0 is valid
349     SkASSERT(fX0 >= 0);
350     return fDstWidth;
351 }
352 
353 /*
354  *
355  * Swizzle the specified row
356  *
357  */
swizzle(void * dst,const uint8_t * SK_RESTRICT src)358 void SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
359     SkASSERT(nullptr != dst && nullptr != src);
360     fRowProc(dst, src, fDstWidth, fMasks, fX0, fSampleX);
361 }
362