OLD | NEW |
| (Empty) |
1 /* libs/graphics/sgl/SkBlitter_A8.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkCoreBlitters.h" | |
19 #include "SkColorPriv.h" | |
20 #include "SkShader.h" | |
21 #include "SkXfermode.h" | |
22 | |
23 SkA8_Blitter::SkA8_Blitter(const SkBitmap& device, const SkPaint& paint) | |
24 : INHERITED(device) | |
25 { | |
26 fSrcA = SkColorGetA(paint.getColor()); | |
27 } | |
28 | |
29 const SkBitmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) | |
30 { | |
31 if (255 == fSrcA) | |
32 { | |
33 *value = 255; | |
34 return &fDevice; | |
35 } | |
36 return NULL; | |
37 } | |
38 | |
39 void SkA8_Blitter::blitH(int x, int y, int width) | |
40 { | |
41 SkASSERT(x >= 0 && y >= 0 && (unsigned)(x + width) <= (unsigned)fDevice.widt
h()); | |
42 | |
43 if (fSrcA == 0) | |
44 return; | |
45 | |
46 uint8_t* device = fDevice.getAddr8(x, y); | |
47 | |
48 if (fSrcA == 255) | |
49 { | |
50 memset(device, 0xFF, width); | |
51 } | |
52 else | |
53 { | |
54 unsigned scale = 256 - SkAlpha255To256(fSrcA); | |
55 unsigned srcA = fSrcA; | |
56 | |
57 for (int i = 0; i < width; i++) | |
58 { | |
59 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); | |
60 } | |
61 } | |
62 } | |
63 | |
64 void SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int1
6_t runs[]) | |
65 { | |
66 if (fSrcA == 0) | |
67 return; | |
68 | |
69 uint8_t* device = fDevice.getAddr8(x, y); | |
70 unsigned srcA = fSrcA; | |
71 | |
72 for (;;) | |
73 { | |
74 int count = runs[0]; | |
75 SkASSERT(count >= 0); | |
76 if (count == 0) | |
77 return; | |
78 unsigned aa = antialias[0]; | |
79 | |
80 if (aa == 255 && srcA == 255) | |
81 memset(device, 0xFF, count); | |
82 else | |
83 { | |
84 unsigned sa = SkAlphaMul(srcA, SkAlpha255To256(aa)); | |
85 unsigned scale = 256 - sa; | |
86 | |
87 for (int i = 0; i < count; i++) | |
88 { | |
89 device[i] = SkToU8(sa + SkAlphaMul(device[i], scale)); | |
90 } | |
91 } | |
92 runs += count; | |
93 antialias += count; | |
94 device += count; | |
95 } | |
96 } | |
97 | |
98 ////////////////////////////////////////////////////////////////////////////////
///// | |
99 | |
100 #define solid_8_pixels(mask, dst) \ | |
101 do { \ | |
102 if (mask & 0x80) dst[0] = 0xFF; \ | |
103 if (mask & 0x40) dst[1] = 0xFF; \ | |
104 if (mask & 0x20) dst[2] = 0xFF; \ | |
105 if (mask & 0x10) dst[3] = 0xFF; \ | |
106 if (mask & 0x08) dst[4] = 0xFF; \ | |
107 if (mask & 0x04) dst[5] = 0xFF; \ | |
108 if (mask & 0x02) dst[6] = 0xFF; \ | |
109 if (mask & 0x01) dst[7] = 0xFF; \ | |
110 } while (0) | |
111 | |
112 #define SK_BLITBWMASK_NAME SkA8_BlitBW | |
113 #define SK_BLITBWMASK_ARGS | |
114 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst) | |
115 #define SK_BLITBWMASK_GETADDR getAddr8 | |
116 #define SK_BLITBWMASK_DEVTYPE uint8_t | |
117 #include "SkBlitBWMaskTemplate.h" | |
118 | |
119 static inline void blend_8_pixels(U8CPU bw, uint8_t dst[], U8CPU sa, unsigned ds
t_scale) | |
120 { | |
121 if (bw & 0x80) dst[0] = SkToU8(sa + SkAlphaMul(dst[0], dst_scale)); | |
122 if (bw & 0x40) dst[1] = SkToU8(sa + SkAlphaMul(dst[1], dst_scale)); | |
123 if (bw & 0x20) dst[2] = SkToU8(sa + SkAlphaMul(dst[2], dst_scale)); | |
124 if (bw & 0x10) dst[3] = SkToU8(sa + SkAlphaMul(dst[3], dst_scale)); | |
125 if (bw & 0x08) dst[4] = SkToU8(sa + SkAlphaMul(dst[4], dst_scale)); | |
126 if (bw & 0x04) dst[5] = SkToU8(sa + SkAlphaMul(dst[5], dst_scale)); | |
127 if (bw & 0x02) dst[6] = SkToU8(sa + SkAlphaMul(dst[6], dst_scale)); | |
128 if (bw & 0x01) dst[7] = SkToU8(sa + SkAlphaMul(dst[7], dst_scale)); | |
129 } | |
130 | |
131 #define SK_BLITBWMASK_NAME SkA8_BlendBW | |
132 #define SK_BLITBWMASK_ARGS , U8CPU sa, unsigned dst_scale | |
133 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sa, dst_sc
ale) | |
134 #define SK_BLITBWMASK_GETADDR getAddr8 | |
135 #define SK_BLITBWMASK_DEVTYPE uint8_t | |
136 #include "SkBlitBWMaskTemplate.h" | |
137 | |
138 void SkA8_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) | |
139 { | |
140 if (fSrcA == 0) | |
141 return; | |
142 | |
143 if (mask.fFormat == SkMask::kBW_Format) | |
144 { | |
145 if (fSrcA == 0xFF) | |
146 SkA8_BlitBW(fDevice, mask, clip); | |
147 else | |
148 SkA8_BlendBW(fDevice, mask, clip, fSrcA, SkAlpha255To256(255 - fSrcA
)); | |
149 return; | |
150 } | |
151 | |
152 int x = clip.fLeft; | |
153 int y = clip.fTop; | |
154 int width = clip.width(); | |
155 int height = clip.height(); | |
156 uint8_t* device = fDevice.getAddr8(x, y); | |
157 const uint8_t* alpha = mask.getAddr(x, y); | |
158 unsigned srcA = fSrcA; | |
159 | |
160 while (--height >= 0) | |
161 { | |
162 for (int i = width - 1; i >= 0; --i) | |
163 { | |
164 unsigned sa; | |
165 // scale our src by the alpha value | |
166 { | |
167 int aa = alpha[i]; | |
168 if (aa == 0) | |
169 continue; | |
170 | |
171 if (aa == 255) | |
172 { | |
173 if (srcA == 255) | |
174 { | |
175 device[i] = 0xFF; | |
176 continue; | |
177 } | |
178 sa = srcA; | |
179 } | |
180 else | |
181 sa = SkAlphaMul(srcA, SkAlpha255To256(aa)); | |
182 } | |
183 | |
184 int scale = 256 - SkAlpha255To256(sa); | |
185 device[i] = SkToU8(sa + SkAlphaMul(device[i], scale)); | |
186 } | |
187 device += fDevice.rowBytes(); | |
188 alpha += mask.fRowBytes; | |
189 } | |
190 } | |
191 | |
192 ////////////////////////////////////////////////////////////////////////////////
/////// | |
193 | |
194 void SkA8_Blitter::blitV(int x, int y, int height, SkAlpha alpha) | |
195 { | |
196 if (fSrcA == 0) | |
197 return; | |
198 | |
199 unsigned sa = SkAlphaMul(fSrcA, SkAlpha255To256(alpha)); | |
200 uint8_t* device = fDevice.getAddr8(x, y); | |
201 int rowBytes = fDevice.rowBytes(); | |
202 | |
203 if (sa == 0xFF) | |
204 { | |
205 for (int i = 0; i < height; i++) | |
206 { | |
207 *device = SkToU8(sa); | |
208 device += rowBytes; | |
209 } | |
210 } | |
211 else | |
212 { | |
213 unsigned scale = 256 - SkAlpha255To256(sa); | |
214 | |
215 for (int i = 0; i < height; i++) | |
216 { | |
217 *device = SkToU8(sa + SkAlphaMul(*device, scale)); | |
218 device += rowBytes; | |
219 } | |
220 } | |
221 } | |
222 | |
223 void SkA8_Blitter::blitRect(int x, int y, int width, int height) | |
224 { | |
225 SkASSERT(x >= 0 && y >= 0 && (unsigned)(x + width) <= (unsigned)fDevice.widt
h() && (unsigned)(y + height) <= (unsigned)fDevice.height()); | |
226 | |
227 if (fSrcA == 0) | |
228 return; | |
229 | |
230 uint8_t* device = fDevice.getAddr8(x, y); | |
231 unsigned srcA = fSrcA; | |
232 | |
233 if (srcA == 255) | |
234 { | |
235 while (--height >= 0) | |
236 { | |
237 memset(device, 0xFF, width); | |
238 device += fDevice.rowBytes(); | |
239 } | |
240 } | |
241 else | |
242 { | |
243 unsigned scale = 256 - SkAlpha255To256(srcA); | |
244 | |
245 while (--height >= 0) | |
246 { | |
247 for (int i = 0; i < width; i++) | |
248 { | |
249 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); | |
250 } | |
251 device += fDevice.rowBytes(); | |
252 } | |
253 } | |
254 } | |
255 | |
256 /////////////////////////////////////////////////////////////////////// | |
257 | |
258 SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint&
paint) | |
259 : INHERITED(device, paint) | |
260 { | |
261 if ((fXfermode = paint.getXfermode()) != NULL) | |
262 { | |
263 fXfermode->ref(); | |
264 SkASSERT(fShader); | |
265 } | |
266 | |
267 int width = device.width(); | |
268 fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4
(width) >> 2))); | |
269 fAAExpand = (uint8_t*)(fBuffer + width); | |
270 } | |
271 | |
272 SkA8_Shader_Blitter::~SkA8_Shader_Blitter() | |
273 { | |
274 fXfermode->safeUnref(); | |
275 sk_free(fBuffer); | |
276 } | |
277 | |
278 void SkA8_Shader_Blitter::blitH(int x, int y, int width) | |
279 { | |
280 SkASSERT(x >= 0 && y >= 0 && (unsigned)(x + width) <= (unsigned)fDevice.widt
h()); | |
281 | |
282 uint8_t* device = fDevice.getAddr8(x, y); | |
283 | |
284 if ((fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) && fXfermode == NULL
) | |
285 { | |
286 memset(device, 0xFF, width); | |
287 } | |
288 else | |
289 { | |
290 SkPMColor* span = fBuffer; | |
291 | |
292 fShader->shadeSpan(x, y, span, width); | |
293 if (fXfermode) | |
294 fXfermode->xferA8(device, span, width, NULL); | |
295 else | |
296 { | |
297 for (int i = width - 1; i >= 0; --i) | |
298 { | |
299 unsigned srcA = SkGetPackedA32(span[i]); | |
300 unsigned scale = 256 - SkAlpha255To256(srcA); | |
301 | |
302 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); | |
303 } | |
304 } | |
305 } | |
306 } | |
307 | |
308 static inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) | |
309 { | |
310 SkASSERT((unsigned)aa <= 255); | |
311 | |
312 int src_scale = SkAlpha255To256(aa); | |
313 int sa = SkGetPackedA32(src); | |
314 int dst_scale = 256 - SkAlphaMul(sa, src_scale); | |
315 | |
316 return SkToU8((sa * src_scale + da * dst_scale) >> 8); | |
317 } | |
318 | |
319 void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], con
st int16_t runs[]) | |
320 { | |
321 SkShader* shader = fShader; | |
322 SkXfermode* mode = fXfermode; | |
323 uint8_t* aaExpand = fAAExpand; | |
324 SkPMColor* span = fBuffer; | |
325 uint8_t* device = fDevice.getAddr8(x, y); | |
326 int opaque = fShader->getFlags() & SkShader::kOpaqueAlpha_Flag; | |
327 | |
328 for (;;) | |
329 { | |
330 int count = *runs; | |
331 if (count == 0) | |
332 break; | |
333 int aa = *antialias; | |
334 if (aa) | |
335 { | |
336 if (opaque && aa == 255 && mode == NULL) | |
337 memset(device, 0xFF, count); | |
338 else | |
339 { | |
340 shader->shadeSpan(x, y, span, count); | |
341 if (mode) | |
342 { | |
343 memset(aaExpand, aa, count); | |
344 mode->xferA8(device, span, count, aaExpand); | |
345 } | |
346 else | |
347 { | |
348 for (int i = count - 1; i >= 0; --i) | |
349 device[i] = aa_blend8(span[i], device[i], aa); | |
350 } | |
351 } | |
352 } | |
353 device += count; | |
354 runs += count; | |
355 antialias += count; | |
356 x += count; | |
357 } | |
358 } | |
359 | |
360 void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) | |
361 { | |
362 if (mask.fFormat == SkMask::kBW_Format) | |
363 { | |
364 this->INHERITED::blitMask(mask, clip); | |
365 return; | |
366 } | |
367 | |
368 int x = clip.fLeft; | |
369 int y = clip.fTop; | |
370 int width = clip.width(); | |
371 int height = clip.height(); | |
372 uint8_t* device = fDevice.getAddr8(x, y); | |
373 const uint8_t* alpha = mask.getAddr(x, y); | |
374 | |
375 SkPMColor* span = fBuffer; | |
376 | |
377 while (--height >= 0) | |
378 { | |
379 fShader->shadeSpan(x, y, span, width); | |
380 fXfermode->xferA8(device, span, width, alpha); | |
381 | |
382 y += 1; | |
383 device += fDevice.rowBytes(); | |
384 alpha += mask.fRowBytes; | |
385 } | |
386 } | |
387 | |
OLD | NEW |