/* Copyright 2006, Google Inc. ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #if 0 #include "SkBitmapShader.h" #include "SkBitmapSampler.h" #ifdef SK_SUPPORT_MIPMAP static SkFixed find_mip_level(SkFixed dx, SkFixed dy) { dx = SkAbs32(dx); dy = SkAbs32(dy); if (dx < dy) dx = dy; if (dx < SK_Fixed1) return 0; int clz = SkCLZ(dx); SkASSERT(clz >= 1 && clz <= 15); return SkIntToFixed(15 - clz) + ((unsigned)(dx << (clz + 1)) >> 16); } #endif SkBitmapShader::SkBitmapShader(const SkBitmap& src, bool doFilter, TileMode tmx, TileMode tmy) : #ifdef SK_SUPPORT_MIPMAP fMipLevel(0), fMipSrcBitmap(src), #endif fOrigSrcBitmap(src) { fFilterBitmap = doFilter; fTileModeX = SkToU8(tmx); fTileModeY = SkToU8(tmy); } SkBitmapShader::SkBitmapShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { Bitmap src; buffer.readBitmap(&src); #ifdef SK_SUPPORT_MIPMAP fMipLevel = 0; fMipSrcBitmap = src; #endif fOrigSrcBitmap = src; fFilterBitmap = buffer.readU8(); fTileModeX = buffer.readU8(); fTileModeY = buffer.readU8(); } void SkBitmapShader::flatten(SkFlattenableWriteBuffer& buffer) { this->INHERITED::flatten(buffer); buffer.writeBitmap(&fOrigSrcBitmap); buffer.write8(fFilterBitmap); buffer.write8(fTileModeX); buffer.write8(fTileModeY); } bool SkBitmapShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { // do this first, so we have a correct inverse matrix if (!this->INHERITED::setContext(device, paint, matrix)) return false; if (fOrigSrcBitmap.getConfig() == SkBitmap::kNo_Config || fOrigSrcBitmap.width() == 0 || fOrigSrcBitmap.height() == 0) return false; SkBitmap& bm = fOrigSrcBitmap; #ifdef SK_SUPPORT_MIPMAP if (fOrigSrcBitmap.countMipLevels()) { const SkMatrix& inv = this->getTotalInverse(); fMipLevel = SkMin32(find_mip_level( SkScalarToFixed(inv.getScaleX()), SkScalarToFixed(inv.getSkewY())), SkIntToFixed(fOrigSrcBitmap.countMipLevels() - 1)); // SkDEBUGF(("BitmapShader miplevel=%x\n", fMipLevel)); const SkBitmap::MipLevel* mm = fOrigSrcBitmap.getMipLevel(fMipLevel >> 16); fMipSrcBitmap.setConfig(fOrigSrcBitmap.getConfig(), mm->fWidth, mm->fHeight, mm->fRowBytes); fMipSrcBitmap.setPixels(mm->fPixels); bm = fMipSrcBitmap; } else { fMipLevel = 0; fMipSrcBitmap = fOrigSrcBitmap; } #endif fFlags = 0; if (paint.getAlpha() == 255 && bm.isOpaque()) fFlags |= kOpaqueAlpha_Flag; return true; } /////////////////////////////////////////////////////////////////////////// #include "SkColorPriv.h" #include "SkBitmapSampler.h" #include "SkPerspIter.h" class Sampler_BitmapShader : public SkBitmapShader { public: Sampler_BitmapShader(const SkBitmap& src, bool doFilter, TileMode tmx, TileMode tmy) : SkBitmapShader(src, doFilter, tmx, tmy) { // make sure to pass our copy of the src bitmap to the sampler, and not the // original parameter (which might go away). fSampler = NULL; } virtual ~Sampler_BitmapShader() { SkDELETE(fSampler); } virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { if (this->INHERITED::setContext(device, paint, matrix)) { SkDELETE(fSampler); fSampler = SkBitmapSampler::Create(this->getSrcBitmap(), this->getFilterBitmap(), this->getTileModeX(), this->getTileModeY()); fSampler->setPaint(paint); return true; } return false; } enum { kMaxPointStorageCount = 32 }; virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) { unsigned scale = SkAlpha255To256(this->getPaintAlpha()); const SkMatrix& inv = this->getTotalInverse(); SkMatrix::MapPtProc proc = this->getInverseMapPtProc(); SkBitmapSampler* sampler = fSampler; MatrixClass mc = this->getInverseClass(); SkPoint srcPt; if (mc != kPerspective_MatrixClass) { proc(inv, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, &srcPt); SkFixed fx = SkScalarToFixed(srcPt.fX); SkFixed fy = SkScalarToFixed(srcPt.fY); SkFixed dx, dy; if (mc == kLinear_MatrixClass) { dx = SkScalarToFixed(inv.getScaleX()); dy = SkScalarToFixed(inv.getSkewY()); } else (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy); #if defined(SK_SUPPORT_MIPMAP) { int level = this->getMipLevel() >> 16; fx >>= level; fy >>= level; dx >>= level; dy >>= level; } #endif if (scale == 256) { for (int i = 0; i < count; i++) { dstC[i] = sampler->sample(fx, fy); fx += dx; fy += dy; } } else { for (int i = 0; i < count; i++) { uint32_t c = sampler->sample(fx, fy); dstC[i] = SkAlphaMulQ(c, scale); fx += dx; fy += dy; } } } else { SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, count); if (scale == 256) { while ((count = iter.next()) != 0) { const SkFixed* src = iter.getXY(); for (int i = 0; i < count; i++) { *dstC++ = sampler->sample(src[0], src[1]); src += 2; } } } else { while ((count = iter.next()) != 0) { const SkFixed* src = iter.getXY(); for (int i = 0; i < count; i++) { uint32_t c = sampler->sample(src[0] - SK_FixedHalf, src[1] - SK_FixedHalf); *dstC++ = SkAlphaMulQ(c, scale); src += 2; } } } } } protected: const SkMatrix& getUnitInverse() const { return fUnitInverse; } SkMatrix::MapPtProc getUnitInverseProc() const { return fUnitInverseProc; } /* takes computed inverse (from setContext) and computes fUnitInverse, taking srcBitmap width/height into account, so that fUnitInverse walks 0...1, allowing the tile modes to all operate in a fast 16bit space (no need for mod). The resulting coords need to be scaled by width/height to get back into src space (coord * width >> 16). */ void computeUnitInverse() { const SkBitmap& src = getSrcBitmap(); fUnitInverse = this->getTotalInverse(); fUnitInverse.postIDiv(src.width(), src.height()); fUnitInverseProc = fUnitInverse.getMapPtProc(); } private: SkBitmapSampler* fSampler; SkMatrix fUnitInverse; SkMatrix::MapPtProc fUnitInverseProc; typedef SkBitmapShader INHERITED; }; /////////////////////////////////////////////////////////////////////////// class HasSpan16_Sampler_BitmapShader : public Sampler_BitmapShader { public: HasSpan16_Sampler_BitmapShader(const SkBitmap& src, bool doFilter, TileMode tmx, TileMode tmy) : Sampler_BitmapShader(src, doFilter, tmx, tmy) { } virtual uint32_t getFlags() { uint32_t flags = this->INHERITED::getFlags(); switch (this->getSrcBitmap().getConfig()) { case SkBitmap::kRGB_565_Config: flags |= kHasSpan16_Flag; break; case SkBitmap::kIndex8_Config: case SkBitmap::kARGB_8888_Config: if (this->getSrcBitmap().isOpaque()) flags |= kHasSpan16_Flag; break; default: break; } return flags; } const SkBitmap& revealSrcBitmap() const { return this->getSrcBitmap(); } uint8_t revealPaintAlpha() const { return this->getPaintAlpha(); } const SkMatrix& revealTotalInverse() const { return this->getTotalInverse(); } private: typedef Sampler_BitmapShader INHERITED; }; /////////////////////////////////////////////////////////////////////////// static void Index8_RepeatTile_Sprite16(HasSpan16_Sampler_BitmapShader* shader, int x, int y, uint16_t dstC[], int count) { const SkMatrix& inv = shader->revealTotalInverse(); const SkBitmap& srcBitmap = shader->revealSrcBitmap(); int width = srcBitmap.width(); int height = srcBitmap.height(); SkColorTable* ctable = srcBitmap.getColorTable(); const uint16_t* colors = ctable->lock16BitCache(); x += SkScalarRound(inv[SkMatrix::kMTransX]); y += SkScalarRound(inv[SkMatrix::kMTransY]); x = do_repeat_mod(x, width - 1); y = do_repeat_mod(y, height - 1); const uint8_t* row = srcBitmap.getAddr8(0, y); const uint8_t* src = row + x; // do the first partial run int n = width - x; if (n > count) n = count; count -= n; SkASSERT(n > 0); do { *dstC++ = colors[*src++]; } while (--n > 0); // do 1 complete run if (count >= width) { uint16_t* baseDstC = dstC; // remember the first complete run start n = width; count -= width; src = row; do { *dstC++ = colors[*src++]; } while (--n > 0); // do the rest of the complete runs while (count >= width) { count -= width; memcpy(dstC, baseDstC, width << 1); dstC += width; } // do final partial run if (count > 0) memcpy(dstC, baseDstC, count << 1); } else // do final partial { if (count > 0) { src = row; do { *dstC++ = colors[*src++]; } while (--count > 0); } } ctable->unlock16BitCache(); } static void Index8_RepeatTile_Sprite32(HasSpan16_Sampler_BitmapShader* shader, int x, int y, SkPMColor dstC[], int count) { const SkMatrix& inv = shader->revealTotalInverse(); const SkBitmap& srcBitmap = shader->revealSrcBitmap(); int width = srcBitmap.width(); int height = srcBitmap.height(); SkColorTable* ctable = srcBitmap.getColorTable(); const SkPMColor* colors = ctable->lockColors(); x += SkScalarRound(inv[SkMatrix::kMTransX]); y += SkScalarRound(inv[SkMatrix::kMTransY]); x = do_repeat_mod(x, width - 1); y = do_repeat_mod(y, height - 1); const uint8_t* row = srcBitmap.getAddr8(0, y); const uint8_t* src = row + x; // do the first partial run int n = width - x; if (n > count) n = count; count -= n; SkASSERT(n > 0); do { *dstC++ = colors[*src++]; } while (--n > 0); // do 1 complete run if (count >= width) { SkPMColor* baseDstC = dstC; // remember the first complete run start n = width; count -= width; src = row; do { *dstC++ = colors[*src++]; } while (--n > 0); // do the rest of the complete runs while (count >= width) { count -= width; memcpy(dstC, baseDstC, width << 2); dstC += width; } // do final partial run if (count > 0) memcpy(dstC, baseDstC, count << 2); } else // do final partial { if (count > 0) { src = row; do { *dstC++ = colors[*src++]; } while (--count > 0); } } ctable->unlockColors(false); } static void RGB16_RepeatTile_Sprite16(HasSpan16_Sampler_BitmapShader* shader, int x, int y, uint16_t dstC[], int count) { SkASSERT(count > 0); const SkMatrix& inv = shader->revealTotalInverse(); const SkBitmap& srcBitmap = shader->revealSrcBitmap(); int width = srcBitmap.width(); int height = srcBitmap.height(); SkASSERT(width > 0 && height > 0); x += SkScalarRound(inv[SkMatrix::kMTransX]); y += SkScalarRound(inv[SkMatrix::kMTransY]); x = do_repeat_mod(x, width - 1); y = do_repeat_mod(y, height - 1); const uint16_t* row = srcBitmap.getAddr16(0, y); const uint16_t* src = row + x; int n = SkMin32(width - x, count); for (;;) { SkASSERT(n > 0 && count >= n); memcpy(dstC, src, n << 1); count -= n; if (count == 0) break; dstC += n; src = row; n = SkMin32(width, count); } } static void RGB16_RepeatTile_Sprite32(HasSpan16_Sampler_BitmapShader* shader, int x, int y, SkPMColor dstC[], int count) { SkASSERT(count > 0); const SkMatrix& inv = shader->revealTotalInverse(); const SkBitmap& srcBitmap = shader->revealSrcBitmap(); int width = srcBitmap.width(); int height = srcBitmap.height(); SkASSERT(width > 0 && height > 0); x += SkScalarRound(inv[SkMatrix::kMTransX]); y += SkScalarRound(inv[SkMatrix::kMTransY]); x = do_repeat_mod(x, width - 1); y = do_repeat_mod(y, height - 1); const uint16_t* row = srcBitmap.getAddr16(0, y); const uint16_t* src = row + x; int n = SkMin32(width - x, count); // do the first partial run count -= n; SkASSERT(n > 0); do { *dstC++ = SkPixel16ToPixel32(*src++); } while (--n > 0); // do 1 complete run if (count >= width) { SkPMColor* baseDstC = dstC; // remember the first complete run start n = width; count -= width; src = row; do { *dstC++ = SkPixel16ToPixel32(*src++); } while (--n > 0); // do the rest of the complete runs while (count >= width) { count -= width; memcpy(dstC, baseDstC, width << 2); dstC += width; } // do final partial run if (count > 0) memcpy(dstC, baseDstC, count << 2); } else // do final partial { if (count > 0) { src = row; do { *dstC++ = SkPixel16ToPixel32(*src++);; } while (--count > 0); } } } static void ARGB32_RepeatTile_Sprite16(HasSpan16_Sampler_BitmapShader* shader, int x, int y, uint16_t dstC[], int count) { SkASSERT(count > 0); const SkMatrix& inv = shader->revealTotalInverse(); const SkBitmap& srcBitmap = shader->revealSrcBitmap(); int width = srcBitmap.width(); int height = srcBitmap.height(); SkASSERT(width > 0 && height > 0); x += SkScalarRound(inv[SkMatrix::kMTransX]); y += SkScalarRound(inv[SkMatrix::kMTransY]); x = do_repeat_mod(x, width - 1); y = do_repeat_mod(y, height - 1); const SkPMColor* row = srcBitmap.getAddr32(0, y); const SkPMColor* src = row + x; int n = SkMin32(width - x, count); // do the first partial run count -= n; SkASSERT(n > 0); do { *dstC++ = SkPixel32ToPixel16(*src++); } while (--n > 0); // do 1 complete run if (count >= width) { uint16_t* baseDstC = dstC; // remember the first complete run start n = width; count -= width; src = row; do { *dstC++ = SkPixel32ToPixel16(*src++); } while (--n > 0); // do the rest of the complete runs while (count >= width) { count -= width; memcpy(dstC, baseDstC, width << 1); dstC += width; } // do final partial run if (count > 0) memcpy(dstC, baseDstC, count << 1); } else // do final partial { if (count > 0) { src = row; do { *dstC++ = SkPixel32ToPixel16(*src++);; } while (--count > 0); } } } static void ARGB32_RepeatTile_Sprite32(HasSpan16_Sampler_BitmapShader* shader, int x, int y, SkPMColor dstC[], int count) { SkASSERT(count > 0); const SkMatrix& inv = shader->revealTotalInverse(); const SkBitmap& srcBitmap = shader->revealSrcBitmap(); int width = srcBitmap.width(); int height = srcBitmap.height(); SkASSERT(width > 0 && height > 0); x += SkScalarRound(inv[SkMatrix::kMTransX]); y += SkScalarRound(inv[SkMatrix::kMTransY]); x = do_repeat_mod(x, width - 1); y = do_repeat_mod(y, height - 1); const SkPMColor* row = srcBitmap.getAddr32(0, y); const SkPMColor* src = row + x; int n = SkMin32(width - x, count); for (;;) { SkASSERT(n > 0 && count >= n); memcpy(dstC, src, n << 2); count -= n; if (count == 0) break; dstC += n; src = row; n = SkMin32(width, count); } } /////////////////////////////////////////////////////////////////////////// #define NOFILTER_BITMAP_SHADER_CLASS Index8_NoFilter_RepeatTile_BitmapShader #define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMode #define NOFILTER_BITMAP_SHADER_TILEPROC(x, max) (fixed_repeat(x) * (max + 1) >> 16) #define NOFILTER_BITMAP_SHADER_TYPE uint8_t #define NOFILTER_BITMAP_SHADER_SAMPLE_X(p, x) colors32[p[x]] #define NOFILTER_BITMAP_SHADER_SAMPLE_XY(p, x, y, rb) colors32[p[x + y * rb]] #define NOFILTER_BITMAP_SHADER_PREAMBLE(bitmap, rb) const SkPMColor* colors32 = bitmap.getColorTable()->lockColors() #define NOFILTER_BITMAP_SHADER_POSTAMBLE(bitmap) bitmap.getColorTable()->unlockColors(false) #define NOFILTER_BITMAP_SHADER_SAMPLE_X16(p, x) colors16[p[x]] #define NOFILTER_BITMAP_SHADER_SAMPLE_XY16(p, x, y, rb) colors16[p[x + y * rb]] #define NOFILTER_BITMAP_SHADER_PREAMBLE16(bitmap, rb) const uint16_t* colors16 = bitmap.getColorTable()->lock16BitCache() #define NOFILTER_BITMAP_SHADER_POSTAMBLE16(bitmap) bitmap.getColorTable()->unlock16BitCache() #define NOFILTER_BITMAP_SHADER_USE_UNITINVERSE #define NOFILTER_BITMAP_SHADER_SPRITEPROC16 Index8_RepeatTile_Sprite16 #define NOFILTER_BITMAP_SHADER_SPRITEPROC32 Index8_RepeatTile_Sprite32 #include "SkBitmapShaderTemplate.h" #define NOFILTER_BITMAP_SHADER_CLASS U16_NoFilter_RepeatTile_BitmapShader #define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMode #define NOFILTER_BITMAP_SHADER_TILEPROC(x, max) (fixed_repeat(x) * (max + 1) >> 16) #define NOFILTER_BITMAP_SHADER_TYPE uint16_t #define NOFILTER_BITMAP_SHADER_SAMPLE_X(p, x) SkPixel16ToPixel32(p[x]) #define NOFILTER_BITMAP_SHADER_SAMPLE_XY(p, x, y, rb) SkPixel16ToPixel32(*(const uint16_t*)((const char*)p + y * rb + (x << 1))) #define NOFILTER_BITMAP_SHADER_SAMPLE_X16(p, x) p[x] #define NOFILTER_BITMAP_SHADER_SAMPLE_XY16(p, x, y, rb) *(const uint16_t*)((const char*)p + y * rb + (x << 1)) #define NOFILTER_BITMAP_SHADER_USE_UNITINVERSE #define NOFILTER_BITMAP_SHADER_SPRITEPROC16 RGB16_RepeatTile_Sprite16 #define NOFILTER_BITMAP_SHADER_SPRITEPROC32 RGB16_RepeatTile_Sprite32 #include "SkBitmapShaderTemplate.h" #define NOFILTER_BITMAP_SHADER_CLASS U32_NoFilter_RepeatTile_BitmapShader #define NOFILTER_BITMAP_SHADER_TILEMODE SkShader::kRepeat_TileMode #define NOFILTER_BITMAP_SHADER_TILEPROC(x, max) (fixed_repeat(x) * (max + 1) >> 16) #define NOFILTER_BITMAP_SHADER_TYPE uint32_t #define NOFILTER_BITMAP_SHADER_SAMPLE_X(p, x) p[x] #define NOFILTER_BITMAP_SHADER_SAMPLE_XY(p, x, y, rb) *(const uint32_t*)((const char*)p + y * rb + (x << 2)) #define NOFILTER_BITMAP_SHADER_SAMPLE_X16(p, x) SkPixel32ToPixel16_ToU16(p[x]) #define NOFILTER_BITMAP_SHADER_SAMPLE_XY16(p, x, y, rb) SkPixel32ToPixel16_ToU16(*(const uint32_t*)((const char*)p + y * rb + (x << 2))) #define NOFILTER_BITMAP_SHADER_USE_UNITINVERSE #define NOFILTER_BITMAP_SHADER_SPRITEPROC16 ARGB32_RepeatTile_Sprite16 #define NOFILTER_BITMAP_SHADER_SPRITEPROC32 ARGB32_RepeatTile_Sprite32 #include "SkBitmapShaderTemplate.h" /////////////////////////////////////////////////////////////////////////////////////////////////////// static inline SkPMColor expanded_rgb16_to_8888(uint32_t c, U8CPU alpha) { // GGGG Gggg gggR RRRR rrrr r|BB BBBb bbbb SkASSERT(alpha <= 255); #if 1 int scale = SkAlpha255To256(alpha); int r = (c & 0xF800) * scale >> 16; int g = ((c >> 21) & 0x3F) * scale >> 6; int b = (c & 0x1F) * scale >> 5; return SkPackARGB32(alpha, r, g, b); #else int scale = SkAlpha255To256(alpha) >> 3; c &= 0x07E0F81F; c = c * scale; int r = (c >> 13) & 0xFF; int g = (c >> 24) & 0xFF; int b = (c >> 2) & 0xFF; return SkPackARGB32(alpha, r, g, b); #endif } #define BILERP_BITMAP16_SHADER_CLASS U16_Bilerp_BitmapShader #define BILERP_BITMAP16_SHADER_TYPE uint16_t #define BILERP_BITMAP16_SHADER_PREAMBLE(bm) #define BILERP_BITMAP16_SHADER_PIXEL(c) (c) #define BILERP_BITMAP16_SHADER_POSTAMBLE(bm) #include "SkBitmapShader16BilerpTemplate.h" #define BILERP_BITMAP16_SHADER_CLASS Index8_Bilerp_BitmapShader #define BILERP_BITMAP16_SHADER_TYPE uint8_t #define BILERP_BITMAP16_SHADER_PREAMBLE(bm) SkColorTable* ctable = (bm).getColorTable(); const uint16_t* colors16 = ctable->lock16BitCache() #define BILERP_BITMAP16_SHADER_PIXEL(c) colors16[c] #define BILERP_BITMAP16_SHADER_POSTAMBLE(bm) ctable->unlock16BitCache() #include "SkBitmapShader16BilerpTemplate.h" #include "ARGB32_Clamp_Bilinear_BitmapShader.h" /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// #include "SkBitmapProcShader.h" /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// #include "SkTemplatesPriv.h" SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, bool doFilter, TileMode tmx, TileMode tmy, void* storage, size_t storageSize) { #if 1 SkShader* shader; SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, storageSize, (src, doFilter, tmx, tmy)); return shader; #else if (!doFilter) { if (kClamp_TileMode == tmx && kClamp_TileMode == tmy) { SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, storageSize, (src, doFilter, tmx, tmy)); } else if (kRepeat_TileMode == tmx && kRepeat_TileMode == tmy) { #if 1 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, storageSize, (src, doFilter, tmx, tmy)); #else switch (src.getConfig()) { case SkBitmap::kIndex8_Config: SK_PLACEMENT_NEW_ARGS(shader, Index8_NoFilter_RepeatTile_BitmapShader, storage, storageSize, (src)); break; case SkBitmap::kRGB_565_Config: SK_PLACEMENT_NEW_ARGS(shader, U16_NoFilter_RepeatTile_BitmapShader, storage, storageSize, (src)); break; case SkBitmap::kARGB_8888_Config: SK_PLACEMENT_NEW_ARGS(shader, U32_NoFilter_RepeatTile_BitmapShader, storage, storageSize, (src)); break; default: break; } #endif } } else if (kClamp_TileMode == tmx && kClamp_TileMode == tmy) { #if 1 if (SkBitmapProcShader::CanDo(src, tmx, tmy)) { SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, storageSize, (src, doFilter, tmx, tmy)); } #else switch (src.getConfig()) { case SkBitmap::kIndex8_Config: if (src.isOpaque()) SK_PLACEMENT_NEW_ARGS(shader, Index8_Bilerp_BitmapShader, storage, storageSize, (src)); break; case SkBitmap::kRGB_565_Config: SK_PLACEMENT_NEW_ARGS(shader, U16_Bilerp_BitmapShader, storage, storageSize, (src)); break; case SkBitmap::kARGB_8888_Config: SK_PLACEMENT_NEW_ARGS(shader, ARGB32_Clamp_Bilinear_BitmapShader, storage, storageSize, (src)); break; default: break; } #endif } // if shader is null, then none of the special cases could handle the request // so fall through to our slow-general case if (shader == NULL) SK_PLACEMENT_NEW_ARGS(shader, Sampler_BitmapShader, storage, storageSize, (src, doFilter, tmx, tmy)); return shader; #endif } SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, bool doFilter, TileMode tmx, TileMode tmy) { return SkShader::CreateBitmapShader(src, doFilter, tmx, tmy, NULL, 0); } #endif