| /* Copyright 2006, The Android Open Source Project |
| ** |
| ** 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 |