| OLD | NEW |
| (Empty) |
| 1 /* Copyright 2006, The Android Open Source Project | |
| 2 ** | |
| 3 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 ** you may not use this file except in compliance with the License. | |
| 5 ** You may obtain a copy of the License at | |
| 6 ** | |
| 7 ** http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 ** | |
| 9 ** Unless required by applicable law or agreed to in writing, software | |
| 10 ** distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 ** See the License for the specific language governing permissions and | |
| 13 ** limitations under the License. | |
| 14 */ | |
| 15 | |
| 16 #if 0 | |
| 17 | |
| 18 #include "SkBitmapShader.h" | |
| 19 #include "SkBitmapSampler.h" | |
| 20 | |
| 21 #ifdef SK_SUPPORT_MIPMAP | |
| 22 static SkFixed find_mip_level(SkFixed dx, SkFixed dy) | |
| 23 { | |
| 24 dx = SkAbs32(dx); | |
| 25 dy = SkAbs32(dy); | |
| 26 if (dx < dy) | |
| 27 dx = dy; | |
| 28 | |
| 29 if (dx < SK_Fixed1) | |
| 30 return 0; | |
| 31 | |
| 32 int clz = SkCLZ(dx); | |
| 33 SkASSERT(clz >= 1 && clz <= 15); | |
| 34 return SkIntToFixed(15 - clz) + ((unsigned)(dx << (clz + 1)) >> 16); | |
| 35 } | |
| 36 #endif | |
| 37 | |
| 38 SkBitmapShader::SkBitmapShader(const SkBitmap& src, bool doFilter, | |
| 39 TileMode tmx, TileMode tmy) | |
| 40 : | |
| 41 #ifdef SK_SUPPORT_MIPMAP | |
| 42 fMipLevel(0), fMipSrcBitmap(src), | |
| 43 #endif | |
| 44 fOrigSrcBitmap(src) | |
| 45 | |
| 46 { | |
| 47 fFilterBitmap = doFilter; | |
| 48 fTileModeX = SkToU8(tmx); | |
| 49 fTileModeY = SkToU8(tmy); | |
| 50 } | |
| 51 | |
| 52 SkBitmapShader::SkBitmapShader(SkFlattenableReadBuffer& buffer) : | |
| 53 INHERITED(buffer) | |
| 54 { | |
| 55 Bitmap src; | |
| 56 buffer.readBitmap(&src); | |
| 57 #ifdef SK_SUPPORT_MIPMAP | |
| 58 fMipLevel = 0; | |
| 59 fMipSrcBitmap = src; | |
| 60 #endif | |
| 61 fOrigSrcBitmap = src; | |
| 62 fFilterBitmap = buffer.readU8(); | |
| 63 fTileModeX = buffer.readU8(); | |
| 64 fTileModeY = buffer.readU8(); | |
| 65 } | |
| 66 | |
| 67 void SkBitmapShader::flatten(SkFlattenableWriteBuffer& buffer) | |
| 68 { | |
| 69 this->INHERITED::flatten(buffer); | |
| 70 buffer.writeBitmap(&fOrigSrcBitmap); | |
| 71 buffer.write8(fFilterBitmap); | |
| 72 buffer.write8(fTileModeX); | |
| 73 buffer.write8(fTileModeY); | |
| 74 } | |
| 75 | |
| 76 bool SkBitmapShader::setContext(const SkBitmap& device, const SkPaint& paint, co
nst SkMatrix& matrix) | |
| 77 { | |
| 78 // do this first, so we have a correct inverse matrix | |
| 79 if (!this->INHERITED::setContext(device, paint, matrix)) | |
| 80 return false; | |
| 81 | |
| 82 if (fOrigSrcBitmap.getConfig() == SkBitmap::kNo_Config || | |
| 83 fOrigSrcBitmap.width() == 0 || | |
| 84 fOrigSrcBitmap.height() == 0) | |
| 85 return false; | |
| 86 | |
| 87 SkBitmap& bm = fOrigSrcBitmap; | |
| 88 | |
| 89 #ifdef SK_SUPPORT_MIPMAP | |
| 90 if (fOrigSrcBitmap.countMipLevels()) | |
| 91 { | |
| 92 const SkMatrix& inv = this->getTotalInverse(); | |
| 93 | |
| 94 fMipLevel = SkMin32(find_mip_level( SkScalarToFixed(inv.getScaleX()), | |
| 95 SkScalarToFixed(inv.getSkewY())), | |
| 96 SkIntToFixed(fOrigSrcBitmap.countMipLevels() - 1)); | |
| 97 | |
| 98 // SkDEBUGF(("BitmapShader miplevel=%x\n", fMipLevel)); | |
| 99 | |
| 100 const SkBitmap::MipLevel* mm = fOrigSrcBitmap.getMipLevel(fMipLevel >> 1
6); | |
| 101 | |
| 102 fMipSrcBitmap.setConfig(fOrigSrcBitmap.getConfig(), | |
| 103 mm->fWidth, | |
| 104 mm->fHeight, | |
| 105 mm->fRowBytes); | |
| 106 fMipSrcBitmap.setPixels(mm->fPixels); | |
| 107 bm = fMipSrcBitmap; | |
| 108 } | |
| 109 else | |
| 110 { | |
| 111 fMipLevel = 0; | |
| 112 fMipSrcBitmap = fOrigSrcBitmap; | |
| 113 } | |
| 114 #endif | |
| 115 | |
| 116 fFlags = 0; | |
| 117 if (paint.getAlpha() == 255 && bm.isOpaque()) | |
| 118 fFlags |= kOpaqueAlpha_Flag; | |
| 119 | |
| 120 return true; | |
| 121 } | |
| 122 | |
| 123 /////////////////////////////////////////////////////////////////////////// | |
| 124 | |
| 125 #include "SkColorPriv.h" | |
| 126 #include "SkBitmapSampler.h" | |
| 127 #include "SkPerspIter.h" | |
| 128 | |
| 129 class Sampler_BitmapShader : public SkBitmapShader { | |
| 130 public: | |
| 131 Sampler_BitmapShader(const SkBitmap& src, bool doFilter, | |
| 132 TileMode tmx, TileMode tmy) | |
| 133 : SkBitmapShader(src, doFilter, tmx, tmy) | |
| 134 { | |
| 135 // make sure to pass our copy of the src bitmap to the sampler, and not
the | |
| 136 // original parameter (which might go away). | |
| 137 fSampler = NULL; | |
| 138 } | |
| 139 | |
| 140 virtual ~Sampler_BitmapShader() | |
| 141 { | |
| 142 SkDELETE(fSampler); | |
| 143 } | |
| 144 | |
| 145 virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const
SkMatrix& matrix) | |
| 146 { | |
| 147 if (this->INHERITED::setContext(device, paint, matrix)) | |
| 148 { | |
| 149 SkDELETE(fSampler); | |
| 150 fSampler = SkBitmapSampler::Create(this->getSrcBitmap(), this->getFi
lterBitmap(), | |
| 151 this->getTileModeX(), this->getTi
leModeY()); | |
| 152 fSampler->setPaint(paint); | |
| 153 return true; | |
| 154 } | |
| 155 return false; | |
| 156 } | |
| 157 | |
| 158 enum { | |
| 159 kMaxPointStorageCount = 32 | |
| 160 }; | |
| 161 | |
| 162 virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) | |
| 163 { | |
| 164 unsigned scale = SkAlpha255To256(this->getPaintAlpha()); | |
| 165 const SkMatrix& inv = this->getTotalInverse(); | |
| 166 SkMatrix::MapPtProc proc = this->getInverseMapPtProc(); | |
| 167 SkBitmapSampler* sampler = fSampler; | |
| 168 MatrixClass mc = this->getInverseClass(); | |
| 169 | |
| 170 SkPoint srcPt; | |
| 171 | |
| 172 if (mc != kPerspective_MatrixClass) | |
| 173 { | |
| 174 proc(inv, SkIntToScalar(x) + SK_ScalarHalf, | |
| 175 SkIntToScalar(y) + SK_ScalarHalf, &srcPt); | |
| 176 | |
| 177 SkFixed fx = SkScalarToFixed(srcPt.fX); | |
| 178 SkFixed fy = SkScalarToFixed(srcPt.fY); | |
| 179 SkFixed dx, dy; | |
| 180 | |
| 181 if (mc == kLinear_MatrixClass) | |
| 182 { | |
| 183 dx = SkScalarToFixed(inv.getScaleX()); | |
| 184 dy = SkScalarToFixed(inv.getSkewY()); | |
| 185 } | |
| 186 else | |
| 187 (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy); | |
| 188 | |
| 189 #if defined(SK_SUPPORT_MIPMAP) | |
| 190 { int level = this->getMipLevel() >> 16; | |
| 191 fx >>= level; | |
| 192 fy >>= level; | |
| 193 dx >>= level; | |
| 194 dy >>= level; | |
| 195 } | |
| 196 #endif | |
| 197 if (scale == 256) | |
| 198 { | |
| 199 for (int i = 0; i < count; i++) | |
| 200 { | |
| 201 dstC[i] = sampler->sample(fx, fy); | |
| 202 fx += dx; | |
| 203 fy += dy; | |
| 204 } | |
| 205 } | |
| 206 else | |
| 207 { | |
| 208 for (int i = 0; i < count; i++) | |
| 209 { | |
| 210 uint32_t c = sampler->sample(fx, fy); | |
| 211 dstC[i] = SkAlphaMulQ(c, scale); | |
| 212 fx += dx; | |
| 213 fy += dy; | |
| 214 } | |
| 215 } | |
| 216 } | |
| 217 else | |
| 218 { | |
| 219 SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf, | |
| 220 SkIntToScalar(y) + SK_ScalarHalf, count); | |
| 221 if (scale == 256) | |
| 222 { | |
| 223 while ((count = iter.next()) != 0) | |
| 224 { | |
| 225 const SkFixed* src = iter.getXY(); | |
| 226 for (int i = 0; i < count; i++) | |
| 227 { | |
| 228 *dstC++ = sampler->sample(src[0], src[1]); | |
| 229 src += 2; | |
| 230 } | |
| 231 } | |
| 232 } | |
| 233 else | |
| 234 { | |
| 235 while ((count = iter.next()) != 0) | |
| 236 { | |
| 237 const SkFixed* src = iter.getXY(); | |
| 238 for (int i = 0; i < count; i++) | |
| 239 { | |
| 240 uint32_t c = sampler->sample(src[0] - SK_FixedHalf, src[
1] - SK_FixedHalf); | |
| 241 *dstC++ = SkAlphaMulQ(c, scale); | |
| 242 src += 2; | |
| 243 } | |
| 244 } | |
| 245 } | |
| 246 } | |
| 247 } | |
| 248 | |
| 249 protected: | |
| 250 | |
| 251 const SkMatrix& getUnitInverse() const { return fUnitInverse; } | |
| 252 SkMatrix::MapPtProc getUnitInverseProc() const { return fUnitInverseProc; } | |
| 253 | |
| 254 /* takes computed inverse (from setContext) and computes fUnitInverse, | |
| 255 taking srcBitmap width/height into account, so that fUnitInverse | |
| 256 walks 0...1, allowing the tile modes to all operate in a fast 16bit | |
| 257 space (no need for mod). The resulting coords need to be scaled by | |
| 258 width/height to get back into src space (coord * width >> 16). | |
| 259 */ | |
| 260 void computeUnitInverse() | |
| 261 { | |
| 262 const SkBitmap& src = getSrcBitmap(); | |
| 263 fUnitInverse = this->getTotalInverse(); | |
| 264 fUnitInverse.postIDiv(src.width(), src.height()); | |
| 265 fUnitInverseProc = fUnitInverse.getMapPtProc(); | |
| 266 } | |
| 267 | |
| 268 private: | |
| 269 SkBitmapSampler* fSampler; | |
| 270 SkMatrix fUnitInverse; | |
| 271 SkMatrix::MapPtProc fUnitInverseProc; | |
| 272 | |
| 273 typedef SkBitmapShader INHERITED; | |
| 274 }; | |
| 275 | |
| 276 /////////////////////////////////////////////////////////////////////////// | |
| 277 | |
| 278 class HasSpan16_Sampler_BitmapShader : public Sampler_BitmapShader { | |
| 279 public: | |
| 280 HasSpan16_Sampler_BitmapShader(const SkBitmap& src, bool doFilter, | |
| 281 TileMode tmx, TileMode tmy) | |
| 282 : Sampler_BitmapShader(src, doFilter, tmx, tmy) | |
| 283 { | |
| 284 } | |
| 285 | |
| 286 virtual uint32_t getFlags() | |
| 287 { | |
| 288 uint32_t flags = this->INHERITED::getFlags(); | |
| 289 | |
| 290 switch (this->getSrcBitmap().getConfig()) { | |
| 291 case SkBitmap::kRGB_565_Config: | |
| 292 flags |= kHasSpan16_Flag; | |
| 293 break; | |
| 294 case SkBitmap::kIndex8_Config: | |
| 295 case SkBitmap::kARGB_8888_Config: | |
| 296 if (this->getSrcBitmap().isOpaque()) | |
| 297 flags |= kHasSpan16_Flag; | |
| 298 break; | |
| 299 default: | |
| 300 break; | |
| 301 } | |
| 302 return flags; | |
| 303 } | |
| 304 | |
| 305 const SkBitmap& revealSrcBitmap() const { return this->getSrcBitmap(); } | |
| 306 uint8_t revealPaintAlpha() const { return this->getPaintAlpha(); } | |
| 307 const SkMatrix& revealTotalInverse() const { return this->getTotalInverse();
} | |
| 308 | |
| 309 private: | |
| 310 typedef Sampler_BitmapShader INHERITED; | |
| 311 }; | |
| 312 | |
| 313 /////////////////////////////////////////////////////////////////////////// | |
| 314 | |
| 315 static void Index8_RepeatTile_Sprite16(HasSpan16_Sampler_BitmapShader* shader, | |
| 316 int x, int y, uint16_t dstC[], int count) | |
| 317 { | |
| 318 const SkMatrix& inv = shader->revealTotalInverse(); | |
| 319 const SkBitmap& srcBitmap = shader->revealSrcBitmap(); | |
| 320 int width = srcBitmap.width(); | |
| 321 int height = srcBitmap.height(); | |
| 322 | |
| 323 SkColorTable* ctable = srcBitmap.getColorTable(); | |
| 324 const uint16_t* colors = ctable->lock16BitCache(); | |
| 325 | |
| 326 x += SkScalarRound(inv[SkMatrix::kMTransX]); | |
| 327 y += SkScalarRound(inv[SkMatrix::kMTransY]); | |
| 328 | |
| 329 x = do_repeat_mod(x, width - 1); | |
| 330 y = do_repeat_mod(y, height - 1); | |
| 331 const uint8_t* row = srcBitmap.getAddr8(0, y); | |
| 332 const uint8_t* src = row + x; | |
| 333 | |
| 334 // do the first partial run | |
| 335 int n = width - x; | |
| 336 if (n > count) n = count; | |
| 337 count -= n; | |
| 338 SkASSERT(n > 0); | |
| 339 do { | |
| 340 *dstC++ = colors[*src++]; | |
| 341 } while (--n > 0); | |
| 342 | |
| 343 // do 1 complete run | |
| 344 if (count >= width) | |
| 345 { | |
| 346 uint16_t* baseDstC = dstC; // remember the first complete run start | |
| 347 n = width; | |
| 348 count -= width; | |
| 349 src = row; | |
| 350 do { | |
| 351 *dstC++ = colors[*src++]; | |
| 352 } while (--n > 0); | |
| 353 | |
| 354 // do the rest of the complete runs | |
| 355 while (count >= width) | |
| 356 { | |
| 357 count -= width; | |
| 358 memcpy(dstC, baseDstC, width << 1); | |
| 359 dstC += width; | |
| 360 } | |
| 361 // do final partial run | |
| 362 if (count > 0) | |
| 363 memcpy(dstC, baseDstC, count << 1); | |
| 364 } | |
| 365 else // do final partial | |
| 366 { | |
| 367 if (count > 0) | |
| 368 { | |
| 369 src = row; | |
| 370 do { | |
| 371 *dstC++ = colors[*src++]; | |
| 372 } while (--count > 0); | |
| 373 } | |
| 374 } | |
| 375 | |
| 376 ctable->unlock16BitCache(); | |
| 377 } | |
| 378 | |
| 379 static void Index8_RepeatTile_Sprite32(HasSpan16_Sampler_BitmapShader* shader, | |
| 380 int x, int y, SkPMColor dstC[], int count
) | |
| 381 { | |
| 382 const SkMatrix& inv = shader->revealTotalInverse(); | |
| 383 const SkBitmap& srcBitmap = shader->revealSrcBitmap(); | |
| 384 int width = srcBitmap.width(); | |
| 385 int height = srcBitmap.height(); | |
| 386 | |
| 387 SkColorTable* ctable = srcBitmap.getColorTable(); | |
| 388 const SkPMColor* colors = ctable->lockColors(); | |
| 389 | |
| 390 x += SkScalarRound(inv[SkMatrix::kMTransX]); | |
| 391 y += SkScalarRound(inv[SkMatrix::kMTransY]); | |
| 392 | |
| 393 x = do_repeat_mod(x, width - 1); | |
| 394 y = do_repeat_mod(y, height - 1); | |
| 395 | |
| 396 const uint8_t* row = srcBitmap.getAddr8(0, y); | |
| 397 const uint8_t* src = row + x; | |
| 398 | |
| 399 // do the first partial run | |
| 400 int n = width - x; | |
| 401 if (n > count) n = count; | |
| 402 count -= n; | |
| 403 SkASSERT(n > 0); | |
| 404 do { | |
| 405 *dstC++ = colors[*src++]; | |
| 406 } while (--n > 0); | |
| 407 | |
| 408 // do 1 complete run | |
| 409 if (count >= width) | |
| 410 { | |
| 411 SkPMColor* baseDstC = dstC; // remember the first complete run start | |
| 412 n = width; | |
| 413 count -= width; | |
| 414 src = row; | |
| 415 do { | |
| 416 *dstC++ = colors[*src++]; | |
| 417 } while (--n > 0); | |
| 418 | |
| 419 // do the rest of the complete runs | |
| 420 while (count >= width) | |
| 421 { | |
| 422 count -= width; | |
| 423 memcpy(dstC, baseDstC, width << 2); | |
| 424 dstC += width; | |
| 425 } | |
| 426 // do final partial run | |
| 427 if (count > 0) | |
| 428 memcpy(dstC, baseDstC, count << 2); | |
| 429 } | |
| 430 else // do final partial | |
| 431 { | |
| 432 if (count > 0) | |
| 433 { | |
| 434 src = row; | |
| 435 do { | |
| 436 *dstC++ = colors[*src++]; | |
| 437 } while (--count > 0); | |
| 438 } | |
| 439 } | |
| 440 | |
| 441 ctable->unlockColors(false); | |
| 442 } | |
| 443 | |
| 444 static void RGB16_RepeatTile_Sprite16(HasSpan16_Sampler_BitmapShader* shader, | |
| 445 int x, int y, uint16_t dstC[], int count) | |
| 446 { | |
| 447 SkASSERT(count > 0); | |
| 448 | |
| 449 const SkMatrix& inv = shader->revealTotalInverse(); | |
| 450 const SkBitmap& srcBitmap = shader->revealSrcBitmap(); | |
| 451 int width = srcBitmap.width(); | |
| 452 int height = srcBitmap.height(); | |
| 453 | |
| 454 SkASSERT(width > 0 && height > 0); | |
| 455 | |
| 456 x += SkScalarRound(inv[SkMatrix::kMTransX]); | |
| 457 y += SkScalarRound(inv[SkMatrix::kMTransY]); | |
| 458 | |
| 459 x = do_repeat_mod(x, width - 1); | |
| 460 y = do_repeat_mod(y, height - 1); | |
| 461 | |
| 462 const uint16_t* row = srcBitmap.getAddr16(0, y); | |
| 463 const uint16_t* src = row + x; | |
| 464 | |
| 465 int n = SkMin32(width - x, count); | |
| 466 | |
| 467 for (;;) | |
| 468 { | |
| 469 SkASSERT(n > 0 && count >= n); | |
| 470 memcpy(dstC, src, n << 1); | |
| 471 count -= n; | |
| 472 if (count == 0) | |
| 473 break; | |
| 474 dstC += n; | |
| 475 src = row; | |
| 476 n = SkMin32(width, count); | |
| 477 } | |
| 478 } | |
| 479 | |
| 480 static void RGB16_RepeatTile_Sprite32(HasSpan16_Sampler_BitmapShader* shader, | |
| 481 int x, int y, SkPMColor dstC[], int count
) | |
| 482 { | |
| 483 SkASSERT(count > 0); | |
| 484 | |
| 485 const SkMatrix& inv = shader->revealTotalInverse(); | |
| 486 const SkBitmap& srcBitmap = shader->revealSrcBitmap(); | |
| 487 int width = srcBitmap.width(); | |
| 488 int height = srcBitmap.height(); | |
| 489 | |
| 490 SkASSERT(width > 0 && height > 0); | |
| 491 | |
| 492 x += SkScalarRound(inv[SkMatrix::kMTransX]); | |
| 493 y += SkScalarRound(inv[SkMatrix::kMTransY]); | |
| 494 | |
| 495 x = do_repeat_mod(x, width - 1); | |
| 496 y = do_repeat_mod(y, height - 1); | |
| 497 | |
| 498 const uint16_t* row = srcBitmap.getAddr16(0, y); | |
| 499 const uint16_t* src = row + x; | |
| 500 | |
| 501 int n = SkMin32(width - x, count); | |
| 502 | |
| 503 // do the first partial run | |
| 504 count -= n; | |
| 505 SkASSERT(n > 0); | |
| 506 do { | |
| 507 *dstC++ = SkPixel16ToPixel32(*src++); | |
| 508 } while (--n > 0); | |
| 509 | |
| 510 // do 1 complete run | |
| 511 if (count >= width) | |
| 512 { | |
| 513 SkPMColor* baseDstC = dstC; // remember the first complete run start | |
| 514 n = width; | |
| 515 count -= width; | |
| 516 src = row; | |
| 517 do { | |
| 518 *dstC++ = SkPixel16ToPixel32(*src++); | |
| 519 } while (--n > 0); | |
| 520 | |
| 521 // do the rest of the complete runs | |
| 522 while (count >= width) | |
| 523 { | |
| 524 count -= width; | |
| 525 memcpy(dstC, baseDstC, width << 2); | |
| 526 dstC += width; | |
| 527 } | |
| 528 // do final partial run | |
| 529 if (count > 0) | |
| 530 memcpy(dstC, baseDstC, count << 2); | |
| 531 } | |
| 532 else // do final partial | |
| 533 { | |
| 534 if (count > 0) | |
| 535 { | |
| 536 src = row; | |
| 537 do { | |
| 538 *dstC++ = SkPixel16ToPixel32(*src++);; | |
| 539 } while (--count > 0); | |
| 540 } | |
| 541 } | |
| 542 } | |
| 543 | |
| 544 static void ARGB32_RepeatTile_Sprite16(HasSpan16_Sampler_BitmapShader* shader, | |
| 545 int x, int y, uint16_t dstC[], int count) | |
| 546 { | |
| 547 SkASSERT(count > 0); | |
| 548 | |
| 549 const SkMatrix& inv = shader->revealTotalInverse(); | |
| 550 const SkBitmap& srcBitmap = shader->revealSrcBitmap(); | |
| 551 int width = srcBitmap.width(); | |
| 552 int height = srcBitmap.height(); | |
| 553 | |
| 554 SkASSERT(width > 0 && height > 0); | |
| 555 | |
| 556 x += SkScalarRound(inv[SkMatrix::kMTransX]); | |
| 557 y += SkScalarRound(inv[SkMatrix::kMTransY]); | |
| 558 | |
| 559 x = do_repeat_mod(x, width - 1); | |
| 560 y = do_repeat_mod(y, height - 1); | |
| 561 | |
| 562 const SkPMColor* row = srcBitmap.getAddr32(0, y); | |
| 563 const SkPMColor* src = row + x; | |
| 564 | |
| 565 int n = SkMin32(width - x, count); | |
| 566 | |
| 567 // do the first partial run | |
| 568 count -= n; | |
| 569 SkASSERT(n > 0); | |
| 570 do { | |
| 571 *dstC++ = SkPixel32ToPixel16(*src++); | |
| 572 } while (--n > 0); | |
| 573 | |
| 574 // do 1 complete run | |
| 575 if (count >= width) | |
| 576 { | |
| 577 uint16_t* baseDstC = dstC; // remember the first complete run start | |
| 578 n = width; | |
| 579 count -= width; | |
| 580 src = row; | |
| 581 do { | |
| 582 *dstC++ = SkPixel32ToPixel16(*src++); | |
| 583 } while (--n > 0); | |
| 584 | |
| 585 // do the rest of the complete runs | |
| 586 while (count >= width) | |
| 587 { | |
| 588 count -= width; | |
| 589 memcpy(dstC, baseDstC, width << 1); | |
| 590 dstC += width; | |
| 591 } | |
| 592 // do final partial run | |
| 593 if (count > 0) | |
| 594 memcpy(dstC, baseDstC, count << 1); | |
| 595 } | |
| 596 else // do final partial | |
| 597 { | |
| 598 if (count > 0) | |
| 599 { | |
| 600 src = row; | |
| 601 do { | |
| 602 *dstC++ = SkPixel32ToPixel16(*src++);; | |
| 603 } while (--count > 0); | |
| 604 } | |
| 605 } | |
| 606 } | |
| 607 | |
| 608 static void ARGB32_RepeatTile_Sprite32(HasSpan16_Sampler_BitmapShader* shader, | |
| 609 int x, int y, SkPMColor dstC[], int count
) | |
| 610 { | |
| 611 SkASSERT(count > 0); | |
| 612 | |
| 613 const SkMatrix& inv = shader->revealTotalInverse(); | |
| 614 const SkBitmap& srcBitmap = shader->revealSrcBitmap(); | |
| 615 int width = srcBitmap.width(); | |
| 616 int height = srcBitmap.height(); | |
| 617 | |
| 618 SkASSERT(width > 0 && height > 0); | |
| 619 | |
| 620 x += SkScalarRound(inv[SkMatrix::kMTransX]); | |
| 621 y += SkScalarRound(inv[SkMatrix::kMTransY]); | |
| 622 | |
| 623 x = do_repeat_mod(x, width - 1); | |
| 624 y = do_repeat_mod(y, height - 1); | |
| 625 | |
| 626 const SkPMColor* row = srcBitmap.getAddr32(0, y); | |
| 627 const SkPMColor* src = row + x; | |
| 628 | |
| 629 int n = SkMin32(width - x, count); | |
| 630 | |
| 631 for (;;) | |
| 632 { | |
| 633 SkASSERT(n > 0 && count >= n); | |
| 634 memcpy(dstC, src, n << 2); | |
| 635 count -= n; | |
| 636 if (count == 0) | |
| 637 break; | |
| 638 dstC += n; | |
| 639 src = row; | |
| 640 n = SkMin32(width, count); | |
| 641 } | |
| 642 } | |
| 643 | |
| 644 /////////////////////////////////////////////////////////////////////////// | |
| 645 | |
| 646 #define NOFILTER_BITMAP_SHADER_CLASS Index8_NoFilter_RepeatTi
le_BitmapShader | |
| 647 #define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMo
de | |
| 648 #define NOFILTER_BITMAP_SHADER_TILEPROC(x, max) (fixed_repeat(x) * (max
+ 1) >> 16) | |
| 649 #define NOFILTER_BITMAP_SHADER_TYPE uint8_t | |
| 650 #define NOFILTER_BITMAP_SHADER_SAMPLE_X(p, x) colors32[p[x]] | |
| 651 #define NOFILTER_BITMAP_SHADER_SAMPLE_XY(p, x, y, rb) colors32[p[x + y * rb]] | |
| 652 #define NOFILTER_BITMAP_SHADER_PREAMBLE(bitmap, rb) const SkPMColor* colors3
2 = bitmap.getColorTable()->lockColors() | |
| 653 #define NOFILTER_BITMAP_SHADER_POSTAMBLE(bitmap) bitmap.getColorTable()->
unlockColors(false) | |
| 654 #define NOFILTER_BITMAP_SHADER_SAMPLE_X16(p, x) colors16[p[x]] | |
| 655 #define NOFILTER_BITMAP_SHADER_SAMPLE_XY16(p, x, y, rb) colors16[p[x + y * rb]] | |
| 656 #define NOFILTER_BITMAP_SHADER_PREAMBLE16(bitmap, rb) const uint16_t* colors16
= bitmap.getColorTable()->lock16BitCache() | |
| 657 #define NOFILTER_BITMAP_SHADER_POSTAMBLE16(bitmap) bitmap.getColorTable()->
unlock16BitCache() | |
| 658 #define NOFILTER_BITMAP_SHADER_USE_UNITINVERSE | |
| 659 #define NOFILTER_BITMAP_SHADER_SPRITEPROC16 Index8_RepeatTile_Sprite
16 | |
| 660 #define NOFILTER_BITMAP_SHADER_SPRITEPROC32 Index8_RepeatTile_Sprite
32 | |
| 661 #include "SkBitmapShaderTemplate.h" | |
| 662 | |
| 663 #define NOFILTER_BITMAP_SHADER_CLASS U16_NoFilter_RepeatTile_
BitmapShader | |
| 664 #define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMo
de | |
| 665 #define NOFILTER_BITMAP_SHADER_TILEPROC(x, max) (fixed_repeat(x) * (max
+ 1) >> 16) | |
| 666 #define NOFILTER_BITMAP_SHADER_TYPE uint16_t | |
| 667 #define NOFILTER_BITMAP_SHADER_SAMPLE_X(p, x) SkPixel16ToPixel32(p[x]) | |
| 668 #define NOFILTER_BITMAP_SHADER_SAMPLE_XY(p, x, y, rb) SkPixel16ToPixel32(*(con
st uint16_t*)((const char*)p + y * rb + (x << 1))) | |
| 669 #define NOFILTER_BITMAP_SHADER_SAMPLE_X16(p, x) p[x] | |
| 670 #define NOFILTER_BITMAP_SHADER_SAMPLE_XY16(p, x, y, rb) *(const uint16_t*)((cons
t char*)p + y * rb + (x << 1)) | |
| 671 #define NOFILTER_BITMAP_SHADER_USE_UNITINVERSE | |
| 672 #define NOFILTER_BITMAP_SHADER_SPRITEPROC16 RGB16_RepeatTile_Sprite1
6 | |
| 673 #define NOFILTER_BITMAP_SHADER_SPRITEPROC32 RGB16_RepeatTile_Sprite3
2 | |
| 674 #include "SkBitmapShaderTemplate.h" | |
| 675 | |
| 676 #define NOFILTER_BITMAP_SHADER_CLASS U32_NoFilter_RepeatTile_
BitmapShader | |
| 677 #define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMo
de | |
| 678 #define NOFILTER_BITMAP_SHADER_TILEPROC(x, max) (fixed_repeat(x) * (max
+ 1) >> 16) | |
| 679 #define NOFILTER_BITMAP_SHADER_TYPE uint32_t | |
| 680 #define NOFILTER_BITMAP_SHADER_SAMPLE_X(p, x) p[x] | |
| 681 #define NOFILTER_BITMAP_SHADER_SAMPLE_XY(p, x, y, rb) *(const uint32_t*)((cons
t char*)p + y * rb + (x << 2)) | |
| 682 #define NOFILTER_BITMAP_SHADER_SAMPLE_X16(p, x) SkPixel32ToPixel16_ToU16
(p[x]) | |
| 683 #define NOFILTER_BITMAP_SHADER_SAMPLE_XY16(p, x, y, rb) SkPixel32ToPixel16_ToU16
(*(const uint32_t*)((const char*)p + y * rb + (x << 2))) | |
| 684 #define NOFILTER_BITMAP_SHADER_USE_UNITINVERSE | |
| 685 #define NOFILTER_BITMAP_SHADER_SPRITEPROC16 ARGB32_RepeatTile_Sprite
16 | |
| 686 #define NOFILTER_BITMAP_SHADER_SPRITEPROC32 ARGB32_RepeatTile_Sprite
32 | |
| 687 #include "SkBitmapShaderTemplate.h" | |
| 688 | |
| 689 ////////////////////////////////////////////////////////////////////////////////
/////////////////////// | |
| 690 | |
| 691 static inline SkPMColor expanded_rgb16_to_8888(uint32_t c, U8CPU alpha) | |
| 692 { | |
| 693 // GGGG Gggg gggR RRRR rrrr r|BB BBBb bbbb | |
| 694 SkASSERT(alpha <= 255); | |
| 695 | |
| 696 #if 1 | |
| 697 int scale = SkAlpha255To256(alpha); | |
| 698 int r = (c & 0xF800) * scale >> 16; | |
| 699 int g = ((c >> 21) & 0x3F) * scale >> 6; | |
| 700 int b = (c & 0x1F) * scale >> 5; | |
| 701 return SkPackARGB32(alpha, r, g, b); | |
| 702 #else | |
| 703 int scale = SkAlpha255To256(alpha) >> 3; | |
| 704 c &= 0x07E0F81F; | |
| 705 c = c * scale; | |
| 706 int r = (c >> 13) & 0xFF; | |
| 707 int g = (c >> 24) & 0xFF; | |
| 708 int b = (c >> 2) & 0xFF; | |
| 709 return SkPackARGB32(alpha, r, g, b); | |
| 710 #endif | |
| 711 } | |
| 712 | |
| 713 #define BILERP_BITMAP16_SHADER_CLASS U16_Bilerp_BitmapShader | |
| 714 #define BILERP_BITMAP16_SHADER_TYPE uint16_t | |
| 715 #define BILERP_BITMAP16_SHADER_PREAMBLE(bm) | |
| 716 #define BILERP_BITMAP16_SHADER_PIXEL(c) (c) | |
| 717 #define BILERP_BITMAP16_SHADER_POSTAMBLE(bm) | |
| 718 #include "SkBitmapShader16BilerpTemplate.h" | |
| 719 | |
| 720 #define BILERP_BITMAP16_SHADER_CLASS Index8_Bilerp_BitmapShader | |
| 721 #define BILERP_BITMAP16_SHADER_TYPE uint8_t | |
| 722 #define BILERP_BITMAP16_SHADER_PREAMBLE(bm) SkColorTable* ctable = (bm).getC
olorTable(); const uint16_t* colors16 = ctable->lock16BitCache() | |
| 723 #define BILERP_BITMAP16_SHADER_PIXEL(c) colors16[c] | |
| 724 #define BILERP_BITMAP16_SHADER_POSTAMBLE(bm) ctable->unlock16BitCache() | |
| 725 #include "SkBitmapShader16BilerpTemplate.h" | |
| 726 | |
| 727 #include "ARGB32_Clamp_Bilinear_BitmapShader.h" | |
| 728 | |
| 729 /////////////////////////////////////////////////////////////////////////// | |
| 730 /////////////////////////////////////////////////////////////////////////// | |
| 731 | |
| 732 #include "SkBitmapProcShader.h" | |
| 733 | |
| 734 /////////////////////////////////////////////////////////////////////////// | |
| 735 /////////////////////////////////////////////////////////////////////////// | |
| 736 | |
| 737 #include "SkTemplatesPriv.h" | |
| 738 | |
| 739 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, | |
| 740 bool doFilter, | |
| 741 TileMode tmx, TileMode tmy, | |
| 742 void* storage, size_t storageSize) | |
| 743 { | |
| 744 #if 1 | |
| 745 | |
| 746 SkShader* shader; | |
| 747 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, | |
| 748 storageSize, (src, doFilter, tmx, tmy)); | |
| 749 return shader; | |
| 750 #else | |
| 751 | |
| 752 if (!doFilter) | |
| 753 { | |
| 754 if (kClamp_TileMode == tmx && kClamp_TileMode == tmy) | |
| 755 { | |
| 756 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, | |
| 757 storageSize, (src, doFilter, tmx, tmy)); | |
| 758 } | |
| 759 else if (kRepeat_TileMode == tmx && kRepeat_TileMode == tmy) | |
| 760 { | |
| 761 #if 1 | |
| 762 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, | |
| 763 storageSize, (src, doFilter, tmx, tmy)); | |
| 764 #else | |
| 765 switch (src.getConfig()) { | |
| 766 case SkBitmap::kIndex8_Config: | |
| 767 SK_PLACEMENT_NEW_ARGS(shader, Index8_NoFilter_RepeatTile_BitmapS
hader, storage, storageSize, (src)); | |
| 768 break; | |
| 769 case SkBitmap::kRGB_565_Config: | |
| 770 SK_PLACEMENT_NEW_ARGS(shader, U16_NoFilter_RepeatTile_BitmapShad
er, storage, storageSize, (src)); | |
| 771 break; | |
| 772 case SkBitmap::kARGB_8888_Config: | |
| 773 SK_PLACEMENT_NEW_ARGS(shader, U32_NoFilter_RepeatTile_BitmapShad
er, storage, storageSize, (src)); | |
| 774 break; | |
| 775 default: | |
| 776 break; | |
| 777 } | |
| 778 #endif | |
| 779 } | |
| 780 } | |
| 781 else if (kClamp_TileMode == tmx && kClamp_TileMode == tmy) | |
| 782 { | |
| 783 #if 1 | |
| 784 if (SkBitmapProcShader::CanDo(src, tmx, tmy)) | |
| 785 { | |
| 786 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, | |
| 787 storageSize, (src, doFilter, tmx, tmy)); | |
| 788 } | |
| 789 #else | |
| 790 switch (src.getConfig()) { | |
| 791 case SkBitmap::kIndex8_Config: | |
| 792 if (src.isOpaque()) | |
| 793 SK_PLACEMENT_NEW_ARGS(shader, Index8_Bilerp_BitmapShader, storag
e, storageSize, (src)); | |
| 794 break; | |
| 795 case SkBitmap::kRGB_565_Config: | |
| 796 SK_PLACEMENT_NEW_ARGS(shader, U16_Bilerp_BitmapShader, storage, stor
ageSize, (src)); | |
| 797 break; | |
| 798 case SkBitmap::kARGB_8888_Config: | |
| 799 SK_PLACEMENT_NEW_ARGS(shader, ARGB32_Clamp_Bilinear_BitmapShader, st
orage, storageSize, (src)); | |
| 800 break; | |
| 801 default: | |
| 802 break; | |
| 803 } | |
| 804 #endif | |
| 805 } | |
| 806 | |
| 807 // if shader is null, then none of the special cases could handle the reques
t | |
| 808 // so fall through to our slow-general case | |
| 809 if (shader == NULL) | |
| 810 SK_PLACEMENT_NEW_ARGS(shader, Sampler_BitmapShader, storage, storageSize
, | |
| 811 (src, doFilter, tmx, tmy)); | |
| 812 return shader; | |
| 813 #endif | |
| 814 } | |
| 815 | |
| 816 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, bool doFilter, | |
| 817 TileMode tmx, TileMode tmy) | |
| 818 { | |
| 819 return SkShader::CreateBitmapShader(src, doFilter, tmx, tmy, NULL, 0); | |
| 820 } | |
| 821 | |
| 822 #endif | |
| OLD | NEW |