odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

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