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