/* * Copyright 2006 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkBitmapSampler_DEFINED #define SkBitmapSampler_DEFINED #include "SkBitmap.h" #include "SkPaint.h" #include "SkShader.h" typedef int (*SkTileModeProc)(int value, unsigned max); class SkBitmapSampler { public: SkBitmapSampler(const SkBitmap&, bool filter, SkShader::TileMode tmx, SkShader::TileMode tmy); virtual ~SkBitmapSampler() {} const SkBitmap& getBitmap() const { return fBitmap; } bool getFilterBitmap() const { return fFilterBitmap; } SkShader::TileMode getTileModeX() const { return fTileModeX; } SkShader::TileMode getTileModeY() const { return fTileModeY; } /** Given a pixel center at [x,y], return the color sample */ virtual SkPMColor sample(SkFixed x, SkFixed y) const = 0; virtual void setPaint(const SkPaint& paint); // This is the factory for finding an optimal subclass static SkBitmapSampler* Create(const SkBitmap&, bool filter, SkShader::TileMode tmx, SkShader::TileMode tmy); protected: const SkBitmap& fBitmap; uint16_t fMaxX, fMaxY; bool fFilterBitmap; SkShader::TileMode fTileModeX; SkShader::TileMode fTileModeY; SkTileModeProc fTileProcX; SkTileModeProc fTileProcY; // illegal SkBitmapSampler& operator=(const SkBitmapSampler&); }; static inline int fixed_clamp(SkFixed x) { #ifdef SK_CPU_HAS_CONDITIONAL_INSTR if (x >> 16) x = 0xFFFF; if (x < 0) x = 0; #else if (x >> 16) { if (x < 0) x = 0; else x = 0xFFFF; } #endif return x; } ////////////////////////////////////////////////////////////////////////////////////// static inline int fixed_repeat(SkFixed x) { return x & 0xFFFF; } static inline int fixed_mirror(SkFixed x) { SkFixed s = x << 15 >> 31; // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval return (x ^ s) & 0xFFFF; } static inline bool is_pow2(int count) { SkASSERT(count > 0); return (count & (count - 1)) == 0; } static inline int do_clamp(int index, unsigned max) { SkASSERT((int)max >= 0); #ifdef SK_CPU_HAS_CONDITIONAL_INSTR if (index > (int)max) index = max; if (index < 0) index = 0; #else if ((unsigned)index > max) { if (index < 0) index = 0; else index = max; } #endif return index; } static inline int do_repeat_mod(int index, unsigned max) { SkASSERT((int)max >= 0); if ((unsigned)index > max) { if (index < 0) index = max - (~index % (max + 1)); else index = index % (max + 1); } return index; } static inline int do_repeat_pow2(int index, unsigned max) { SkASSERT((int)max >= 0 && is_pow2(max + 1)); return index & max; } static inline int do_mirror_mod(int index, unsigned max) { SkASSERT((int)max >= 0); // have to handle negatives so that // -1 -> 0, -2 -> 1, -3 -> 2, etc. // so we can't just cal abs index ^= index >> 31; if ((unsigned)index > max) { int mod = (max + 1) << 1; index = index % mod; if ((unsigned)index > max) index = mod - index - 1; } return index; } static inline int do_mirror_pow2(int index, unsigned max) { SkASSERT((int)max >= 0 && is_pow2(max + 1)); int s = (index & (max + 1)) - 1; s = ~(s >> 31); // at this stage, s is FFFFFFFF if we're on an odd interval, or 0 if an even interval return (index ^ s) & max; } #endif