Line data Source code
1 : /*
2 : * Copyright 2006 The Android Open Source Project
3 : *
4 : * Use of this source code is governed by a BSD-style license that can be
5 : * found in the LICENSE file.
6 : */
7 :
8 : #ifndef SkColorPriv_DEFINED
9 : #define SkColorPriv_DEFINED
10 :
11 : // turn this own for extra debug checking when blending onto 565
12 : #ifdef SK_DEBUG
13 : #define CHECK_FOR_565_OVERFLOW
14 : #endif
15 :
16 : #include "SkColor.h"
17 : #include "SkMath.h"
18 :
19 : //////////////////////////////////////////////////////////////////////////////
20 :
21 : #define SkASSERT_IS_BYTE(x) SkASSERT(0 == ((x) & ~0xFF))
22 :
23 : /*
24 : * Skia's 32bit backend only supports 1 sizzle order at a time (compile-time).
25 : * This is specified by 4 defines SK_A32_SHIFT, SK_R32_SHIFT, ... for G and B.
26 : *
27 : * For easier compatibility with Skia's GPU backend, we further restrict these
28 : * to either (in memory-byte-order) RGBA or BGRA. Note that this "order" does
29 : * not directly correspond to the same shift-order, since we have to take endianess
30 : * into account.
31 : *
32 : * Here we enforce this constraint.
33 : */
34 :
35 : #ifdef SK_CPU_BENDIAN
36 : #define SK_RGBA_R32_SHIFT 24
37 : #define SK_RGBA_G32_SHIFT 16
38 : #define SK_RGBA_B32_SHIFT 8
39 : #define SK_RGBA_A32_SHIFT 0
40 :
41 : #define SK_BGRA_B32_SHIFT 24
42 : #define SK_BGRA_G32_SHIFT 16
43 : #define SK_BGRA_R32_SHIFT 8
44 : #define SK_BGRA_A32_SHIFT 0
45 : #else
46 : #define SK_RGBA_R32_SHIFT 0
47 : #define SK_RGBA_G32_SHIFT 8
48 : #define SK_RGBA_B32_SHIFT 16
49 : #define SK_RGBA_A32_SHIFT 24
50 :
51 : #define SK_BGRA_B32_SHIFT 0
52 : #define SK_BGRA_G32_SHIFT 8
53 : #define SK_BGRA_R32_SHIFT 16
54 : #define SK_BGRA_A32_SHIFT 24
55 : #endif
56 :
57 : #if defined(SK_PMCOLOR_IS_RGBA) && defined(SK_PMCOLOR_IS_BGRA)
58 : #error "can't define PMCOLOR to be RGBA and BGRA"
59 : #endif
60 :
61 : #define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA \
62 : (SK_A32_SHIFT == SK_RGBA_A32_SHIFT && \
63 : SK_R32_SHIFT == SK_RGBA_R32_SHIFT && \
64 : SK_G32_SHIFT == SK_RGBA_G32_SHIFT && \
65 : SK_B32_SHIFT == SK_RGBA_B32_SHIFT)
66 :
67 : #define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA \
68 : (SK_A32_SHIFT == SK_BGRA_A32_SHIFT && \
69 : SK_R32_SHIFT == SK_BGRA_R32_SHIFT && \
70 : SK_G32_SHIFT == SK_BGRA_G32_SHIFT && \
71 : SK_B32_SHIFT == SK_BGRA_B32_SHIFT)
72 :
73 :
74 : #define SK_A_INDEX (SK_A32_SHIFT/8)
75 : #define SK_R_INDEX (SK_R32_SHIFT/8)
76 : #define SK_G_INDEX (SK_G32_SHIFT/8)
77 : #define SK_B_INDEX (SK_B32_SHIFT/8)
78 :
79 : #if defined(SK_PMCOLOR_IS_RGBA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
80 : #error "SK_PMCOLOR_IS_RGBA does not match SK_*32_SHIFT values"
81 : #endif
82 :
83 : #if defined(SK_PMCOLOR_IS_BGRA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
84 : #error "SK_PMCOLOR_IS_BGRA does not match SK_*32_SHIFT values"
85 : #endif
86 :
87 : #if !defined(SK_PMCOLOR_IS_RGBA) && !defined(SK_PMCOLOR_IS_BGRA)
88 : // deduce which to define from the _SHIFT defines
89 :
90 : #if LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
91 : #define SK_PMCOLOR_IS_RGBA
92 : #elif LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
93 : #define SK_PMCOLOR_IS_BGRA
94 : #else
95 : #error "need 32bit packing to be either RGBA or BGRA"
96 : #endif
97 : #endif
98 :
99 : // hide these now that we're done
100 : #undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
101 : #undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
102 :
103 : //////////////////////////////////////////////////////////////////////////////
104 :
105 : // Reverse the bytes coorsponding to RED and BLUE in a packed pixels. Note the
106 : // pair of them are in the same 2 slots in both RGBA and BGRA, thus there is
107 : // no need to pass in the colortype to this function.
108 0 : static inline uint32_t SkSwizzle_RB(uint32_t c) {
109 : static const uint32_t kRBMask = (0xFF << SK_R32_SHIFT) | (0xFF << SK_B32_SHIFT);
110 :
111 0 : unsigned c0 = (c >> SK_R32_SHIFT) & 0xFF;
112 0 : unsigned c1 = (c >> SK_B32_SHIFT) & 0xFF;
113 0 : return (c & ~kRBMask) | (c0 << SK_B32_SHIFT) | (c1 << SK_R32_SHIFT);
114 : }
115 :
116 0 : static inline uint32_t SkPackARGB_as_RGBA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
117 0 : SkASSERT_IS_BYTE(a);
118 0 : SkASSERT_IS_BYTE(r);
119 0 : SkASSERT_IS_BYTE(g);
120 0 : SkASSERT_IS_BYTE(b);
121 0 : return (a << SK_RGBA_A32_SHIFT) | (r << SK_RGBA_R32_SHIFT) |
122 0 : (g << SK_RGBA_G32_SHIFT) | (b << SK_RGBA_B32_SHIFT);
123 : }
124 :
125 0 : static inline uint32_t SkPackARGB_as_BGRA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
126 0 : SkASSERT_IS_BYTE(a);
127 0 : SkASSERT_IS_BYTE(r);
128 0 : SkASSERT_IS_BYTE(g);
129 0 : SkASSERT_IS_BYTE(b);
130 0 : return (a << SK_BGRA_A32_SHIFT) | (r << SK_BGRA_R32_SHIFT) |
131 0 : (g << SK_BGRA_G32_SHIFT) | (b << SK_BGRA_B32_SHIFT);
132 : }
133 :
134 0 : static inline SkPMColor SkSwizzle_RGBA_to_PMColor(uint32_t c) {
135 : #ifdef SK_PMCOLOR_IS_RGBA
136 : return c;
137 : #else
138 0 : return SkSwizzle_RB(c);
139 : #endif
140 : }
141 :
142 0 : static inline SkPMColor SkSwizzle_BGRA_to_PMColor(uint32_t c) {
143 : #ifdef SK_PMCOLOR_IS_BGRA
144 0 : return c;
145 : #else
146 : return SkSwizzle_RB(c);
147 : #endif
148 : }
149 :
150 : //////////////////////////////////////////////////////////////////////////////
151 :
152 : ///@{
153 : /** See ITU-R Recommendation BT.709 at http://www.itu.int/rec/R-REC-BT.709/ .*/
154 : #define SK_ITU_BT709_LUM_COEFF_R (0.2126f)
155 : #define SK_ITU_BT709_LUM_COEFF_G (0.7152f)
156 : #define SK_ITU_BT709_LUM_COEFF_B (0.0722f)
157 : ///@}
158 :
159 : ///@{
160 : /** A float value which specifies this channel's contribution to luminance. */
161 : #define SK_LUM_COEFF_R SK_ITU_BT709_LUM_COEFF_R
162 : #define SK_LUM_COEFF_G SK_ITU_BT709_LUM_COEFF_G
163 : #define SK_LUM_COEFF_B SK_ITU_BT709_LUM_COEFF_B
164 : ///@}
165 :
166 : /** Computes the luminance from the given r, g, and b in accordance with
167 : SK_LUM_COEFF_X. For correct results, r, g, and b should be in linear space.
168 : */
169 0 : static inline U8CPU SkComputeLuminance(U8CPU r, U8CPU g, U8CPU b) {
170 : //The following is
171 : //r * SK_LUM_COEFF_R + g * SK_LUM_COEFF_G + b * SK_LUM_COEFF_B
172 : //with SK_LUM_COEFF_X in 1.8 fixed point (rounding adjusted to sum to 256).
173 0 : return (r * 54 + g * 183 + b * 19) >> 8;
174 : }
175 :
176 : /** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
177 : byte into a scale value, so that we can say scale * value >> 8 instead of
178 : alpha * value / 255.
179 :
180 : In debugging, asserts that alpha is 0..255
181 : */
182 81567 : static inline unsigned SkAlpha255To256(U8CPU alpha) {
183 81567 : SkASSERT(SkToU8(alpha) == alpha);
184 : // this one assues that blending on top of an opaque dst keeps it that way
185 : // even though it is less accurate than a+(a>>7) for non-opaque dsts
186 81567 : return alpha + 1;
187 : }
188 :
189 : /**
190 : * Turn a 0..255 value into a 0..256 value, rounding up if the value is >= 0x80.
191 : * This is slightly more accurate than SkAlpha255To256.
192 : */
193 0 : static inline unsigned Sk255To256(U8CPU value) {
194 0 : SkASSERT(SkToU8(value) == value);
195 0 : return value + (value >> 7);
196 : }
197 :
198 : /** Multiplify value by 0..256, and shift the result down 8
199 : (i.e. return (value * alpha256) >> 8)
200 : */
201 : #define SkAlphaMul(value, alpha256) (((value) * (alpha256)) >> 8)
202 :
203 : /** Calculates 256 - (value * alpha256) / 255 in range [0,256],
204 : * for [0,255] value and [0,256] alpha256.
205 : */
206 2465 : static inline U16CPU SkAlphaMulInv256(U16CPU value, U16CPU alpha256) {
207 2465 : unsigned prod = 0xFFFF - value * alpha256;
208 2465 : return (prod + (prod >> 8)) >> 8;
209 : }
210 :
211 : // The caller may want negative values, so keep all params signed (int)
212 : // so we don't accidentally slip into unsigned math and lose the sign
213 : // extension when we shift (in SkAlphaMul)
214 0 : static inline int SkAlphaBlend(int src, int dst, int scale256) {
215 0 : SkASSERT((unsigned)scale256 <= 256);
216 0 : return dst + SkAlphaMul(src - dst, scale256);
217 : }
218 :
219 : /**
220 : * Returns (src * alpha + dst * (255 - alpha)) / 255
221 : *
222 : * This is more accurate than SkAlphaBlend, but slightly slower
223 : */
224 : static inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) {
225 : SkASSERT((int16_t)src == src);
226 : SkASSERT((int16_t)dst == dst);
227 : SkASSERT((uint8_t)alpha == alpha);
228 :
229 : int prod = (src - dst) * alpha + 128;
230 : prod = (prod + (prod >> 8)) >> 8;
231 : return dst + prod;
232 : }
233 :
234 : static inline U8CPU SkUnitScalarClampToByte(SkScalar x) {
235 : return static_cast<U8CPU>(SkScalarPin(x, 0, 1) * 255 + 0.5);
236 : }
237 :
238 : #define SK_R16_BITS 5
239 : #define SK_G16_BITS 6
240 : #define SK_B16_BITS 5
241 :
242 : #define SK_R16_SHIFT (SK_B16_BITS + SK_G16_BITS)
243 : #define SK_G16_SHIFT (SK_B16_BITS)
244 : #define SK_B16_SHIFT 0
245 :
246 : #define SK_R16_MASK ((1 << SK_R16_BITS) - 1)
247 : #define SK_G16_MASK ((1 << SK_G16_BITS) - 1)
248 : #define SK_B16_MASK ((1 << SK_B16_BITS) - 1)
249 :
250 : #define SkGetPackedR16(color) (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
251 : #define SkGetPackedG16(color) (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
252 : #define SkGetPackedB16(color) (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
253 :
254 : #define SkR16Assert(r) SkASSERT((unsigned)(r) <= SK_R16_MASK)
255 : #define SkG16Assert(g) SkASSERT((unsigned)(g) <= SK_G16_MASK)
256 : #define SkB16Assert(b) SkASSERT((unsigned)(b) <= SK_B16_MASK)
257 :
258 0 : static inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
259 0 : SkASSERT(r <= SK_R16_MASK);
260 0 : SkASSERT(g <= SK_G16_MASK);
261 0 : SkASSERT(b <= SK_B16_MASK);
262 :
263 0 : return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
264 : }
265 :
266 : #define SK_R16_MASK_IN_PLACE (SK_R16_MASK << SK_R16_SHIFT)
267 : #define SK_G16_MASK_IN_PLACE (SK_G16_MASK << SK_G16_SHIFT)
268 : #define SK_B16_MASK_IN_PLACE (SK_B16_MASK << SK_B16_SHIFT)
269 :
270 : /** Expand the 16bit color into a 32bit value that can be scaled all at once
271 : by a value up to 32. Used in conjunction with SkCompact_rgb_16.
272 : */
273 0 : static inline uint32_t SkExpand_rgb_16(U16CPU c) {
274 0 : SkASSERT(c == (uint16_t)c);
275 :
276 0 : return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
277 : }
278 :
279 : /** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit
280 : color value. The computation yields only 16bits of valid data, but we claim
281 : to return 32bits, so that the compiler won't generate extra instructions to
282 : "clean" the top 16bits. However, the top 16 can contain garbage, so it is
283 : up to the caller to safely ignore them.
284 : */
285 0 : static inline U16CPU SkCompact_rgb_16(uint32_t c) {
286 0 : return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
287 : }
288 :
289 : /** Scale the 16bit color value by the 0..256 scale parameter.
290 : The computation yields only 16bits of valid data, but we claim
291 : to return 32bits, so that the compiler won't generate extra instructions to
292 : "clean" the top 16bits.
293 : */
294 0 : static inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
295 0 : return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
296 : }
297 :
298 : // this helper explicitly returns a clean 16bit value (but slower)
299 : #define SkAlphaMulRGB16_ToU16(c, s) (uint16_t)SkAlphaMulRGB16(c, s)
300 :
301 : /** Blend pre-expanded RGB32 with 16bit color value by the 0..32 scale parameter.
302 : The computation yields only 16bits of valid data, but we claim to return
303 : 32bits, so that the compiler won't generate extra instructions to "clean"
304 : the top 16bits.
305 : */
306 0 : static inline U16CPU SkBlend32_RGB16(uint32_t src_expand, uint16_t dst, unsigned scale) {
307 0 : uint32_t dst_expand = SkExpand_rgb_16(dst) * scale;
308 0 : return SkCompact_rgb_16((src_expand + dst_expand) >> 5);
309 : }
310 :
311 : /** Blend src and dst 16bit colors by the 0..256 scale parameter.
312 : The computation yields only 16bits of valid data, but we claim
313 : to return 32bits, so that the compiler won't generate extra instructions to
314 : "clean" the top 16bits.
315 : */
316 0 : static inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
317 0 : SkASSERT((unsigned)srcScale <= 256);
318 :
319 0 : srcScale >>= 3;
320 :
321 0 : uint32_t src32 = SkExpand_rgb_16(src);
322 0 : uint32_t dst32 = SkExpand_rgb_16(dst);
323 0 : return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
324 : }
325 :
326 : static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
327 : int srcScale, int count) {
328 : SkASSERT(count > 0);
329 : SkASSERT((unsigned)srcScale <= 256);
330 :
331 : srcScale >>= 3;
332 :
333 : do {
334 : uint32_t src32 = SkExpand_rgb_16(*src++);
335 : uint32_t dst32 = SkExpand_rgb_16(*dst);
336 : *dst++ = static_cast<uint16_t>(
337 : SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)));
338 : } while (--count > 0);
339 : }
340 :
341 : #ifdef SK_DEBUG
342 : static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
343 : SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
344 : SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
345 : SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
346 :
347 : return a + b;
348 : }
349 : #else
350 : #define SkRGB16Add(a, b) ((a) + (b))
351 : #endif
352 :
353 : ///////////////////////////////////////////////////////////////////////////////
354 :
355 : #define SK_A32_BITS 8
356 : #define SK_R32_BITS 8
357 : #define SK_G32_BITS 8
358 : #define SK_B32_BITS 8
359 :
360 : #define SK_A32_MASK ((1 << SK_A32_BITS) - 1)
361 : #define SK_R32_MASK ((1 << SK_R32_BITS) - 1)
362 : #define SK_G32_MASK ((1 << SK_G32_BITS) - 1)
363 : #define SK_B32_MASK ((1 << SK_B32_BITS) - 1)
364 :
365 : #define SkGetPackedA32(packed) ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
366 : #define SkGetPackedR32(packed) ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
367 : #define SkGetPackedG32(packed) ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
368 : #define SkGetPackedB32(packed) ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
369 :
370 : #define SkA32Assert(a) SkASSERT((unsigned)(a) <= SK_A32_MASK)
371 : #define SkR32Assert(r) SkASSERT((unsigned)(r) <= SK_R32_MASK)
372 : #define SkG32Assert(g) SkASSERT((unsigned)(g) <= SK_G32_MASK)
373 : #define SkB32Assert(b) SkASSERT((unsigned)(b) <= SK_B32_MASK)
374 :
375 : #ifdef SK_DEBUG
376 : #define SkPMColorAssert(color_value) \
377 : do { \
378 : SkPMColor pm_color_value = (color_value); \
379 : uint32_t alpha_color_value = SkGetPackedA32(pm_color_value); \
380 : SkA32Assert(alpha_color_value); \
381 : SkASSERT(SkGetPackedR32(pm_color_value) <= alpha_color_value); \
382 : SkASSERT(SkGetPackedG32(pm_color_value) <= alpha_color_value); \
383 : SkASSERT(SkGetPackedB32(pm_color_value) <= alpha_color_value); \
384 : } while (false)
385 : #else
386 : #define SkPMColorAssert(c)
387 : #endif
388 :
389 : static inline bool SkPMColorValid(SkPMColor c) {
390 : auto a = SkGetPackedA32(c);
391 : bool valid = a <= SK_A32_MASK
392 : && SkGetPackedR32(c) <= a
393 : && SkGetPackedG32(c) <= a
394 : && SkGetPackedB32(c) <= a;
395 : if (valid) {
396 : SkPMColorAssert(c); // Make sure we're consistent when it counts.
397 : }
398 : return valid;
399 : }
400 :
401 : /**
402 : * Pack the components into a SkPMColor, checking (in the debug version) that
403 : * the components are 0..255, and are already premultiplied (i.e. alpha >= color)
404 : */
405 30721 : static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
406 30721 : SkA32Assert(a);
407 30721 : SkASSERT(r <= a);
408 30721 : SkASSERT(g <= a);
409 30721 : SkASSERT(b <= a);
410 :
411 61442 : return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
412 61442 : (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
413 : }
414 :
415 : static inline uint32_t SkPackPMColor_as_RGBA(SkPMColor c) {
416 : return SkPackARGB_as_RGBA(SkGetPackedA32(c), SkGetPackedR32(c),
417 : SkGetPackedG32(c), SkGetPackedB32(c));
418 : }
419 :
420 : static inline uint32_t SkPackPMColor_as_BGRA(SkPMColor c) {
421 : return SkPackARGB_as_BGRA(SkGetPackedA32(c), SkGetPackedR32(c),
422 : SkGetPackedG32(c), SkGetPackedB32(c));
423 : }
424 :
425 : /**
426 : * Abstract 4-byte interpolation, implemented on top of SkPMColor
427 : * utility functions. Third parameter controls blending of the first two:
428 : * (src, dst, 0) returns dst
429 : * (src, dst, 0xFF) returns src
430 : * srcWeight is [0..256], unlike SkFourByteInterp which takes [0..255]
431 : */
432 0 : static inline SkPMColor SkFourByteInterp256(SkPMColor src, SkPMColor dst,
433 : unsigned scale) {
434 0 : unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
435 0 : unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
436 0 : unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
437 0 : unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
438 :
439 0 : return SkPackARGB32(a, r, g, b);
440 : }
441 :
442 : /**
443 : * Abstract 4-byte interpolation, implemented on top of SkPMColor
444 : * utility functions. Third parameter controls blending of the first two:
445 : * (src, dst, 0) returns dst
446 : * (src, dst, 0xFF) returns src
447 : */
448 0 : static inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst,
449 : U8CPU srcWeight) {
450 0 : unsigned scale = SkAlpha255To256(srcWeight);
451 0 : return SkFourByteInterp256(src, dst, scale);
452 : }
453 :
454 : /**
455 : * 0xAARRGGBB -> 0x00AA00GG, 0x00RR00BB
456 : */
457 : static inline void SkSplay(uint32_t color, uint32_t* ag, uint32_t* rb) {
458 : const uint32_t mask = 0x00FF00FF;
459 : *ag = (color >> 8) & mask;
460 : *rb = color & mask;
461 : }
462 :
463 : /**
464 : * 0xAARRGGBB -> 0x00AA00GG00RR00BB
465 : * (note, ARGB -> AGRB)
466 : */
467 55924 : static inline uint64_t SkSplay(uint32_t color) {
468 55924 : const uint32_t mask = 0x00FF00FF;
469 55924 : uint64_t agrb = (color >> 8) & mask; // 0x0000000000AA00GG
470 55924 : agrb <<= 32; // 0x00AA00GG00000000
471 55924 : agrb |= color & mask; // 0x00AA00GG00RR00BB
472 55924 : return agrb;
473 : }
474 :
475 : /**
476 : * 0xAAxxGGxx, 0xRRxxBBxx-> 0xAARRGGBB
477 : */
478 : static inline uint32_t SkUnsplay(uint32_t ag, uint32_t rb) {
479 : const uint32_t mask = 0xFF00FF00;
480 : return (ag & mask) | ((rb & mask) >> 8);
481 : }
482 :
483 : /**
484 : * 0xAAxxGGxxRRxxBBxx -> 0xAARRGGBB
485 : * (note, AGRB -> ARGB)
486 : */
487 27962 : static inline uint32_t SkUnsplay(uint64_t agrb) {
488 27962 : const uint32_t mask = 0xFF00FF00;
489 : return SkPMColor(
490 27962 : ((agrb & mask) >> 8) | // 0x00RR00BB
491 27962 : ((agrb >> 32) & mask)); // 0xAARRGGBB
492 : }
493 :
494 : static inline SkPMColor SkFastFourByteInterp256_32(SkPMColor src, SkPMColor dst, unsigned scale) {
495 : SkASSERT(scale <= 256);
496 :
497 : // Two 8-bit blends per two 32-bit registers, with space to make sure the math doesn't collide.
498 : uint32_t src_ag, src_rb, dst_ag, dst_rb;
499 : SkSplay(src, &src_ag, &src_rb);
500 : SkSplay(dst, &dst_ag, &dst_rb);
501 :
502 : const uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag;
503 : const uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb;
504 :
505 : return SkUnsplay(ret_ag, ret_rb);
506 : }
507 :
508 27962 : static inline SkPMColor SkFastFourByteInterp256_64(SkPMColor src, SkPMColor dst, unsigned scale) {
509 27962 : SkASSERT(scale <= 256);
510 : // Four 8-bit blends in one 64-bit register, with space to make sure the math doesn't collide.
511 27962 : return SkUnsplay(SkSplay(src) * scale + (256-scale) * SkSplay(dst));
512 : }
513 :
514 : // TODO(mtklein): Replace slow versions with fast versions, using scale + (scale>>7) everywhere.
515 :
516 : /**
517 : * Same as SkFourByteInterp256, but faster.
518 : */
519 27962 : static inline SkPMColor SkFastFourByteInterp256(SkPMColor src, SkPMColor dst, unsigned scale) {
520 : // On a 64-bit machine, _64 is about 10% faster than _32, but ~40% slower on a 32-bit machine.
521 : if (sizeof(void*) == 4) {
522 : return SkFastFourByteInterp256_32(src, dst, scale);
523 : } else {
524 27962 : return SkFastFourByteInterp256_64(src, dst, scale);
525 : }
526 : }
527 :
528 : /**
529 : * Nearly the same as SkFourByteInterp, but faster and a touch more accurate, due to better
530 : * srcWeight scaling to [0, 256].
531 : */
532 5632 : static inline SkPMColor SkFastFourByteInterp(SkPMColor src,
533 : SkPMColor dst,
534 : U8CPU srcWeight) {
535 5632 : SkASSERT(srcWeight <= 255);
536 : // scale = srcWeight + (srcWeight >> 7) is more accurate than
537 : // scale = srcWeight + 1, but 7% slower
538 5632 : return SkFastFourByteInterp256(src, dst, srcWeight + (srcWeight >> 7));
539 : }
540 :
541 : /**
542 : * Same as SkPackARGB32, but this version guarantees to not check that the
543 : * values are premultiplied in the debug version.
544 : */
545 81 : static inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
546 162 : return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
547 162 : (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
548 : }
549 :
550 : static inline
551 18830 : SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
552 18830 : SkA32Assert(a);
553 18830 : SkR32Assert(r);
554 18830 : SkG32Assert(g);
555 18830 : SkB32Assert(b);
556 :
557 18830 : if (a != 255) {
558 18491 : r = SkMulDiv255Round(r, a);
559 18491 : g = SkMulDiv255Round(g, a);
560 18491 : b = SkMulDiv255Round(b, a);
561 : }
562 18830 : return SkPackARGB32(a, r, g, b);
563 : }
564 :
565 : // When Android is compiled optimizing for size, SkAlphaMulQ doesn't get
566 : // inlined; forcing inlining significantly improves performance.
567 : static SK_ALWAYS_INLINE uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
568 71721 : uint32_t mask = 0xFF00FF;
569 :
570 71721 : uint32_t rb = ((c & mask) * scale) >> 8;
571 71721 : uint32_t ag = ((c >> 8) & mask) * scale;
572 71721 : return (rb & mask) | (ag & ~mask);
573 : }
574 :
575 46309 : static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
576 92618 : return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
577 : }
578 :
579 : /**
580 : * Interpolates between colors src and dst using [0,256] scale.
581 : */
582 22330 : static inline SkPMColor SkPMLerp(SkPMColor src, SkPMColor dst, unsigned scale) {
583 22330 : return SkFastFourByteInterp256(src, dst, scale);
584 : }
585 :
586 2465 : static inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
587 2465 : SkASSERT((unsigned)aa <= 255);
588 :
589 2465 : unsigned src_scale = SkAlpha255To256(aa);
590 2465 : unsigned dst_scale = SkAlphaMulInv256(SkGetPackedA32(src), src_scale);
591 :
592 2465 : const uint32_t mask = 0xFF00FF;
593 :
594 2465 : uint32_t src_rb = (src & mask) * src_scale;
595 2465 : uint32_t src_ag = ((src >> 8) & mask) * src_scale;
596 :
597 2465 : uint32_t dst_rb = (dst & mask) * dst_scale;
598 2465 : uint32_t dst_ag = ((dst >> 8) & mask) * dst_scale;
599 :
600 2465 : return (((src_rb + dst_rb) >> 8) & mask) | ((src_ag + dst_ag) & ~mask);
601 : }
602 :
603 : ////////////////////////////////////////////////////////////////////////////////////////////
604 : // Convert a 32bit pixel to a 16bit pixel (no dither)
605 :
606 : #define SkR32ToR16_MACRO(r) ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
607 : #define SkG32ToG16_MACRO(g) ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
608 : #define SkB32ToB16_MACRO(b) ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
609 :
610 : #ifdef SK_DEBUG
611 17191 : static inline unsigned SkR32ToR16(unsigned r) {
612 17191 : SkR32Assert(r);
613 17191 : return SkR32ToR16_MACRO(r);
614 : }
615 17191 : static inline unsigned SkG32ToG16(unsigned g) {
616 17191 : SkG32Assert(g);
617 17191 : return SkG32ToG16_MACRO(g);
618 : }
619 17191 : static inline unsigned SkB32ToB16(unsigned b) {
620 17191 : SkB32Assert(b);
621 17191 : return SkB32ToB16_MACRO(b);
622 : }
623 : #else
624 : #define SkR32ToR16(r) SkR32ToR16_MACRO(r)
625 : #define SkG32ToG16(g) SkG32ToG16_MACRO(g)
626 : #define SkB32ToB16(b) SkB32ToB16_MACRO(b)
627 : #endif
628 :
629 : #define SkPacked32ToR16(c) (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
630 : #define SkPacked32ToG16(c) (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
631 : #define SkPacked32ToB16(c) (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
632 :
633 0 : static inline U16CPU SkPixel32ToPixel16(SkPMColor c) {
634 0 : unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
635 0 : unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
636 0 : unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
637 0 : return r | g | b;
638 : }
639 :
640 17191 : static inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
641 34382 : return (SkR32ToR16(r) << SK_R16_SHIFT) |
642 17191 : (SkG32ToG16(g) << SK_G16_SHIFT) |
643 17191 : (SkB32ToB16(b) << SK_B16_SHIFT);
644 : }
645 :
646 : #define SkPixel32ToPixel16_ToU16(src) SkToU16(SkPixel32ToPixel16(src))
647 :
648 : /////////////////////////////////////////////////////////////////////////////////////////
649 : // Fast dither from 32->16
650 :
651 : #define SkShouldDitherXY(x, y) (((x) ^ (y)) & 1)
652 :
653 0 : static inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
654 0 : r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
655 0 : g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
656 0 : b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
657 :
658 0 : return SkPackRGB16(r, g, b);
659 : }
660 :
661 : static inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) {
662 : return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
663 : }
664 :
665 : /* Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
666 : It is now suitable for combining with a scaled expanded_rgb_16 color
667 : as in SkSrcOver32To16().
668 : We must do this 565 high-bit replication, in order for the subsequent add
669 : to saturate properly (and not overflow). If we take the 8 bits as is, it is
670 : possible to overflow.
671 : */
672 : static inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) {
673 : unsigned sr = SkPacked32ToR16(c);
674 : unsigned sg = SkPacked32ToG16(c);
675 : unsigned sb = SkPacked32ToB16(c);
676 :
677 : sr = (sr << 5) | sr;
678 : sg = (sg << 5) | (sg >> 1);
679 : sb = (sb << 5) | sb;
680 : return (sr << 11) | (sg << 21) | (sb << 0);
681 : }
682 :
683 : /* SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
684 : (with dirt in the high 16bits, so caller beware).
685 : */
686 0 : static inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
687 0 : unsigned sr = SkGetPackedR32(src);
688 0 : unsigned sg = SkGetPackedG32(src);
689 0 : unsigned sb = SkGetPackedB32(src);
690 :
691 0 : unsigned dr = SkGetPackedR16(dst);
692 0 : unsigned dg = SkGetPackedG16(dst);
693 0 : unsigned db = SkGetPackedB16(dst);
694 :
695 0 : unsigned isa = 255 - SkGetPackedA32(src);
696 :
697 0 : dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
698 0 : dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
699 0 : db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
700 :
701 0 : return SkPackRGB16(dr, dg, db);
702 : }
703 :
704 : ////////////////////////////////////////////////////////////////////////////////////////////
705 : // Convert a 16bit pixel to a 32bit pixel
706 :
707 0 : static inline unsigned SkR16ToR32(unsigned r) {
708 0 : return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
709 : }
710 :
711 0 : static inline unsigned SkG16ToG32(unsigned g) {
712 0 : return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
713 : }
714 :
715 0 : static inline unsigned SkB16ToB32(unsigned b) {
716 0 : return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
717 : }
718 :
719 : #define SkPacked16ToR32(c) SkR16ToR32(SkGetPackedR16(c))
720 : #define SkPacked16ToG32(c) SkG16ToG32(SkGetPackedG16(c))
721 : #define SkPacked16ToB32(c) SkB16ToB32(SkGetPackedB16(c))
722 :
723 0 : static inline SkPMColor SkPixel16ToPixel32(U16CPU src) {
724 0 : SkASSERT(src == SkToU16(src));
725 :
726 0 : unsigned r = SkPacked16ToR32(src);
727 0 : unsigned g = SkPacked16ToG32(src);
728 0 : unsigned b = SkPacked16ToB32(src);
729 :
730 0 : SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
731 0 : SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
732 0 : SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
733 :
734 0 : return SkPackARGB32(0xFF, r, g, b);
735 : }
736 :
737 : // similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor
738 0 : static inline SkColor SkPixel16ToColor(U16CPU src) {
739 0 : SkASSERT(src == SkToU16(src));
740 :
741 0 : unsigned r = SkPacked16ToR32(src);
742 0 : unsigned g = SkPacked16ToG32(src);
743 0 : unsigned b = SkPacked16ToB32(src);
744 :
745 0 : SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
746 0 : SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
747 0 : SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
748 :
749 0 : return SkColorSetRGB(r, g, b);
750 : }
751 :
752 : ///////////////////////////////////////////////////////////////////////////////
753 :
754 : typedef uint16_t SkPMColor16;
755 :
756 : // Put in OpenGL order (r g b a)
757 : #define SK_A4444_SHIFT 0
758 : #define SK_R4444_SHIFT 12
759 : #define SK_G4444_SHIFT 8
760 : #define SK_B4444_SHIFT 4
761 :
762 : #define SkA32To4444(a) ((unsigned)(a) >> 4)
763 : #define SkR32To4444(r) ((unsigned)(r) >> 4)
764 : #define SkG32To4444(g) ((unsigned)(g) >> 4)
765 : #define SkB32To4444(b) ((unsigned)(b) >> 4)
766 :
767 0 : static inline U8CPU SkReplicateNibble(unsigned nib) {
768 0 : SkASSERT(nib <= 0xF);
769 0 : return (nib << 4) | nib;
770 : }
771 :
772 : #define SkA4444ToA32(a) SkReplicateNibble(a)
773 : #define SkR4444ToR32(r) SkReplicateNibble(r)
774 : #define SkG4444ToG32(g) SkReplicateNibble(g)
775 : #define SkB4444ToB32(b) SkReplicateNibble(b)
776 :
777 : #define SkGetPackedA4444(c) (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
778 : #define SkGetPackedR4444(c) (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
779 : #define SkGetPackedG4444(c) (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
780 : #define SkGetPackedB4444(c) (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
781 :
782 : #define SkPacked4444ToA32(c) SkReplicateNibble(SkGetPackedA4444(c))
783 : #define SkPacked4444ToR32(c) SkReplicateNibble(SkGetPackedR4444(c))
784 : #define SkPacked4444ToG32(c) SkReplicateNibble(SkGetPackedG4444(c))
785 : #define SkPacked4444ToB32(c) SkReplicateNibble(SkGetPackedB4444(c))
786 :
787 : #ifdef SK_DEBUG
788 : static inline void SkPMColor16Assert(U16CPU c) {
789 : unsigned a = SkGetPackedA4444(c);
790 : unsigned r = SkGetPackedR4444(c);
791 : unsigned g = SkGetPackedG4444(c);
792 : unsigned b = SkGetPackedB4444(c);
793 :
794 : SkASSERT(a <= 0xF);
795 : SkASSERT(r <= a);
796 : SkASSERT(g <= a);
797 : SkASSERT(b <= a);
798 : }
799 : #else
800 : #define SkPMColor16Assert(c)
801 : #endif
802 :
803 0 : static inline unsigned SkAlpha15To16(unsigned a) {
804 0 : SkASSERT(a <= 0xF);
805 0 : return a + (a >> 3);
806 : }
807 :
808 : #ifdef SK_DEBUG
809 0 : static inline int SkAlphaMul4(int value, int scale) {
810 0 : SkASSERT((unsigned)scale <= 0x10);
811 0 : return value * scale >> 4;
812 : }
813 : #else
814 : #define SkAlphaMul4(value, scale) ((value) * (scale) >> 4)
815 : #endif
816 :
817 0 : static inline unsigned SkR4444ToR565(unsigned r) {
818 0 : SkASSERT(r <= 0xF);
819 0 : return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
820 : }
821 :
822 0 : static inline unsigned SkG4444ToG565(unsigned g) {
823 0 : SkASSERT(g <= 0xF);
824 0 : return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
825 : }
826 :
827 0 : static inline unsigned SkB4444ToB565(unsigned b) {
828 0 : SkASSERT(b <= 0xF);
829 0 : return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
830 : }
831 :
832 : static inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
833 : unsigned g, unsigned b) {
834 : SkASSERT(a <= 0xF);
835 : SkASSERT(r <= a);
836 : SkASSERT(g <= a);
837 : SkASSERT(b <= a);
838 :
839 : return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
840 : (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
841 : }
842 :
843 0 : static inline SkPMColor16 SkAlphaMulQ4(SkPMColor16 c, int scale) {
844 0 : SkASSERT(scale <= 16);
845 :
846 0 : const unsigned mask = 0xF0F; //gMask_0F0F;
847 :
848 : #if 0
849 : unsigned rb = ((c & mask) * scale) >> 4;
850 : unsigned ag = ((c >> 4) & mask) * scale;
851 : return (rb & mask) | (ag & ~mask);
852 : #else
853 0 : unsigned expanded_c = (c & mask) | ((c & (mask << 4)) << 12);
854 0 : unsigned scaled_c = (expanded_c * scale) >> 4;
855 0 : return (scaled_c & mask) | ((scaled_c >> 12) & (mask << 4));
856 : #endif
857 : }
858 :
859 : /** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
860 : once by a value up to 16.
861 : */
862 0 : static inline uint32_t SkExpand_4444(U16CPU c) {
863 0 : SkASSERT(c == (uint16_t)c);
864 :
865 0 : const unsigned mask = 0xF0F; //gMask_0F0F;
866 0 : return (c & mask) | ((c & ~mask) << 12);
867 : }
868 :
869 0 : static inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) {
870 0 : unsigned sa = SkGetPackedA4444(s);
871 0 : unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
872 0 : unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
873 0 : unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
874 :
875 : // To avoid overflow, we have to clear the low bit of the synthetic sg
876 : // if the src alpha is <= 7.
877 : // to see why, try blending 0x4444 on top of 565-white and watch green
878 : // overflow (sum == 64)
879 0 : sg &= ~(~(sa >> 3) & 1);
880 :
881 0 : unsigned scale = SkAlpha15To16(15 - sa);
882 0 : unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
883 0 : unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
884 0 : unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
885 :
886 : #if 0
887 : if (sg + dg > 63) {
888 : SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
889 : }
890 : #endif
891 0 : return SkPackRGB16(sr + dr, sg + dg, sb + db);
892 : }
893 :
894 0 : static inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) {
895 0 : SkASSERT((unsigned)scale16 <= 16);
896 :
897 0 : return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
898 : }
899 :
900 0 : static inline SkPMColor SkPixel4444ToPixel32(U16CPU c) {
901 0 : uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
902 0 : (SkGetPackedR4444(c) << SK_R32_SHIFT) |
903 0 : (SkGetPackedG4444(c) << SK_G32_SHIFT) |
904 0 : (SkGetPackedB4444(c) << SK_B32_SHIFT);
905 0 : return d | (d << 4);
906 : }
907 :
908 : static inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) {
909 : return (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
910 : (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
911 : (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
912 : (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
913 : }
914 :
915 : // cheap 2x2 dither
916 : static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
917 : U8CPU g, U8CPU b) {
918 : // to ensure that we stay a legal premultiplied color, we take the max()
919 : // of the truncated and dithered alpha values. If we didn't, cases like
920 : // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...)
921 : // which is not legal premultiplied, since a < color
922 : unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
923 : a = SkMax32(a >> 4, dithered_a);
924 : // these we just dither in place
925 : r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
926 : g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
927 : b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
928 :
929 : return SkPackARGB4444(a, r, g, b);
930 : }
931 :
932 : static inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) {
933 : return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
934 : SkGetPackedG32(c), SkGetPackedB32(c));
935 : }
936 :
937 : /* Assumes 16bit is in standard RGBA order.
938 : Transforms a normal ARGB_8888 into the same byte order as
939 : expanded ARGB_4444, but keeps each component 8bits
940 : */
941 : static inline uint32_t SkExpand_8888(SkPMColor c) {
942 : return (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
943 : (((c >> SK_G32_SHIFT) & 0xFF) << 8) |
944 : (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
945 : (((c >> SK_A32_SHIFT) & 0xFF) << 0);
946 : }
947 :
948 : /* Undo the operation of SkExpand_8888, turning the argument back into
949 : a SkPMColor.
950 : */
951 0 : static inline SkPMColor SkCompact_8888(uint32_t c) {
952 0 : return (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
953 0 : (((c >> 8) & 0xFF) << SK_G32_SHIFT) |
954 0 : (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
955 0 : (((c >> 0) & 0xFF) << SK_A32_SHIFT);
956 : }
957 :
958 : /* Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
959 : but this routine just keeps the high 4bits of each component in the low
960 : 4bits of the result (just like a newly expanded PMColor16).
961 : */
962 : static inline uint32_t SkExpand32_4444(SkPMColor c) {
963 : return (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
964 : (((c >> (SK_G32_SHIFT + 4)) & 0xF) << 8) |
965 : (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
966 : (((c >> (SK_A32_SHIFT + 4)) & 0xF) << 0);
967 : }
968 :
969 : // takes two values and alternamtes them as part of a memset16
970 : // used for cheap 2x2 dithering when the colors are opaque
971 : void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
972 :
973 : ///////////////////////////////////////////////////////////////////////////////
974 :
975 18642 : static inline int SkUpscale31To32(int value) {
976 18642 : SkASSERT((unsigned)value <= 31);
977 18642 : return value + (value >> 4);
978 : }
979 :
980 18642 : static inline int SkBlend32(int src, int dst, int scale) {
981 18642 : SkASSERT((unsigned)src <= 0xFF);
982 18642 : SkASSERT((unsigned)dst <= 0xFF);
983 18642 : SkASSERT((unsigned)scale <= 32);
984 18642 : return dst + ((src - dst) * scale >> 5);
985 : }
986 :
987 4812 : static inline SkPMColor SkBlendLCD16(int srcA, int srcR, int srcG, int srcB,
988 : SkPMColor dst, uint16_t mask) {
989 4812 : if (mask == 0) {
990 2763 : return dst;
991 : }
992 :
993 : /* We want all of these in 5bits, hence the shifts in case one of them
994 : * (green) is 6bits.
995 : */
996 2049 : int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
997 2049 : int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
998 2049 : int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
999 :
1000 : // Now upscale them to 0..32, so we can use blend32
1001 2049 : maskR = SkUpscale31To32(maskR);
1002 2049 : maskG = SkUpscale31To32(maskG);
1003 2049 : maskB = SkUpscale31To32(maskB);
1004 :
1005 : // srcA has been upscaled to 256 before passed into this function
1006 2049 : maskR = maskR * srcA >> 8;
1007 2049 : maskG = maskG * srcA >> 8;
1008 2049 : maskB = maskB * srcA >> 8;
1009 :
1010 2049 : int dstR = SkGetPackedR32(dst);
1011 2049 : int dstG = SkGetPackedG32(dst);
1012 2049 : int dstB = SkGetPackedB32(dst);
1013 :
1014 : // LCD blitting is only supported if the dst is known/required
1015 : // to be opaque
1016 6147 : return SkPackARGB32(0xFF,
1017 2049 : SkBlend32(srcR, dstR, maskR),
1018 2049 : SkBlend32(srcG, dstG, maskG),
1019 4098 : SkBlend32(srcB, dstB, maskB));
1020 : }
1021 :
1022 11811 : static inline SkPMColor SkBlendLCD16Opaque(int srcR, int srcG, int srcB,
1023 : SkPMColor dst, uint16_t mask,
1024 : SkPMColor opaqueDst) {
1025 11811 : if (mask == 0) {
1026 7001 : return dst;
1027 : }
1028 :
1029 4810 : if (0xFFFF == mask) {
1030 645 : return opaqueDst;
1031 : }
1032 :
1033 : /* We want all of these in 5bits, hence the shifts in case one of them
1034 : * (green) is 6bits.
1035 : */
1036 4165 : int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
1037 4165 : int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
1038 4165 : int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
1039 :
1040 : // Now upscale them to 0..32, so we can use blend32
1041 4165 : maskR = SkUpscale31To32(maskR);
1042 4165 : maskG = SkUpscale31To32(maskG);
1043 4165 : maskB = SkUpscale31To32(maskB);
1044 :
1045 4165 : int dstR = SkGetPackedR32(dst);
1046 4165 : int dstG = SkGetPackedG32(dst);
1047 4165 : int dstB = SkGetPackedB32(dst);
1048 :
1049 : // LCD blitting is only supported if the dst is known/required
1050 : // to be opaque
1051 12495 : return SkPackARGB32(0xFF,
1052 4165 : SkBlend32(srcR, dstR, maskR),
1053 4165 : SkBlend32(srcG, dstG, maskG),
1054 8330 : SkBlend32(srcB, dstB, maskB));
1055 : }
1056 :
1057 0 : static inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t mask[],
1058 : SkColor src, int width, SkPMColor) {
1059 0 : int srcA = SkColorGetA(src);
1060 0 : int srcR = SkColorGetR(src);
1061 0 : int srcG = SkColorGetG(src);
1062 0 : int srcB = SkColorGetB(src);
1063 :
1064 0 : srcA = SkAlpha255To256(srcA);
1065 :
1066 0 : for (int i = 0; i < width; i++) {
1067 0 : dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], mask[i]);
1068 : }
1069 0 : }
1070 :
1071 0 : static inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t mask[],
1072 : SkColor src, int width,
1073 : SkPMColor opaqueDst) {
1074 0 : int srcR = SkColorGetR(src);
1075 0 : int srcG = SkColorGetG(src);
1076 0 : int srcB = SkColorGetB(src);
1077 :
1078 0 : for (int i = 0; i < width; i++) {
1079 0 : dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], mask[i],
1080 : opaqueDst);
1081 : }
1082 0 : }
1083 :
1084 : #endif
|