blob: 294229c37c6e914be706ee89cf605af06edafc25 [file] [log] [blame]
scroggof24f2242015-03-03 08:59:20 -08001/*
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
msarett74114382015-03-16 11:55:18 -07008#include "SkCodecPriv.h"
scroggof24f2242015-03-03 08:59:20 -08009#include "SkColorPriv.h"
10#include "SkSwizzler.h"
11#include "SkTemplates.h"
msarett438b2ad2015-04-09 12:43:10 -070012#include "SkUtils.h"
scroggof24f2242015-03-03 08:59:20 -080013
msarett74114382015-03-16 11:55:18 -070014SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha,
15 uint8_t maxAlpha) {
16 // In the transparent case, this returns 0x0000
17 // In the opaque case, this returns 0xFFFF
18 // If the row is neither transparent nor opaque, returns something else
19 return (((uint16_t) maxAlpha) << 8) | zeroAlpha;
msarett36758742015-03-16 08:27:53 -070020}
21
msarett74114382015-03-16 11:55:18 -070022// kIndex1, kIndex2, kIndex4
23
msarett438b2ad2015-04-09 12:43:10 -070024static SkSwizzler::ResultAlpha swizzle_small_index_to_index(
25 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
26 int bitsPerPixel, int y, const SkPMColor ctable[]) {
27
28 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
29 INIT_RESULT_ALPHA;
30 const uint32_t pixelsPerByte = 8 / bitsPerPixel;
31 const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte);
32 const uint8_t mask = (1 << bitsPerPixel) - 1;
33 int x = 0;
34 for (uint32_t byte = 0; byte < rowBytes; byte++) {
35 uint8_t pixelData = src[byte];
36 for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) {
37 uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask;
38 UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT);
39 dst[x] = index;
40 pixelData <<= bitsPerPixel;
41 x++;
42 }
43 }
44 return COMPUTE_RESULT_ALPHA;
45}
46
msarett74114382015-03-16 11:55:18 -070047static SkSwizzler::ResultAlpha swizzle_small_index_to_n32(
48 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
49 int bitsPerPixel, int y, const SkPMColor ctable[]) {
50
51 SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow;
52 INIT_RESULT_ALPHA;
53 const uint32_t pixelsPerByte = 8 / bitsPerPixel;
54 const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte);
55 const uint8_t mask = (1 << bitsPerPixel) - 1;
56 int x = 0;
57 for (uint32_t byte = 0; byte < rowBytes; byte++) {
58 uint8_t pixelData = src[byte];
59 for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) {
60 uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask;
61 SkPMColor c = ctable[index];
62 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
63 dst[x] = c;
64 pixelData <<= bitsPerPixel;
65 x++;
66 }
67 }
68 return COMPUTE_RESULT_ALPHA;
69}
70
msarette16b04a2015-04-15 07:32:19 -070071// kIndex
72
msarett438b2ad2015-04-09 12:43:10 -070073static SkSwizzler::ResultAlpha swizzle_index_to_index(
msaretteed039b2015-03-18 11:11:19 -070074 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
msarett438b2ad2015-04-09 12:43:10 -070075 int bytesPerPixel, int y, const SkPMColor ctable[]) {
msaretteed039b2015-03-18 11:11:19 -070076
msarett438b2ad2015-04-09 12:43:10 -070077 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow;
78 memcpy(dst, src, width);
79 // TODO (msarett): Should we skip the loop here and guess that the row is opaque/not opaque?
80 // SkScaledBitmap sampler just guesses that it is opaque. This is dangerous
81 // and probably wrong since gif and bmp (rarely) may have alpha.
82 INIT_RESULT_ALPHA;
83 for (int x = 0; x < width; x++) {
84 UPDATE_RESULT_ALPHA(ctable[src[x]] >> SK_A32_SHIFT);
msaretteed039b2015-03-18 11:11:19 -070085 }
msarett438b2ad2015-04-09 12:43:10 -070086 return COMPUTE_RESULT_ALPHA;
msaretteed039b2015-03-18 11:11:19 -070087}
88
msarett74114382015-03-16 11:55:18 -070089static SkSwizzler::ResultAlpha swizzle_index_to_n32(
90 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
91 int bytesPerPixel, int y, const SkPMColor ctable[]) {
msarett36758742015-03-16 08:27:53 -070092
93 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -070094 INIT_RESULT_ALPHA;
msarett36758742015-03-16 08:27:53 -070095 for (int x = 0; x < width; x++) {
msarett438b2ad2015-04-09 12:43:10 -070096 SkPMColor c = ctable[src[x]];
msarett74114382015-03-16 11:55:18 -070097 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
98 dst[x] = c;
msarett74114382015-03-16 11:55:18 -070099 }
100 return COMPUTE_RESULT_ALPHA;
101}
102
103static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ(
104 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
105 int bytesPerPixel, int y, const SkPMColor ctable[]) {
106
107 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
108 INIT_RESULT_ALPHA;
109 for (int x = 0; x < width; x++) {
msarett438b2ad2015-04-09 12:43:10 -0700110 SkPMColor c = ctable[src[x]];
msarett74114382015-03-16 11:55:18 -0700111 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
scroggof24f2242015-03-03 08:59:20 -0800112 if (c != 0) {
113 dst[x] = c;
114 }
scroggof24f2242015-03-03 08:59:20 -0800115 }
msarett74114382015-03-16 11:55:18 -0700116 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800117}
118
119#undef A32_MASK_IN_PLACE
120
msarette16b04a2015-04-15 07:32:19 -0700121// kGray
122
123static SkSwizzler::ResultAlpha swizzle_gray_to_n32(
124 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
125 int bytesPerPixel, int y, const SkPMColor ctable[]) {
126
127 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
128 for (int x = 0; x < width; x++) {
129 dst[x] = SkPackARGB32NoCheck(0xFF, src[x], src[x], src[x]);
130 }
131 return SkSwizzler::kOpaque_ResultAlpha;
132}
133
134static SkSwizzler::ResultAlpha swizzle_gray_to_gray(
135 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
136 int bytesPerPixel, int y, const SkPMColor ctable[]) {
137 memcpy(dstRow, src, width);
138 return SkSwizzler::kOpaque_ResultAlpha;
139}
140
141// kBGRX
142
msarett74114382015-03-16 11:55:18 -0700143static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32(
144 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
145 int bytesPerPixel, int y, const SkPMColor ctable[]) {
146
147 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
148 for (int x = 0; x < width; x++) {
149 dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]);
150 src += bytesPerPixel;
151 }
152 return SkSwizzler::kOpaque_ResultAlpha;
153}
154
155// kBGRA
156
msaretteed039b2015-03-18 11:11:19 -0700157static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_unpremul(
msarett74114382015-03-16 11:55:18 -0700158 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
159 int bytesPerPixel, int y, const SkPMColor ctable[]) {
160
161 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
162 INIT_RESULT_ALPHA;
163 for (int x = 0; x < width; x++) {
164 uint8_t alpha = src[3];
165 UPDATE_RESULT_ALPHA(alpha);
166 dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]);
167 src += bytesPerPixel;
168 }
169 return COMPUTE_RESULT_ALPHA;
170}
171
msaretteed039b2015-03-18 11:11:19 -0700172static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_premul(
173 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
174 int bytesPerPixel, int y, const SkPMColor ctable[]) {
175
176 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
177 INIT_RESULT_ALPHA;
178 for (int x = 0; x < width; x++) {
179 uint8_t alpha = src[3];
180 UPDATE_RESULT_ALPHA(alpha);
181 dst[x] = SkPreMultiplyARGB(alpha, src[2], src[1], src[0]);
182 src += bytesPerPixel;
183 }
184 return COMPUTE_RESULT_ALPHA;
185}
186
scroggof24f2242015-03-03 08:59:20 -0800187// n32
msarett74114382015-03-16 11:55:18 -0700188static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32(
189 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
190 int bytesPerPixel, int y, const SkPMColor ctable[]) {
191
scroggof24f2242015-03-03 08:59:20 -0800192 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
193 for (int x = 0; x < width; x++) {
194 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
msarett74114382015-03-16 11:55:18 -0700195 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800196 }
msarett74114382015-03-16 11:55:18 -0700197 return SkSwizzler::kOpaque_ResultAlpha;
scroggof24f2242015-03-03 08:59:20 -0800198}
199
msarett74114382015-03-16 11:55:18 -0700200static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul(
201 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
202 int bytesPerPixel, int y, const SkPMColor ctable[]) {
203
scroggof24f2242015-03-03 08:59:20 -0800204 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -0700205 INIT_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800206 for (int x = 0; x < width; x++) {
207 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700208 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800209 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
msarett74114382015-03-16 11:55:18 -0700210 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800211 }
msarett74114382015-03-16 11:55:18 -0700212 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800213}
214
msarett74114382015-03-16 11:55:18 -0700215static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_unpremul(
216 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
217 int bytesPerPixel, int y, const SkPMColor ctable[]) {
218
scroggof24f2242015-03-03 08:59:20 -0800219 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
msarett74114382015-03-16 11:55:18 -0700220 INIT_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800221 for (int x = 0; x < width; x++) {
222 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700223 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800224 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
msarett74114382015-03-16 11:55:18 -0700225 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800226 }
msarett74114382015-03-16 11:55:18 -0700227 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800228}
229
msarett74114382015-03-16 11:55:18 -0700230static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ(
231 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
232 int bytesPerPixel, int y, const SkPMColor ctable[]) {
233
scroggof24f2242015-03-03 08:59:20 -0800234 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
msarett74114382015-03-16 11:55:18 -0700235 INIT_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800236 for (int x = 0; x < width; x++) {
237 unsigned alpha = src[3];
msarett74114382015-03-16 11:55:18 -0700238 UPDATE_RESULT_ALPHA(alpha);
scroggof24f2242015-03-03 08:59:20 -0800239 if (0 != alpha) {
240 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
241 }
msarett74114382015-03-16 11:55:18 -0700242 src += bytesPerPixel;
scroggof24f2242015-03-03 08:59:20 -0800243 }
msarett74114382015-03-16 11:55:18 -0700244 return COMPUTE_RESULT_ALPHA;
scroggof24f2242015-03-03 08:59:20 -0800245}
246
247/**
248 FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes.
249 This would be fine for drawing normally, but not for drawing with transfer modes. Being
250 honest means we can draw correctly with transfer modes, with the cost of not being able
251 to take advantage of Android's free unwritten pages. Something to keep in mind when we
252 decide whether to switch to unpremul default.
253static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow,
254 const uint8_t* SK_RESTRICT src,
msarett74114382015-03-16 11:55:18 -0700255 int width, int bitsPerPixel,
scroggof24f2242015-03-03 08:59:20 -0800256 const SkPMColor[]) {
257 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
258 unsigned alphaMask = 0xFF;
259 for (int x = 0; x < width; x++) {
260 unsigned alpha = src[3];
261 // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible
262 // the color components are not zero, but we skip them anyway, meaning they'll remain
263 // zero (implied by the request to skip zeroes).
264 if (0 != alpha) {
265 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
266 }
267 src += deltaSrc;
268 alphaMask &= alpha;
269 }
270 return alphaMask != 0xFF;
271}
272*/
273
msarett74114382015-03-16 11:55:18 -0700274SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
275 const SkPMColor* ctable,
scroggof24f2242015-03-03 08:59:20 -0800276 const SkImageInfo& info, void* dst,
scroggo95526622015-03-17 05:02:17 -0700277 size_t dstRowBytes,
278 SkImageGenerator::ZeroInitialized zeroInit) {
scroggo05245902015-03-25 11:11:52 -0700279 if (info.colorType() == kUnknown_SkColorType || kUnknown == sc) {
scroggof24f2242015-03-03 08:59:20 -0800280 return NULL;
281 }
282 if (info.minRowBytes() > dstRowBytes) {
283 return NULL;
284 }
msarett74114382015-03-16 11:55:18 -0700285 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc)
286 && NULL == ctable) {
scroggof24f2242015-03-03 08:59:20 -0800287 return NULL;
288 }
289 RowProc proc = NULL;
290 switch (sc) {
msarett74114382015-03-16 11:55:18 -0700291 case kIndex1:
292 case kIndex2:
293 case kIndex4:
294 switch (info.colorType()) {
295 case kN32_SkColorType:
296 proc = &swizzle_small_index_to_n32;
297 break;
msarett438b2ad2015-04-09 12:43:10 -0700298 case kIndex_8_SkColorType:
299 proc = &swizzle_small_index_to_index;
msaretteed039b2015-03-18 11:11:19 -0700300 break;
msarett74114382015-03-16 11:55:18 -0700301 default:
302 break;
303 }
304 break;
scroggof24f2242015-03-03 08:59:20 -0800305 case kIndex:
306 switch (info.colorType()) {
307 case kN32_SkColorType:
scroggo95526622015-03-17 05:02:17 -0700308 // We assume the color premultiplied ctable (or not) as desired.
309 if (SkImageGenerator::kYes_ZeroInitialized == zeroInit) {
scroggof24f2242015-03-03 08:59:20 -0800310 proc = &swizzle_index_to_n32_skipZ;
msaretteed039b2015-03-18 11:11:19 -0700311 break;
scroggof24f2242015-03-03 08:59:20 -0800312 } else {
313 proc = &swizzle_index_to_n32;
msaretteed039b2015-03-18 11:11:19 -0700314 break;
scroggof24f2242015-03-03 08:59:20 -0800315 }
316 break;
msarett438b2ad2015-04-09 12:43:10 -0700317 case kIndex_8_SkColorType:
318 proc = &swizzle_index_to_index;
msaretteed039b2015-03-18 11:11:19 -0700319 break;
msarett74114382015-03-16 11:55:18 -0700320 default:
321 break;
322 }
323 break;
msarette16b04a2015-04-15 07:32:19 -0700324 case kGray:
325 switch (info.colorType()) {
326 case kN32_SkColorType:
327 proc = &swizzle_gray_to_n32;
328 break;
329 case kGray_8_SkColorType:
330 proc = &swizzle_gray_to_gray;
331 default:
332 break;
333 }
334 break;
msarett74114382015-03-16 11:55:18 -0700335 case kBGR:
336 case kBGRX:
337 switch (info.colorType()) {
338 case kN32_SkColorType:
339 proc = &swizzle_bgrx_to_n32;
340 break;
341 default:
342 break;
343 }
344 break;
345 case kBGRA:
346 switch (info.colorType()) {
347 case kN32_SkColorType:
msaretteed039b2015-03-18 11:11:19 -0700348 switch (info.alphaType()) {
349 case kUnpremul_SkAlphaType:
350 proc = &swizzle_bgra_to_n32_unpremul;
351 break;
352 case kPremul_SkAlphaType:
353 proc = &swizzle_bgra_to_n32_premul;
354 break;
355 default:
356 break;
357 }
msarett74114382015-03-16 11:55:18 -0700358 break;
scroggof24f2242015-03-03 08:59:20 -0800359 default:
360 break;
361 }
362 break;
363 case kRGBX:
364 // TODO: Support other swizzles.
365 switch (info.colorType()) {
366 case kN32_SkColorType:
367 proc = &swizzle_rgbx_to_n32;
368 break;
369 default:
370 break;
371 }
372 break;
373 case kRGBA:
374 switch (info.colorType()) {
375 case kN32_SkColorType:
376 if (info.alphaType() == kUnpremul_SkAlphaType) {
scroggo95526622015-03-17 05:02:17 -0700377 // Respect zeroInit?
scroggof24f2242015-03-03 08:59:20 -0800378 proc = &swizzle_rgba_to_n32_unpremul;
379 } else {
scroggo95526622015-03-17 05:02:17 -0700380 if (SkImageGenerator::kYes_ZeroInitialized == zeroInit) {
scroggof24f2242015-03-03 08:59:20 -0800381 proc = &swizzle_rgba_to_n32_premul_skipZ;
382 } else {
383 proc = &swizzle_rgba_to_n32_premul;
384 }
385 }
386 break;
387 default:
388 break;
389 }
390 break;
msarett74114382015-03-16 11:55:18 -0700391 case kRGB:
392 switch (info.colorType()) {
393 case kN32_SkColorType:
394 proc = &swizzle_rgbx_to_n32;
395 break;
396 default:
397 break;
398 }
399 break;
scroggof24f2242015-03-03 08:59:20 -0800400 default:
401 break;
402 }
403 if (NULL == proc) {
404 return NULL;
405 }
msarett74114382015-03-16 11:55:18 -0700406
407 // Store deltaSrc in bytes if it is an even multiple, otherwise use bits
408 int deltaSrc = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) :
409 BitsPerPixel(sc);
410 return SkNEW_ARGS(SkSwizzler, (proc, ctable, deltaSrc, info, dst,
411 dstRowBytes));
scroggof24f2242015-03-03 08:59:20 -0800412}
413
msarett74114382015-03-16 11:55:18 -0700414SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable,
415 int deltaSrc, const SkImageInfo& info, void* dst,
416 size_t rowBytes)
scroggof24f2242015-03-03 08:59:20 -0800417 : fRowProc(proc)
418 , fColorTable(ctable)
msarett74114382015-03-16 11:55:18 -0700419 , fDeltaSrc(deltaSrc)
scroggof24f2242015-03-03 08:59:20 -0800420 , fDstInfo(info)
421 , fDstRow(dst)
422 , fDstRowBytes(rowBytes)
423 , fCurrY(0)
424{
msarett74114382015-03-16 11:55:18 -0700425 SkDEBUGCODE(fNextMode = kUninitialized_NextMode);
scroggof24f2242015-03-03 08:59:20 -0800426}
427
msarett74114382015-03-16 11:55:18 -0700428SkSwizzler::ResultAlpha SkSwizzler::next(const uint8_t* SK_RESTRICT src) {
429 SkASSERT(0 <= fCurrY && fCurrY < fDstInfo.height());
scroggo05245902015-03-25 11:11:52 -0700430 SkASSERT(fDstRow != NULL);
msarett74114382015-03-16 11:55:18 -0700431 SkASSERT(kDesignateRow_NextMode != fNextMode);
432 SkDEBUGCODE(fNextMode = kConsecutive_NextMode);
433
434 // Decode a row
435 const ResultAlpha result = fRowProc(fDstRow, src, fDstInfo.width(),
436 fDeltaSrc, fCurrY, fColorTable);
437
438 // Move to the next row and return the result
scroggo05245902015-03-25 11:11:52 -0700439 fCurrY++;
scroggof24f2242015-03-03 08:59:20 -0800440 fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes);
msarett74114382015-03-16 11:55:18 -0700441 return result;
442}
443
444SkSwizzler::ResultAlpha SkSwizzler::next(const uint8_t* SK_RESTRICT src,
445 int y) {
446 SkASSERT(0 <= y && y < fDstInfo.height());
447 SkASSERT(kConsecutive_NextMode != fNextMode);
448 SkDEBUGCODE(fNextMode = kDesignateRow_NextMode);
449
450 // Choose the row
451 void* row = SkTAddOffset<void>(fDstRow, y*fDstRowBytes);
452
453 // Decode the row
454 return fRowProc(row, src, fDstInfo.width(), fDeltaSrc, fCurrY,
455 fColorTable);
scroggof24f2242015-03-03 08:59:20 -0800456}
msarett438b2ad2015-04-09 12:43:10 -0700457
msarett3c309db2015-04-10 14:36:48 -0700458void SkSwizzler::Fill(void* dstStartRow, const SkImageInfo& dstInfo, size_t dstRowBytes,
459 uint32_t numRows, uint32_t colorOrIndex, const SkPMColor* colorTable) {
460 SkASSERT(dstStartRow != NULL);
461 SkASSERT(numRows <= (uint32_t) dstInfo.height());
msarett438b2ad2015-04-09 12:43:10 -0700462
msarett3c309db2015-04-10 14:36:48 -0700463 // Calculate bytes to fill. We use getSafeSize since the last row may not be padded.
464 const size_t bytesToFill = dstInfo.makeWH(dstInfo.width(), numRows).getSafeSize(dstRowBytes);
msarett438b2ad2015-04-09 12:43:10 -0700465
466 // Use the proper memset routine to fill the remaining bytes
467 switch(dstInfo.colorType()) {
468 case kN32_SkColorType:
469 // Assume input is an index if we have a color table
470 uint32_t color;
471 if (NULL != colorTable) {
472 SkASSERT(colorOrIndex == (uint8_t) colorOrIndex);
473 color = colorTable[colorOrIndex];
474 // Otherwise, assume the input is a color
475 } else {
476 color = colorOrIndex;
477 }
478
479 // We must fill row by row in the case of unaligned row bytes
msarett3c309db2015-04-10 14:36:48 -0700480 if (SkIsAlign4((size_t) dstStartRow) && SkIsAlign4(dstRowBytes)) {
481 sk_memset32((uint32_t*) dstStartRow, color,
482 (uint32_t) bytesToFill / sizeof(SkPMColor));
msarett438b2ad2015-04-09 12:43:10 -0700483 } else {
484 // This is an unlikely, slow case
485 SkCodecPrintf("Warning: Strange number of row bytes, fill will be slow.\n");
msarett3c309db2015-04-10 14:36:48 -0700486 uint32_t* dstRow = (uint32_t*) dstStartRow;
487 for (uint32_t row = 0; row < numRows; row++) {
msarett438b2ad2015-04-09 12:43:10 -0700488 for (int32_t col = 0; col < dstInfo.width(); col++) {
msarett3c309db2015-04-10 14:36:48 -0700489 dstRow[col] = color;
msarett438b2ad2015-04-09 12:43:10 -0700490 }
msarett3c309db2015-04-10 14:36:48 -0700491 dstRow = SkTAddOffset<uint32_t>(dstRow, dstRowBytes);
msarett438b2ad2015-04-09 12:43:10 -0700492 }
493 }
494 break;
495 // On an index destination color type, always assume the input is an index
496 case kIndex_8_SkColorType:
497 SkASSERT(colorOrIndex == (uint8_t) colorOrIndex);
msarett3c309db2015-04-10 14:36:48 -0700498 memset(dstStartRow, colorOrIndex, bytesToFill);
msarett438b2ad2015-04-09 12:43:10 -0700499 break;
msarette16b04a2015-04-15 07:32:19 -0700500 case kGray_8_SkColorType:
501 // If the destination is kGray, the caller passes in an 8-bit color.
502 // We will not assert that the high bits of colorOrIndex must be zeroed.
503 // This allows us to take advantage of the fact that the low 8 bits of an
504 // SKPMColor may be a valid a grayscale color. For example, the low 8
505 // bits of SK_ColorBLACK are identical to the grayscale representation
506 // for black.
507 memset(dstStartRow, (uint8_t) colorOrIndex, bytesToFill);
508 break;
msarett438b2ad2015-04-09 12:43:10 -0700509 default:
510 SkCodecPrintf("Error: Unsupported dst color type for fill(). Doing nothing.\n");
511 SkASSERT(false);
512 break;
513 }
514}