| |
| /* |
| * 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 |