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 #ifndef SkBitmapSampler_DEFINED
11 #define SkBitmapSampler_DEFINED
12
13 #include "SkBitmap.h"
14 #include "SkPaint.h"
15 #include "SkShader.h"
16
17 typedef int (*SkTileModeProc)(int value, unsigned max);
18
19 class SkBitmapSampler {
20 public:
21 SkBitmapSampler(const SkBitmap&, bool filter, SkShader::TileMode tmx, SkShader::TileMode tmy);
~SkBitmapSampler()22 virtual ~SkBitmapSampler() {}
23
getBitmap()24 const SkBitmap& getBitmap() const { return fBitmap; }
getFilterBitmap()25 bool getFilterBitmap() const { return fFilterBitmap; }
getTileModeX()26 SkShader::TileMode getTileModeX() const { return fTileModeX; }
getTileModeY()27 SkShader::TileMode getTileModeY() const { return fTileModeY; }
28
29 /** Given a pixel center at [x,y], return the color sample
30 */
31 virtual SkPMColor sample(SkFixed x, SkFixed y) const = 0;
32
33 virtual void setPaint(const SkPaint& paint);
34
35 // This is the factory for finding an optimal subclass
36 static SkBitmapSampler* Create(const SkBitmap&, bool filter,
37 SkShader::TileMode tmx, SkShader::TileMode tmy);
38
39 protected:
40 const SkBitmap& fBitmap;
41 uint16_t fMaxX, fMaxY;
42 bool fFilterBitmap;
43 SkShader::TileMode fTileModeX;
44 SkShader::TileMode fTileModeY;
45 SkTileModeProc fTileProcX;
46 SkTileModeProc fTileProcY;
47
48 // illegal
49 SkBitmapSampler& operator=(const SkBitmapSampler&);
50 };
51
fixed_clamp(SkFixed x)52 static inline int fixed_clamp(SkFixed x)
53 {
54 #ifdef SK_CPU_HAS_CONDITIONAL_INSTR
55 if (x >> 16)
56 x = 0xFFFF;
57 if (x < 0)
58 x = 0;
59 #else
60 if (x >> 16)
61 {
62 if (x < 0)
63 x = 0;
64 else
65 x = 0xFFFF;
66 }
67 #endif
68 return x;
69 }
70
71 //////////////////////////////////////////////////////////////////////////////////////
72
fixed_repeat(SkFixed x)73 static inline int fixed_repeat(SkFixed x)
74 {
75 return x & 0xFFFF;
76 }
77
fixed_mirror(SkFixed x)78 static inline int fixed_mirror(SkFixed x)
79 {
80 SkFixed s = x << 15 >> 31;
81 // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
82 return (x ^ s) & 0xFFFF;
83 }
84
is_pow2(int count)85 static inline bool is_pow2(int count)
86 {
87 SkASSERT(count > 0);
88 return (count & (count - 1)) == 0;
89 }
90
do_clamp(int index,unsigned max)91 static inline int do_clamp(int index, unsigned max)
92 {
93 SkASSERT((int)max >= 0);
94
95 #ifdef SK_CPU_HAS_CONDITIONAL_INSTR
96 if (index > (int)max)
97 index = max;
98 if (index < 0)
99 index = 0;
100 #else
101 if ((unsigned)index > max)
102 {
103 if (index < 0)
104 index = 0;
105 else
106 index = max;
107 }
108 #endif
109 return index;
110 }
111
do_repeat_mod(int index,unsigned max)112 static inline int do_repeat_mod(int index, unsigned max)
113 {
114 SkASSERT((int)max >= 0);
115
116 if ((unsigned)index > max)
117 {
118 if (index < 0)
119 index = max - (~index % (max + 1));
120 else
121 index = index % (max + 1);
122 }
123 return index;
124 }
125
do_repeat_pow2(int index,unsigned max)126 static inline int do_repeat_pow2(int index, unsigned max)
127 {
128 SkASSERT((int)max >= 0 && is_pow2(max + 1));
129
130 return index & max;
131 }
132
do_mirror_mod(int index,unsigned max)133 static inline int do_mirror_mod(int index, unsigned max)
134 {
135 SkASSERT((int)max >= 0);
136
137 // have to handle negatives so that
138 // -1 -> 0, -2 -> 1, -3 -> 2, etc.
139 // so we can't just cal abs
140 index ^= index >> 31;
141
142 if ((unsigned)index > max)
143 {
144 int mod = (max + 1) << 1;
145 index = index % mod;
146 if ((unsigned)index > max)
147 index = mod - index - 1;
148 }
149 return index;
150 }
151
do_mirror_pow2(int index,unsigned max)152 static inline int do_mirror_pow2(int index, unsigned max)
153 {
154 SkASSERT((int)max >= 0 && is_pow2(max + 1));
155
156 int s = (index & (max + 1)) - 1;
157 s = ~(s >> 31);
158 // at this stage, s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
159 return (index ^ s) & max;
160 }
161
162 #endif
163