• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkSwizzler.h"
11 #include "SkTemplates.h"
12 #include "SkUtils.h"
13 
GetResult(uint8_t zeroAlpha,uint8_t maxAlpha)14 SkSwizzler::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;
20 }
21 
22 // kIndex1, kIndex2, kIndex4
23 
swizzle_small_index_to_index(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bitsPerPixel,int y,const SkPMColor ctable[])24 static 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 
swizzle_small_index_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bitsPerPixel,int y,const SkPMColor ctable[])47 static 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 
71 // kIndex
72 
swizzle_index_to_index(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])73 static SkSwizzler::ResultAlpha swizzle_index_to_index(
74         void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width,
75         int bytesPerPixel, int y, const SkPMColor ctable[]) {
76 
77     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);
85     }
86     return COMPUTE_RESULT_ALPHA;
87 }
88 
swizzle_index_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])89 static 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[]) {
92 
93     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
94     INIT_RESULT_ALPHA;
95     for (int x = 0; x < width; x++) {
96         SkPMColor c = ctable[src[x]];
97         UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
98         dst[x] = c;
99     }
100     return COMPUTE_RESULT_ALPHA;
101 }
102 
swizzle_index_to_n32_skipZ(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])103 static 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++) {
110         SkPMColor c = ctable[src[x]];
111         UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT);
112         if (c != 0) {
113             dst[x] = c;
114         }
115     }
116     return COMPUTE_RESULT_ALPHA;
117 }
118 
119 #undef A32_MASK_IN_PLACE
120 
121 // kGray
122 
swizzle_gray_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])123 static 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 
swizzle_gray_to_gray(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])134 static 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 
swizzle_bgrx_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])143 static 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 
swizzle_bgra_to_n32_unpremul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])157 static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_unpremul(
158         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 
swizzle_bgra_to_n32_premul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])172 static 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 
187 // n32
swizzle_rgbx_to_n32(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])188 static 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 
192     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]);
195         src += bytesPerPixel;
196     }
197     return SkSwizzler::kOpaque_ResultAlpha;
198 }
199 
swizzle_rgba_to_n32_premul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])200 static 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 
204     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
205     INIT_RESULT_ALPHA;
206     for (int x = 0; x < width; x++) {
207         unsigned alpha = src[3];
208         UPDATE_RESULT_ALPHA(alpha);
209         dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
210         src += bytesPerPixel;
211     }
212     return COMPUTE_RESULT_ALPHA;
213 }
214 
swizzle_rgba_to_n32_unpremul(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])215 static 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 
219     uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
220     INIT_RESULT_ALPHA;
221     for (int x = 0; x < width; x++) {
222         unsigned alpha = src[3];
223         UPDATE_RESULT_ALPHA(alpha);
224         dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
225         src += bytesPerPixel;
226     }
227     return COMPUTE_RESULT_ALPHA;
228 }
229 
swizzle_rgba_to_n32_premul_skipZ(void * SK_RESTRICT dstRow,const uint8_t * SK_RESTRICT src,int width,int bytesPerPixel,int y,const SkPMColor ctable[])230 static 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 
234     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
235     INIT_RESULT_ALPHA;
236     for (int x = 0; x < width; x++) {
237         unsigned alpha = src[3];
238         UPDATE_RESULT_ALPHA(alpha);
239         if (0 != alpha) {
240             dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
241         }
242         src += bytesPerPixel;
243     }
244     return COMPUTE_RESULT_ALPHA;
245 }
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.
253 static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow,
254                                                const uint8_t* SK_RESTRICT src,
255                                                int width, int bitsPerPixel,
256                                                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 
CreateSwizzler(SkSwizzler::SrcConfig sc,const SkPMColor * ctable,const SkImageInfo & info,void * dst,size_t dstRowBytes,SkImageGenerator::ZeroInitialized zeroInit)274 SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc,
275                                        const SkPMColor* ctable,
276                                        const SkImageInfo& info, void* dst,
277                                        size_t dstRowBytes,
278                                        SkImageGenerator::ZeroInitialized zeroInit) {
279     if (info.colorType() == kUnknown_SkColorType || kUnknown == sc) {
280         return NULL;
281     }
282     if (info.minRowBytes() > dstRowBytes) {
283         return  NULL;
284     }
285     if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc)
286             && NULL == ctable) {
287         return NULL;
288     }
289     RowProc proc = NULL;
290     switch (sc) {
291         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;
298                 case kIndex_8_SkColorType:
299                     proc = &swizzle_small_index_to_index;
300                     break;
301                 default:
302                     break;
303             }
304             break;
305         case kIndex:
306             switch (info.colorType()) {
307                 case kN32_SkColorType:
308                     // We assume the color premultiplied ctable (or not) as desired.
309                     if (SkImageGenerator::kYes_ZeroInitialized == zeroInit) {
310                         proc = &swizzle_index_to_n32_skipZ;
311                         break;
312                     } else {
313                         proc = &swizzle_index_to_n32;
314                         break;
315                     }
316                     break;
317                 case kIndex_8_SkColorType:
318                     proc = &swizzle_index_to_index;
319                     break;
320                 default:
321                     break;
322             }
323             break;
324         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;
335         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:
348                     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                     }
358                     break;
359                 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) {
377                         // Respect zeroInit?
378                         proc = &swizzle_rgba_to_n32_unpremul;
379                     } else {
380                         if (SkImageGenerator::kYes_ZeroInitialized == zeroInit) {
381                             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;
391         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;
400         default:
401             break;
402     }
403     if (NULL == proc) {
404         return NULL;
405     }
406 
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));
412 }
413 
SkSwizzler(RowProc proc,const SkPMColor * ctable,int deltaSrc,const SkImageInfo & info,void * dst,size_t rowBytes)414 SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable,
415                        int deltaSrc, const SkImageInfo& info, void* dst,
416                        size_t rowBytes)
417     : fRowProc(proc)
418     , fColorTable(ctable)
419     , fDeltaSrc(deltaSrc)
420     , fDstInfo(info)
421     , fDstRow(dst)
422     , fDstRowBytes(rowBytes)
423     , fCurrY(0)
424 {
425     SkDEBUGCODE(fNextMode = kUninitialized_NextMode);
426 }
427 
next(const uint8_t * SK_RESTRICT src)428 SkSwizzler::ResultAlpha SkSwizzler::next(const uint8_t* SK_RESTRICT src) {
429     SkASSERT(0 <= fCurrY && fCurrY < fDstInfo.height());
430     SkASSERT(fDstRow != NULL);
431     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
439     fCurrY++;
440     fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes);
441     return result;
442 }
443 
next(const uint8_t * SK_RESTRICT src,int y)444 SkSwizzler::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);
456 }
457 
Fill(void * dstStartRow,const SkImageInfo & dstInfo,size_t dstRowBytes,uint32_t numRows,uint32_t colorOrIndex,const SkPMColor * colorTable)458 void 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());
462 
463     // 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);
465 
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
480             if (SkIsAlign4((size_t) dstStartRow) && SkIsAlign4(dstRowBytes)) {
481                 sk_memset32((uint32_t*) dstStartRow, color,
482                         (uint32_t) bytesToFill / sizeof(SkPMColor));
483             } else {
484                 // This is an unlikely, slow case
485                 SkCodecPrintf("Warning: Strange number of row bytes, fill will be slow.\n");
486                 uint32_t* dstRow = (uint32_t*) dstStartRow;
487                 for (uint32_t row = 0; row < numRows; row++) {
488                     for (int32_t col = 0; col < dstInfo.width(); col++) {
489                         dstRow[col] = color;
490                     }
491                     dstRow = SkTAddOffset<uint32_t>(dstRow, dstRowBytes);
492                 }
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);
498             memset(dstStartRow, colorOrIndex, bytesToFill);
499             break;
500         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;
509         default:
510             SkCodecPrintf("Error: Unsupported dst color type for fill().  Doing nothing.\n");
511             SkASSERT(false);
512             break;
513     }
514 }
515