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