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 #include "SkCoreBlitters.h" 11 #include "SkColorPriv.h" 12 #include "SkShader.h" 13 #include "SkXfermode.h" 14 15 SkA8_Blitter::SkA8_Blitter(const SkBitmap& device, const SkPaint& paint) 16 : INHERITED(device) { 17 fSrcA = paint.getAlpha(); 18 } 19 20 const SkBitmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) { 21 if (255 == fSrcA) { 22 *value = 255; 23 return &fDevice; 24 } 25 return NULL; 26 } 27 28 void SkA8_Blitter::blitH(int x, int y, int width) { 29 SkASSERT(x >= 0 && y >= 0 && 30 (unsigned)(x + width) <= (unsigned)fDevice.width()); 31 32 if (fSrcA == 0) { 33 return; 34 } 35 36 uint8_t* device = fDevice.getAddr8(x, y); 37 38 if (fSrcA == 255) { 39 memset(device, 0xFF, width); 40 } else { 41 unsigned scale = 256 - SkAlpha255To256(fSrcA); 42 unsigned srcA = fSrcA; 43 44 for (int i = 0; i < width; i++) { 45 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 46 } 47 } 48 } 49 50 void SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 51 const int16_t runs[]) { 52 if (fSrcA == 0) { 53 return; 54 } 55 56 uint8_t* device = fDevice.getAddr8(x, y); 57 unsigned srcA = fSrcA; 58 59 for (;;) { 60 int count = runs[0]; 61 SkASSERT(count >= 0); 62 if (count == 0) { 63 return; 64 } 65 unsigned aa = antialias[0]; 66 67 if (aa == 255 && srcA == 255) { 68 memset(device, 0xFF, count); 69 } else { 70 unsigned sa = SkAlphaMul(srcA, SkAlpha255To256(aa)); 71 unsigned scale = 256 - sa; 72 73 for (int i = 0; i < count; i++) { 74 device[i] = SkToU8(sa + SkAlphaMul(device[i], scale)); 75 } 76 } 77 runs += count; 78 antialias += count; 79 device += count; 80 } 81 } 82 83 ///////////////////////////////////////////////////////////////////////////////////// 84 85 #define solid_8_pixels(mask, dst) \ 86 do { \ 87 if (mask & 0x80) dst[0] = 0xFF; \ 88 if (mask & 0x40) dst[1] = 0xFF; \ 89 if (mask & 0x20) dst[2] = 0xFF; \ 90 if (mask & 0x10) dst[3] = 0xFF; \ 91 if (mask & 0x08) dst[4] = 0xFF; \ 92 if (mask & 0x04) dst[5] = 0xFF; \ 93 if (mask & 0x02) dst[6] = 0xFF; \ 94 if (mask & 0x01) dst[7] = 0xFF; \ 95 } while (0) 96 97 #define SK_BLITBWMASK_NAME SkA8_BlitBW 98 #define SK_BLITBWMASK_ARGS 99 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst) 100 #define SK_BLITBWMASK_GETADDR getAddr8 101 #define SK_BLITBWMASK_DEVTYPE uint8_t 102 #include "SkBlitBWMaskTemplate.h" 103 104 static inline void blend_8_pixels(U8CPU bw, uint8_t dst[], U8CPU sa, 105 unsigned dst_scale) { 106 if (bw & 0x80) dst[0] = SkToU8(sa + SkAlphaMul(dst[0], dst_scale)); 107 if (bw & 0x40) dst[1] = SkToU8(sa + SkAlphaMul(dst[1], dst_scale)); 108 if (bw & 0x20) dst[2] = SkToU8(sa + SkAlphaMul(dst[2], dst_scale)); 109 if (bw & 0x10) dst[3] = SkToU8(sa + SkAlphaMul(dst[3], dst_scale)); 110 if (bw & 0x08) dst[4] = SkToU8(sa + SkAlphaMul(dst[4], dst_scale)); 111 if (bw & 0x04) dst[5] = SkToU8(sa + SkAlphaMul(dst[5], dst_scale)); 112 if (bw & 0x02) dst[6] = SkToU8(sa + SkAlphaMul(dst[6], dst_scale)); 113 if (bw & 0x01) dst[7] = SkToU8(sa + SkAlphaMul(dst[7], dst_scale)); 114 } 115 116 #define SK_BLITBWMASK_NAME SkA8_BlendBW 117 #define SK_BLITBWMASK_ARGS , U8CPU sa, unsigned dst_scale 118 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sa, dst_scale) 119 #define SK_BLITBWMASK_GETADDR getAddr8 120 #define SK_BLITBWMASK_DEVTYPE uint8_t 121 #include "SkBlitBWMaskTemplate.h" 122 123 void SkA8_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 124 if (fSrcA == 0) { 125 return; 126 } 127 128 if (mask.fFormat == SkMask::kBW_Format) { 129 if (fSrcA == 0xFF) { 130 SkA8_BlitBW(fDevice, mask, clip); 131 } else { 132 SkA8_BlendBW(fDevice, mask, clip, fSrcA, 133 SkAlpha255To256(255 - fSrcA)); 134 } 135 return; 136 } 137 138 int x = clip.fLeft; 139 int y = clip.fTop; 140 int width = clip.width(); 141 int height = clip.height(); 142 uint8_t* device = fDevice.getAddr8(x, y); 143 const uint8_t* alpha = mask.getAddr8(x, y); 144 unsigned srcA = fSrcA; 145 146 while (--height >= 0) { 147 for (int i = width - 1; i >= 0; --i) { 148 unsigned sa; 149 // scale our src by the alpha value 150 { 151 int aa = alpha[i]; 152 if (aa == 0) { 153 continue; 154 } 155 if (aa == 255) { 156 if (srcA == 255) { 157 device[i] = 0xFF; 158 continue; 159 } 160 sa = srcA; 161 } else { 162 sa = SkAlphaMul(srcA, SkAlpha255To256(aa)); 163 } 164 } 165 166 int scale = 256 - SkAlpha255To256(sa); 167 device[i] = SkToU8(sa + SkAlphaMul(device[i], scale)); 168 } 169 device += fDevice.rowBytes(); 170 alpha += mask.fRowBytes; 171 } 172 } 173 174 /////////////////////////////////////////////////////////////////////////////// 175 176 void SkA8_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 177 if (fSrcA == 0) { 178 return; 179 } 180 181 unsigned sa = SkAlphaMul(fSrcA, SkAlpha255To256(alpha)); 182 uint8_t* device = fDevice.getAddr8(x, y); 183 int rowBytes = fDevice.rowBytes(); 184 185 if (sa == 0xFF) { 186 for (int i = 0; i < height; i++) { 187 *device = SkToU8(sa); 188 device += rowBytes; 189 } 190 } else { 191 unsigned scale = 256 - SkAlpha255To256(sa); 192 193 for (int i = 0; i < height; i++) { 194 *device = SkToU8(sa + SkAlphaMul(*device, scale)); 195 device += rowBytes; 196 } 197 } 198 } 199 200 void SkA8_Blitter::blitRect(int x, int y, int width, int height) { 201 SkASSERT(x >= 0 && y >= 0 && 202 (unsigned)(x + width) <= (unsigned)fDevice.width() && 203 (unsigned)(y + height) <= (unsigned)fDevice.height()); 204 205 if (fSrcA == 0) { 206 return; 207 } 208 209 uint8_t* device = fDevice.getAddr8(x, y); 210 unsigned srcA = fSrcA; 211 212 if (srcA == 255) { 213 while (--height >= 0) { 214 memset(device, 0xFF, width); 215 device += fDevice.rowBytes(); 216 } 217 } else { 218 unsigned scale = 256 - SkAlpha255To256(srcA); 219 220 while (--height >= 0) { 221 for (int i = 0; i < width; i++) { 222 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 223 } 224 device += fDevice.rowBytes(); 225 } 226 } 227 } 228 229 /////////////////////////////////////////////////////////////////////// 230 231 SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint) 232 : INHERITED(device, paint) { 233 if ((fXfermode = paint.getXfermode()) != NULL) { 234 fXfermode->ref(); 235 SkASSERT(fShader); 236 } 237 238 int width = device.width(); 239 fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4(width) >> 2))); 240 fAAExpand = (uint8_t*)(fBuffer + width); 241 } 242 243 SkA8_Shader_Blitter::~SkA8_Shader_Blitter() { 244 if (fXfermode) SkSafeUnref(fXfermode); 245 sk_free(fBuffer); 246 } 247 248 void SkA8_Shader_Blitter::blitH(int x, int y, int width) { 249 SkASSERT(x >= 0 && y >= 0 && 250 (unsigned)(x + width) <= (unsigned)fDevice.width()); 251 252 uint8_t* device = fDevice.getAddr8(x, y); 253 254 if ((fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) { 255 memset(device, 0xFF, width); 256 } else { 257 SkPMColor* span = fBuffer; 258 259 fShader->shadeSpan(x, y, span, width); 260 if (fXfermode) { 261 fXfermode->xferA8(device, span, width, NULL); 262 } else { 263 for (int i = width - 1; i >= 0; --i) { 264 unsigned srcA = SkGetPackedA32(span[i]); 265 unsigned scale = 256 - SkAlpha255To256(srcA); 266 267 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 268 } 269 } 270 } 271 } 272 273 static inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) { 274 SkASSERT((unsigned)aa <= 255); 275 276 int src_scale = SkAlpha255To256(aa); 277 int sa = SkGetPackedA32(src); 278 int dst_scale = 256 - SkAlphaMul(sa, src_scale); 279 280 return SkToU8((sa * src_scale + da * dst_scale) >> 8); 281 } 282 283 void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 284 const int16_t runs[]) { 285 SkShader* shader = fShader; 286 SkXfermode* mode = fXfermode; 287 uint8_t* aaExpand = fAAExpand; 288 SkPMColor* span = fBuffer; 289 uint8_t* device = fDevice.getAddr8(x, y); 290 int opaque = fShader->getFlags() & SkShader::kOpaqueAlpha_Flag; 291 292 for (;;) { 293 int count = *runs; 294 if (count == 0) { 295 break; 296 } 297 int aa = *antialias; 298 if (aa) { 299 if (opaque && aa == 255 && mode == NULL) { 300 memset(device, 0xFF, count); 301 } else { 302 shader->shadeSpan(x, y, span, count); 303 if (mode) { 304 memset(aaExpand, aa, count); 305 mode->xferA8(device, span, count, aaExpand); 306 } else { 307 for (int i = count - 1; i >= 0; --i) { 308 device[i] = aa_blend8(span[i], device[i], aa); 309 } 310 } 311 } 312 } 313 device += count; 314 runs += count; 315 antialias += count; 316 x += count; 317 } 318 } 319 320 void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 321 if (mask.fFormat == SkMask::kBW_Format) { 322 this->INHERITED::blitMask(mask, clip); 323 return; 324 } 325 326 int x = clip.fLeft; 327 int y = clip.fTop; 328 int width = clip.width(); 329 int height = clip.height(); 330 uint8_t* device = fDevice.getAddr8(x, y); 331 const uint8_t* alpha = mask.getAddr8(x, y); 332 333 SkPMColor* span = fBuffer; 334 335 while (--height >= 0) { 336 fShader->shadeSpan(x, y, span, width); 337 if (fXfermode) { 338 fXfermode->xferA8(device, span, width, alpha); 339 } 340 341 y += 1; 342 device += fDevice.rowBytes(); 343 alpha += mask.fRowBytes; 344 } 345 } 346 347