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 23SkA8_Blitter::SkA8_Blitter(const SkBitmap& device, const SkPaint& paint) 24 : INHERITED(device) 25{ 26 fSrcA = SkColorGetA(paint.getColor()); 27} 28 29const 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 39void SkA8_Blitter::blitH(int x, int y, int width) 40{ 41 SkASSERT(x >= 0 && y >= 0 && (unsigned)(x + width) <= (unsigned)fDevice.width()); 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 64void SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_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 119static inline void blend_8_pixels(U8CPU bw, uint8_t dst[], U8CPU sa, unsigned dst_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_scale) 134#define SK_BLITBWMASK_GETADDR getAddr8 135#define SK_BLITBWMASK_DEVTYPE uint8_t 136#include "SkBlitBWMaskTemplate.h" 137 138void 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 194void 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 223void SkA8_Blitter::blitRect(int x, int y, int width, int height) 224{ 225 SkASSERT(x >= 0 && y >= 0 && (unsigned)(x + width) <= (unsigned)fDevice.width() && (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 258SkA8_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 272SkA8_Shader_Blitter::~SkA8_Shader_Blitter() 273{ 274 fXfermode->safeUnref(); 275 sk_free(fBuffer); 276} 277 278void SkA8_Shader_Blitter::blitH(int x, int y, int width) 279{ 280 SkASSERT(x >= 0 && y >= 0 && (unsigned)(x + width) <= (unsigned)fDevice.width()); 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 308static 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 319void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const 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 360void 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 388