OLD | NEW |
| (Empty) |
1 /* libs/graphics/sgl/SkBitmapSampler.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkBitmapSampler.h" | |
19 | |
20 static SkTileModeProc get_tilemode_proc(SkShader::TileMode mode) | |
21 { | |
22 switch (mode) { | |
23 case SkShader::kClamp_TileMode: | |
24 return do_clamp; | |
25 case SkShader::kRepeat_TileMode: | |
26 return do_repeat_mod; | |
27 case SkShader::kMirror_TileMode: | |
28 return do_mirror_mod; | |
29 default: | |
30 SkASSERT(!"unknown mode"); | |
31 return NULL; | |
32 } | |
33 } | |
34 | |
35 SkBitmapSampler::SkBitmapSampler(const SkBitmap& bm, bool filter, | |
36 SkShader::TileMode tmx, SkShader::TileMode tmy) | |
37 : fBitmap(bm), fFilterBitmap(filter), fTileModeX(tmx), fTileModeY(tmy) | |
38 { | |
39 SkASSERT(bm.width() > 0 && bm.height() > 0); | |
40 | |
41 fMaxX = SkToU16(bm.width() - 1); | |
42 fMaxY = SkToU16(bm.height() - 1); | |
43 | |
44 fTileProcX = get_tilemode_proc(tmx); | |
45 fTileProcY = get_tilemode_proc(tmy); | |
46 } | |
47 | |
48 void SkBitmapSampler::setPaint(const SkPaint& paint) | |
49 { | |
50 } | |
51 | |
52 class SkNullBitmapSampler : public SkBitmapSampler { | |
53 public: | |
54 SkNullBitmapSampler(const SkBitmap& bm, bool filter, | |
55 SkShader::TileMode tmx, SkShader::TileMode tmy) | |
56 : SkBitmapSampler(bm, filter, tmx, tmy) {} | |
57 | |
58 virtual SkPMColor sample(SkFixed x, SkFixed y) const { return 0; } | |
59 }; | |
60 | |
61 ////////////////////////////////////////////////////////////////////////////////
/ | |
62 ////////////////////////////////////////////////////////////////////////////////
/ | |
63 | |
64 #define BITMAP_CLASSNAME_PREFIX(name) ARGB32##name | |
65 #define BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) *bitmap.getAddr32(x, y) | |
66 #include "SkBitmapSamplerTemplate.h" | |
67 | |
68 #include "SkColorPriv.h" | |
69 | |
70 #define BITMAP_CLASSNAME_PREFIX(name) RGB16##name | |
71 #define BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) SkPixel16ToPixel32(*bitmap.getAd
dr16(x, y)) | |
72 #include "SkBitmapSamplerTemplate.h" | |
73 | |
74 #define BITMAP_CLASSNAME_PREFIX(name) Index8##name | |
75 #define BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) bitmap.getIndex8Color(x, y) | |
76 #include "SkBitmapSamplerTemplate.h" | |
77 | |
78 ////////////////////////////////////////////////////////////////////////////////
/ | |
79 ////////////////////////////////////////////////////////////////////////////////
/ | |
80 ///////////////// The Bilinear versions | |
81 | |
82 #include "SkFilterProc.h" | |
83 | |
84 class ARGB32_Bilinear_Sampler : public SkBitmapSampler { | |
85 public: | |
86 ARGB32_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader
::TileMode tmy) | |
87 : SkBitmapSampler(bm, true, tmx, tmy) | |
88 { | |
89 fPtrProcTable = SkGetBilinearFilterPtrProcTable(); | |
90 } | |
91 | |
92 virtual SkPMColor sample(SkFixed x, SkFixed y) const | |
93 { | |
94 const uint32_t *p00, *p01, *p10, *p11; | |
95 | |
96 // turn pixel centers into the top-left of our filter-box | |
97 x -= SK_FixedHalf; | |
98 y -= SK_FixedHalf; | |
99 | |
100 // compute our pointers | |
101 { | |
102 const SkBitmap* bitmap = &fBitmap; | |
103 int ix = x >> 16; | |
104 int iy = y >> 16; | |
105 | |
106 int maxX = fMaxX; | |
107 SkTileModeProc procX = fTileProcX; | |
108 int maxY = fMaxY; | |
109 SkTileModeProc procY = fTileProcY; | |
110 | |
111 int tmpx = procX(ix, maxX); | |
112 int tmpy = procY(iy, maxY); | |
113 p00 = bitmap->getAddr32(tmpx, tmpy); | |
114 | |
115 int tmpx1 = procX(ix + 1, maxX); | |
116 p01 = bitmap->getAddr32(tmpx1, tmpy); | |
117 | |
118 int tmpy1 = procY(iy + 1, maxY); | |
119 p10 = bitmap->getAddr32(tmpx, tmpy1); | |
120 | |
121 p11 = bitmap->getAddr32(tmpx1, tmpy1); | |
122 } | |
123 | |
124 SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(fPtrProcTable, x, y); | |
125 return proc(p00, p01, p10, p11); | |
126 } | |
127 | |
128 private: | |
129 const SkFilterPtrProc* fPtrProcTable; | |
130 }; | |
131 | |
132 class RGB16_Bilinear_Sampler : public SkBitmapSampler { | |
133 public: | |
134 RGB16_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader:
:TileMode tmy) | |
135 : SkBitmapSampler(bm, true, tmx, tmy) | |
136 { | |
137 fProcTable = SkGetBilinearFilterProcTable(); | |
138 } | |
139 | |
140 virtual SkPMColor sample(SkFixed x, SkFixed y) const | |
141 { | |
142 const uint16_t *p00, *p01, *p10, *p11; | |
143 | |
144 // turn pixel centers into the top-left of our filter-box | |
145 x -= SK_FixedHalf; | |
146 y -= SK_FixedHalf; | |
147 | |
148 // compute our pointers | |
149 { | |
150 const SkBitmap* bitmap = &fBitmap; | |
151 int ix = x >> 16; | |
152 int iy = y >> 16; | |
153 | |
154 int maxX = fMaxX; | |
155 SkTileModeProc procX = fTileProcX; | |
156 int maxY = fMaxY; | |
157 SkTileModeProc procY = fTileProcY; | |
158 | |
159 int tmpx = procX(ix, maxX); | |
160 int tmpy = procY(iy, maxY); | |
161 p00 = bitmap->getAddr16(tmpx, tmpy); | |
162 | |
163 int tmpx1 = procX(ix + 1, maxX); | |
164 p01 = bitmap->getAddr16(tmpx1, tmpy); | |
165 | |
166 int tmpy1 = procY(iy + 1, maxY); | |
167 p10 = bitmap->getAddr16(tmpx, tmpy1); | |
168 | |
169 p11 = bitmap->getAddr16(tmpx1, tmpy1); | |
170 } | |
171 | |
172 SkFilterProc proc = SkGetBilinearFilterProc(fProcTable, x, y); | |
173 uint32_t c = proc(SkExpand_rgb_16(*p00), SkExpand_rgb_16(*p01), | |
174 SkExpand_rgb_16(*p10), SkExpand_rgb_16(*p11)); | |
175 | |
176 return SkPixel16ToPixel32((uint16_t)SkCompact_rgb_16(c)); | |
177 } | |
178 | |
179 private: | |
180 const SkFilterProc* fProcTable; | |
181 }; | |
182 | |
183 // If we had a init/term method on sampler, we could avoid the per-pixel | |
184 // call to lockColors/unlockColors | |
185 | |
186 class Index8_Bilinear_Sampler : public SkBitmapSampler { | |
187 public: | |
188 Index8_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader
::TileMode tmy) | |
189 : SkBitmapSampler(bm, true, tmx, tmy) | |
190 { | |
191 fPtrProcTable = SkGetBilinearFilterPtrProcTable(); | |
192 } | |
193 | |
194 virtual SkPMColor sample(SkFixed x, SkFixed y) const | |
195 { | |
196 const SkBitmap* bitmap = &fBitmap; | |
197 | |
198 const uint8_t *p00, *p01, *p10, *p11; | |
199 | |
200 // turn pixel centers into the top-left of our filter-box | |
201 x -= SK_FixedHalf; | |
202 y -= SK_FixedHalf; | |
203 | |
204 // compute our pointers | |
205 { | |
206 int ix = x >> 16; | |
207 int iy = y >> 16; | |
208 | |
209 int maxX = fMaxX; | |
210 SkTileModeProc procX = fTileProcX; | |
211 int maxY = fMaxY; | |
212 SkTileModeProc procY = fTileProcY; | |
213 | |
214 int tmpx = procX(ix, maxX); | |
215 int tmpy = procY(iy, maxY); | |
216 p00 = bitmap->getAddr8(tmpx, tmpy); | |
217 | |
218 int tmpx1 = procX(ix + 1, maxX); | |
219 p01 = bitmap->getAddr8(tmpx1, tmpy); | |
220 | |
221 int tmpy1 = procY(iy + 1, maxY); | |
222 p10 = bitmap->getAddr8(tmpx, tmpy1); | |
223 | |
224 p11 = bitmap->getAddr8(tmpx1, tmpy1); | |
225 } | |
226 | |
227 const SkPMColor* colors = bitmap->getColorTable()->lockColors(); | |
228 | |
229 SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(fPtrProcTable, x, y); | |
230 uint32_t c = proc(&colors[*p00], &colors[*p01], &colors[*p10], &colors[*
p11]); | |
231 | |
232 bitmap->getColorTable()->unlockColors(false); | |
233 | |
234 return c; | |
235 } | |
236 | |
237 private: | |
238 const SkFilterPtrProc* fPtrProcTable; | |
239 }; | |
240 | |
241 class A8_Bilinear_Sampler : public SkBitmapSampler { | |
242 public: | |
243 A8_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::Ti
leMode tmy) | |
244 : SkBitmapSampler(bm, true, tmx, tmy) | |
245 { | |
246 fProcTable = SkGetBilinearFilterProcTable(); | |
247 } | |
248 | |
249 virtual void setPaint(const SkPaint& paint) | |
250 { | |
251 fColor = SkPreMultiplyColor(paint.getColor()); | |
252 } | |
253 | |
254 virtual SkPMColor sample(SkFixed x, SkFixed y) const | |
255 { | |
256 const uint8_t *p00, *p01, *p10, *p11; | |
257 | |
258 // turn pixel centers into the top-left of our filter-box | |
259 x -= SK_FixedHalf; | |
260 y -= SK_FixedHalf; | |
261 | |
262 // compute our pointers | |
263 { | |
264 const SkBitmap* bitmap = &fBitmap; | |
265 int ix = x >> 16; | |
266 int iy = y >> 16; | |
267 | |
268 int maxX = fMaxX; | |
269 SkTileModeProc procX = fTileProcX; | |
270 int maxY = fMaxY; | |
271 SkTileModeProc procY = fTileProcY; | |
272 | |
273 int tmpx = procX(ix, maxX); | |
274 int tmpy = procY(iy, maxY); | |
275 p00 = bitmap->getAddr8(tmpx, tmpy); | |
276 | |
277 int tmpx1 = procX(ix + 1, maxX); | |
278 p01 = bitmap->getAddr8(tmpx1, tmpy); | |
279 | |
280 int tmpy1 = procY(iy + 1, maxY); | |
281 p10 = bitmap->getAddr8(tmpx, tmpy1); | |
282 | |
283 p11 = bitmap->getAddr8(tmpx1, tmpy1); | |
284 } | |
285 | |
286 SkFilterProc proc = SkGetBilinearFilterProc(fProcTable, x, y); | |
287 int alpha = proc(*p00, *p01, *p10, *p11); | |
288 return SkAlphaMulQ(fColor, SkAlpha255To256(alpha)); | |
289 } | |
290 | |
291 private: | |
292 const SkFilterProc* fProcTable; | |
293 SkPMColor fColor; | |
294 }; | |
295 | |
296 class A8_NoFilter_Sampler : public SkBitmapSampler { | |
297 public: | |
298 A8_NoFilter_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::Ti
leMode tmy) | |
299 : SkBitmapSampler(bm, false, tmx, tmy) | |
300 { | |
301 } | |
302 | |
303 virtual void setPaint(const SkPaint& paint) | |
304 { | |
305 fColor = SkPreMultiplyColor(paint.getColor()); | |
306 } | |
307 | |
308 virtual SkPMColor sample(SkFixed x, SkFixed y) const | |
309 { | |
310 int ix = SkFixedFloor(x); | |
311 int iy = SkFixedFloor(y); | |
312 | |
313 int alpha = *fBitmap.getAddr8(fTileProcX(ix, fMaxX), fTileProcY(iy, fMax
Y)); | |
314 return SkAlphaMulQ(fColor, SkAlpha255To256(alpha)); | |
315 } | |
316 | |
317 private: | |
318 const SkFilterProc* fProcTable; | |
319 SkPMColor fColor; | |
320 }; | |
321 | |
322 /////////////////////////////////////////////////////////////////////////////// | |
323 /////////////////////////////////////////////////////////////////////////////// | |
324 | |
325 SkBitmapSampler* SkBitmapSampler::Create(const SkBitmap& bm, bool doFilter, | |
326 SkShader::TileMode tmx, | |
327 SkShader::TileMode tmy) | |
328 { | |
329 switch (bm.getConfig()) { | |
330 case SkBitmap::kARGB_8888_Config: | |
331 if (doFilter) | |
332 return SkNEW_ARGS(ARGB32_Bilinear_Sampler, (bm, tmx, tmy)); | |
333 | |
334 if (tmx == tmy) { | |
335 switch (tmx) { | |
336 case SkShader::kClamp_TileMode: | |
337 return SkNEW_ARGS(ARGB32_Point_Clamp_Sampler, (bm)); | |
338 case SkShader::kRepeat_TileMode: | |
339 if (is_pow2(bm.width()) && is_pow2(bm.height())) | |
340 return SkNEW_ARGS(ARGB32_Point_Repeat_Pow2_Sampler, (bm)); | |
341 else | |
342 return SkNEW_ARGS(ARGB32_Point_Repeat_Mod_Sampler, (bm)); | |
343 case SkShader::kMirror_TileMode: | |
344 if (is_pow2(bm.width()) && is_pow2(bm.height())) | |
345 return SkNEW_ARGS(ARGB32_Point_Mirror_Pow2_Sampler, (bm)); | |
346 else | |
347 return SkNEW_ARGS(ARGB32_Point_Mirror_Mod_Sampler, (bm)); | |
348 default: | |
349 SkASSERT(!"unknown mode"); | |
350 } | |
351 } | |
352 else { // tmx != tmy | |
353 return SkNEW_ARGS(ARGB32_Point_Sampler, (bm, tmx, tmy)); | |
354 } | |
355 break; | |
356 | |
357 case SkBitmap::kRGB_565_Config: | |
358 if (doFilter) | |
359 return SkNEW_ARGS(RGB16_Bilinear_Sampler, (bm, tmx, tmy)); | |
360 | |
361 if (tmx == tmy) { | |
362 switch (tmx) { | |
363 case SkShader::kClamp_TileMode: | |
364 return SkNEW_ARGS(RGB16_Point_Clamp_Sampler, (bm)); | |
365 case SkShader::kRepeat_TileMode: | |
366 if (is_pow2(bm.width()) && is_pow2(bm.height())) | |
367 return SkNEW_ARGS(RGB16_Point_Repeat_Pow2_Sampler, (bm)); | |
368 else | |
369 return SkNEW_ARGS(RGB16_Point_Repeat_Mod_Sampler, (bm)); | |
370 case SkShader::kMirror_TileMode: | |
371 if (is_pow2(bm.width()) && is_pow2(bm.height())) | |
372 return SkNEW_ARGS(RGB16_Point_Mirror_Pow2_Sampler, (bm)); | |
373 else | |
374 return SkNEW_ARGS(RGB16_Point_Mirror_Mod_Sampler, (bm)); | |
375 default: | |
376 SkASSERT(!"unknown mode"); | |
377 } | |
378 } | |
379 else { // tmx != tmy | |
380 return SkNEW_ARGS(RGB16_Point_Sampler, (bm, tmx, tmy)); | |
381 } | |
382 break; | |
383 | |
384 case SkBitmap::kIndex8_Config: | |
385 if (doFilter) | |
386 return SkNEW_ARGS(Index8_Bilinear_Sampler, (bm, tmx, tmy)); | |
387 | |
388 if (tmx == tmy) { | |
389 switch (tmx) { | |
390 case SkShader::kClamp_TileMode: | |
391 return SkNEW_ARGS(Index8_Point_Clamp_Sampler, (bm)); | |
392 case SkShader::kRepeat_TileMode: | |
393 if (is_pow2(bm.width()) && is_pow2(bm.height())) | |
394 return SkNEW_ARGS(Index8_Point_Repeat_Pow2_Sampler, (bm)); | |
395 else | |
396 return SkNEW_ARGS(Index8_Point_Repeat_Mod_Sampler, (bm)); | |
397 case SkShader::kMirror_TileMode: | |
398 if (is_pow2(bm.width()) && is_pow2(bm.height())) | |
399 return SkNEW_ARGS(Index8_Point_Mirror_Pow2_Sampler, (bm)); | |
400 else | |
401 return SkNEW_ARGS(Index8_Point_Mirror_Mod_Sampler, (bm)); | |
402 default: | |
403 SkASSERT(!"unknown mode"); | |
404 } | |
405 } | |
406 else { // tmx != tmy | |
407 return SkNEW_ARGS(Index8_Point_Sampler, (bm, tmx, tmy)); | |
408 } | |
409 break; | |
410 | |
411 case SkBitmap::kA8_Config: | |
412 if (doFilter) | |
413 return SkNEW_ARGS(A8_Bilinear_Sampler, (bm, tmx, tmy)); | |
414 else | |
415 return SkNEW_ARGS(A8_NoFilter_Sampler, (bm, tmx, tmy)); | |
416 break; | |
417 | |
418 default: | |
419 SkASSERT(!"unknown device"); | |
420 } | |
421 return SkNEW_ARGS(SkNullBitmapSampler, (bm, doFilter, tmx, tmy)); | |
422 } | |
423 | |
OLD | NEW |