• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 class ARGB32_Clamp_Bilinear_BitmapShader : public SkBitmapShader {
10 public:
ARGB32_Clamp_Bilinear_BitmapShader(const SkBitmap & src)11     ARGB32_Clamp_Bilinear_BitmapShader(const SkBitmap& src)
12         : SkBitmapShader(src, true,
13                          SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)
14     {}
15 
16     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
17 };
18 
19 SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY,
20                         const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table);
sample_bilerp(SkFixed fx,SkFixed fy,unsigned srcMaxX,unsigned srcMaxY,const SkPMColor * srcPixels,int srcRB,const SkFilterPtrProc * proc_table)21 SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY,
22                         const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table)
23 {
24     int ix = fx >> 16;
25     int iy = fy >> 16;
26 
27     const SkPMColor *p00, *p01, *p10, *p11;
28 
29     p00 = p01 = ((const SkPMColor*)((const char*)srcPixels
30                                     + SkClampMax(iy, srcMaxY) * srcRB))
31                                     + SkClampMax(ix, srcMaxX);
32 
33     if ((unsigned)ix < srcMaxX)
34         p01 += 1;
35     p10 = p00;
36     p11 = p01;
37     if ((unsigned)iy < srcMaxY)
38     {
39         p10 = (const SkPMColor*)((const char*)p10 + srcRB);
40         p11 = (const SkPMColor*)((const char*)p11 + srcRB);
41     }
42 
43     SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(proc_table, fx, fy);
44     return proc(p00, p01, p10, p11);
45 }
46 
sample_bilerpx(SkFixed fx,unsigned srcMaxX,const SkPMColor * srcPixels,int srcRB,const SkFilterPtrProc * proc_table)47 static inline SkPMColor sample_bilerpx(SkFixed fx, unsigned srcMaxX, const SkPMColor* srcPixels,
48                                        int srcRB, const SkFilterPtrProc* proc_table)
49 {
50     int ix = fx >> 16;
51 
52     const SkPMColor *p00, *p01, *p10, *p11;
53 
54     p00 = p01 = srcPixels + SkClampMax(ix, srcMaxX);
55     if ((unsigned)ix < srcMaxX)
56         p01 += 1;
57 
58     p10 = (const SkPMColor*)((const char*)p00 + srcRB);
59     p11 = (const SkPMColor*)((const char*)p01 + srcRB);
60 
61     SkFilterPtrProc proc = SkGetBilinearFilterPtrXProc(proc_table, fx);
62     return proc(p00, p01, p10, p11);
63 }
64 
shadeSpan(int x,int y,SkPMColor dstC[],int count)65 void ARGB32_Clamp_Bilinear_BitmapShader::shadeSpan(int x, int y, SkPMColor dstC[], int count)
66 {
67     SkASSERT(count > 0);
68 
69     unsigned srcScale = SkAlpha255To256(this->getPaintAlpha());
70 
71     const SkMatrix& inv = this->getTotalInverse();
72     const SkBitmap& srcBitmap = this->getSrcBitmap();
73     unsigned        srcMaxX = srcBitmap.width() - 1;
74     unsigned        srcMaxY = srcBitmap.height() - 1;
75     unsigned        srcRB = srcBitmap.rowBytes();
76 
77     const SkFilterPtrProc* proc_table = SkGetBilinearFilterPtrProcTable();
78     const SkPMColor* srcPixels = (const SkPMColor*)srcBitmap.getPixels();
79 
80     if (this->getInverseClass() == kPerspective_MatrixClass)
81     {
82         SkPerspIter   iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
83                                 SkIntToScalar(y) + SK_ScalarHalf, count);
84 
85         if (256 == srcScale)
86         {
87             while ((count = iter.next()) != 0)
88             {
89                 const SkFixed* srcXY = iter.getXY();
90                 while (--count >= 0)
91                 {
92                     SkFixed fx = *srcXY++ - SK_FixedHalf;
93                     SkFixed fy = *srcXY++ - SK_FixedHalf;
94                     *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
95                 }
96             }
97         }
98         else    // scale by srcScale
99         {
100             while ((count = iter.next()) != 0)
101             {
102                 const SkFixed* srcXY = iter.getXY();
103                 while (--count >= 0)
104                 {
105                     SkFixed fx = *srcXY++ - SK_FixedHalf;
106                     SkFixed fy = *srcXY++ - SK_FixedHalf;
107                     SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
108                     *dstC++ = SkAlphaMulQ(c, srcScale);
109                 }
110             }
111         }
112     }
113     else    // linear case
114     {
115         SkFixed fx, fy, dx, dy;
116 
117         // now init fx, fy, dx, dy
118         {
119             SkPoint srcPt;
120             this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf,
121                                              SkIntToScalar(y) + SK_ScalarHalf,
122                                              &srcPt);
123 
124             fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf;
125             fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf;
126 
127             if (this->getInverseClass() == kFixedStepInX_MatrixClass)
128                 (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
129             else
130             {
131                 dx = SkScalarToFixed(inv.getScaleX());
132                 dy = SkScalarToFixed(inv.getSkewY());
133             }
134         }
135 
136         if (dy == 0 && (unsigned)(fy >> 16) < srcMaxY)
137         {
138             srcPixels = (const SkPMColor*)((const char*)srcPixels + (fy >> 16) * srcRB);
139             proc_table = SkGetBilinearFilterPtrProcYTable(proc_table, fy);
140             if (256 == srcScale)
141             {
142                 do {
143                     *dstC++ = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table);
144                     fx += dx;
145                 } while (--count != 0);
146             }
147             else
148             {
149                 do {
150                     SkPMColor c = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table);
151                     *dstC++ = SkAlphaMulQ(c, srcScale);
152                     fx += dx;
153                 } while (--count != 0);
154             }
155         }
156         else    // dy is != 0
157         {
158             if (256 == srcScale)
159             {
160                 do {
161                     *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
162                     fx += dx;
163                     fy += dy;
164                 } while (--count != 0);
165             }
166             else
167             {
168                 do {
169                     SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
170                     *dstC++ = SkAlphaMulQ(c, srcScale);
171                     fx += dx;
172                     fy += dy;
173                 } while (--count != 0);
174             }
175         }
176     }
177 }
178 
179