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