| 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 |