1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkBitmapProcState_MatrixTemplates_DEFINED
9 #define SkBitmapProcState_MatrixTemplates_DEFINED
10 
11 #include "SkMath.h"
12 #include "SkMathPriv.h"
13 
14 template <typename TileProc, bool tryDecal>
NoFilterProc_Scale(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)15 void NoFilterProc_Scale(const SkBitmapProcState& s, uint32_t xy[],
16                         int count, int x, int y) {
17     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
18                              SkMatrix::kScale_Mask)) == 0);
19 
20     // we store y, x, x, x, x, x
21 
22     const unsigned maxX = s.fPixmap.width() - 1;
23     SkFractionalInt fx;
24     {
25         const SkBitmapProcStateAutoMapper mapper(s, x, y);
26         const unsigned maxY = s.fPixmap.height() - 1;
27         *xy++ = TileProc::Y(s, mapper.fixedY(), maxY);
28         fx = mapper.fractionalIntX();
29     }
30 
31     if (0 == maxX) {
32         // all of the following X values must be 0
33         memset(xy, 0, count * sizeof(uint16_t));
34         return;
35     }
36 
37     const SkFractionalInt dx = s.fInvSxFractionalInt;
38 
39     if (tryDecal && can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
40         decal_nofilter_scale(xy, SkFractionalIntToFixed(fx),
41                              SkFractionalIntToFixed(dx), count);
42     } else {
43         int i;
44         for (i = (count >> 2); i > 0; --i) {
45             unsigned a, b;
46             a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
47             b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
48 #ifdef SK_CPU_BENDIAN
49             *xy++ = (a << 16) | b;
50 #else
51             *xy++ = (b << 16) | a;
52 #endif
53             a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
54             b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
55 #ifdef SK_CPU_BENDIAN
56             *xy++ = (a << 16) | b;
57 #else
58             *xy++ = (b << 16) | a;
59 #endif
60         }
61         uint16_t* xx = (uint16_t*)xy;
62         for (i = (count & 3); i > 0; --i) {
63             *xx++ = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
64         }
65     }
66 }
67 
68 // note: we could special-case on a matrix which is skewed in X but not Y.
69 // this would require a more general setup thatn SCALE does, but could use
70 // SCALE's inner loop that only looks at dx
71 
72 template <typename TileProc>
NoFilterProc_Affine(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)73 void NoFilterProc_Affine(const SkBitmapProcState& s, uint32_t xy[],
74                          int count, int x, int y) {
75     SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
76     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
77                              SkMatrix::kScale_Mask |
78                              SkMatrix::kAffine_Mask)) == 0);
79 
80     const SkBitmapProcStateAutoMapper mapper(s, x, y);
81 
82     SkFractionalInt fx = mapper.fractionalIntX();
83     SkFractionalInt fy = mapper.fractionalIntY();
84     SkFractionalInt dx = s.fInvSxFractionalInt;
85     SkFractionalInt dy = s.fInvKyFractionalInt;
86     int maxX = s.fPixmap.width() - 1;
87     int maxY = s.fPixmap.height() - 1;
88 
89     for (int i = count; i > 0; --i) {
90         *xy++ = (TileProc::Y(s, SkFractionalIntToFixed(fy), maxY) << 16) |
91                  TileProc::X(s, SkFractionalIntToFixed(fx), maxX);
92         fx += dx; fy += dy;
93     }
94 }
95 
96 template <typename TileProc>
NoFilterProc_Persp(const SkBitmapProcState & s,uint32_t * SK_RESTRICT xy,int count,int x,int y)97 void NoFilterProc_Persp(const SkBitmapProcState& s, uint32_t* SK_RESTRICT xy,
98                         int count, int x, int y) {
99     SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
100 
101     int maxX = s.fPixmap.width() - 1;
102     int maxY = s.fPixmap.height() - 1;
103 
104     SkPerspIter   iter(s.fInvMatrix,
105                        SkIntToScalar(x) + SK_ScalarHalf,
106                        SkIntToScalar(y) + SK_ScalarHalf, count);
107 
108     while ((count = iter.next()) != 0) {
109         const SkFixed* SK_RESTRICT srcXY = iter.getXY();
110         while (--count >= 0) {
111             *xy++ = (TileProc::Y(s, srcXY[1], maxY) << 16) |
112                      TileProc::X(s, srcXY[0], maxX);
113             srcXY += 2;
114         }
115     }
116 }
117 
118 #endif
119