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
17typedef int (*SkTileModeProc)(int value, unsigned max);
18
19class SkBitmapSampler {
20public:
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
39protected:
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
52static 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
73static inline int fixed_repeat(SkFixed x)
74{
75    return x & 0xFFFF;
76}
77
78static 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
85static inline bool is_pow2(int count)
86{
87    SkASSERT(count > 0);
88    return (count & (count - 1)) == 0;
89}
90
91static 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
112static 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
126static 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
133static 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
152static 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