pixelgeneric_p.h (34032B)
1 // This file is part of Blend2D project <https://blend2d.com> 2 // 3 // See blend2d.h or LICENSE.md for license and copyright information 4 // SPDX-License-Identifier: Zlib 5 6 #ifndef BLEND2D_PIPELINE_REFERENCE_PIXELGENERIC_P_H_INCLUDED 7 #define BLEND2D_PIPELINE_REFERENCE_PIXELGENERIC_P_H_INCLUDED 8 9 #include "../../pipeline/pipedefs_p.h" 10 11 //! \cond INTERNAL 12 //! \addtogroup blend2d_pipeline_reference 13 //! \{ 14 15 namespace bl::Pipeline::Reference { 16 namespace Pixel { 17 18 enum class Type : uint32_t { 19 kRGBA = 0, 20 kRGBA_Premultiplied, 21 kRGB, 22 kAlpha 23 }; 24 25 enum class Component : uint32_t { 26 kR = 0, 27 kG = 1, 28 kB = 2, 29 kA = 3, 30 kX = 0xFFu 31 }; 32 33 struct Repeat { 34 uint32_t v; 35 36 BL_INLINE_CONSTEXPR uint32_t u16x2() const noexcept { return v | (v << 16); } 37 BL_INLINE_CONSTEXPR uint64_t u16x4() const noexcept { return uint64_t(u16x2()) | (uint64_t(u16x2()) << 32); } 38 }; 39 40 template<typename Format> struct P32_8888; 41 template<typename Format> struct U32_8888; 42 43 struct FormatA8 { 44 static inline constexpr Type kType = Type::kAlpha; 45 static inline constexpr uint32_t kBPP = 1; 46 }; 47 48 template<uint32_t r_shift, uint32_t g_shift, uint32_t b_shift, uint32_t a_shift> 49 struct Format8888 { 50 static constexpr Type kType = Type::kRGBA_Premultiplied; 51 52 enum Sizes : uint32_t { 53 kRSize = 8, 54 kGSize = 8, 55 kBSize = 8, 56 kASize = 8 57 }; 58 59 enum Shifts : uint32_t { 60 kRShift = r_shift, 61 kGShift = g_shift, 62 kBShift = b_shift, 63 kAShift = a_shift 64 }; 65 66 static BL_INLINE constexpr Component component_from_shift(uint32_t shift) noexcept { 67 return (shift == kRShift) ? Component::kR : 68 (shift == kGShift) ? Component::kG : 69 (shift == kBShift) ? Component::kB : 70 (shift == kAShift) ? Component::kA : Component::kX; 71 } 72 73 static BL_INLINE constexpr Component component_from_index(uint32_t index) noexcept { 74 return component_from_shift(index * 8u); 75 } 76 77 static BL_INLINE constexpr uint32_t shift_from_component(Component component) noexcept { 78 return (component == Component::kR) ? kRShift : 79 (component == Component::kG) ? kGShift : 80 (component == Component::kB) ? kBShift : 81 (component == Component::kA) ? kAShift : 0xFFFFFFFFu; 82 } 83 }; 84 85 typedef Format8888<16, 8, 0, 24> Format_A8R8G8B8; 86 87 struct U8_Alpha; 88 89 //! Packed 8-bit alpha value. 90 struct P8_Alpha { 91 //! Packed pixel value. 92 uint8_t p; 93 94 //! Pixel format information. 95 typedef FormatA8 Format; 96 97 //! Type of a packed compatible pixel. 98 typedef P8_Alpha Packed; 99 100 //! Type of an unpacked compatible pixel. 101 typedef U8_Alpha Unpacked; 102 103 static BL_INLINE_NODEBUG Packed from_value(uint32_t value) noexcept { return Packed { uint8_t(value) }; } 104 105 BL_INLINE_NODEBUG uint32_t a() const noexcept { return p; } 106 BL_INLINE_NODEBUG uint32_t value() noexcept { return p; } 107 108 BL_INLINE_NODEBUG Packed pack() const noexcept { return *this; } 109 BL_INLINE_NODEBUG Unpacked unpack() const noexcept; 110 111 BL_INLINE_NODEBUG Packed operator&(uint32_t x) const noexcept { return Packed { uint8_t(uint8_t(p & x) & 0xFFu) }; } 112 BL_INLINE_NODEBUG Packed operator|(uint32_t x) const noexcept { return Packed { uint8_t(uint8_t(p | x) & 0xFFu) }; } 113 BL_INLINE_NODEBUG Packed operator^(uint32_t x) const noexcept { return Packed { uint8_t(uint8_t(p ^ x) & 0xFFu) }; } 114 BL_INLINE_NODEBUG Packed operator+(uint32_t x) const noexcept { return Packed { uint8_t(uint8_t(p + x) & 0xFFu) }; } 115 BL_INLINE_NODEBUG Packed operator-(uint32_t x) const noexcept { return Packed { uint8_t(uint8_t(p - x) & 0xFFu) }; } 116 BL_INLINE_NODEBUG Packed operator*(uint32_t x) const noexcept { return Packed { uint8_t(uint8_t(p * x) & 0xFFu) }; } 117 BL_INLINE_NODEBUG Packed operator>>(uint32_t x) const noexcept { return Packed { uint8_t(uint8_t(p >> x) & 0xFFu) }; } 118 BL_INLINE_NODEBUG Packed operator<<(uint32_t x) const noexcept { return Packed { uint8_t(uint8_t(p << x) & 0xFFu) }; } 119 120 BL_INLINE_NODEBUG Packed operator&(const Packed& x) const noexcept { return Packed { uint8_t(uint8_t(p & x.p) & 0xFFu) }; } 121 BL_INLINE_NODEBUG Packed operator|(const Packed& x) const noexcept { return Packed { uint8_t(uint8_t(p | x.p) & 0xFFu) }; } 122 BL_INLINE_NODEBUG Packed operator^(const Packed& x) const noexcept { return Packed { uint8_t(uint8_t(p ^ x.p) & 0xFFu) }; } 123 BL_INLINE_NODEBUG Packed operator+(const Packed& x) const noexcept { return Packed { uint8_t(uint8_t(p + x.p) & 0xFFu) }; } 124 BL_INLINE_NODEBUG Packed operator-(const Packed& x) const noexcept { return Packed { uint8_t(uint8_t(p - x.p) & 0xFFu) }; } 125 BL_INLINE_NODEBUG Packed operator*(const Packed& x) const noexcept { return Packed { uint8_t(uint8_t(p * x.p) & 0xFFu) }; } 126 127 BL_INLINE_NODEBUG Packed& operator&=(uint32_t x) noexcept { *this = *this & x; return *this; } 128 BL_INLINE_NODEBUG Packed& operator|=(uint32_t x) noexcept { *this = *this | x; return *this; } 129 BL_INLINE_NODEBUG Packed& operator^=(uint32_t x) noexcept { *this = *this ^ x; return *this; } 130 BL_INLINE_NODEBUG Packed& operator+=(uint32_t x) noexcept { *this = *this + x; return *this; } 131 BL_INLINE_NODEBUG Packed& operator-=(uint32_t x) noexcept { *this = *this - x; return *this; } 132 BL_INLINE_NODEBUG Packed& operator*=(uint32_t x) noexcept { *this = *this * x; return *this; } 133 BL_INLINE_NODEBUG Packed& operator>>=(uint32_t x) noexcept { *this = *this >> x; return *this; } 134 BL_INLINE_NODEBUG Packed& operator<<=(uint32_t x) noexcept { *this = *this << x; return *this; } 135 136 BL_INLINE_NODEBUG Packed& operator&=(const Packed& x) noexcept { *this = *this & x; return *this; } 137 BL_INLINE_NODEBUG Packed& operator|=(const Packed& x) noexcept { *this = *this | x; return *this; } 138 BL_INLINE_NODEBUG Packed& operator^=(const Packed& x) noexcept { *this = *this ^ x; return *this; } 139 BL_INLINE_NODEBUG Packed& operator+=(const Packed& x) noexcept { *this = *this + x; return *this; } 140 BL_INLINE_NODEBUG Packed& operator-=(const Packed& x) noexcept { *this = *this - x; return *this; } 141 BL_INLINE_NODEBUG Packed& operator*=(const Packed& x) noexcept { *this = *this * x; return *this; } 142 }; 143 144 //! Unpacked 8-bit alpha value to 16-bit. 145 struct U8_Alpha { 146 //! Unpacked pixel value. 147 uint16_t u; 148 149 //! Pixel format information. 150 typedef FormatA8 Format; 151 152 //! Type of a packed compatible pixel. 153 typedef P8_Alpha Packed; 154 155 //! Type of an unpacked compatible pixel. 156 typedef U8_Alpha Unpacked; 157 158 static BL_INLINE_NODEBUG Unpacked from_value(uint32_t value) noexcept { return Unpacked{uint16_t(value)}; } 159 160 BL_INLINE_NODEBUG uint32_t a() const noexcept { return u; } 161 BL_INLINE_NODEBUG uint32_t value() noexcept { return u; } 162 163 BL_INLINE_NODEBUG Packed pack() const noexcept { return Packed{uint8_t(u & 0xFFu)}; } 164 BL_INLINE_NODEBUG Unpacked unpack() const noexcept { return Unpacked{u}; } 165 166 BL_INLINE_NODEBUG Unpacked operator&(uint32_t x) const noexcept { return Unpacked{uint16_t((uint32_t(u) & x) & 0xFFFFu)}; } 167 BL_INLINE_NODEBUG Unpacked operator|(uint32_t x) const noexcept { return Unpacked{uint16_t((uint32_t(u) | x) & 0xFFFFu)}; } 168 BL_INLINE_NODEBUG Unpacked operator^(uint32_t x) const noexcept { return Unpacked{uint16_t((uint32_t(u) ^ x) & 0xFFFFu)}; } 169 BL_INLINE_NODEBUG Unpacked operator+(uint32_t x) const noexcept { return Unpacked{uint16_t((uint32_t(u) + x) & 0xFFFFu)}; } 170 BL_INLINE_NODEBUG Unpacked operator-(uint32_t x) const noexcept { return Unpacked{uint16_t((uint32_t(u) - x) & 0xFFFFu)}; } 171 BL_INLINE_NODEBUG Unpacked operator*(uint32_t x) const noexcept { return Unpacked{uint16_t((uint32_t(u) * x) & 0xFFFFu)}; } 172 BL_INLINE_NODEBUG Unpacked operator>>(uint32_t x) const noexcept { return Unpacked{uint16_t((uint32_t(u) >> x) & 0xFFFFu)}; } 173 BL_INLINE_NODEBUG Unpacked operator<<(uint32_t x) const noexcept { return Unpacked{uint16_t((uint32_t(u) << x) & 0xFFFFu)}; } 174 175 BL_INLINE_NODEBUG Unpacked operator&(const Repeat& x) const noexcept { return Unpacked{uint16_t((uint32_t(u) & x.v) & 0xFFFFu)}; } 176 BL_INLINE_NODEBUG Unpacked operator|(const Repeat& x) const noexcept { return Unpacked{uint16_t((uint32_t(u) | x.v) & 0xFFFFu)}; } 177 BL_INLINE_NODEBUG Unpacked operator^(const Repeat& x) const noexcept { return Unpacked{uint16_t((uint32_t(u) ^ x.v) & 0xFFFFu)}; } 178 BL_INLINE_NODEBUG Unpacked operator+(const Repeat& x) const noexcept { return Unpacked{uint16_t((uint32_t(u) + x.v) & 0xFFFFu)}; } 179 BL_INLINE_NODEBUG Unpacked operator-(const Repeat& x) const noexcept { return Unpacked{uint16_t((uint32_t(u) - x.v) & 0xFFFFu)}; } 180 BL_INLINE_NODEBUG Unpacked operator*(const Repeat& x) const noexcept { return Unpacked{uint16_t((uint32_t(u) * x.v) & 0xFFFFu)}; } 181 BL_INLINE_NODEBUG Unpacked operator>>(const Repeat& x) const noexcept { return Unpacked{uint16_t((uint32_t(u) >> x.v) & 0xFFFFu)}; } 182 BL_INLINE_NODEBUG Unpacked operator<<(const Repeat& x) const noexcept { return Unpacked{uint16_t((uint32_t(u) << x.v) & 0xFFFFu)}; } 183 184 BL_INLINE_NODEBUG Unpacked operator&(const Unpacked& x) const noexcept { return Unpacked { uint16_t((uint32_t(u) & x.u) & 0xFFFFu) }; } 185 BL_INLINE_NODEBUG Unpacked operator|(const Unpacked& x) const noexcept { return Unpacked { uint16_t((uint32_t(u) | x.u) & 0xFFFFu) }; } 186 BL_INLINE_NODEBUG Unpacked operator^(const Unpacked& x) const noexcept { return Unpacked { uint16_t((uint32_t(u) ^ x.u) & 0xFFFFu) }; } 187 BL_INLINE_NODEBUG Unpacked operator+(const Unpacked& x) const noexcept { return Unpacked { uint16_t((uint32_t(u) + x.u) & 0xFFFFu) }; } 188 BL_INLINE_NODEBUG Unpacked operator-(const Unpacked& x) const noexcept { return Unpacked { uint16_t((uint32_t(u) - x.u) & 0xFFFFu) }; } 189 BL_INLINE_NODEBUG Unpacked operator*(const Unpacked& x) const noexcept { return Unpacked { uint16_t((uint32_t(u) * x.u) & 0xFFFFu) }; } 190 191 BL_INLINE_NODEBUG Unpacked& operator&=(uint32_t x) noexcept { *this = *this & x; return *this; } 192 BL_INLINE_NODEBUG Unpacked& operator|=(uint32_t x) noexcept { *this = *this | x; return *this; } 193 BL_INLINE_NODEBUG Unpacked& operator^=(uint32_t x) noexcept { *this = *this ^ x; return *this; } 194 BL_INLINE_NODEBUG Unpacked& operator+=(uint32_t x) noexcept { *this = *this + x; return *this; } 195 BL_INLINE_NODEBUG Unpacked& operator-=(uint32_t x) noexcept { *this = *this - x; return *this; } 196 BL_INLINE_NODEBUG Unpacked& operator*=(uint32_t x) noexcept { *this = *this * x; return *this; } 197 BL_INLINE_NODEBUG Unpacked& operator>>=(uint32_t x) noexcept { *this = *this >> x; return *this; } 198 BL_INLINE_NODEBUG Unpacked& operator<<=(uint32_t x) noexcept { *this = *this << x; return *this; } 199 200 BL_INLINE_NODEBUG Unpacked& operator&=(const Repeat& x) noexcept { *this = *this & x; return *this; } 201 BL_INLINE_NODEBUG Unpacked& operator|=(const Repeat& x) noexcept { *this = *this | x; return *this; } 202 BL_INLINE_NODEBUG Unpacked& operator^=(const Repeat& x) noexcept { *this = *this ^ x; return *this; } 203 BL_INLINE_NODEBUG Unpacked& operator+=(const Repeat& x) noexcept { *this = *this + x; return *this; } 204 BL_INLINE_NODEBUG Unpacked& operator-=(const Repeat& x) noexcept { *this = *this - x; return *this; } 205 BL_INLINE_NODEBUG Unpacked& operator*=(const Repeat& x) noexcept { *this = *this * x; return *this; } 206 207 BL_INLINE_NODEBUG Unpacked& operator&=(const Unpacked& x) noexcept { *this = *this & x; return *this; } 208 BL_INLINE_NODEBUG Unpacked& operator|=(const Unpacked& x) noexcept { *this = *this | x; return *this; } 209 BL_INLINE_NODEBUG Unpacked& operator^=(const Unpacked& x) noexcept { *this = *this ^ x; return *this; } 210 BL_INLINE_NODEBUG Unpacked& operator+=(const Unpacked& x) noexcept { *this = *this + x; return *this; } 211 BL_INLINE_NODEBUG Unpacked& operator-=(const Unpacked& x) noexcept { *this = *this - x; return *this; } 212 BL_INLINE_NODEBUG Unpacked& operator*=(const Unpacked& x) noexcept { *this = *this * x; return *this; } 213 214 BL_INLINE Unpacked div255() const noexcept { 215 Unpacked u = *this + Repeat{0x80u}; 216 return ((u + ((u >> 8) & Repeat{0xFFu})) >> 8) & Repeat{0xFFu}; 217 } 218 219 BL_INLINE Unpacked div256() const noexcept { 220 return (*this >> 8) & Repeat{0xFFu}; 221 } 222 223 BL_INLINE Unpacked addus8(const Unpacked& x) const noexcept { 224 Unpacked val = (*this + x); 225 Unpacked msk = ((val >> 8) & Repeat{0x1u}) * Repeat{0xFF}; 226 return (val | msk) & Repeat{0xFFu}; 227 } 228 }; 229 230 BL_INLINE_NODEBUG U8_Alpha P8_Alpha::unpack() const noexcept { return Unpacked{p}; } 231 232 //! Packed 32-bit pixel. 233 template<typename FormatT> 234 struct P32_8888 { 235 //! Packed pixel value. 236 uint32_t p; 237 238 //! Pixel format information. 239 typedef FormatT Format; 240 241 //! Type of a packed compatible pixel. 242 typedef P32_8888<Format> Packed; 243 244 //! Type of an unpacked compatible pixel. 245 typedef U32_8888<Format> Unpacked; 246 247 static BL_INLINE_NODEBUG Packed from_value(uint32_t value) noexcept { return Packed { value }; } 248 249 BL_INLINE_NODEBUG uint32_t r() const noexcept { return (p >> Format::kRShift) & 0xFF; } 250 BL_INLINE_NODEBUG uint32_t g() const noexcept { return (p >> Format::kGShift) & 0xFF; } 251 BL_INLINE_NODEBUG uint32_t b() const noexcept { return (p >> Format::kBShift) & 0xFF; } 252 BL_INLINE_NODEBUG uint32_t a() const noexcept { return (p >> Format::kAShift) & 0xFF; } 253 BL_INLINE_NODEBUG uint32_t value() noexcept { return p; } 254 255 BL_INLINE_NODEBUG Packed pack() const noexcept { return *this; } 256 BL_INLINE_NODEBUG Unpacked unpack() const noexcept; 257 258 BL_INLINE_NODEBUG Packed operator&(uint32_t x) const noexcept { return Packed { p & x }; } 259 BL_INLINE_NODEBUG Packed operator|(uint32_t x) const noexcept { return Packed { p | x }; } 260 BL_INLINE_NODEBUG Packed operator^(uint32_t x) const noexcept { return Packed { p ^ x }; } 261 BL_INLINE_NODEBUG Packed operator+(uint32_t x) const noexcept { return Packed { p + x }; } 262 BL_INLINE_NODEBUG Packed operator-(uint32_t x) const noexcept { return Packed { p - x }; } 263 BL_INLINE_NODEBUG Packed operator*(uint32_t x) const noexcept { return Packed { p * x }; } 264 BL_INLINE_NODEBUG Packed operator>>(uint32_t x) const noexcept { return Packed { p >> x }; } 265 BL_INLINE_NODEBUG Packed operator<<(uint32_t x) const noexcept { return Packed { p << x }; } 266 267 BL_INLINE_NODEBUG Packed operator&(const Packed& x) const noexcept { return Packed { p & x.p }; } 268 BL_INLINE_NODEBUG Packed operator|(const Packed& x) const noexcept { return Packed { p | x.p }; } 269 BL_INLINE_NODEBUG Packed operator^(const Packed& x) const noexcept { return Packed { p ^ x.p }; } 270 BL_INLINE_NODEBUG Packed operator+(const Packed& x) const noexcept { return Packed { p + x.p }; } 271 BL_INLINE_NODEBUG Packed operator-(const Packed& x) const noexcept { return Packed { p - x.p }; } 272 273 BL_INLINE_NODEBUG Packed& operator&=(uint32_t x) noexcept { *this = *this & x; return *this; } 274 BL_INLINE_NODEBUG Packed& operator|=(uint32_t x) noexcept { *this = *this | x; return *this; } 275 BL_INLINE_NODEBUG Packed& operator^=(uint32_t x) noexcept { *this = *this ^ x; return *this; } 276 BL_INLINE_NODEBUG Packed& operator+=(uint32_t x) noexcept { *this = *this + x; return *this; } 277 BL_INLINE_NODEBUG Packed& operator-=(uint32_t x) noexcept { *this = *this - x; return *this; } 278 BL_INLINE_NODEBUG Packed& operator*=(uint32_t x) noexcept { *this = *this * x; return *this; } 279 BL_INLINE_NODEBUG Packed& operator>>=(uint32_t x) noexcept { *this = *this >> x; return *this; } 280 BL_INLINE_NODEBUG Packed& operator<<=(uint32_t x) noexcept { *this = *this << x; return *this; } 281 282 BL_INLINE_NODEBUG Packed& operator&=(const Packed& x) noexcept { *this = *this & x; return *this; } 283 BL_INLINE_NODEBUG Packed& operator|=(const Packed& x) noexcept { *this = *this | x; return *this; } 284 BL_INLINE_NODEBUG Packed& operator^=(const Packed& x) noexcept { *this = *this ^ x; return *this; } 285 BL_INLINE_NODEBUG Packed& operator+=(const Packed& x) noexcept { *this = *this + x; return *this; } 286 BL_INLINE_NODEBUG Packed& operator-=(const Packed& x) noexcept { *this = *this - x; return *this; } 287 }; 288 289 #if BL_TARGET_ARCH_BITS >= 64 290 291 //! Unpacked 32-bit pixel to 64-bit data type. 292 template<typename FormatT> 293 struct U32_8888 { 294 //! Unpacked components [.3.1.2.0] 295 uint64_t u3120; 296 297 //! Pixel format information. 298 typedef FormatT Format; 299 300 //! Type of a packed compatible pixel. 301 typedef P32_8888<Format> Packed; 302 303 //! Type of an unpacked compatible pixel. 304 typedef U32_8888<Format> Unpacked; 305 306 template<uint32_t shift> 307 BL_INLINE uint32_t value_by_shift_t() const noexcept { 308 BL_STATIC_ASSERT(shift == 0 || shift == 8 || shift == 16 || shift == 24); 309 310 if (shift == 0) 311 return uint32_t((u3120 >> 0) & 0xFFFFu); 312 else if (shift == 8) 313 return uint32_t((u3120 >> 32) & 0xFFFFu); 314 else if (shift == 16) 315 return uint32_t((u3120 >> 16) & 0xFFFFu); 316 else 317 return uint32_t((u3120 >> 48)); 318 } 319 320 template<uint32_t index> 321 BL_INLINE uint32_t value_by_index_t() const noexcept { 322 return value_by_shift_t<index * 8>(); 323 } 324 325 template<Component component> 326 BL_INLINE uint32_t value_by_component_t() const noexcept { 327 return value_by_shift_t<Format::shift_from_component(component)>(); 328 } 329 330 BL_INLINE_NODEBUG uint32_t r() const noexcept { return value_by_component_t<Component::kR>(); } 331 BL_INLINE_NODEBUG uint32_t g() const noexcept { return value_by_component_t<Component::kG>(); } 332 BL_INLINE_NODEBUG uint32_t b() const noexcept { return value_by_component_t<Component::kB>(); } 333 BL_INLINE_NODEBUG uint32_t a() const noexcept { return value_by_component_t<Component::kA>(); } 334 335 BL_INLINE_NODEBUG Packed pack() const noexcept { return Packed { (uint32_t)(((u3120 >> 24) | u3120) & 0xFFFFFFFFu) }; } 336 BL_INLINE_NODEBUG Unpacked unpack() const noexcept { return *this; } 337 338 BL_INLINE_NODEBUG Unpacked operator>>(uint32_t x) const noexcept { return Unpacked { u3120 >> x }; } 339 BL_INLINE_NODEBUG Unpacked operator<<(uint32_t x) const noexcept { return Unpacked { u3120 << x }; } 340 341 BL_INLINE_NODEBUG Unpacked operator&(const Repeat& x) const noexcept { return Unpacked { u3120 & x.u16x4() }; } 342 BL_INLINE_NODEBUG Unpacked operator|(const Repeat& x) const noexcept { return Unpacked { u3120 | x.u16x4() }; } 343 BL_INLINE_NODEBUG Unpacked operator^(const Repeat& x) const noexcept { return Unpacked { u3120 ^ x.u16x4() }; } 344 BL_INLINE_NODEBUG Unpacked operator+(const Repeat& x) const noexcept { return Unpacked { u3120 + x.u16x4() }; } 345 BL_INLINE_NODEBUG Unpacked operator-(const Repeat& x) const noexcept { return Unpacked { u3120 - x.u16x4() }; } 346 BL_INLINE_NODEBUG Unpacked operator*(const Repeat& x) const noexcept { return Unpacked { u3120 * x.v }; } 347 BL_INLINE_NODEBUG Unpacked operator>>(const Repeat& x) const noexcept { return Unpacked { u3120 >> x.v }; } 348 BL_INLINE_NODEBUG Unpacked operator<<(const Repeat& x) const noexcept { return Unpacked { u3120 << x.v }; } 349 350 BL_INLINE_NODEBUG Unpacked operator&(const Unpacked& x) const noexcept { return Unpacked { u3120 & x.u3120 }; } 351 BL_INLINE_NODEBUG Unpacked operator|(const Unpacked& x) const noexcept { return Unpacked { u3120 | x.u3120 }; } 352 BL_INLINE_NODEBUG Unpacked operator^(const Unpacked& x) const noexcept { return Unpacked { u3120 ^ x.u3120 }; } 353 BL_INLINE_NODEBUG Unpacked operator+(const Unpacked& x) const noexcept { return Unpacked { u3120 + x.u3120 }; } 354 BL_INLINE_NODEBUG Unpacked operator-(const Unpacked& x) const noexcept { return Unpacked { u3120 - x.u3120 }; } 355 BL_INLINE_NODEBUG Unpacked operator*(const Unpacked& x) const noexcept { return cmul(x); } 356 357 BL_INLINE_NODEBUG Unpacked& operator>>=(uint32_t x) noexcept { *this = *this >> x; return *this; } 358 BL_INLINE_NODEBUG Unpacked& operator<<=(uint32_t x) noexcept { *this = *this << x; return *this; } 359 360 BL_INLINE_NODEBUG Unpacked& operator&=(const Repeat& x) noexcept { *this = *this & x; return *this; } 361 BL_INLINE_NODEBUG Unpacked& operator|=(const Repeat& x) noexcept { *this = *this | x; return *this; } 362 BL_INLINE_NODEBUG Unpacked& operator^=(const Repeat& x) noexcept { *this = *this ^ x; return *this; } 363 BL_INLINE_NODEBUG Unpacked& operator+=(const Repeat& x) noexcept { *this = *this + x; return *this; } 364 BL_INLINE_NODEBUG Unpacked& operator-=(const Repeat& x) noexcept { *this = *this - x; return *this; } 365 BL_INLINE_NODEBUG Unpacked& operator*=(const Repeat& x) noexcept { *this = *this * x; return *this; } 366 BL_INLINE_NODEBUG Unpacked& operator>>=(const Repeat& x) noexcept { *this = *this >> x; return *this; } 367 BL_INLINE_NODEBUG Unpacked& operator<<=(const Repeat& x) noexcept { *this = *this << x; return *this; } 368 369 BL_INLINE_NODEBUG Unpacked& operator&=(const Unpacked& x) noexcept { *this = *this & x; return *this; } 370 BL_INLINE_NODEBUG Unpacked& operator|=(const Unpacked& x) noexcept { *this = *this | x; return *this; } 371 BL_INLINE_NODEBUG Unpacked& operator^=(const Unpacked& x) noexcept { *this = *this ^ x; return *this; } 372 BL_INLINE_NODEBUG Unpacked& operator+=(const Unpacked& x) noexcept { *this = *this + x; return *this; } 373 BL_INLINE_NODEBUG Unpacked& operator-=(const Unpacked& x) noexcept { *this = *this - x; return *this; } 374 BL_INLINE_NODEBUG Unpacked& operator*=(const Unpacked& x) noexcept { *this = *this * x; return *this; } 375 376 template<typename XFormat> 377 BL_INLINE Unpacked cmul(const U32_8888<XFormat>& x) const noexcept { 378 uint32_t u0 = value_by_index_t<0>() * x.template value_by_component_t<Format::component_from_index(0)>(); 379 uint32_t u1 = value_by_index_t<1>() * x.template value_by_component_t<Format::component_from_index(1)>(); 380 uint32_t u2 = value_by_index_t<2>() * x.template value_by_component_t<Format::component_from_index(2)>(); 381 uint32_t u3 = value_by_index_t<3>() * x.template value_by_component_t<Format::component_from_index(3)>(); 382 383 return Unpacked { uint64_t(u0) | (uint64_t(u1) << 32) | (uint64_t(u2) << 16) | (uint64_t(u3) << 48) }; 384 } 385 386 BL_INLINE Unpacked div255() const noexcept { 387 Unpacked u = *this + Repeat{0x80u}; 388 return ((u + ((u >> 8) & Repeat{0xFFu})) >> 8) & Repeat{0xFFu}; 389 } 390 391 BL_INLINE Unpacked div256() const noexcept { 392 return (*this >> 8) & Repeat{0xFFu}; 393 } 394 395 BL_INLINE Unpacked addus8(const Unpacked& x) const noexcept { 396 Unpacked val = (*this + x); 397 Unpacked msk = ((val >> 8) & Repeat{0x1u}) * Repeat{0xFF}; 398 return (val | msk) & Repeat{0xFFu}; 399 } 400 }; 401 402 template<typename Format> 403 BL_INLINE U32_8888<Format> P32_8888<Format>::unpack() const noexcept { 404 return Unpacked { uint64_t(p & 0x00FF00FFu) | (uint64_t(p & 0xFF00FF00u) << 24) }; 405 } 406 407 #else 408 409 //! Unpacked 32-bit pixel to 64-bit data type. 410 template<typename FormatT> 411 struct U32_8888 { 412 //! Unpacked components [.2.0]. 413 uint32_t u20; 414 //! Unpacked components [3.1.]. 415 uint32_t u31; 416 417 //! Pixel format information. 418 typedef FormatT Format; 419 420 //! Type of a packed compatible pixel. 421 typedef P32_8888<Format> Packed; 422 423 //! Type of an unpacked compatible pixel. 424 typedef U32_8888<Format> Unpacked; 425 426 template<uint32_t shift> 427 BL_INLINE uint32_t value_by_shift_t() const noexcept { 428 BL_STATIC_ASSERT(shift == 0 || shift == 8 || shift == 16 || shift == 24); 429 430 if (shift == 0) 431 return u20 & 0xFFFFu; 432 else if (shift == 8) 433 return u31 & 0xFFFFu; 434 else if (shift == 16) 435 return u20 >> 16; 436 else 437 return u31 >> 16; 438 } 439 440 template<uint32_t index> 441 BL_INLINE_NODEBUG uint32_t value_by_index_t() const noexcept { 442 return value_by_shift_t<index * 8>(); 443 } 444 445 template<Component component> 446 BL_INLINE_NODEBUG uint32_t value_by_component_t() const noexcept { 447 return value_by_shift_t<Format::shift_from_component(component)>(); 448 } 449 450 BL_INLINE_NODEBUG uint32_t r() const noexcept { return value_by_component_t<Component::kR>(); } 451 BL_INLINE_NODEBUG uint32_t g() const noexcept { return value_by_component_t<Component::kG>(); } 452 BL_INLINE_NODEBUG uint32_t b() const noexcept { return value_by_component_t<Component::kB>(); } 453 BL_INLINE_NODEBUG uint32_t a() const noexcept { return value_by_component_t<Component::kA>(); } 454 455 BL_INLINE_NODEBUG Packed pack() const noexcept { return Packed { u20 | (u31 << 8) }; } 456 BL_INLINE_NODEBUG Unpacked unpack() const noexcept { return *this; } 457 458 BL_INLINE_NODEBUG Unpacked operator>>(uint32_t x) const noexcept { return Unpacked { u20 >> x, u31 >> x }; } 459 BL_INLINE_NODEBUG Unpacked operator<<(uint32_t x) const noexcept { return Unpacked { u20 << x, u31 << x }; } 460 461 BL_INLINE_NODEBUG Unpacked operator&(const Repeat& x) const noexcept { return Unpacked { u20 & x.u16x2(), u31 & x.u16x2() }; } 462 BL_INLINE_NODEBUG Unpacked operator|(const Repeat& x) const noexcept { return Unpacked { u20 | x.u16x2(), u31 | x.u16x2() }; } 463 BL_INLINE_NODEBUG Unpacked operator^(const Repeat& x) const noexcept { return Unpacked { u20 ^ x.u16x2(), u31 ^ x.u16x2() }; } 464 BL_INLINE_NODEBUG Unpacked operator+(const Repeat& x) const noexcept { return Unpacked { u20 + x.u16x2(), u31 + x.u16x2() }; } 465 BL_INLINE_NODEBUG Unpacked operator-(const Repeat& x) const noexcept { return Unpacked { u20 - x.u16x2(), u31 - x.u16x2() }; } 466 BL_INLINE_NODEBUG Unpacked operator*(const Repeat& x) const noexcept { return Unpacked { u20 * x.v, u31 * x.v }; } 467 BL_INLINE_NODEBUG Unpacked operator>>(const Repeat& x) const noexcept { return Unpacked { u20 >> x.v, u31 >> x.v }; } 468 BL_INLINE_NODEBUG Unpacked operator<<(const Repeat& x) const noexcept { return Unpacked { u20 << x.v, u31 << x.v }; } 469 470 BL_INLINE_NODEBUG Unpacked operator&(const Unpacked& x) const noexcept { return Unpacked { u20 & x.u20, u31 & x.u31 }; } 471 BL_INLINE_NODEBUG Unpacked operator|(const Unpacked& x) const noexcept { return Unpacked { u20 | x.u20, u31 | x.u31 }; } 472 BL_INLINE_NODEBUG Unpacked operator^(const Unpacked& x) const noexcept { return Unpacked { u20 ^ x.u20, u31 ^ x.u31 }; } 473 BL_INLINE_NODEBUG Unpacked operator+(const Unpacked& x) const noexcept { return Unpacked { u20 + x.u20, u31 + x.u31 }; } 474 BL_INLINE_NODEBUG Unpacked operator-(const Unpacked& x) const noexcept { return Unpacked { u20 - x.u20, u31 - x.u31 }; } 475 BL_INLINE_NODEBUG Unpacked operator*(const Unpacked& x) const noexcept { return cmul(x); } 476 477 BL_INLINE_NODEBUG Unpacked& operator>>=(uint32_t x) noexcept { *this = *this >> x; return *this; } 478 BL_INLINE_NODEBUG Unpacked& operator<<=(uint32_t x) noexcept { *this = *this << x; return *this; } 479 480 BL_INLINE_NODEBUG Unpacked& operator&=(const Repeat& x) noexcept { *this = *this & x; return *this; } 481 BL_INLINE_NODEBUG Unpacked& operator|=(const Repeat& x) noexcept { *this = *this | x; return *this; } 482 BL_INLINE_NODEBUG Unpacked& operator^=(const Repeat& x) noexcept { *this = *this ^ x; return *this; } 483 BL_INLINE_NODEBUG Unpacked& operator+=(const Repeat& x) noexcept { *this = *this + x; return *this; } 484 BL_INLINE_NODEBUG Unpacked& operator-=(const Repeat& x) noexcept { *this = *this - x; return *this; } 485 BL_INLINE_NODEBUG Unpacked& operator*=(const Repeat& x) noexcept { *this = *this * x; return *this; } 486 BL_INLINE_NODEBUG Unpacked& operator>>=(const Repeat& x) noexcept { *this = *this >> x; return *this; } 487 BL_INLINE_NODEBUG Unpacked& operator<<=(const Repeat& x) noexcept { *this = *this << x; return *this; } 488 489 BL_INLINE_NODEBUG Unpacked& operator&=(const Unpacked& x) noexcept { *this = *this & x; return *this; } 490 BL_INLINE_NODEBUG Unpacked& operator|=(const Unpacked& x) noexcept { *this = *this | x; return *this; } 491 BL_INLINE_NODEBUG Unpacked& operator^=(const Unpacked& x) noexcept { *this = *this ^ x; return *this; } 492 BL_INLINE_NODEBUG Unpacked& operator+=(const Unpacked& x) noexcept { *this = *this + x; return *this; } 493 BL_INLINE_NODEBUG Unpacked& operator-=(const Unpacked& x) noexcept { *this = *this - x; return *this; } 494 BL_INLINE_NODEBUG Unpacked& operator*=(const Unpacked& x) noexcept { *this = *this * x; return *this; } 495 496 template<typename XFormat> 497 BL_INLINE Unpacked cmul(const U32_8888<XFormat>& x) const noexcept { 498 return Unpacked { 499 ((u20 & 0xFFFF0000u) * x.template value_by_component_t<Format::component_from_index(2)>()) | 500 ((u20 & 0x0000FFFFu) * x.template value_by_component_t<Format::component_from_index(0)>()) 501 , 502 ((u31 & 0xFFFF0000u) * x.template value_by_component_t<Format::component_from_index(3)>()) | 503 ((u31 & 0x0000FFFFu) * x.template value_by_component_t<Format::component_from_index(1)>()) 504 }; 505 } 506 507 BL_INLINE Unpacked div255() const noexcept { 508 Unpacked u = *this + Repeat{0x80u}; 509 return ((u + ((u >> 8) & Repeat{0xFFu})) >> 8) & Repeat{0xFFu}; 510 } 511 512 BL_INLINE Unpacked div256() const noexcept { 513 return (*this >> 8) & Repeat{0xFFu}; 514 } 515 516 BL_INLINE Unpacked addus8(const Unpacked& x) const noexcept { 517 Unpacked val = (*this + x); 518 Unpacked msk = ((val >> 8) & Repeat{0x1u}) * Repeat{0xFF}; 519 return (val | msk) & Repeat{0xFFu}; 520 } 521 }; 522 523 template<typename Format> 524 BL_INLINE U32_8888<Format> P32_8888<Format>::unpack() const noexcept { 525 return Unpacked { p & 0x00FF00FFu, (p >> 8) & 0x00FF00FFu }; 526 } 527 528 #endif 529 530 typedef P32_8888<Format_A8R8G8B8> P32_A8R8G8B8; 531 typedef U32_8888<Format_A8R8G8B8> U32_A8R8G8B8; 532 533 } // {Pixel} 534 535 template<FormatExt format> 536 struct FormatMetadata {}; 537 538 template<> 539 struct FormatMetadata<FormatExt::kPRGB32> { 540 static inline constexpr bool kHasAlpha = true; 541 static inline constexpr bool kHasRGB = true; 542 static inline constexpr bool kIsPremultiplied = true; 543 static inline constexpr uint32_t kBPP = 4; 544 }; 545 546 template<> 547 struct FormatMetadata<FormatExt::kXRGB32> { 548 static inline constexpr bool kHasAlpha = false; 549 static inline constexpr bool kHasRGB = true; 550 static inline constexpr bool kIsPremultiplied = false; 551 static inline constexpr uint32_t kBPP = 4; 552 }; 553 554 template<> 555 struct FormatMetadata<FormatExt::kA8> { 556 static inline constexpr bool kHasAlpha = true; 557 static inline constexpr bool kHasRGB = false; 558 static inline constexpr bool kIsPremultiplied = false; 559 static inline constexpr uint32_t kBPP = 1; 560 }; 561 562 template<> 563 struct FormatMetadata<FormatExt::kFRGB32> { 564 static inline constexpr bool kHasAlpha = true; 565 static inline constexpr bool kHasRGB = true; 566 static inline constexpr bool kIsPremultiplied = true; 567 static inline constexpr uint32_t kBPP = 4; 568 }; 569 570 template<> 571 struct FormatMetadata<FormatExt::kZERO32> { 572 static inline constexpr bool kHasAlpha = true; 573 static inline constexpr bool kHasRGB = true; 574 static inline constexpr bool kIsPremultiplied = true; 575 static inline constexpr uint32_t kBPP = 4; 576 }; 577 578 template<typename PixelT> 579 struct PixelTypeToFormat {}; 580 581 template<> 582 struct PixelTypeToFormat<Pixel::P8_Alpha> { 583 static constexpr FormatExt kFormat = FormatExt::kA8; 584 }; 585 586 template<> 587 struct PixelTypeToFormat<Pixel::P32_A8R8G8B8> { 588 static constexpr FormatExt kFormat = FormatExt::kPRGB32; 589 }; 590 591 template<typename PixelT, FormatExt kFormat> 592 struct PixelIO {}; 593 594 template<> 595 struct PixelIO<Pixel::P8_Alpha, FormatExt::kPRGB32> { 596 typedef Pixel::P8_Alpha PixelType; 597 598 static BL_INLINE_NODEBUG PixelType make(uint32_t r, uint32_t g, uint32_t b, uint32_t a = 0xFFu) noexcept { 599 bl_unused(r, g, b); 600 return PixelType::from_value(a); 601 } 602 603 static BL_INLINE_NODEBUG PixelType fetch(const void* src) noexcept { return PixelType{uint8_t(*static_cast<const uint32_t*>(src) >> 24)}; } 604 }; 605 606 template<> 607 struct PixelIO<Pixel::P8_Alpha, FormatExt::kXRGB32> { 608 typedef Pixel::P8_Alpha PixelType; 609 610 static BL_INLINE_NODEBUG PixelType make(uint32_t r, uint32_t g, uint32_t b, uint32_t a = 0xFFu) noexcept { 611 bl_unused(r, g, b); 612 return PixelType::from_value(a); 613 } 614 615 static BL_INLINE_NODEBUG PixelType fetch(const void* src) noexcept { 616 bl_unused(src); 617 return PixelType{uint8_t(0xFFu)}; 618 } 619 }; 620 621 template<> 622 struct PixelIO<Pixel::P8_Alpha, FormatExt::kFRGB32> : public PixelIO<Pixel::P8_Alpha, FormatExt::kXRGB32> {}; 623 624 template<> 625 struct PixelIO<Pixel::P8_Alpha, FormatExt::kA8> { 626 typedef Pixel::P8_Alpha PixelType; 627 628 static BL_INLINE_NODEBUG PixelType make(uint32_t r, uint32_t g, uint32_t b, uint32_t a = 0xFFu) noexcept { 629 bl_unused(r, g, b); 630 return PixelType::from_value(a); 631 } 632 633 static BL_INLINE_NODEBUG PixelType fetch(const void* src) noexcept { return PixelType{*static_cast<const uint8_t*>(src)}; } 634 static BL_INLINE_NODEBUG void store(void* dst, const PixelType& src) noexcept { *static_cast<uint8_t*>(dst) = src.p; } 635 }; 636 637 template<> 638 struct PixelIO<Pixel::P32_A8R8G8B8, FormatExt::kPRGB32> { 639 typedef Pixel::P32_A8R8G8B8 PixelType; 640 641 static BL_INLINE_NODEBUG PixelType make(uint32_t r, uint32_t g, uint32_t b, uint32_t a = 0xFFu) noexcept { 642 return PixelType::from_value((a << 24) | (r << 16) | (g << 8) | b); 643 } 644 645 static BL_INLINE_NODEBUG PixelType fetch(const void* src) noexcept { return PixelType{*static_cast<const uint32_t*>(src)}; } 646 static BL_INLINE_NODEBUG void store(void* dst, PixelType src) noexcept { *static_cast<uint32_t*>(dst) = src.p; } 647 }; 648 649 template<> 650 struct PixelIO<Pixel::P32_A8R8G8B8, FormatExt::kXRGB32> { 651 typedef Pixel::P32_A8R8G8B8 PixelType; 652 653 static BL_INLINE_NODEBUG PixelType make(uint32_t r, uint32_t g, uint32_t b, uint32_t a = 0xFFu) noexcept { 654 bl_unused(a); 655 return PixelType::from_value((0xFFu << 24) | (r << 16) | (g << 8) | b); 656 } 657 658 static BL_INLINE_NODEBUG PixelType fetch(const void* src) noexcept { return PixelType{*static_cast<const uint32_t*>(src) | uint32_t(0xFF000000u)}; } 659 static BL_INLINE_NODEBUG void store(void* dst, const PixelType& src) noexcept { *static_cast<uint32_t*>(dst) = src.p; } 660 }; 661 662 template<> 663 struct PixelIO<Pixel::P32_A8R8G8B8, FormatExt::kA8> { 664 typedef Pixel::P32_A8R8G8B8 PixelType; 665 666 static BL_INLINE_NODEBUG PixelType make(uint32_t r, uint32_t g, uint32_t b, uint32_t a = 0xFFu) noexcept { 667 bl_unused(r, g, b); 668 return PixelType::from_value(a * 0x01010101u); 669 } 670 671 static BL_INLINE_NODEBUG PixelType fetch(const void* src) noexcept { return PixelType{uint32_t(*static_cast<const uint8_t*>(src)) * uint32_t(0x01010101u)}; } 672 static BL_INLINE_NODEBUG void store(void* dst, PixelType src) noexcept { *static_cast<uint8_t*>(dst) = uint8_t(src.a()); } 673 }; 674 675 template<> struct PixelIO<Pixel::P32_A8R8G8B8, FormatExt::kFRGB32> : public PixelIO<Pixel::P32_A8R8G8B8, FormatExt::kPRGB32> {}; 676 template<> struct PixelIO<Pixel::P32_A8R8G8B8, FormatExt::kZERO32> : public PixelIO<Pixel::P32_A8R8G8B8, FormatExt::kPRGB32> {}; 677 678 } // {bl::Pipeline::Reference} 679 680 //! \} 681 //! \endcond 682 683 #endif // BLEND2D_PIPELINE_REFERENCE_PIXELGENERIC_P_H_INCLUDED