| 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 |