1 2 /* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #ifndef SkBitmapSampler_DEFINED 11 #define SkBitmapSampler_DEFINED 12 13 #include "SkBitmap.h" 14 #include "SkPaint.h" 15 #include "SkShader.h" 16 17 typedef int (*SkTileModeProc)(int value, unsigned max); 18 19 class SkBitmapSampler { 20 public: 21 SkBitmapSampler(const SkBitmap&, bool filter, SkShader::TileMode tmx, SkShader::TileMode tmy); 22 virtual ~SkBitmapSampler() {} 23 24 const SkBitmap& getBitmap() const { return fBitmap; } 25 bool getFilterBitmap() const { return fFilterBitmap; } 26 SkShader::TileMode getTileModeX() const { return fTileModeX; } 27 SkShader::TileMode getTileModeY() const { return fTileModeY; } 28 29 /** Given a pixel center at [x,y], return the color sample 30 */ 31 virtual SkPMColor sample(SkFixed x, SkFixed y) const = 0; 32 33 virtual void setPaint(const SkPaint& paint); 34 35 // This is the factory for finding an optimal subclass 36 static SkBitmapSampler* Create(const SkBitmap&, bool filter, 37 SkShader::TileMode tmx, SkShader::TileMode tmy); 38 39 protected: 40 const SkBitmap& fBitmap; 41 uint16_t fMaxX, fMaxY; 42 bool fFilterBitmap; 43 SkShader::TileMode fTileModeX; 44 SkShader::TileMode fTileModeY; 45 SkTileModeProc fTileProcX; 46 SkTileModeProc fTileProcY; 47 48 // illegal 49 SkBitmapSampler& operator=(const SkBitmapSampler&); 50 }; 51 52 static inline int fixed_clamp(SkFixed x) 53 { 54 #ifdef SK_CPU_HAS_CONDITIONAL_INSTR 55 if (x >> 16) 56 x = 0xFFFF; 57 if (x < 0) 58 x = 0; 59 #else 60 if (x >> 16) 61 { 62 if (x < 0) 63 x = 0; 64 else 65 x = 0xFFFF; 66 } 67 #endif 68 return x; 69 } 70 71 ////////////////////////////////////////////////////////////////////////////////////// 72 73 static inline int fixed_repeat(SkFixed x) 74 { 75 return x & 0xFFFF; 76 } 77 78 static inline int fixed_mirror(SkFixed x) 79 { 80 SkFixed s = x << 15 >> 31; 81 // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval 82 return (x ^ s) & 0xFFFF; 83 } 84 85 static inline bool is_pow2(int count) 86 { 87 SkASSERT(count > 0); 88 return (count & (count - 1)) == 0; 89 } 90 91 static inline int do_clamp(int index, unsigned max) 92 { 93 SkASSERT((int)max >= 0); 94 95 #ifdef SK_CPU_HAS_CONDITIONAL_INSTR 96 if (index > (int)max) 97 index = max; 98 if (index < 0) 99 index = 0; 100 #else 101 if ((unsigned)index > max) 102 { 103 if (index < 0) 104 index = 0; 105 else 106 index = max; 107 } 108 #endif 109 return index; 110 } 111 112 static inline int do_repeat_mod(int index, unsigned max) 113 { 114 SkASSERT((int)max >= 0); 115 116 if ((unsigned)index > max) 117 { 118 if (index < 0) 119 index = max - (~index % (max + 1)); 120 else 121 index = index % (max + 1); 122 } 123 return index; 124 } 125 126 static inline int do_repeat_pow2(int index, unsigned max) 127 { 128 SkASSERT((int)max >= 0 && is_pow2(max + 1)); 129 130 return index & max; 131 } 132 133 static inline int do_mirror_mod(int index, unsigned max) 134 { 135 SkASSERT((int)max >= 0); 136 137 // have to handle negatives so that 138 // -1 -> 0, -2 -> 1, -3 -> 2, etc. 139 // so we can't just cal abs 140 index ^= index >> 31; 141 142 if ((unsigned)index > max) 143 { 144 int mod = (max + 1) << 1; 145 index = index % mod; 146 if ((unsigned)index > max) 147 index = mod - index - 1; 148 } 149 return index; 150 } 151 152 static inline int do_mirror_pow2(int index, unsigned max) 153 { 154 SkASSERT((int)max >= 0 && is_pow2(max + 1)); 155 156 int s = (index & (max + 1)) - 1; 157 s = ~(s >> 31); 158 // at this stage, s is FFFFFFFF if we're on an odd interval, or 0 if an even interval 159 return (index ^ s) & max; 160 } 161 162 #endif 163