summaryrefslogtreecommitdiffstats
path: root/skia/sgl/SkBitmapShader.cpp
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:09:42 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:09:42 +0000
commitae2c20f398933a9e86c387dcc465ec0f71065ffc (patch)
treede668b1411e2ee0b4e49b6d8f8b68183134ac990 /skia/sgl/SkBitmapShader.cpp
parent09911bf300f1a419907a9412154760efd0b7abc3 (diff)
downloadchromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.zip
chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.gz
chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.bz2
Add skia to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/sgl/SkBitmapShader.cpp')
-rw-r--r--skia/sgl/SkBitmapShader.cpp822
1 files changed, 822 insertions, 0 deletions
diff --git a/skia/sgl/SkBitmapShader.cpp b/skia/sgl/SkBitmapShader.cpp
new file mode 100644
index 0000000..939080d
--- /dev/null
+++ b/skia/sgl/SkBitmapShader.cpp
@@ -0,0 +1,822 @@
+/* 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