OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkPM4fPriv_DEFINED | 8 #ifndef SkPM4fPriv_DEFINED |
9 #define SkPM4fPriv_DEFINED | 9 #define SkPM4fPriv_DEFINED |
10 | 10 |
11 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
12 #include "SkPM4f.h" | 12 #include "SkPM4f.h" |
| 13 #include "SkSRGB.h" |
13 | 14 |
14 static inline float get_alpha(const Sk4f& f4) { | 15 static inline Sk4f set_alpha(const Sk4f& px, float alpha) { |
15 return f4[SkPM4f::A]; | 16 return { px[0], px[1], px[2], alpha }; |
16 } | 17 } |
17 | 18 |
18 static inline Sk4f set_alpha(const Sk4f& f4, float alpha) { | 19 static inline float get_alpha(const Sk4f& px) { |
19 static_assert(3 == SkPM4f::A, ""); | 20 return px[3]; |
20 return Sk4f(f4[0], f4[1], f4[2], alpha); | |
21 } | 21 } |
22 | 22 |
23 static inline uint32_t to_4b(const Sk4f& f4) { | 23 |
24 uint32_t b4; | 24 static inline Sk4f Sk4f_fromL32(uint32_t px) { |
25 SkNx_cast<uint8_t>(f4).store((uint8_t*)&b4); | 25 return SkNx_cast<float>(Sk4b::Load(&px)) * (1/255.0f); |
26 return b4; | |
27 } | 26 } |
28 | 27 |
29 static inline Sk4f to_4f(uint32_t b4) { | 28 static inline Sk4f Sk4f_fromS32(uint32_t px) { |
30 return SkNx_cast<float>(Sk4b::Load((const uint8_t*)&b4)); | 29 return { sk_linear_from_srgb[(px >> 0) & 0xff], |
| 30 sk_linear_from_srgb[(px >> 8) & 0xff], |
| 31 sk_linear_from_srgb[(px >> 16) & 0xff], |
| 32 (1/255.0f) * (px >> 24) }; |
31 } | 33 } |
32 | 34 |
33 static inline Sk4f to_4f_rgba(uint32_t b4) { | 35 static inline uint32_t Sk4f_toL32(const Sk4f& px) { |
34 return swizzle_rb_if_bgra(to_4f(b4)); | 36 uint32_t l32; |
| 37 SkNx_cast<uint8_t>(Sk4f_round(px * 255.0f)).store(&l32); |
| 38 return l32; |
35 } | 39 } |
36 | 40 |
37 static inline Sk4f srgb_to_linear(const Sk4f& s4) { | 41 static inline uint32_t Sk4f_toS32(const Sk4f& px) { |
38 return set_alpha(s4 * s4, get_alpha(s4)); | 42 Sk4i rgb = sk_linear_to_srgb(px), |
| 43 srgb = { rgb[0], rgb[1], rgb[2], (int)(255.0f * px[3] + 0.5f) }; |
| 44 |
| 45 uint32_t s32; |
| 46 SkNx_cast<uint8_t>(srgb).store(&s32); |
| 47 return s32; |
39 } | 48 } |
40 | 49 |
41 static inline Sk4f linear_to_srgb(const Sk4f& l4) { | |
42 return set_alpha(l4.rsqrt().invert(), get_alpha(l4)); | |
43 } | |
44 | 50 |
45 static inline float srgb_to_linear(float x) { | 51 // SkColor handling: |
46 return x * x; | |
47 } | |
48 | |
49 static inline float linear_to_srgb(float x) { | |
50 return sqrtf(x); | |
51 } | |
52 | |
53 static void assert_unit(float x) { | |
54 SkASSERT(x >= 0 && x <= 1); | |
55 } | |
56 | |
57 static inline float exact_srgb_to_linear(float x) { | |
58 assert_unit(x); | |
59 float linear; | |
60 if (x <= 0.04045) { | |
61 linear = x / 12.92f; | |
62 } else { | |
63 linear = powf((x + 0.055f) / 1.055f, 2.4f); | |
64 } | |
65 assert_unit(linear); | |
66 return linear; | |
67 } | |
68 | |
69 static inline float exact_linear_to_srgb(float x) { | |
70 assert_unit(x); | |
71 float srgb; | |
72 if (x <= 0.0031308f) { | |
73 srgb = x * 12.92f; | |
74 } else { | |
75 srgb = 1.055f * powf(x, 0.41666667f) - 0.055f; | |
76 } | |
77 assert_unit(srgb); | |
78 return srgb; | |
79 } | |
80 | |
81 static inline Sk4f exact_srgb_to_linear(const Sk4f& x) { | |
82 Sk4f linear(exact_srgb_to_linear(x[0]), | |
83 exact_srgb_to_linear(x[1]), | |
84 exact_srgb_to_linear(x[2]), 1); | |
85 return set_alpha(linear, get_alpha(x)); | |
86 } | |
87 | |
88 static inline Sk4f exact_linear_to_srgb(const Sk4f& x) { | |
89 Sk4f srgb(exact_linear_to_srgb(x[0]), | |
90 exact_linear_to_srgb(x[1]), | |
91 exact_linear_to_srgb(x[2]), 1); | |
92 return set_alpha(srgb, get_alpha(x)); | |
93 } | |
94 | |
95 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
96 | |
97 static inline Sk4f Sk4f_fromL32(uint32_t src) { | |
98 return to_4f(src) * Sk4f(1.0f/255); | |
99 } | |
100 | |
101 static inline Sk4f Sk4f_fromS32(uint32_t src) { | |
102 return srgb_to_linear(to_4f(src) * Sk4f(1.0f/255)); | |
103 } | |
104 | |
105 // Color handling: | |
106 // SkColor has an ordering of (b, g, r, a) if cast to an Sk4f, so the code swi
zzles r and b to | 52 // SkColor has an ordering of (b, g, r, a) if cast to an Sk4f, so the code swi
zzles r and b to |
107 // produce the needed (r, g, b, a) ordering. | 53 // produce the needed (r, g, b, a) ordering. |
108 static inline Sk4f Sk4f_from_SkColor(SkColor color) { | 54 static inline Sk4f Sk4f_from_SkColor(SkColor color) { |
109 return swizzle_rb(Sk4f_fromS32(color)); | 55 return swizzle_rb(Sk4f_fromS32(color)); |
110 } | 56 } |
111 | 57 |
112 static inline uint32_t Sk4f_toL32(const Sk4f& x4) { | 58 static inline void assert_unit(float x) { |
113 return to_4b(x4 * Sk4f(255) + Sk4f(0.5f)); | 59 SkASSERT(0 <= x && x <= 1); |
114 } | 60 } |
115 | 61 |
116 static inline uint32_t Sk4f_toS32(const Sk4f& x4) { | 62 static inline float exact_srgb_to_linear(float srgb) { |
117 return to_4b(linear_to_srgb(x4) * Sk4f(255) + Sk4f(0.5f)); | 63 assert_unit(srgb); |
118 } | 64 float linear; |
119 | 65 if (srgb <= 0.04045) { |
120 static inline Sk4f exact_Sk4f_fromS32(uint32_t src) { | 66 linear = srgb / 12.92f; |
121 return exact_srgb_to_linear(to_4f(src) * Sk4f(1.0f/255)); | 67 } else { |
122 } | 68 linear = powf((srgb + 0.055f) / 1.055f, 2.4f); |
123 static inline uint32_t exact_Sk4f_toS32(const Sk4f& x4) { | |
124 return to_4b(exact_linear_to_srgb(x4) * Sk4f(255) + Sk4f(0.5f)); | |
125 } | |
126 | |
127 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | |
128 // An implementation of SrcOver from bytes to bytes in linear space that takes a
dvantage of the | |
129 // observation that the 255's cancel. | |
130 // invA = 1 - (As / 255); | |
131 // | |
132 // R = 255 * sqrt((Rs/255)^2 + (Rd/255)^2 * invA) | |
133 // => R = 255 * sqrt((Rs^2 + Rd^2 * invA)/255^2) | |
134 // => R = sqrt(Rs^2 + Rd^2 * invA) | |
135 // Note: src is assumed to be linear. | |
136 static inline void srcover_blend_srgb8888_srgb_1(uint32_t* dst, const Sk4f& src)
{ | |
137 Sk4f d = srgb_to_linear(to_4f(*dst)); | |
138 Sk4f invAlpha = 1.0f - Sk4f{src[SkPM4f::A]} * (1.0f / 255.0f); | |
139 Sk4f r = linear_to_srgb(src + d * invAlpha) + 0.5f; | |
140 *dst = to_4b(r); | |
141 } | |
142 | |
143 static inline void srcover_srgb8888_srgb_1(uint32_t* dst, const uint32_t pixel)
{ | |
144 if ((~pixel & 0xFF000000) == 0) { | |
145 *dst = pixel; | |
146 } else if ((pixel & 0xFF000000) != 0) { | |
147 srcover_blend_srgb8888_srgb_1(dst, srgb_to_linear(to_4f(pixel))); | |
148 } | 69 } |
| 70 assert_unit(linear); |
| 71 return linear; |
149 } | 72 } |
150 | 73 |
151 #endif | 74 #endif |
OLD | NEW |