1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SkColorPriv_DEFINED 18 #define SkColorPriv_DEFINED 19 20 // turn this own for extra debug checking when blending onto 565 21 #ifdef SK_DEBUG 22 #define CHECK_FOR_565_OVERFLOW 23 #endif 24 25 #include "SkColor.h" 26 #include "SkMath.h" 27 28 /** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a 29 byte into a scale value, so that we can say scale * value >> 8 instead of 30 alpha * value / 255. 31 32 In debugging, asserts that alpha is 0..255 33 */ 34 static inline unsigned SkAlpha255To256(U8CPU alpha) { 35 SkASSERT(SkToU8(alpha) == alpha); 36 // this one assues that blending on top of an opaque dst keeps it that way 37 // even though it is less accurate than a+(a>>7) for non-opaque dsts 38 return alpha + 1; 39 } 40 41 /** Multiplify value by 0..256, and shift the result down 8 42 (i.e. return (value * alpha256) >> 8) 43 */ 44 #define SkAlphaMul(value, alpha256) (SkMulS16(value, alpha256) >> 8) 45 46 // The caller may want negative values, so keep all params signed (int) 47 // so we don't accidentally slip into unsigned math and lose the sign 48 // extension when we shift (in SkAlphaMul) 49 static inline int SkAlphaBlend(int src, int dst, int scale256) { 50 SkASSERT((unsigned)scale256 <= 256); 51 return dst + SkAlphaMul(src - dst, scale256); 52 } 53 54 #define SK_R16_BITS 5 55 #define SK_G16_BITS 6 56 #define SK_B16_BITS 5 57 58 #define SK_R16_SHIFT (SK_B16_BITS + SK_G16_BITS) 59 #define SK_G16_SHIFT (SK_B16_BITS) 60 #define SK_B16_SHIFT 0 61 62 #define SK_R16_MASK ((1 << SK_R16_BITS) - 1) 63 #define SK_G16_MASK ((1 << SK_G16_BITS) - 1) 64 #define SK_B16_MASK ((1 << SK_B16_BITS) - 1) 65 66 #define SkGetPackedR16(color) (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK) 67 #define SkGetPackedG16(color) (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK) 68 #define SkGetPackedB16(color) (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK) 69 70 #define SkR16Assert(r) SkASSERT((unsigned)(r) <= SK_R16_MASK) 71 #define SkG16Assert(g) SkASSERT((unsigned)(g) <= SK_G16_MASK) 72 #define SkB16Assert(b) SkASSERT((unsigned)(b) <= SK_B16_MASK) 73 74 static inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) { 75 SkASSERT(r <= SK_R16_MASK); 76 SkASSERT(g <= SK_G16_MASK); 77 SkASSERT(b <= SK_B16_MASK); 78 79 return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT)); 80 } 81 82 #define SK_R16_MASK_IN_PLACE (SK_R16_MASK << SK_R16_SHIFT) 83 #define SK_G16_MASK_IN_PLACE (SK_G16_MASK << SK_G16_SHIFT) 84 #define SK_B16_MASK_IN_PLACE (SK_B16_MASK << SK_B16_SHIFT) 85 86 /** Expand the 16bit color into a 32bit value that can be scaled all at once 87 by a value up to 32. Used in conjunction with SkCompact_rgb_16. 88 */ 89 static inline uint32_t SkExpand_rgb_16(U16CPU c) { 90 SkASSERT(c == (uint16_t)c); 91 92 return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE); 93 } 94 95 /** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit 96 color value. The computation yields only 16bits of valid data, but we claim 97 to return 32bits, so that the compiler won't generate extra instructions to 98 "clean" the top 16bits. However, the top 16 can contain garbage, so it is 99 up to the caller to safely ignore them. 100 */ 101 static inline U16CPU SkCompact_rgb_16(uint32_t c) { 102 return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE); 103 } 104 105 /** Scale the 16bit color value by the 0..256 scale parameter. 106 The computation yields only 16bits of valid data, but we claim 107 to return 32bits, so that the compiler won't generate extra instructions to 108 "clean" the top 16bits. 109 */ 110 static inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) { 111 return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5); 112 } 113 114 // this helper explicitly returns a clean 16bit value (but slower) 115 #define SkAlphaMulRGB16_ToU16(c, s) (uint16_t)SkAlphaMulRGB16(c, s) 116 117 /** Blend src and dst 16bit colors by the 0..256 scale parameter. 118 The computation yields only 16bits of valid data, but we claim 119 to return 32bits, so that the compiler won't generate extra instructions to 120 "clean" the top 16bits. 121 */ 122 static inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) { 123 SkASSERT((unsigned)srcScale <= 256); 124 125 srcScale >>= 3; 126 127 uint32_t src32 = SkExpand_rgb_16(src); 128 uint32_t dst32 = SkExpand_rgb_16(dst); 129 return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)); 130 } 131 132 static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[], 133 int srcScale, int count) { 134 SkASSERT(count > 0); 135 SkASSERT((unsigned)srcScale <= 256); 136 137 srcScale >>= 3; 138 139 do { 140 uint32_t src32 = SkExpand_rgb_16(*src++); 141 uint32_t dst32 = SkExpand_rgb_16(*dst); 142 *dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)); 143 } while (--count > 0); 144 } 145 146 #ifdef SK_DEBUG 147 static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) { 148 SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK); 149 SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK); 150 SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK); 151 152 return a + b; 153 } 154 #else 155 #define SkRGB16Add(a, b) ((a) + (b)) 156 #endif 157 158 ///////////////////////////////////////////////////////////////////////////////////////////// 159 160 #define SK_A32_BITS 8 161 #define SK_R32_BITS 8 162 #define SK_G32_BITS 8 163 #define SK_B32_BITS 8 164 165 /* we check to see if the SHIFT value has already been defined (SkUserConfig.h) 166 if not, we define it ourself to some default values. We default to OpenGL 167 order (in memory: r,g,b,a) 168 */ 169 #ifndef SK_A32_SHIFT 170 #ifdef SK_CPU_BENDIAN 171 #define SK_R32_SHIFT 24 172 #define SK_G32_SHIFT 16 173 #define SK_B32_SHIFT 8 174 #define SK_A32_SHIFT 0 175 #else 176 #define SK_R32_SHIFT 0 177 #define SK_G32_SHIFT 8 178 #define SK_B32_SHIFT 16 179 #define SK_A32_SHIFT 24 180 #endif 181 #endif 182 183 #define SK_A32_MASK ((1 << SK_A32_BITS) - 1) 184 #define SK_R32_MASK ((1 << SK_R32_BITS) - 1) 185 #define SK_G32_MASK ((1 << SK_G32_BITS) - 1) 186 #define SK_B32_MASK ((1 << SK_B32_BITS) - 1) 187 188 #define SkGetPackedA32(packed) ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24) 189 #define SkGetPackedR32(packed) ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24) 190 #define SkGetPackedG32(packed) ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24) 191 #define SkGetPackedB32(packed) ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24) 192 193 #define SkA32Assert(a) SkASSERT((unsigned)(a) <= SK_A32_MASK) 194 #define SkR32Assert(r) SkASSERT((unsigned)(r) <= SK_R32_MASK) 195 #define SkG32Assert(g) SkASSERT((unsigned)(g) <= SK_G32_MASK) 196 #define SkB32Assert(b) SkASSERT((unsigned)(b) <= SK_B32_MASK) 197 198 #ifdef SK_DEBUG 199 static inline void SkPMColorAssert(SkPMColor c) { 200 unsigned a = SkGetPackedA32(c); 201 unsigned r = SkGetPackedR32(c); 202 unsigned g = SkGetPackedG32(c); 203 unsigned b = SkGetPackedB32(c); 204 205 SkA32Assert(a); 206 SkASSERT(r <= a); 207 SkASSERT(g <= a); 208 SkASSERT(b <= a); 209 } 210 #else 211 #define SkPMColorAssert(c) 212 #endif 213 214 static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { 215 SkA32Assert(a); 216 SkASSERT(r <= a); 217 SkASSERT(g <= a); 218 SkASSERT(b <= a); 219 220 return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) | 221 (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT); 222 } 223 224 extern const uint32_t gMask_00FF00FF; 225 226 static inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) { 227 uint32_t mask = gMask_00FF00FF; 228 // uint32_t mask = 0xFF00FF; 229 230 uint32_t rb = ((c & mask) * scale) >> 8; 231 uint32_t ag = ((c >> 8) & mask) * scale; 232 return (rb & mask) | (ag & ~mask); 233 } 234 235 static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) { 236 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 237 } 238 239 static inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) { 240 SkASSERT((unsigned)aa <= 255); 241 242 unsigned src_scale = SkAlpha255To256(aa); 243 unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale)); 244 245 return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale); 246 } 247 248 //////////////////////////////////////////////////////////////////////////////////////////// 249 // Convert a 32bit pixel to a 16bit pixel (no dither) 250 251 #define SkR32ToR16_MACRO(r) ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS)) 252 #define SkG32ToG16_MACRO(g) ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS)) 253 #define SkB32ToB16_MACRO(b) ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS)) 254 255 #ifdef SK_DEBUG 256 static inline unsigned SkR32ToR16(unsigned r) { 257 SkR32Assert(r); 258 return SkR32ToR16_MACRO(r); 259 } 260 static inline unsigned SkG32ToG16(unsigned g) { 261 SkG32Assert(g); 262 return SkG32ToG16_MACRO(g); 263 } 264 static inline unsigned SkB32ToB16(unsigned b) { 265 SkB32Assert(b); 266 return SkB32ToB16_MACRO(b); 267 } 268 #else 269 #define SkR32ToR16(r) SkR32ToR16_MACRO(r) 270 #define SkG32ToG16(g) SkG32ToG16_MACRO(g) 271 #define SkB32ToB16(b) SkB32ToB16_MACRO(b) 272 #endif 273 274 #define SkPacked32ToR16(c) (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK) 275 #define SkPacked32ToG16(c) (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK) 276 #define SkPacked32ToB16(c) (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK) 277 278 static inline U16CPU SkPixel32ToPixel16(SkPMColor c) { 279 unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT; 280 unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT; 281 unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT; 282 return r | g | b; 283 } 284 285 static inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) { 286 return (SkR32ToR16(r) << SK_R16_SHIFT) | 287 (SkG32ToG16(g) << SK_G16_SHIFT) | 288 (SkB32ToB16(b) << SK_B16_SHIFT); 289 } 290 291 #define SkPixel32ToPixel16_ToU16(src) SkToU16(SkPixel32ToPixel16(src)) 292 293 ///////////////////////////////////////////////////////////////////////////////////////// 294 // Fast dither from 32->16 295 296 #define SkShouldDitherXY(x, y) (((x) ^ (y)) & 1) 297 298 static inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) { 299 r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS); 300 g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS); 301 b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS); 302 303 return SkPackRGB16(r, g, b); 304 } 305 306 static inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) { 307 return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c)); 308 } 309 310 /* Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits) 311 It is now suitable for combining with a scaled expanded_rgb_16 color 312 as in SkSrcOver32To16(). 313 We must do this 565 high-bit replication, in order for the subsequent add 314 to saturate properly (and not overflow). If we take the 8 bits as is, it is 315 possible to overflow. 316 */ 317 static inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) { 318 unsigned sr = SkPacked32ToR16(c); 319 unsigned sg = SkPacked32ToG16(c); 320 unsigned sb = SkPacked32ToB16(c); 321 322 sr = (sr << 5) | sr; 323 sg = (sg << 5) | (sg >> 1); 324 sb = (sb << 5) | sb; 325 return (sr << 11) | (sg << 21) | (sb << 0); 326 } 327 328 /* SrcOver the 32bit src color with the 16bit dst, returning a 16bit value 329 (with dirt in the high 16bits, so caller beware). 330 */ 331 static inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) { 332 unsigned sr = SkGetPackedR32(src); 333 unsigned sg = SkGetPackedG32(src); 334 unsigned sb = SkGetPackedB32(src); 335 336 unsigned dr = SkGetPackedR16(dst); 337 unsigned dg = SkGetPackedG16(dst); 338 unsigned db = SkGetPackedB16(dst); 339 340 unsigned isa = 255 - SkGetPackedA32(src); 341 342 dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS); 343 dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS); 344 db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS); 345 346 return SkPackRGB16(dr, dg, db); 347 } 348 349 //////////////////////////////////////////////////////////////////////////////////////////// 350 // Convert a 16bit pixel to a 32bit pixel 351 352 static inline unsigned SkR16ToR32(unsigned r) { 353 return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8)); 354 } 355 356 static inline unsigned SkG16ToG32(unsigned g) { 357 return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8)); 358 } 359 360 static inline unsigned SkB16ToB32(unsigned b) { 361 return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8)); 362 } 363 364 #define SkPacked16ToR32(c) SkR16ToR32(SkGetPackedR16(c)) 365 #define SkPacked16ToG32(c) SkG16ToG32(SkGetPackedG16(c)) 366 #define SkPacked16ToB32(c) SkB16ToB32(SkGetPackedB16(c)) 367 368 static inline SkPMColor SkPixel16ToPixel32(U16CPU src) { 369 SkASSERT(src == SkToU16(src)); 370 371 unsigned r = SkPacked16ToR32(src); 372 unsigned g = SkPacked16ToG32(src); 373 unsigned b = SkPacked16ToB32(src); 374 375 SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src)); 376 SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src)); 377 SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src)); 378 379 return SkPackARGB32(0xFF, r, g, b); 380 } 381 382 // similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor 383 static inline SkColor SkPixel16ToColor(U16CPU src) { 384 SkASSERT(src == SkToU16(src)); 385 386 unsigned r = SkPacked16ToR32(src); 387 unsigned g = SkPacked16ToG32(src); 388 unsigned b = SkPacked16ToB32(src); 389 390 SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src)); 391 SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src)); 392 SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src)); 393 394 return SkColorSetRGB(r, g, b); 395 } 396 397 /////////////////////////////////////////////////////////////////////////////// 398 399 typedef uint16_t SkPMColor16; 400 401 // Put in OpenGL order (r g b a) 402 #define SK_A4444_SHIFT 0 403 #define SK_R4444_SHIFT 12 404 #define SK_G4444_SHIFT 8 405 #define SK_B4444_SHIFT 4 406 407 #define SkA32To4444(a) ((unsigned)(a) >> 4) 408 #define SkR32To4444(r) ((unsigned)(r) >> 4) 409 #define SkG32To4444(g) ((unsigned)(g) >> 4) 410 #define SkB32To4444(b) ((unsigned)(b) >> 4) 411 412 static inline U8CPU SkReplicateNibble(unsigned nib) { 413 SkASSERT(nib <= 0xF); 414 return (nib << 4) | nib; 415 } 416 417 #define SkA4444ToA32(a) SkReplicateNibble(a) 418 #define SkR4444ToR32(r) SkReplicateNibble(r) 419 #define SkG4444ToG32(g) SkReplicateNibble(g) 420 #define SkB4444ToB32(b) SkReplicateNibble(b) 421 422 #define SkGetPackedA4444(c) (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF) 423 #define SkGetPackedR4444(c) (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF) 424 #define SkGetPackedG4444(c) (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF) 425 #define SkGetPackedB4444(c) (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF) 426 427 #define SkPacked4444ToA32(c) SkReplicateNibble(SkGetPackedA4444(c)) 428 #define SkPacked4444ToR32(c) SkReplicateNibble(SkGetPackedR4444(c)) 429 #define SkPacked4444ToG32(c) SkReplicateNibble(SkGetPackedG4444(c)) 430 #define SkPacked4444ToB32(c) SkReplicateNibble(SkGetPackedB4444(c)) 431 432 #ifdef SK_DEBUG 433 static inline void SkPMColor16Assert(U16CPU c) { 434 unsigned a = SkGetPackedA4444(c); 435 unsigned r = SkGetPackedR4444(c); 436 unsigned g = SkGetPackedG4444(c); 437 unsigned b = SkGetPackedB4444(c); 438 439 SkASSERT(a <= 0xF); 440 SkASSERT(r <= a); 441 SkASSERT(g <= a); 442 SkASSERT(b <= a); 443 } 444 #else 445 #define SkPMColor16Assert(c) 446 #endif 447 448 static inline unsigned SkAlpha15To16(unsigned a) { 449 SkASSERT(a <= 0xF); 450 return a + (a >> 3); 451 } 452 453 #ifdef SK_DEBUG 454 static inline int SkAlphaMul4(int value, int scale) { 455 SkASSERT((unsigned)scale <= 0x10); 456 return value * scale >> 4; 457 } 458 #else 459 #define SkAlphaMul4(value, scale) ((value) * (scale) >> 4) 460 #endif 461 462 static inline unsigned SkR4444ToR565(unsigned r) { 463 SkASSERT(r <= 0xF); 464 return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS)); 465 } 466 467 static inline unsigned SkG4444ToG565(unsigned g) { 468 SkASSERT(g <= 0xF); 469 return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS)); 470 } 471 472 static inline unsigned SkB4444ToB565(unsigned b) { 473 SkASSERT(b <= 0xF); 474 return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS)); 475 } 476 477 static inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r, 478 unsigned g, unsigned b) { 479 SkASSERT(a <= 0xF); 480 SkASSERT(r <= a); 481 SkASSERT(g <= a); 482 SkASSERT(b <= a); 483 484 return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) | 485 (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT)); 486 } 487 488 extern const uint16_t gMask_0F0F; 489 490 static inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale) { 491 SkASSERT(scale <= 16); 492 493 const unsigned mask = 0xF0F; //gMask_0F0F; 494 495 #if 0 496 unsigned rb = ((c & mask) * scale) >> 4; 497 unsigned ag = ((c >> 4) & mask) * scale; 498 return (rb & mask) | (ag & ~mask); 499 #else 500 c = (c & mask) | ((c & (mask << 4)) << 12); 501 c = c * scale >> 4; 502 return (c & mask) | ((c >> 12) & (mask << 4)); 503 #endif 504 } 505 506 /** Expand the SkPMColor16 color into a 32bit value that can be scaled all at 507 once by a value up to 16. Used in conjunction with SkCompact_4444. 508 */ 509 static inline uint32_t SkExpand_4444(U16CPU c) { 510 SkASSERT(c == (uint16_t)c); 511 512 const unsigned mask = 0xF0F; //gMask_0F0F; 513 return (c & mask) | ((c & ~mask) << 12); 514 } 515 516 /** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16. 517 NOTE: this explicitly does not clean the top 16 bits (which may be garbage). 518 It does this for speed, since if it is being written directly to 16bits of 519 memory, the top 16bits will be ignored. Casting the result to uint16_t here 520 would add 2 more instructions, slow us down. It is up to the caller to 521 perform the cast if needed. 522 */ 523 static inline U16CPU SkCompact_4444(uint32_t c) { 524 const unsigned mask = 0xF0F; //gMask_0F0F; 525 return (c & mask) | ((c >> 12) & ~mask); 526 } 527 528 static inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) { 529 unsigned sa = SkGetPackedA4444(s); 530 unsigned sr = SkR4444ToR565(SkGetPackedR4444(s)); 531 unsigned sg = SkG4444ToG565(SkGetPackedG4444(s)); 532 unsigned sb = SkB4444ToB565(SkGetPackedB4444(s)); 533 534 // To avoid overflow, we have to clear the low bit of the synthetic sg 535 // if the src alpha is <= 7. 536 // to see why, try blending 0x4444 on top of 565-white and watch green 537 // overflow (sum == 64) 538 sg &= ~(~(sa >> 3) & 1); 539 540 unsigned scale = SkAlpha15To16(15 - sa); 541 unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale); 542 unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale); 543 unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale); 544 545 #if 0 546 if (sg + dg > 63) { 547 SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg); 548 } 549 #endif 550 return SkPackRGB16(sr + dr, sg + dg, sb + db); 551 } 552 553 static inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) { 554 SkASSERT((unsigned)scale16 <= 16); 555 556 return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst); 557 } 558 559 static inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16) { 560 SkASSERT((unsigned)scale16 <= 16); 561 562 uint32_t src32 = SkExpand_4444(src) * scale16; 563 // the scaled srcAlpha is the bottom byte 564 #ifdef SK_DEBUG 565 { 566 unsigned srcA = SkGetPackedA4444(src) * scale16; 567 SkASSERT(srcA == (src32 & 0xFF)); 568 } 569 #endif 570 unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4; 571 uint32_t dst32 = SkExpand_4444(dst) * dstScale; 572 return SkCompact_4444((src32 + dst32) >> 4); 573 } 574 575 static inline SkPMColor SkPixel4444ToPixel32(U16CPU c) { 576 uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) | 577 (SkGetPackedR4444(c) << SK_R32_SHIFT) | 578 (SkGetPackedG4444(c) << SK_G32_SHIFT) | 579 (SkGetPackedB4444(c) << SK_B32_SHIFT); 580 return d | (d << 4); 581 } 582 583 static inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) { 584 return (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) | 585 (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) | 586 (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) | 587 (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT); 588 } 589 590 // cheap 2x2 dither 591 static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r, 592 U8CPU g, U8CPU b) { 593 // to ensure that we stay a legal premultiplied color, we take the max() 594 // of the truncated and dithered alpha values. If we didn't, cases like 595 // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...) 596 // which is not legal premultiplied, since a < color 597 unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4; 598 a = SkMax32(a >> 4, dithered_a); 599 // these we just dither in place 600 r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4; 601 g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4; 602 b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4; 603 604 return SkPackARGB4444(a, r, g, b); 605 } 606 607 static inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) { 608 return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c), 609 SkGetPackedG32(c), SkGetPackedB32(c)); 610 } 611 612 /* Assumes 16bit is in standard RGBA order. 613 Transforms a normal ARGB_8888 into the same byte order as 614 expanded ARGB_4444, but keeps each component 8bits 615 */ 616 static inline uint32_t SkExpand_8888(SkPMColor c) { 617 return (((c >> SK_R32_SHIFT) & 0xFF) << 24) | 618 (((c >> SK_G32_SHIFT) & 0xFF) << 8) | 619 (((c >> SK_B32_SHIFT) & 0xFF) << 16) | 620 (((c >> SK_A32_SHIFT) & 0xFF) << 0); 621 } 622 623 /* Undo the operation of SkExpand_8888, turning the argument back into 624 a SkPMColor. 625 */ 626 static inline SkPMColor SkCompact_8888(uint32_t c) { 627 return (((c >> 24) & 0xFF) << SK_R32_SHIFT) | 628 (((c >> 8) & 0xFF) << SK_G32_SHIFT) | 629 (((c >> 16) & 0xFF) << SK_B32_SHIFT) | 630 (((c >> 0) & 0xFF) << SK_A32_SHIFT); 631 } 632 633 /* Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format, 634 but this routine just keeps the high 4bits of each component in the low 635 4bits of the result (just like a newly expanded PMColor16). 636 */ 637 static inline uint32_t SkExpand32_4444(SkPMColor c) { 638 return (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) | 639 (((c >> (SK_G32_SHIFT + 4)) & 0xF) << 8) | 640 (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) | 641 (((c >> (SK_A32_SHIFT + 4)) & 0xF) << 0); 642 } 643 644 // takes two values and alternamtes them as part of a memset16 645 // used for cheap 2x2 dithering when the colors are opaque 646 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n); 647 648 #endif 649 650