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, const 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 >> 16); 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->getFilterBitmap(), 151 this->getTileModeX(), this->getTileModeY()); 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_RepeatTile_BitmapShader 647 #define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMode 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* colors32 = 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_Sprite16 660 #define NOFILTER_BITMAP_SHADER_SPRITEPROC32 Index8_RepeatTile_Sprite32 661 #include "SkBitmapShaderTemplate.h" 662 663 #define NOFILTER_BITMAP_SHADER_CLASS U16_NoFilter_RepeatTile_BitmapShader 664 #define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMode 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(*(const 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*)((const char*)p + y * rb + (x << 1)) 671 #define NOFILTER_BITMAP_SHADER_USE_UNITINVERSE 672 #define NOFILTER_BITMAP_SHADER_SPRITEPROC16 RGB16_RepeatTile_Sprite16 673 #define NOFILTER_BITMAP_SHADER_SPRITEPROC32 RGB16_RepeatTile_Sprite32 674 #include "SkBitmapShaderTemplate.h" 675 676 #define NOFILTER_BITMAP_SHADER_CLASS U32_NoFilter_RepeatTile_BitmapShader 677 #define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMode 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*)((const 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_Sprite16 686 #define NOFILTER_BITMAP_SHADER_SPRITEPROC32 ARGB32_RepeatTile_Sprite32 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).getColorTable(); 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_BitmapShader, storage, storageSize, (src)); 768 break; 769 case SkBitmap::kRGB_565_Config: 770 SK_PLACEMENT_NEW_ARGS(shader, U16_NoFilter_RepeatTile_BitmapShader, storage, storageSize, (src)); 771 break; 772 case SkBitmap::kARGB_8888_Config: 773 SK_PLACEMENT_NEW_ARGS(shader, U32_NoFilter_RepeatTile_BitmapShader, 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, storage, storageSize, (src)); 794 break; 795 case SkBitmap::kRGB_565_Config: 796 SK_PLACEMENT_NEW_ARGS(shader, U16_Bilerp_BitmapShader, storage, storageSize, (src)); 797 break; 798 case SkBitmap::kARGB_8888_Config: 799 SK_PLACEMENT_NEW_ARGS(shader, ARGB32_Clamp_Bilinear_BitmapShader, storage, 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 request 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 823