• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* 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
22 static 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 
38 SkBitmapShader::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 
52 SkBitmapShader::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 
67 void 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 
76 bool 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 
129 class Sampler_BitmapShader : public SkBitmapShader {
130 public:
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 
249 protected:
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 
268 private:
269     SkBitmapSampler*    fSampler;
270     SkMatrix            fUnitInverse;
271     SkMatrix::MapPtProc fUnitInverseProc;
272 
273     typedef SkBitmapShader INHERITED;
274 };
275 
276 ///////////////////////////////////////////////////////////////////////////
277 
278 class HasSpan16_Sampler_BitmapShader : public Sampler_BitmapShader {
279 public:
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 
309 private:
310     typedef Sampler_BitmapShader INHERITED;
311 };
312 
313 ///////////////////////////////////////////////////////////////////////////
314 
315 static 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 
379 static 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 
444 static 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 
480 static 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 
544 static 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 
608 static 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 
691 static 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 
739 SkShader* 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 
816 SkShader* 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
823