SkBlitMask_D32.cpp revision 83a444602ec580a0040713eed588c245b4ae0ee9
1#include "SkBlitMask.h" 2#include "SkColor.h" 3#include "SkColorPriv.h" 4 5static void D32_A8_Color(void* SK_RESTRICT dst, size_t dstRB, 6 const void* SK_RESTRICT maskPtr, size_t maskRB, 7 SkColor color, int width, int height) { 8 SkPMColor pmc = SkPreMultiplyColor(color); 9 size_t dstOffset = dstRB - (width << 2); 10 size_t maskOffset = maskRB - width; 11 SkPMColor* SK_RESTRICT device = (SkPMColor *)dst; 12 const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr; 13 14 do { 15 int w = width; 16 do { 17 unsigned aa = *mask++; 18 *device = SkBlendARGB32(pmc, *device, aa); 19 device += 1; 20 } while (--w != 0); 21 device = (uint32_t*)((char*)device + dstOffset); 22 mask += maskOffset; 23 } while (--height != 0); 24} 25 26static void D32_A8_Opaque(void* SK_RESTRICT dst, size_t dstRB, 27 const void* SK_RESTRICT maskPtr, size_t maskRB, 28 SkColor color, int width, int height) { 29 SkPMColor pmc = SkPreMultiplyColor(color); 30 SkPMColor* SK_RESTRICT device = (SkPMColor*)dst; 31 const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr; 32 33 maskRB -= width; 34 dstRB -= (width << 2); 35 do { 36 int w = width; 37 do { 38 unsigned aa = *mask++; 39 *device = SkAlphaMulQ(pmc, SkAlpha255To256(aa)) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa)); 40 device += 1; 41 } while (--w != 0); 42 device = (uint32_t*)((char*)device + dstRB); 43 mask += maskRB; 44 } while (--height != 0); 45} 46 47static void D32_A8_Black(void* SK_RESTRICT dst, size_t dstRB, 48 const void* SK_RESTRICT maskPtr, size_t maskRB, 49 SkColor, int width, int height) { 50 SkPMColor* SK_RESTRICT device = (SkPMColor*)dst; 51 const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr; 52 53 maskRB -= width; 54 dstRB -= (width << 2); 55 do { 56 int w = width; 57 do { 58 unsigned aa = *mask++; 59 *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa)); 60 device += 1; 61 } while (--w != 0); 62 device = (uint32_t*)((char*)device + dstRB); 63 mask += maskRB; 64 } while (--height != 0); 65} 66 67/////////////////////////////////////////////////////////////////////////////// 68 69static inline int upscale31To32(int value) { 70 SkASSERT((unsigned)value <= 31); 71 return value + (value >> 4); 72} 73 74static inline int blend32(int src, int dst, int scale) { 75 SkASSERT((unsigned)src <= 0xFF); 76 SkASSERT((unsigned)dst <= 0xFF); 77 SkASSERT((unsigned)scale <= 32); 78 return dst + ((src - dst) * scale >> 5); 79} 80 81static void blit_lcd16_row(SkPMColor dst[], const uint16_t src[], 82 SkColor color, int width, SkPMColor) { 83 int srcA = SkColorGetA(color); 84 int srcR = SkColorGetR(color); 85 int srcG = SkColorGetG(color); 86 int srcB = SkColorGetB(color); 87 88 srcA = SkAlpha255To256(srcA); 89 90 for (int i = 0; i < width; i++) { 91 uint16_t mask = src[i]; 92 if (0 == mask) { 93 continue; 94 } 95 96 SkPMColor d = dst[i]; 97 98 /* We want all of these in 5bits, hence the shifts in case one of them 99 * (green) is 6bits. 100 */ 101 int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5); 102 int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5); 103 int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5); 104 105 // Now upscale them to 0..32, so we can use blend32 106 maskR = upscale31To32(maskR); 107 maskG = upscale31To32(maskG); 108 maskB = upscale31To32(maskB); 109 110 maskR = maskR * srcA >> 8; 111 maskG = maskG * srcA >> 8; 112 maskB = maskB * srcA >> 8; 113 114 int dstR = SkGetPackedR32(d); 115 int dstG = SkGetPackedG32(d); 116 int dstB = SkGetPackedB32(d); 117 118 // LCD blitting is only supported if the dst is known/required 119 // to be opaque 120 dst[i] = SkPackARGB32(0xFF, 121 blend32(srcR, dstR, maskR), 122 blend32(srcG, dstG, maskG), 123 blend32(srcB, dstB, maskB)); 124 } 125} 126 127static void blit_lcd16_opaque_row(SkPMColor dst[], const uint16_t src[], 128 SkColor color, int width, SkPMColor opaqueDst) { 129 int srcR = SkColorGetR(color); 130 int srcG = SkColorGetG(color); 131 int srcB = SkColorGetB(color); 132 133 for (int i = 0; i < width; i++) { 134 uint16_t mask = src[i]; 135 if (0 == mask) { 136 continue; 137 } 138 if (0xFFFF == mask) { 139 dst[i] = opaqueDst; 140 continue; 141 } 142 143 SkPMColor d = dst[i]; 144 145 /* We want all of these in 5bits, hence the shifts in case one of them 146 * (green) is 6bits. 147 */ 148 int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5); 149 int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5); 150 int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5); 151 152 // Now upscale them to 0..32, so we can use blend32 153 maskR = upscale31To32(maskR); 154 maskG = upscale31To32(maskG); 155 maskB = upscale31To32(maskB); 156 157 int dstR = SkGetPackedR32(d); 158 int dstG = SkGetPackedG32(d); 159 int dstB = SkGetPackedB32(d); 160 161 // LCD blitting is only supported if the dst is known/required 162 // to be opaque 163 dst[i] = SkPackARGB32(0xFF, 164 blend32(srcR, dstR, maskR), 165 blend32(srcG, dstG, maskG), 166 blend32(srcB, dstB, maskB)); 167 } 168} 169 170static void D32_LCD16_Proc(void* SK_RESTRICT dst, size_t dstRB, 171 const void* SK_RESTRICT mask, size_t maskRB, 172 SkColor color, int width, int height) { 173 174 SkPMColor* dstRow = (SkPMColor*)dst; 175 const uint16_t* srcRow = (const uint16_t*)mask; 176 SkPMColor opaqueDst; 177 178 void (*proc)(SkPMColor dst[], const uint16_t src[], 179 SkColor color, int width, SkPMColor); 180 if (0xFF == SkColorGetA(color)) { 181 proc = blit_lcd16_opaque_row; 182 opaqueDst = SkPreMultiplyColor(color); 183 } else { 184 proc = blit_lcd16_row; 185 opaqueDst = 0; // ignored 186 } 187 188 do { 189 proc(dstRow, srcRow, color, width, opaqueDst); 190 dstRow = (SkPMColor*)((char*)dstRow + dstRB); 191 srcRow = (const uint16_t*)((const char*)srcRow + maskRB); 192 } while (--height != 0); 193} 194 195/////////////////////////////////////////////////////////////////////////////// 196 197static void blit_lcd32_opaque_row(SkPMColor* SK_RESTRICT dst, 198 const SkPMColor* SK_RESTRICT src, 199 SkColor color, int width) { 200 int srcR = SkColorGetR(color); 201 int srcG = SkColorGetG(color); 202 int srcB = SkColorGetB(color); 203 204 for (int i = 0; i < width; i++) { 205 SkPMColor mask = src[i]; 206 if (0 == mask) { 207 continue; 208 } 209 210 SkPMColor d = dst[i]; 211 212 int maskR = SkGetPackedR32(mask); 213 int maskG = SkGetPackedG32(mask); 214 int maskB = SkGetPackedB32(mask); 215 216 // Now upscale them to 0..256, so we can use SkAlphaBlend 217 maskR = SkAlpha255To256(maskR); 218 maskG = SkAlpha255To256(maskG); 219 maskB = SkAlpha255To256(maskB); 220 221 int dstR = SkGetPackedR32(d); 222 int dstG = SkGetPackedG32(d); 223 int dstB = SkGetPackedB32(d); 224 225 // LCD blitting is only supported if the dst is known/required 226 // to be opaque 227 dst[i] = SkPackARGB32(0xFF, 228 SkAlphaBlend(srcR, dstR, maskR), 229 SkAlphaBlend(srcG, dstG, maskG), 230 SkAlphaBlend(srcB, dstB, maskB)); 231 } 232} 233 234static void blit_lcd32_row(SkPMColor* SK_RESTRICT dst, 235 const SkPMColor* SK_RESTRICT src, 236 SkColor color, int width) { 237 int srcA = SkColorGetA(color); 238 int srcR = SkColorGetR(color); 239 int srcG = SkColorGetG(color); 240 int srcB = SkColorGetB(color); 241 242 srcA = SkAlpha255To256(srcA); 243 244 for (int i = 0; i < width; i++) { 245 SkPMColor mask = src[i]; 246 if (0 == mask) { 247 continue; 248 } 249 250 SkPMColor d = dst[i]; 251 252 int maskR = SkGetPackedR32(mask); 253 int maskG = SkGetPackedG32(mask); 254 int maskB = SkGetPackedB32(mask); 255 256 // Now upscale them to 0..256, so we can use SkAlphaBlend 257 maskR = SkAlpha255To256(maskR); 258 maskG = SkAlpha255To256(maskG); 259 maskB = SkAlpha255To256(maskB); 260 261 maskR = maskR * srcA >> 8; 262 maskG = maskG * srcA >> 8; 263 maskB = maskB * srcA >> 8; 264 265 int dstR = SkGetPackedR32(d); 266 int dstG = SkGetPackedG32(d); 267 int dstB = SkGetPackedB32(d); 268 269 // LCD blitting is only supported if the dst is known/required 270 // to be opaque 271 dst[i] = SkPackARGB32(0xFF, 272 SkAlphaBlend(srcR, dstR, maskR), 273 SkAlphaBlend(srcG, dstG, maskG), 274 SkAlphaBlend(srcB, dstB, maskB)); 275 } 276} 277 278static void D32_LCD32_Blend(void* SK_RESTRICT dst, size_t dstRB, 279 const void* SK_RESTRICT mask, size_t maskRB, 280 SkColor color, int width, int height) { 281 SkASSERT(height > 0); 282 SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst; 283 const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask; 284 285 do { 286 blit_lcd32_row(dstRow, srcRow, color, width); 287 dstRow = (SkPMColor*)((char*)dstRow + dstRB); 288 srcRow = (const SkPMColor*)((const char*)srcRow + maskRB); 289 } while (--height != 0); 290} 291 292static void D32_LCD32_Opaque(void* SK_RESTRICT dst, size_t dstRB, 293 const void* SK_RESTRICT mask, size_t maskRB, 294 SkColor color, int width, int height) { 295 SkASSERT(height > 0); 296 SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst; 297 const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask; 298 299 do { 300 blit_lcd32_opaque_row(dstRow, srcRow, color, width); 301 dstRow = (SkPMColor*)((char*)dstRow + dstRB); 302 srcRow = (const SkPMColor*)((const char*)srcRow + maskRB); 303 } while (--height != 0); 304} 305 306/////////////////////////////////////////////////////////////////////////////// 307 308static SkBlitMask::Proc D32_A8_Factory(SkColor color) { 309 if (SK_ColorBLACK == color) { 310 return D32_A8_Black; 311 } else if (0xFF == SkColorGetA(color)) { 312 return D32_A8_Opaque; 313 } else { 314 return D32_A8_Color; 315 } 316} 317 318static SkBlitMask::Proc D32_LCD32_Factory(SkColor color) { 319 return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend; 320} 321 322SkBlitMask::Proc SkBlitMask::Factory(SkBitmap::Config config, 323 SkMask::Format format, SkColor color) { 324 SkBlitMask::Proc proc = PlatformProcs(config, format, color); 325 if (proc) { 326 return proc; 327 } 328 329 switch (config) { 330 case SkBitmap::kARGB_8888_Config: 331 switch (format) { 332 case SkMask::kA8_Format: 333 return D32_A8_Factory(color); 334 case SkMask::kLCD16_Format: 335 return D32_LCD16_Proc; 336 case SkMask::kLCD32_Format: 337 return D32_LCD32_Factory(color); 338 default: 339 break; 340 } 341 break; 342 default: 343 break; 344 } 345 return NULL; 346} 347 348bool SkBlitMask::BlitColor(const SkBitmap& device, const SkMask& mask, 349 const SkIRect& clip, SkColor color) { 350 Proc proc = Factory(device.config(), mask.fFormat, color); 351 if (proc) { 352 int x = clip.fLeft; 353 int y = clip.fTop; 354 proc(device.getAddr32(x, y), device.rowBytes(), mask.getAddr(x, y), 355 mask.fRowBytes, color, clip.width(), clip.height()); 356 return true; 357 } 358 return false; 359} 360 361 362