1
2/*
3 * Copyright 2006 The Android Open Source Project
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
10
11#ifndef NOFILTER_BITMAP_SHADER_PREAMBLE
12    #define NOFILTER_BITMAP_SHADER_PREAMBLE(bitmap, rb)
13#endif
14#ifndef NOFILTER_BITMAP_SHADER_POSTAMBLE
15    #define NOFILTER_BITMAP_SHADER_POSTAMBLE(bitmap)
16#endif
17#ifndef NOFILTER_BITMAP_SHADER_PREAMBLE16
18    #define NOFILTER_BITMAP_SHADER_PREAMBLE16(bitmap, rb)
19#endif
20#ifndef NOFILTER_BITMAP_SHADER_POSTAMBLE16
21    #define NOFILTER_BITMAP_SHADER_POSTAMBLE16(bitmap)
22#endif
23
24class NOFILTER_BITMAP_SHADER_CLASS : public HasSpan16_Sampler_BitmapShader {
25public:
26    NOFILTER_BITMAP_SHADER_CLASS(const SkBitmap& src)
27        : HasSpan16_Sampler_BitmapShader(src, false,
28                                         NOFILTER_BITMAP_SHADER_TILEMODE,
29                                         NOFILTER_BITMAP_SHADER_TILEMODE)
30    {
31    }
32
33    virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix)
34    {
35        if (!this->INHERITED::setContext(device, paint, matrix))
36            return false;
37
38#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
39        this->computeUnitInverse();
40#endif
41        return true;
42    }
43
44    virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
45    {
46        SkASSERT(count > 0);
47
48#ifdef NOFILTER_BITMAP_SHADER_SPRITEPROC32
49        if ((this->getTotalInverse().getType() & ~SkMatrix::kTranslate_Mask) == 0)
50        {
51            NOFILTER_BITMAP_SHADER_SPRITEPROC32(this, x, y, dstC, count);
52            return;
53        }
54#endif
55
56        unsigned        scale = SkAlpha255To256(this->getPaintAlpha());
57#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
58        const SkMatrix& inv = this->getUnitInverse();
59        SkMatrix::MapPtProc invProc = this->getUnitInverseProc();
60#else
61        const SkMatrix& inv = this->getTotalInverse();
62        SkMatrix::MapPtProc invProc = this->getInverseMapPtProc();
63#endif
64        const SkBitmap& srcBitmap = this->getSrcBitmap();
65        unsigned        srcMaxX = srcBitmap.width() - 1;
66        unsigned        srcMaxY = srcBitmap.height() - 1;
67        unsigned        srcRB = srcBitmap.rowBytes();
68        SkFixed         fx, fy, dx, dy;
69
70        const NOFILTER_BITMAP_SHADER_TYPE* srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)srcBitmap.getPixels();
71        NOFILTER_BITMAP_SHADER_PREAMBLE(srcBitmap, srcRB);
72
73        if (this->getInverseClass() == kPerspective_MatrixClass)
74        {
75            SkPerspIter   iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
76                                    SkIntToScalar(y) + SK_ScalarHalf, count);
77            while ((count = iter.next()) != 0)
78            {
79                const SkFixed* srcXY = iter.getXY();
80
81/*  Do I need this?
82#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
83            fx >>= level;
84            fy >>= level;
85#endif
86*/
87                if (256 == scale)
88                {
89                    while (--count >= 0)
90                    {
91                        fx = *srcXY++;
92                        fy = *srcXY++;
93                        unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
94                        unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
95                        *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
96                    }
97                }
98                else
99                {
100                    while (--count >= 0)
101                    {
102                        fx = *srcXY++;
103                        fy = *srcXY++;
104                        unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
105                        unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
106                        uint32_t c = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
107                        *dstC++ = SkAlphaMulQ(c, scale);
108                    }
109                }
110            }
111            return;
112        }
113
114        // now init fx, fy, dx, dy
115        {
116            SkPoint srcPt;
117            invProc(inv, SkIntToScalar(x) + SK_ScalarHalf,
118                         SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
119
120            fx = SkScalarToFixed(srcPt.fX);
121            fy = SkScalarToFixed(srcPt.fY);
122
123            if (this->getInverseClass() == kFixedStepInX_MatrixClass)
124                (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
125            else
126            {
127                dx = SkScalarToFixed(inv.getScaleX());
128                dy = SkScalarToFixed(inv.getSkewY());
129            }
130        }
131
132#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
133        {   int level = this->getMipLevel() >> 16;
134            fx >>= level;
135            fy >>= level;
136            dx >>= level;
137            dy >>= level;
138        }
139#endif
140
141        if (dy == 0)
142        {
143            int y_index = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
144//          SkDEBUGF(("fy = %g, srcMaxY = %d, y_index = %d\n", SkFixedToFloat(fy), srcMaxY, y_index));
145            srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)((const char*)srcPixels + y_index * srcRB);
146            if (scale == 256)
147                while (--count >= 0)
148                {
149                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
150                    fx += dx;
151                    *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_X(srcPixels, x);
152                }
153            else
154                while (--count >= 0)
155                {
156                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
157                    SkPMColor c = NOFILTER_BITMAP_SHADER_SAMPLE_X(srcPixels, x);
158                    fx += dx;
159                    *dstC++ = SkAlphaMulQ(c, scale);
160                }
161        }
162        else    // dy != 0
163        {
164            if (scale == 256)
165                while (--count >= 0)
166                {
167                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
168                    unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
169                    fx += dx;
170                    fy += dy;
171                    *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
172                }
173            else
174                while (--count >= 0)
175                {
176                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
177                    unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
178                    SkPMColor c = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
179                    fx += dx;
180                    fy += dy;
181                    *dstC++ = SkAlphaMulQ(c, scale);
182                }
183        }
184
185        NOFILTER_BITMAP_SHADER_POSTAMBLE(srcBitmap);
186    }
187
188    virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count)
189    {
190        SkASSERT(count > 0);
191        SkASSERT(this->getFlags() & SkShader::kHasSpan16_Flag);
192
193#ifdef NOFILTER_BITMAP_SHADER_SPRITEPROC16
194        if ((this->getTotalInverse().getType() & ~SkMatrix::kTranslate_Mask) == 0)
195        {
196            NOFILTER_BITMAP_SHADER_SPRITEPROC16(this, x, y, dstC, count);
197            return;
198        }
199#endif
200
201#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
202        const SkMatrix& inv = this->getUnitInverse();
203        SkMatrix::MapPtProc invProc = this->getUnitInverseProc();
204#else
205        const SkMatrix& inv = this->getTotalInverse();
206        SkMatrix::MapPtProc invProc = this->getInverseMapPtProc();
207#endif
208        const SkBitmap& srcBitmap = this->getSrcBitmap();
209        unsigned        srcMaxX = srcBitmap.width() - 1;
210        unsigned        srcMaxY = srcBitmap.height() - 1;
211        unsigned        srcRB = srcBitmap.rowBytes();
212        SkFixed         fx, fy, dx, dy;
213
214        const NOFILTER_BITMAP_SHADER_TYPE* srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)srcBitmap.getPixels();
215        NOFILTER_BITMAP_SHADER_PREAMBLE16(srcBitmap, srcRB);
216
217        if (this->getInverseClass() == kPerspective_MatrixClass)
218        {
219            SkPerspIter   iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
220                                    SkIntToScalar(y) + SK_ScalarHalf, count);
221            while ((count = iter.next()) != 0)
222            {
223                const SkFixed* srcXY = iter.getXY();
224
225                while (--count >= 0)
226                {
227                    fx = *srcXY++;
228                    fy = *srcXY++;
229                    unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
230                    unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
231                    *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY16(srcPixels, x, y, srcRB);
232                }
233            }
234            return;
235        }
236
237        // now init fx, fy, dx, dy
238        {
239            SkPoint srcPt;
240            invProc(inv, SkIntToScalar(x) + SK_ScalarHalf,
241                         SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
242
243            fx = SkScalarToFixed(srcPt.fX);
244            fy = SkScalarToFixed(srcPt.fY);
245
246            if (this->getInverseClass() == kFixedStepInX_MatrixClass)
247                (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
248            else
249            {
250                dx = SkScalarToFixed(inv.getScaleX());
251                dy = SkScalarToFixed(inv.getSkewY());
252            }
253        }
254
255#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
256        {   int level = this->getMipLevel() >> 16;
257            fx >>= level;
258            fy >>= level;
259            dx >>= level;
260            dy >>= level;
261        }
262#endif
263
264        if (dy == 0)
265        {
266            srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)((const char*)srcPixels + NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY) * srcRB);
267            do {
268                unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
269                fx += dx;
270                *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_X16(srcPixels, x);
271            } while (--count != 0);
272        }
273        else    // dy != 0
274        {
275            do {
276                unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
277                unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
278                fx += dx;
279                fy += dy;
280                *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY16(srcPixels, x, y, srcRB);
281            } while (--count != 0);
282        }
283
284        NOFILTER_BITMAP_SHADER_POSTAMBLE16(srcBitmap);
285    }
286private:
287    typedef HasSpan16_Sampler_BitmapShader INHERITED;
288};
289
290#undef NOFILTER_BITMAP_SHADER_CLASS
291#undef NOFILTER_BITMAP_SHADER_TYPE
292#undef NOFILTER_BITMAP_SHADER_PREAMBLE
293#undef NOFILTER_BITMAP_SHADER_POSTAMBLE
294#undef NOFILTER_BITMAP_SHADER_SAMPLE_X      //(x)
295#undef NOFILTER_BITMAP_SHADER_SAMPLE_XY     //(x, y, rowBytes)
296#undef NOFILTER_BITMAP_SHADER_TILEMODE
297#undef NOFILTER_BITMAP_SHADER_TILEPROC
298
299#undef NOFILTER_BITMAP_SHADER_PREAMBLE16
300#undef NOFILTER_BITMAP_SHADER_POSTAMBLE16
301#undef NOFILTER_BITMAP_SHADER_SAMPLE_X16        //(x)
302#undef NOFILTER_BITMAP_SHADER_SAMPLE_XY16       //(x, y, rowBytes)
303
304#undef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
305#undef NOFILTER_BITMAP_SHADER_SPRITEPROC16
306#undef NOFILTER_BITMAP_SHADER_SPRITEPROC32
307