blob: 6d7d58160428010db5a3352b9341660317635f32 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkBitmapProcShader.h"
2#include "SkColorPriv.h"
3#include "SkPixelRef.h"
4
5bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
6 switch (bm.config()) {
7 case SkBitmap::kA8_Config:
8 case SkBitmap::kRGB_565_Config:
9 case SkBitmap::kIndex8_Config:
10 case SkBitmap::kARGB_8888_Config:
11 // if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
12 return true;
13 default:
14 break;
15 }
16 return false;
17}
18
19SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
20 TileMode tmx, TileMode tmy) {
21 fRawBitmap = src;
22 fState.fTileModeX = (uint8_t)tmx;
23 fState.fTileModeY = (uint8_t)tmy;
24}
25
26SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
27 : INHERITED(buffer) {
28 fRawBitmap.unflatten(buffer);
29 fState.fTileModeX = buffer.readU8();
30 fState.fTileModeY = buffer.readU8();
31}
32
33void SkBitmapProcShader::beginSession() {
34 this->INHERITED::beginSession();
35
36 fRawBitmap.lockPixels();
37}
38
39void SkBitmapProcShader::endSession() {
40 fRawBitmap.unlockPixels();
41
42 this->INHERITED::endSession();
43}
44
45bool SkBitmapProcShader::asABitmap(SkBitmap* texture, SkMatrix* texM,
46 TileMode xy[]) {
47 if (texture) {
48 *texture = fRawBitmap;
49 }
50 if (texM) {
51 texM->reset();
52 }
53 if (xy) {
54 xy[0] = (TileMode)fState.fTileModeX;
55 xy[1] = (TileMode)fState.fTileModeY;
56 }
57 return true;
58}
59
60void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) {
61 this->INHERITED::flatten(buffer);
62
63 fRawBitmap.flatten(buffer);
64 buffer.write8(fState.fTileModeX);
65 buffer.write8(fState.fTileModeY);
66}
67
68bool SkBitmapProcShader::setContext(const SkBitmap& device,
69 const SkPaint& paint,
70 const SkMatrix& matrix) {
71 // do this first, so we have a correct inverse matrix
72 if (!this->INHERITED::setContext(device, paint, matrix)) {
73 return false;
74 }
75
76 fState.fOrigBitmap = fRawBitmap;
77 fState.fOrigBitmap.lockPixels();
78 if (fState.fOrigBitmap.getPixels() == NULL) {
79 fState.fOrigBitmap.unlockPixels();
80 return false;
81 }
82
83 if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
84 return false;
85 }
86
87 bool bitmapIsOpaque = fState.fBitmap->isOpaque();
88
89 // filtering doesn't guarantee that opaque stays opaque (finite precision)
90 // so pretend we're not opaque if we're being asked to filter. If we had
91 // more blit-procs, we could specialize on opaque src, and just OR in 0xFF
92 // after the filter to be sure...
93 if (paint.isFilterBitmap()) {
94 bitmapIsOpaque = false;
95 }
96
97 // update fFlags
98 fFlags = 0; // this should happen in SkShader.cpp
99
100 if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
101 fFlags |= kOpaqueAlpha_Flag;
102 }
103
104 switch (fState.fBitmap->config()) {
105 case SkBitmap::kRGB_565_Config:
106 fFlags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
107 break;
108 case SkBitmap::kIndex8_Config:
109 case SkBitmap::kARGB_8888_Config:
110 if (bitmapIsOpaque) {
111 fFlags |= kHasSpan16_Flag;
112 }
113 break;
114 case SkBitmap::kA8_Config:
115 break; // never set kHasSpan16_Flag
116 default:
117 break;
118 }
119 return true;
120}
121
122#define BUF_MAX 128
123
124void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
125 uint32_t buffer[BUF_MAX];
126
127 const SkBitmapProcState& state = fState;
128 SkBitmapProcState::MatrixProc mproc = state.fMatrixProc;
129 SkBitmapProcState::SampleProc32 sproc = state.fSampleProc32;
130 int max = fState.fDoFilter ? (BUF_MAX >> 1) : BUF_MAX;
131
132 SkASSERT(state.fBitmap->getPixels());
133 SkASSERT(state.fBitmap->pixelRef() == NULL ||
134 state.fBitmap->pixelRef()->getLockCount());
135
136 for (;;) {
137 int n = count;
138 if (n > max) {
139 n = max;
140 }
141 mproc(state, buffer, n, x, y);
142 sproc(state, buffer, n, dstC);
143
144 if ((count -= n) == 0) {
145 break;
146 }
147 x += n;
148 dstC += n;
149 }
150}
151
152void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
153 uint32_t buffer[BUF_MAX];
154
155 const SkBitmapProcState& state = fState;
156 SkBitmapProcState::MatrixProc mproc = state.fMatrixProc;
157 SkBitmapProcState::SampleProc16 sproc = state.fSampleProc16;
158 int max = fState.fDoFilter ? (BUF_MAX >> 1) : BUF_MAX;
159
160 SkASSERT(state.fBitmap->getPixels());
161 SkASSERT(state.fBitmap->pixelRef() == NULL ||
162 state.fBitmap->pixelRef()->getLockCount());
163
164 for (;;) {
165 int n = count;
166 if (n > max) {
167 n = max;
168 }
169 mproc(state, buffer, n, x, y);
170 sproc(state, buffer, n, dstC);
171
172 if ((count -= n) == 0) {
173 break;
174 }
175 x += n;
176 dstC += n;
177 }
178}
179
180///////////////////////////////////////////////////////////////////////////////
181
182#include "SkTemplatesPriv.h"
183
184SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
185 TileMode tmx, TileMode tmy,
186 void* storage, size_t storageSize) {
187 SkShader* shader;
188 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
189 storageSize, (src, tmx, tmy));
190 return shader;
191}
192
193static SkFlattenable::Registrar gBitmapProcShaderReg("SkBitmapProcShader",
194 SkBitmapProcShader::CreateProc);
195
196///////////////////////////////////////////////////////////////////////////////
197
198static const char* gTileModeName[] = {
199 "clamp", "repeat", "mirror"
200};
201
202bool SkBitmapProcShader::toDumpString(SkString* str) const {
203 str->printf("BitmapShader: [%d %d %d",
204 fRawBitmap.width(), fRawBitmap.height(),
205 fRawBitmap.bytesPerPixel());
206
207 // add the pixelref
208 SkPixelRef* pr = fRawBitmap.pixelRef();
209 if (pr) {
210 const char* uri = pr->getURI();
211 if (uri) {
212 str->appendf(" \"%s\"", uri);
213 }
214 }
215
216 // add the (optional) matrix
217 {
218 SkMatrix m;
219 if (this->getLocalMatrix(&m)) {
220 SkString info;
221 m.toDumpString(&info);
222 str->appendf(" %s", info.c_str());
223 }
224 }
225
226 str->appendf(" [%s %s]]",
227 gTileModeName[fState.fTileModeX],
228 gTileModeName[fState.fTileModeY]);
229 return true;
230}
231