blob: 5d70dd38c24677df8dcae906cba6fc9274ff453d [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* Copyright 2006, The Android Open Source Project
2**
3** Licensed under the Apache License, Version 2.0 (the "License");
4** you may not use this file except in compliance with the License.
5** You may obtain a copy of the License at
6**
7** http://www.apache.org/licenses/LICENSE-2.0
8**
9** Unless required by applicable law or agreed to in writing, software
10** distributed under the License is distributed on an "AS IS" BASIS,
11** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12** See the License for the specific language governing permissions and
13** limitations under the License.
14*/
15
16#if 0
17
18#include "SkBitmapShader.h"
19#include "SkBitmapSampler.h"
20
21#ifdef SK_SUPPORT_MIPMAP
22static SkFixed find_mip_level(SkFixed dx, SkFixed dy)
23{
24 dx = SkAbs32(dx);
25 dy = SkAbs32(dy);
26 if (dx < dy)
27 dx = dy;
28
29 if (dx < SK_Fixed1)
30 return 0;
31
32 int clz = SkCLZ(dx);
33 SkASSERT(clz >= 1 && clz <= 15);
34 return SkIntToFixed(15 - clz) + ((unsigned)(dx << (clz + 1)) >> 16);
35}
36#endif
37
38SkBitmapShader::SkBitmapShader(const SkBitmap& src, bool doFilter,
39 TileMode tmx, TileMode tmy)
40 :
41#ifdef SK_SUPPORT_MIPMAP
42 fMipLevel(0), fMipSrcBitmap(src),
43#endif
44 fOrigSrcBitmap(src)
45
46{
47 fFilterBitmap = doFilter;
48 fTileModeX = SkToU8(tmx);
49 fTileModeY = SkToU8(tmy);
50}
51
52SkBitmapShader::SkBitmapShader(SkFlattenableReadBuffer& buffer) :
53 INHERITED(buffer)
54{
55 Bitmap src;
56 buffer.readBitmap(&src);
57#ifdef SK_SUPPORT_MIPMAP
58 fMipLevel = 0;
59 fMipSrcBitmap = src;
60#endif
61 fOrigSrcBitmap = src;
62 fFilterBitmap = buffer.readU8();
63 fTileModeX = buffer.readU8();
64 fTileModeY = buffer.readU8();
65}
66
67void SkBitmapShader::flatten(SkFlattenableWriteBuffer& buffer)
68{
69 this->INHERITED::flatten(buffer);
70 buffer.writeBitmap(&fOrigSrcBitmap);
71 buffer.write8(fFilterBitmap);
72 buffer.write8(fTileModeX);
73 buffer.write8(fTileModeY);
74}
75
76bool SkBitmapShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix)
77{
78 // do this first, so we have a correct inverse matrix
79 if (!this->INHERITED::setContext(device, paint, matrix))
80 return false;
81
82 if (fOrigSrcBitmap.getConfig() == SkBitmap::kNo_Config ||
83 fOrigSrcBitmap.width() == 0 ||
84 fOrigSrcBitmap.height() == 0)
85 return false;
86
87 SkBitmap& bm = fOrigSrcBitmap;
88
89#ifdef SK_SUPPORT_MIPMAP
90 if (fOrigSrcBitmap.countMipLevels())
91 {
92 const SkMatrix& inv = this->getTotalInverse();
93
94 fMipLevel = SkMin32(find_mip_level( SkScalarToFixed(inv.getScaleX()),
95 SkScalarToFixed(inv.getSkewY())),
96 SkIntToFixed(fOrigSrcBitmap.countMipLevels() - 1));
97
98// SkDEBUGF(("BitmapShader miplevel=%x\n", fMipLevel));
99
100 const SkBitmap::MipLevel* mm = fOrigSrcBitmap.getMipLevel(fMipLevel >> 16);
101
102 fMipSrcBitmap.setConfig(fOrigSrcBitmap.getConfig(),
103 mm->fWidth,
104 mm->fHeight,
105 mm->fRowBytes);
106 fMipSrcBitmap.setPixels(mm->fPixels);
107 bm = fMipSrcBitmap;
108 }
109 else
110 {
111 fMipLevel = 0;
112 fMipSrcBitmap = fOrigSrcBitmap;
113 }
114#endif
115
116 fFlags = 0;
117 if (paint.getAlpha() == 255 && bm.isOpaque())
118 fFlags |= kOpaqueAlpha_Flag;
119
120 return true;
121}
122
123///////////////////////////////////////////////////////////////////////////
124
125#include "SkColorPriv.h"
126#include "SkBitmapSampler.h"
127#include "SkPerspIter.h"
128
129class Sampler_BitmapShader : public SkBitmapShader {
130public:
131 Sampler_BitmapShader(const SkBitmap& src, bool doFilter,
132 TileMode tmx, TileMode tmy)
133 : SkBitmapShader(src, doFilter, tmx, tmy)
134 {
135 // make sure to pass our copy of the src bitmap to the sampler, and not the
136 // original parameter (which might go away).
137 fSampler = NULL;
138 }
139
140 virtual ~Sampler_BitmapShader()
141 {
142 SkDELETE(fSampler);
143 }
144
145 virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix)
146 {
147 if (this->INHERITED::setContext(device, paint, matrix))
148 {
149 SkDELETE(fSampler);
150 fSampler = SkBitmapSampler::Create(this->getSrcBitmap(), this->getFilterBitmap(),
151 this->getTileModeX(), this->getTileModeY());
152 fSampler->setPaint(paint);
153 return true;
154 }
155 return false;
156 }
157
158 enum {
159 kMaxPointStorageCount = 32
160 };
161
162 virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
163 {
164 unsigned scale = SkAlpha255To256(this->getPaintAlpha());
165 const SkMatrix& inv = this->getTotalInverse();
166 SkMatrix::MapPtProc proc = this->getInverseMapPtProc();
167 SkBitmapSampler* sampler = fSampler;
168 MatrixClass mc = this->getInverseClass();
169
170 SkPoint srcPt;
171
172 if (mc != kPerspective_MatrixClass)
173 {
174 proc(inv, SkIntToScalar(x) + SK_ScalarHalf,
175 SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
176
177 SkFixed fx = SkScalarToFixed(srcPt.fX);
178 SkFixed fy = SkScalarToFixed(srcPt.fY);
179 SkFixed dx, dy;
180
181 if (mc == kLinear_MatrixClass)
182 {
183 dx = SkScalarToFixed(inv.getScaleX());
184 dy = SkScalarToFixed(inv.getSkewY());
185 }
186 else
187 (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
188
189#if defined(SK_SUPPORT_MIPMAP)
190 { int level = this->getMipLevel() >> 16;
191 fx >>= level;
192 fy >>= level;
193 dx >>= level;
194 dy >>= level;
195 }
196#endif
197 if (scale == 256)
198 {
199 for (int i = 0; i < count; i++)
200 {
201 dstC[i] = sampler->sample(fx, fy);
202 fx += dx;
203 fy += dy;
204 }
205 }
206 else
207 {
208 for (int i = 0; i < count; i++)
209 {
210 uint32_t c = sampler->sample(fx, fy);
211 dstC[i] = SkAlphaMulQ(c, scale);
212 fx += dx;
213 fy += dy;
214 }
215 }
216 }
217 else
218 {
219 SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
220 SkIntToScalar(y) + SK_ScalarHalf, count);
221 if (scale == 256)
222 {
223 while ((count = iter.next()) != 0)
224 {
225 const SkFixed* src = iter.getXY();
226 for (int i = 0; i < count; i++)
227 {
228 *dstC++ = sampler->sample(src[0], src[1]);
229 src += 2;
230 }
231 }
232 }
233 else
234 {
235 while ((count = iter.next()) != 0)
236 {
237 const SkFixed* src = iter.getXY();
238 for (int i = 0; i < count; i++)
239 {
240 uint32_t c = sampler->sample(src[0] - SK_FixedHalf, src[1] - SK_FixedHalf);
241 *dstC++ = SkAlphaMulQ(c, scale);
242 src += 2;
243 }
244 }
245 }
246 }
247 }
248
249protected:
250
251 const SkMatrix& getUnitInverse() const { return fUnitInverse; }
252 SkMatrix::MapPtProc getUnitInverseProc() const { return fUnitInverseProc; }
253
254 /* takes computed inverse (from setContext) and computes fUnitInverse,
255 taking srcBitmap width/height into account, so that fUnitInverse
256 walks 0...1, allowing the tile modes to all operate in a fast 16bit
257 space (no need for mod). The resulting coords need to be scaled by
258 width/height to get back into src space (coord * width >> 16).
259 */
260 void computeUnitInverse()
261 {
262 const SkBitmap& src = getSrcBitmap();
263 fUnitInverse = this->getTotalInverse();
264 fUnitInverse.postIDiv(src.width(), src.height());
265 fUnitInverseProc = fUnitInverse.getMapPtProc();
266 }
267
268private:
269 SkBitmapSampler* fSampler;
270 SkMatrix fUnitInverse;
271 SkMatrix::MapPtProc fUnitInverseProc;
272
273 typedef SkBitmapShader INHERITED;
274};
275
276///////////////////////////////////////////////////////////////////////////
277
278class HasSpan16_Sampler_BitmapShader : public Sampler_BitmapShader {
279public:
280 HasSpan16_Sampler_BitmapShader(const SkBitmap& src, bool doFilter,
281 TileMode tmx, TileMode tmy)
282 : Sampler_BitmapShader(src, doFilter, tmx, tmy)
283 {
284 }
285
286 virtual uint32_t getFlags()
287 {
288 uint32_t flags = this->INHERITED::getFlags();
289
290 switch (this->getSrcBitmap().getConfig()) {
291 case SkBitmap::kRGB_565_Config:
292 flags |= kHasSpan16_Flag;
293 break;
294 case SkBitmap::kIndex8_Config:
295 case SkBitmap::kARGB_8888_Config:
296 if (this->getSrcBitmap().isOpaque())
297 flags |= kHasSpan16_Flag;
298 break;
299 default:
300 break;
301 }
302 return flags;
303 }
304
305 const SkBitmap& revealSrcBitmap() const { return this->getSrcBitmap(); }
306 uint8_t revealPaintAlpha() const { return this->getPaintAlpha(); }
307 const SkMatrix& revealTotalInverse() const { return this->getTotalInverse(); }
308
309private:
310 typedef Sampler_BitmapShader INHERITED;
311};
312
313///////////////////////////////////////////////////////////////////////////
314
315static void Index8_RepeatTile_Sprite16(HasSpan16_Sampler_BitmapShader* shader,
316 int x, int y, uint16_t dstC[], int count)
317{
318 const SkMatrix& inv = shader->revealTotalInverse();
319 const SkBitmap& srcBitmap = shader->revealSrcBitmap();
320 int width = srcBitmap.width();
321 int height = srcBitmap.height();
322
323 SkColorTable* ctable = srcBitmap.getColorTable();
324 const uint16_t* colors = ctable->lock16BitCache();
325
326 x += SkScalarRound(inv[SkMatrix::kMTransX]);
327 y += SkScalarRound(inv[SkMatrix::kMTransY]);
328
329 x = do_repeat_mod(x, width - 1);
330 y = do_repeat_mod(y, height - 1);
331 const uint8_t* row = srcBitmap.getAddr8(0, y);
332 const uint8_t* src = row + x;
333
334 // do the first partial run
335 int n = width - x;
336 if (n > count) n = count;
337 count -= n;
338 SkASSERT(n > 0);
339 do {
340 *dstC++ = colors[*src++];
341 } while (--n > 0);
342
343 // do 1 complete run
344 if (count >= width)
345 {
346 uint16_t* baseDstC = dstC; // remember the first complete run start
347 n = width;
348 count -= width;
349 src = row;
350 do {
351 *dstC++ = colors[*src++];
352 } while (--n > 0);
353
354 // do the rest of the complete runs
355 while (count >= width)
356 {
357 count -= width;
358 memcpy(dstC, baseDstC, width << 1);
359 dstC += width;
360 }
361 // do final partial run
362 if (count > 0)
363 memcpy(dstC, baseDstC, count << 1);
364 }
365 else // do final partial
366 {
367 if (count > 0)
368 {
369 src = row;
370 do {
371 *dstC++ = colors[*src++];
372 } while (--count > 0);
373 }
374 }
375
376 ctable->unlock16BitCache();
377}
378
379static void Index8_RepeatTile_Sprite32(HasSpan16_Sampler_BitmapShader* shader,
380 int x, int y, SkPMColor dstC[], int count)
381{
382 const SkMatrix& inv = shader->revealTotalInverse();
383 const SkBitmap& srcBitmap = shader->revealSrcBitmap();
384 int width = srcBitmap.width();
385 int height = srcBitmap.height();
386
387 SkColorTable* ctable = srcBitmap.getColorTable();
388 const SkPMColor* colors = ctable->lockColors();
389
390 x += SkScalarRound(inv[SkMatrix::kMTransX]);
391 y += SkScalarRound(inv[SkMatrix::kMTransY]);
392
393 x = do_repeat_mod(x, width - 1);
394 y = do_repeat_mod(y, height - 1);
395
396 const uint8_t* row = srcBitmap.getAddr8(0, y);
397 const uint8_t* src = row + x;
398
399 // do the first partial run
400 int n = width - x;
401 if (n > count) n = count;
402 count -= n;
403 SkASSERT(n > 0);
404 do {
405 *dstC++ = colors[*src++];
406 } while (--n > 0);
407
408 // do 1 complete run
409 if (count >= width)
410 {
411 SkPMColor* baseDstC = dstC; // remember the first complete run start
412 n = width;
413 count -= width;
414 src = row;
415 do {
416 *dstC++ = colors[*src++];
417 } while (--n > 0);
418
419 // do the rest of the complete runs
420 while (count >= width)
421 {
422 count -= width;
423 memcpy(dstC, baseDstC, width << 2);
424 dstC += width;
425 }
426 // do final partial run
427 if (count > 0)
428 memcpy(dstC, baseDstC, count << 2);
429 }
430 else // do final partial
431 {
432 if (count > 0)
433 {
434 src = row;
435 do {
436 *dstC++ = colors[*src++];
437 } while (--count > 0);
438 }
439 }
440
441 ctable->unlockColors(false);
442}
443
444static void RGB16_RepeatTile_Sprite16(HasSpan16_Sampler_BitmapShader* shader,
445 int x, int y, uint16_t dstC[], int count)
446{
447 SkASSERT(count > 0);
448
449 const SkMatrix& inv = shader->revealTotalInverse();
450 const SkBitmap& srcBitmap = shader->revealSrcBitmap();
451 int width = srcBitmap.width();
452 int height = srcBitmap.height();
453
454 SkASSERT(width > 0 && height > 0);
455
456 x += SkScalarRound(inv[SkMatrix::kMTransX]);
457 y += SkScalarRound(inv[SkMatrix::kMTransY]);
458
459 x = do_repeat_mod(x, width - 1);
460 y = do_repeat_mod(y, height - 1);
461
462 const uint16_t* row = srcBitmap.getAddr16(0, y);
463 const uint16_t* src = row + x;
464
465 int n = SkMin32(width - x, count);
466
467 for (;;)
468 {
469 SkASSERT(n > 0 && count >= n);
470 memcpy(dstC, src, n << 1);
471 count -= n;
472 if (count == 0)
473 break;
474 dstC += n;
475 src = row;
476 n = SkMin32(width, count);
477 }
478}
479
480static void RGB16_RepeatTile_Sprite32(HasSpan16_Sampler_BitmapShader* shader,
481 int x, int y, SkPMColor dstC[], int count)
482{
483 SkASSERT(count > 0);
484
485 const SkMatrix& inv = shader->revealTotalInverse();
486 const SkBitmap& srcBitmap = shader->revealSrcBitmap();
487 int width = srcBitmap.width();
488 int height = srcBitmap.height();
489
490 SkASSERT(width > 0 && height > 0);
491
492 x += SkScalarRound(inv[SkMatrix::kMTransX]);
493 y += SkScalarRound(inv[SkMatrix::kMTransY]);
494
495 x = do_repeat_mod(x, width - 1);
496 y = do_repeat_mod(y, height - 1);
497
498 const uint16_t* row = srcBitmap.getAddr16(0, y);
499 const uint16_t* src = row + x;
500
501 int n = SkMin32(width - x, count);
502
503 // do the first partial run
504 count -= n;
505 SkASSERT(n > 0);
506 do {
507 *dstC++ = SkPixel16ToPixel32(*src++);
508 } while (--n > 0);
509
510 // do 1 complete run
511 if (count >= width)
512 {
513 SkPMColor* baseDstC = dstC; // remember the first complete run start
514 n = width;
515 count -= width;
516 src = row;
517 do {
518 *dstC++ = SkPixel16ToPixel32(*src++);
519 } while (--n > 0);
520
521 // do the rest of the complete runs
522 while (count >= width)
523 {
524 count -= width;
525 memcpy(dstC, baseDstC, width << 2);
526 dstC += width;
527 }
528 // do final partial run
529 if (count > 0)
530 memcpy(dstC, baseDstC, count << 2);
531 }
532 else // do final partial
533 {
534 if (count > 0)
535 {
536 src = row;
537 do {
538 *dstC++ = SkPixel16ToPixel32(*src++);;
539 } while (--count > 0);
540 }
541 }
542}
543
544static void ARGB32_RepeatTile_Sprite16(HasSpan16_Sampler_BitmapShader* shader,
545 int x, int y, uint16_t dstC[], int count)
546{
547 SkASSERT(count > 0);
548
549 const SkMatrix& inv = shader->revealTotalInverse();
550 const SkBitmap& srcBitmap = shader->revealSrcBitmap();
551 int width = srcBitmap.width();
552 int height = srcBitmap.height();
553
554 SkASSERT(width > 0 && height > 0);
555
556 x += SkScalarRound(inv[SkMatrix::kMTransX]);
557 y += SkScalarRound(inv[SkMatrix::kMTransY]);
558
559 x = do_repeat_mod(x, width - 1);
560 y = do_repeat_mod(y, height - 1);
561
562 const SkPMColor* row = srcBitmap.getAddr32(0, y);
563 const SkPMColor* src = row + x;
564
565 int n = SkMin32(width - x, count);
566
567 // do the first partial run
568 count -= n;
569 SkASSERT(n > 0);
570 do {
571 *dstC++ = SkPixel32ToPixel16(*src++);
572 } while (--n > 0);
573
574 // do 1 complete run
575 if (count >= width)
576 {
577 uint16_t* baseDstC = dstC; // remember the first complete run start
578 n = width;
579 count -= width;
580 src = row;
581 do {
582 *dstC++ = SkPixel32ToPixel16(*src++);
583 } while (--n > 0);
584
585 // do the rest of the complete runs
586 while (count >= width)
587 {
588 count -= width;
589 memcpy(dstC, baseDstC, width << 1);
590 dstC += width;
591 }
592 // do final partial run
593 if (count > 0)
594 memcpy(dstC, baseDstC, count << 1);
595 }
596 else // do final partial
597 {
598 if (count > 0)
599 {
600 src = row;
601 do {
602 *dstC++ = SkPixel32ToPixel16(*src++);;
603 } while (--count > 0);
604 }
605 }
606}
607
608static void ARGB32_RepeatTile_Sprite32(HasSpan16_Sampler_BitmapShader* shader,
609 int x, int y, SkPMColor dstC[], int count)
610{
611 SkASSERT(count > 0);
612
613 const SkMatrix& inv = shader->revealTotalInverse();
614 const SkBitmap& srcBitmap = shader->revealSrcBitmap();
615 int width = srcBitmap.width();
616 int height = srcBitmap.height();
617
618 SkASSERT(width > 0 && height > 0);
619
620 x += SkScalarRound(inv[SkMatrix::kMTransX]);
621 y += SkScalarRound(inv[SkMatrix::kMTransY]);
622
623 x = do_repeat_mod(x, width - 1);
624 y = do_repeat_mod(y, height - 1);
625
626 const SkPMColor* row = srcBitmap.getAddr32(0, y);
627 const SkPMColor* src = row + x;
628
629 int n = SkMin32(width - x, count);
630
631 for (;;)
632 {
633 SkASSERT(n > 0 && count >= n);
634 memcpy(dstC, src, n << 2);
635 count -= n;
636 if (count == 0)
637 break;
638 dstC += n;
639 src = row;
640 n = SkMin32(width, count);
641 }
642}
643
644///////////////////////////////////////////////////////////////////////////
645
646#define NOFILTER_BITMAP_SHADER_CLASS Index8_NoFilter_RepeatTile_BitmapShader
647#define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMode
648#define NOFILTER_BITMAP_SHADER_TILEPROC(x, max) (fixed_repeat(x) * (max + 1) >> 16)
649#define NOFILTER_BITMAP_SHADER_TYPE uint8_t
650#define NOFILTER_BITMAP_SHADER_SAMPLE_X(p, x) colors32[p[x]]
651#define NOFILTER_BITMAP_SHADER_SAMPLE_XY(p, x, y, rb) colors32[p[x + y * rb]]
652#define NOFILTER_BITMAP_SHADER_PREAMBLE(bitmap, rb) const SkPMColor* colors32 = bitmap.getColorTable()->lockColors()
653#define NOFILTER_BITMAP_SHADER_POSTAMBLE(bitmap) bitmap.getColorTable()->unlockColors(false)
654#define NOFILTER_BITMAP_SHADER_SAMPLE_X16(p, x) colors16[p[x]]
655#define NOFILTER_BITMAP_SHADER_SAMPLE_XY16(p, x, y, rb) colors16[p[x + y * rb]]
656#define NOFILTER_BITMAP_SHADER_PREAMBLE16(bitmap, rb) const uint16_t* colors16 = bitmap.getColorTable()->lock16BitCache()
657#define NOFILTER_BITMAP_SHADER_POSTAMBLE16(bitmap) bitmap.getColorTable()->unlock16BitCache()
658#define NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
659#define NOFILTER_BITMAP_SHADER_SPRITEPROC16 Index8_RepeatTile_Sprite16
660#define NOFILTER_BITMAP_SHADER_SPRITEPROC32 Index8_RepeatTile_Sprite32
661#include "SkBitmapShaderTemplate.h"
662
663#define NOFILTER_BITMAP_SHADER_CLASS U16_NoFilter_RepeatTile_BitmapShader
664#define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMode
665#define NOFILTER_BITMAP_SHADER_TILEPROC(x, max) (fixed_repeat(x) * (max + 1) >> 16)
666#define NOFILTER_BITMAP_SHADER_TYPE uint16_t
667#define NOFILTER_BITMAP_SHADER_SAMPLE_X(p, x) SkPixel16ToPixel32(p[x])
668#define NOFILTER_BITMAP_SHADER_SAMPLE_XY(p, x, y, rb) SkPixel16ToPixel32(*(const uint16_t*)((const char*)p + y * rb + (x << 1)))
669#define NOFILTER_BITMAP_SHADER_SAMPLE_X16(p, x) p[x]
670#define NOFILTER_BITMAP_SHADER_SAMPLE_XY16(p, x, y, rb) *(const uint16_t*)((const char*)p + y * rb + (x << 1))
671#define NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
672#define NOFILTER_BITMAP_SHADER_SPRITEPROC16 RGB16_RepeatTile_Sprite16
673#define NOFILTER_BITMAP_SHADER_SPRITEPROC32 RGB16_RepeatTile_Sprite32
674#include "SkBitmapShaderTemplate.h"
675
676#define NOFILTER_BITMAP_SHADER_CLASS U32_NoFilter_RepeatTile_BitmapShader
677#define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMode
678#define NOFILTER_BITMAP_SHADER_TILEPROC(x, max) (fixed_repeat(x) * (max + 1) >> 16)
679#define NOFILTER_BITMAP_SHADER_TYPE uint32_t
680#define NOFILTER_BITMAP_SHADER_SAMPLE_X(p, x) p[x]
681#define NOFILTER_BITMAP_SHADER_SAMPLE_XY(p, x, y, rb) *(const uint32_t*)((const char*)p + y * rb + (x << 2))
682#define NOFILTER_BITMAP_SHADER_SAMPLE_X16(p, x) SkPixel32ToPixel16_ToU16(p[x])
683#define NOFILTER_BITMAP_SHADER_SAMPLE_XY16(p, x, y, rb) SkPixel32ToPixel16_ToU16(*(const uint32_t*)((const char*)p + y * rb + (x << 2)))
684#define NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
685#define NOFILTER_BITMAP_SHADER_SPRITEPROC16 ARGB32_RepeatTile_Sprite16
686#define NOFILTER_BITMAP_SHADER_SPRITEPROC32 ARGB32_RepeatTile_Sprite32
687#include "SkBitmapShaderTemplate.h"
688
689///////////////////////////////////////////////////////////////////////////////////////////////////////
690
691static inline SkPMColor expanded_rgb16_to_8888(uint32_t c, U8CPU alpha)
692{
693// GGGG Gggg gggR RRRR rrrr r|BB BBBb bbbb
694 SkASSERT(alpha <= 255);
695
696#if 1
697 int scale = SkAlpha255To256(alpha);
698 int r = (c & 0xF800) * scale >> 16;
699 int g = ((c >> 21) & 0x3F) * scale >> 6;
700 int b = (c & 0x1F) * scale >> 5;
701 return SkPackARGB32(alpha, r, g, b);
702#else
703 int scale = SkAlpha255To256(alpha) >> 3;
704 c &= 0x07E0F81F;
705 c = c * scale;
706 int r = (c >> 13) & 0xFF;
707 int g = (c >> 24) & 0xFF;
708 int b = (c >> 2) & 0xFF;
709 return SkPackARGB32(alpha, r, g, b);
710#endif
711}
712
713#define BILERP_BITMAP16_SHADER_CLASS U16_Bilerp_BitmapShader
714#define BILERP_BITMAP16_SHADER_TYPE uint16_t
715#define BILERP_BITMAP16_SHADER_PREAMBLE(bm)
716#define BILERP_BITMAP16_SHADER_PIXEL(c) (c)
717#define BILERP_BITMAP16_SHADER_POSTAMBLE(bm)
718#include "SkBitmapShader16BilerpTemplate.h"
719
720#define BILERP_BITMAP16_SHADER_CLASS Index8_Bilerp_BitmapShader
721#define BILERP_BITMAP16_SHADER_TYPE uint8_t
722#define BILERP_BITMAP16_SHADER_PREAMBLE(bm) SkColorTable* ctable = (bm).getColorTable(); const uint16_t* colors16 = ctable->lock16BitCache()
723#define BILERP_BITMAP16_SHADER_PIXEL(c) colors16[c]
724#define BILERP_BITMAP16_SHADER_POSTAMBLE(bm) ctable->unlock16BitCache()
725#include "SkBitmapShader16BilerpTemplate.h"
726
727#include "ARGB32_Clamp_Bilinear_BitmapShader.h"
728
729///////////////////////////////////////////////////////////////////////////
730///////////////////////////////////////////////////////////////////////////
731
732#include "SkBitmapProcShader.h"
733
734///////////////////////////////////////////////////////////////////////////
735///////////////////////////////////////////////////////////////////////////
736
737#include "SkTemplatesPriv.h"
738
739SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
740 bool doFilter,
741 TileMode tmx, TileMode tmy,
742 void* storage, size_t storageSize)
743{
744#if 1
745
746 SkShader* shader;
747 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
748 storageSize, (src, doFilter, tmx, tmy));
749 return shader;
750#else
751
752 if (!doFilter)
753 {
754 if (kClamp_TileMode == tmx && kClamp_TileMode == tmy)
755 {
756 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
757 storageSize, (src, doFilter, tmx, tmy));
758 }
759 else if (kRepeat_TileMode == tmx && kRepeat_TileMode == tmy)
760 {
761 #if 1
762 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
763 storageSize, (src, doFilter, tmx, tmy));
764 #else
765 switch (src.getConfig()) {
766 case SkBitmap::kIndex8_Config:
767 SK_PLACEMENT_NEW_ARGS(shader, Index8_NoFilter_RepeatTile_BitmapShader, storage, storageSize, (src));
768 break;
769 case SkBitmap::kRGB_565_Config:
770 SK_PLACEMENT_NEW_ARGS(shader, U16_NoFilter_RepeatTile_BitmapShader, storage, storageSize, (src));
771 break;
772 case SkBitmap::kARGB_8888_Config:
773 SK_PLACEMENT_NEW_ARGS(shader, U32_NoFilter_RepeatTile_BitmapShader, storage, storageSize, (src));
774 break;
775 default:
776 break;
777 }
778 #endif
779 }
780 }
781 else if (kClamp_TileMode == tmx && kClamp_TileMode == tmy)
782 {
783#if 1
784 if (SkBitmapProcShader::CanDo(src, tmx, tmy))
785 {
786 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
787 storageSize, (src, doFilter, tmx, tmy));
788 }
789#else
790 switch (src.getConfig()) {
791 case SkBitmap::kIndex8_Config:
792 if (src.isOpaque())
793 SK_PLACEMENT_NEW_ARGS(shader, Index8_Bilerp_BitmapShader, storage, storageSize, (src));
794 break;
795 case SkBitmap::kRGB_565_Config:
796 SK_PLACEMENT_NEW_ARGS(shader, U16_Bilerp_BitmapShader, storage, storageSize, (src));
797 break;
798 case SkBitmap::kARGB_8888_Config:
799 SK_PLACEMENT_NEW_ARGS(shader, ARGB32_Clamp_Bilinear_BitmapShader, storage, storageSize, (src));
800 break;
801 default:
802 break;
803 }
804#endif
805 }
806
807 // if shader is null, then none of the special cases could handle the request
808 // so fall through to our slow-general case
809 if (shader == NULL)
810 SK_PLACEMENT_NEW_ARGS(shader, Sampler_BitmapShader, storage, storageSize,
811 (src, doFilter, tmx, tmy));
812 return shader;
813#endif
814}
815
816SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, bool doFilter,
817 TileMode tmx, TileMode tmy)
818{
819 return SkShader::CreateBitmapShader(src, doFilter, tmx, tmy, NULL, 0);
820}
821
822#endif