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