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