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