tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Types.h (35967B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef MOZILLA_GFX_TYPES_H_
      8 #define MOZILLA_GFX_TYPES_H_
      9 
     10 #include "mozilla/DefineEnum.h"  // for MOZ_DEFINE_ENUM_CLASS_WITH_BASE
     11 #include "mozilla/EndianUtils.h"
     12 #include "mozilla/EnumeratedRange.h"
     13 #include "mozilla/MacroArgs.h"  // for MOZ_CONCAT
     14 #include "mozilla/TypedEnumBits.h"
     15 
     16 #include <iosfwd>  // for ostream
     17 #include <stddef.h>
     18 #include <stdint.h>
     19 #include <optional>
     20 
     21 namespace mozilla {
     22 namespace gfx {
     23 
     24 typedef float Float;
     25 typedef double Double;
     26 
     27 enum class SurfaceType : int8_t {
     28  DATA,                   /* Data surface - bitmap in memory */
     29  CAIRO,                  /* Surface wrapping a cairo surface */
     30  CAIRO_IMAGE,            /* Data surface wrapping a cairo image surface */
     31  COREGRAPHICS_IMAGE,     /* Surface wrapping a CoreGraphics Image */
     32  COREGRAPHICS_CGCONTEXT, /* Surface wrapping a CG context */
     33  SKIA,                   /* Surface wrapping a Skia bitmap */
     34  RECORDING,              /* Surface used for recording */
     35  DATA_SHARED,            /* Data surface using shared memory */
     36  DATA_RECYCLING_SHARED,  /* Data surface using shared memory */
     37  OFFSET,                 /* Offset */
     38  DATA_ALIGNED,           /* Data surface using aligned heap memory */
     39  DATA_SHARED_WRAPPER,    /* Shared memory mapped in from another process */
     40  BLOB_IMAGE,             /* Recorded blob image */
     41  DATA_MAPPED,            /* Data surface wrapping a ScopedMap */
     42  WEBGL,                  /* Surface wrapping a DrawTargetWebgl texture */
     43  D3D11_TEXTURE,          /* Surface wrapping a D3D11Texture */
     44 };
     45 
     46 enum class SurfaceFormat : int8_t {
     47  // The following values are named to reflect layout of colors in memory, from
     48  // lowest byte to highest byte. The 32-bit value layout depends on machine
     49  // endianness.
     50  //               in-memory            32-bit LE value   32-bit BE value
     51  B8G8R8A8,  // [BB, GG, RR, AA]     0xAARRGGBB        0xBBGGRRAA
     52  B8G8R8X8,  // [BB, GG, RR, 00]     0x00RRGGBB        0xBBGGRR00
     53  R8G8B8A8,  // [RR, GG, BB, AA]     0xAABBGGRR        0xRRGGBBAA
     54  R8G8B8X8,  // [RR, GG, BB, 00]     0x00BBGGRR        0xRRGGBB00
     55  A8R8G8B8,  // [AA, RR, GG, BB]     0xBBGGRRAA        0xAARRGGBB
     56  X8R8G8B8,  // [00, RR, GG, BB]     0xBBGGRR00        0x00RRGGBB
     57 
     58  R8G8B8,
     59  B8G8R8,
     60 
     61  // The _UINT16 suffix here indicates that the name reflects the layout when
     62  // viewed as a uint16_t value. In memory these values are stored using native
     63  // endianness.
     64  R5G6B5_UINT16,  // 0bRRRRRGGGGGGBBBBB
     65 
     66  // This one is a single-byte, so endianness isn't an issue.
     67  A8,
     68  A16,
     69 
     70  R8G8,
     71  R16G16,
     72 
     73  // These ones are their own special cases.
     74  YUV420,     // Sometimes called YU12. 3 planes of 8 bit Y, then Cb, then Cr.
     75              // 4:2:0 chroma subsampling.
     76  YUV420P10,  // YUV420 but with 16 bit plane values where the 6 most
     77              // significant bits are 0 (so it's 10-bit format).
     78  YUV422P10,  // 3 planes like YUV420, but with 4:2:2 chroma subampling and
     79              // 16 bit plane values where the 6 least significant bits are 0.
     80  NV12,       // 2 planes. YUV 4:2:0 image with a plane of 8 bit Y samples
     81              // followed by an interleaved U/V plane containing 8 bit 2x2
     82              // subsampled colour difference samples.
     83  P016,       // Similar to NV12, but with 16 bits plane values
     84  P010,       // Identical to P016 but the 6 least significant bits are 0.
     85              // With DXGI in theory entirely compatible, however practice has
     86              // shown that it's not the case.
     87  NV16,       // Similar to NV12, but with 4:2:2 chroma subsampling. Technically
     88              // 8 bit, but we only use it for 10 bit, and it's really only here
     89              // to support the macOS bi-planar 422 formats.
     90  YUY2,       // Sometimes called YUYV. Single plane / packed YUV 4:2:2 8 bit
     91              // samples interleaved as Y`0 Cb Y`1 Cr. Since 4 pixels require
     92              // 64 bits, this can also be considered a 16bpp format, but each
     93              // component is only 8 bits. We sometimes pack RGBA data into
     94              // this format.
     95  HSV,
     96  Lab,
     97  Depth,
     98 
     99  // LE packed 10bit per channel format primarily associated with HDR10 video.
    100  R10G10B10A2_UINT32,  // 0bAARRRRRRRRRRGGGGGGGGGGBBBBBBBBBB
    101  // Same as R10G10B10A2_UINT32 but with the alpha channel ignored.
    102  R10G10B10X2_UINT32,  // 0b00RRRRRRRRRRGGGGGGGGGGBBBBBBBBBB
    103  // 4 half-float (f16) components in RGBA order for HDR rendering, each is
    104  // machine endian.
    105  R16G16B16A16F,
    106 
    107  // This represents the unknown format.
    108  UNKNOWN,  // TODO: Replace uses with Maybe<SurfaceFormat>.
    109 
    110 // The following values are endian-independent synonyms. The _UINT32 suffix
    111 // indicates that the name reflects the layout when viewed as a uint32_t
    112 // value.
    113 #if MOZ_LITTLE_ENDIAN()
    114  A8R8G8B8_UINT32 = B8G8R8A8,  // 0xAARRGGBB
    115  X8R8G8B8_UINT32 = B8G8R8X8,  // 0x00RRGGBB
    116 #elif MOZ_BIG_ENDIAN()
    117  A8R8G8B8_UINT32 = A8R8G8B8,  // 0xAARRGGBB
    118  X8R8G8B8_UINT32 = X8R8G8B8,  // 0x00RRGGBB
    119 #else
    120 #  error "bad endianness"
    121 #endif
    122 
    123  // The following values are OS and endian-independent synonyms.
    124  //
    125  // TODO(aosmond): When everything blocking bug 1581828 has been resolved, we
    126  // can make this use R8B8G8A8 and R8B8G8X8 for non-Windows platforms.
    127  OS_RGBA = A8R8G8B8_UINT32,
    128  OS_RGBX = X8R8G8B8_UINT32
    129 };
    130 
    131 enum class SubpixelOrder : uint8_t {
    132  UNKNOWN,
    133  RGB,
    134  BGR,
    135  VRGB,
    136  VBGR,
    137 };
    138 
    139 struct SurfaceFormatInfo {
    140  bool hasColor;
    141  bool hasAlpha;
    142  bool isYuv;
    143  std::optional<uint8_t> bytesPerPixel;
    144 };
    145 inline std::optional<SurfaceFormatInfo> Info(const SurfaceFormat aFormat) {
    146  auto info = SurfaceFormatInfo{};
    147 
    148  switch (aFormat) {
    149    case SurfaceFormat::B8G8R8A8:
    150    case SurfaceFormat::R8G8B8A8:
    151    case SurfaceFormat::A8R8G8B8:
    152    case SurfaceFormat::R10G10B10A2_UINT32:
    153    case SurfaceFormat::R16G16B16A16F:
    154      info.hasColor = true;
    155      info.hasAlpha = true;
    156      break;
    157 
    158    case SurfaceFormat::B8G8R8X8:
    159    case SurfaceFormat::R8G8B8X8:
    160    case SurfaceFormat::X8R8G8B8:
    161    case SurfaceFormat::R8G8B8:
    162    case SurfaceFormat::B8G8R8:
    163    case SurfaceFormat::R5G6B5_UINT16:
    164    case SurfaceFormat::R10G10B10X2_UINT32:
    165    case SurfaceFormat::R8G8:
    166    case SurfaceFormat::R16G16:
    167    case SurfaceFormat::HSV:
    168    case SurfaceFormat::Lab:
    169      info.hasColor = true;
    170      info.hasAlpha = false;
    171      break;
    172 
    173    case SurfaceFormat::A8:
    174    case SurfaceFormat::A16:
    175      info.hasColor = false;
    176      info.hasAlpha = true;
    177      break;
    178 
    179    case SurfaceFormat::YUV420:
    180    case SurfaceFormat::YUV420P10:
    181    case SurfaceFormat::YUV422P10:
    182    case SurfaceFormat::NV12:
    183    case SurfaceFormat::P016:
    184    case SurfaceFormat::P010:
    185    case SurfaceFormat::NV16:
    186    case SurfaceFormat::YUY2:
    187      info.hasColor = true;
    188      info.hasAlpha = false;
    189      info.isYuv = true;
    190      break;
    191 
    192    case SurfaceFormat::Depth:
    193      info.hasColor = false;
    194      info.hasAlpha = false;
    195      info.isYuv = false;
    196      break;
    197 
    198    case SurfaceFormat::UNKNOWN:
    199      break;
    200  }
    201 
    202  // -
    203  // bytesPerPixel
    204 
    205  switch (aFormat) {
    206    case SurfaceFormat::B8G8R8A8:
    207    case SurfaceFormat::R8G8B8A8:
    208    case SurfaceFormat::A8R8G8B8:
    209    case SurfaceFormat::B8G8R8X8:
    210    case SurfaceFormat::R8G8B8X8:
    211    case SurfaceFormat::X8R8G8B8:
    212    case SurfaceFormat::R16G16:
    213      info.bytesPerPixel = 4;
    214      break;
    215 
    216    case SurfaceFormat::R8G8B8:
    217    case SurfaceFormat::B8G8R8:
    218      info.bytesPerPixel = 3;
    219      break;
    220 
    221    case SurfaceFormat::R5G6B5_UINT16:
    222    case SurfaceFormat::R8G8:
    223    case SurfaceFormat::A16:
    224    case SurfaceFormat::Depth:  // uint16_t
    225      info.bytesPerPixel = 2;
    226      break;
    227 
    228    case SurfaceFormat::A8:
    229      info.bytesPerPixel = 1;
    230      break;
    231 
    232    case SurfaceFormat::R10G10B10A2_UINT32:
    233    case SurfaceFormat::R10G10B10X2_UINT32:
    234      info.bytesPerPixel = 4;
    235      break;
    236 
    237    case SurfaceFormat::R16G16B16A16F:
    238      info.bytesPerPixel = 8;
    239      break;
    240 
    241    case SurfaceFormat::HSV:
    242    case SurfaceFormat::Lab:
    243      info.bytesPerPixel = 3 * sizeof(float);
    244      break;
    245 
    246    case SurfaceFormat::YUV420:
    247    case SurfaceFormat::YUV420P10:
    248    case SurfaceFormat::YUV422P10:
    249    case SurfaceFormat::NV12:
    250    case SurfaceFormat::P016:
    251    case SurfaceFormat::P010:
    252    case SurfaceFormat::NV16:
    253    case SurfaceFormat::YUY2:
    254    case SurfaceFormat::UNKNOWN:
    255      break;  // No bytesPerPixel per se.
    256  }
    257 
    258  // -
    259 
    260  if (aFormat == SurfaceFormat::UNKNOWN) {
    261    return {};
    262  }
    263  return info;
    264 }
    265 
    266 std::ostream& operator<<(std::ostream& aOut, const SurfaceFormat& aFormat);
    267 
    268 // Represents the bit-shifts required to access color channels when the layout
    269 // is viewed as a uint32_t value.
    270 enum class SurfaceFormatBit : uint32_t {
    271 #if MOZ_LITTLE_ENDIAN()
    272  R8G8B8A8_R = 0,
    273  R8G8B8A8_G = 8,
    274  R8G8B8A8_B = 16,
    275  R8G8B8A8_A = 24,
    276 #elif MOZ_BIG_ENDIAN()
    277  R8G8B8A8_A = 0,
    278  R8G8B8A8_B = 8,
    279  R8G8B8A8_G = 16,
    280  R8G8B8A8_R = 24,
    281 #else
    282 #  error "bad endianness"
    283 #endif
    284 
    285  // The following values are endian-independent for A8R8G8B8_UINT32.
    286  A8R8G8B8_UINT32_B = 0,
    287  A8R8G8B8_UINT32_G = 8,
    288  A8R8G8B8_UINT32_R = 16,
    289  A8R8G8B8_UINT32_A = 24,
    290 
    291  // The following values are OS and endian-independent.
    292  //
    293  // TODO(aosmond): When everything blocking bug 1581828 has been resolved, we
    294  // can make this use R8G8B8A8_X for non-Windows platforms.
    295  OS_R = A8R8G8B8_UINT32_R,
    296  OS_G = A8R8G8B8_UINT32_G,
    297  OS_B = A8R8G8B8_UINT32_B,
    298  OS_A = A8R8G8B8_UINT32_A,
    299 };
    300 
    301 inline uint32_t operator<<(uint8_t a, SurfaceFormatBit b) {
    302  return a << static_cast<uint32_t>(b);
    303 }
    304 
    305 inline uint32_t operator>>(uint32_t a, SurfaceFormatBit b) {
    306  return a >> static_cast<uint32_t>(b);
    307 }
    308 
    309 static inline int BytesPerPixel(SurfaceFormat aFormat) {
    310  // TODO: return Info(aFormat).value().bytesPerPixel.value();
    311  switch (aFormat) {
    312    case SurfaceFormat::A8:
    313      return 1;
    314    case SurfaceFormat::R5G6B5_UINT16:
    315    case SurfaceFormat::A16:
    316      return 2;
    317    case SurfaceFormat::R8G8B8:
    318    case SurfaceFormat::B8G8R8:
    319      return 3;
    320    case SurfaceFormat::HSV:
    321    case SurfaceFormat::Lab:
    322      return 3 * sizeof(float);
    323    case SurfaceFormat::Depth:
    324      return sizeof(uint16_t);
    325    case SurfaceFormat::B8G8R8A8:
    326    case SurfaceFormat::B8G8R8X8:
    327    case SurfaceFormat::R8G8B8A8:
    328    case SurfaceFormat::R8G8B8X8:
    329    case SurfaceFormat::A8R8G8B8:
    330    case SurfaceFormat::X8R8G8B8:
    331    case SurfaceFormat::R10G10B10A2_UINT32:
    332    case SurfaceFormat::R10G10B10X2_UINT32:
    333    case SurfaceFormat::R16G16:
    334      return 4;
    335    case SurfaceFormat::R16G16B16A16F:
    336      return 8;
    337    case SurfaceFormat::R8G8:
    338      return 2;
    339    case SurfaceFormat::YUV420:
    340    case SurfaceFormat::YUV420P10:
    341    case SurfaceFormat::YUV422P10:
    342    case SurfaceFormat::NV12:
    343    case SurfaceFormat::NV16:
    344    case SurfaceFormat::YUY2:
    345      // These formats are not easily described in terms of bytes per pixel,
    346      // technically 1.5 bytes per pixel on average, which is guaranteed by the
    347      // width and height being multiples of 2.
    348      return 0;
    349    case SurfaceFormat::P016:
    350    case SurfaceFormat::P010:
    351      // Similar to NV12 but uint16 pixels.
    352      return 0;
    353    case SurfaceFormat::UNKNOWN:
    354      MOZ_ASSERT_UNREACHABLE("unhandled gfx::SurfaceFormat::UNKNOWN");
    355      return 4;
    356  }
    357  MOZ_ASSERT_UNREACHABLE("unhandled enum value for gfx::SurfaceFormat");
    358  return 4;
    359 }
    360 
    361 inline bool IsOpaque(SurfaceFormat aFormat) {
    362  // TODO: return Info(aFormat).value().hasAlpha;
    363  switch (aFormat) {
    364    case SurfaceFormat::B8G8R8X8:
    365    case SurfaceFormat::R8G8B8X8:
    366    case SurfaceFormat::X8R8G8B8:
    367    case SurfaceFormat::R5G6B5_UINT16:
    368    case SurfaceFormat::R10G10B10X2_UINT32:
    369    case SurfaceFormat::R8G8B8:
    370    case SurfaceFormat::B8G8R8:
    371    case SurfaceFormat::R8G8:
    372    case SurfaceFormat::HSV:
    373    case SurfaceFormat::Lab:
    374    case SurfaceFormat::Depth:
    375    case SurfaceFormat::YUV420:
    376    case SurfaceFormat::NV12:
    377    case SurfaceFormat::P010:
    378    case SurfaceFormat::P016:
    379    case SurfaceFormat::YUY2:
    380      return true;
    381    case SurfaceFormat::B8G8R8A8:
    382    case SurfaceFormat::R8G8B8A8:
    383    case SurfaceFormat::A8R8G8B8:
    384    case SurfaceFormat::R10G10B10A2_UINT32:
    385    case SurfaceFormat::R16G16B16A16F:
    386    case SurfaceFormat::A8:
    387    case SurfaceFormat::A16:
    388    case SurfaceFormat::R16G16:
    389    case SurfaceFormat::YUV420P10:
    390    case SurfaceFormat::YUV422P10:
    391    case SurfaceFormat::NV16:
    392    case SurfaceFormat::UNKNOWN:
    393      return false;
    394  }
    395  MOZ_ASSERT_UNREACHABLE("unhandled enum value for gfx::SurfaceFormat");
    396  return false;
    397 }
    398 
    399 // These are standardized Coding-independent Code Points
    400 // See [Rec. ITU-T H.273
    401 // (12/2016)](https://www.itu.int/rec/T-REC-H.273-201612-I/en)
    402 //
    403 // We deliberately use an unscoped enum with fixed uint8_t representation since
    404 // all possible values [0, 255] are legal, but it's unwieldy to declare 200+
    405 // "RESERVED" enumeration values. Having a fixed underlying type avoids any
    406 // potential UB and avoids the need for a cast when passing these values across
    407 // FFI to functions like qcms_profile_create_cicp.
    408 namespace CICP {
    409 enum ColourPrimaries : uint8_t {
    410  CP_RESERVED_MIN = 0,  // 0, 3, [13, 21], [23, 255] are all reserved
    411  CP_BT709 = 1,
    412  CP_UNSPECIFIED = 2,
    413  CP_BT470M = 4,
    414  CP_BT470BG = 5,
    415  CP_BT601 = 6,
    416  CP_SMPTE240 = 7,
    417  CP_GENERIC_FILM = 8,
    418  CP_BT2020 = 9,
    419  CP_XYZ = 10,
    420  CP_SMPTE431 = 11,
    421  CP_SMPTE432 = 12,
    422  CP_EBU3213 = 22,
    423 };
    424 
    425 inline bool IsReserved(ColourPrimaries aIn) {
    426  switch (aIn) {
    427    case CP_BT709:
    428    case CP_UNSPECIFIED:
    429    case CP_BT470M:
    430    case CP_BT470BG:
    431    case CP_BT601:
    432    case CP_SMPTE240:
    433    case CP_GENERIC_FILM:
    434    case CP_BT2020:
    435    case CP_XYZ:
    436    case CP_SMPTE431:
    437    case CP_SMPTE432:
    438    case CP_EBU3213:
    439      return false;
    440    default:
    441      return true;
    442  }
    443 }
    444 
    445 enum TransferCharacteristics : uint8_t {
    446  TC_RESERVED_MIN = 0,  // 0, 3, [19, 255] are all reserved
    447  TC_BT709 = 1,
    448  TC_UNSPECIFIED = 2,
    449  TC_BT470M = 4,
    450  TC_BT470BG = 5,
    451  TC_BT601 = 6,
    452  TC_SMPTE240 = 7,
    453  TC_LINEAR = 8,
    454  TC_LOG_100 = 9,
    455  TC_LOG_100_SQRT10 = 10,
    456  TC_IEC61966 = 11,
    457  TC_BT_1361 = 12,
    458  TC_SRGB = 13,
    459  TC_BT2020_10BIT = 14,
    460  TC_BT2020_12BIT = 15,
    461  TC_SMPTE2084 = 16,
    462  TC_SMPTE428 = 17,
    463  TC_HLG = 18,
    464 };
    465 
    466 inline bool IsReserved(TransferCharacteristics aIn) {
    467  switch (aIn) {
    468    case TC_BT709:
    469    case TC_UNSPECIFIED:
    470    case TC_BT470M:
    471    case TC_BT470BG:
    472    case TC_BT601:
    473    case TC_SMPTE240:
    474    case TC_LINEAR:
    475    case TC_LOG_100:
    476    case TC_LOG_100_SQRT10:
    477    case TC_IEC61966:
    478    case TC_BT_1361:
    479    case TC_SRGB:
    480    case TC_BT2020_10BIT:
    481    case TC_BT2020_12BIT:
    482    case TC_SMPTE2084:
    483    case TC_SMPTE428:
    484    case TC_HLG:
    485      return false;
    486    default:
    487      return true;
    488  }
    489 }
    490 
    491 enum MatrixCoefficients : uint8_t {
    492  MC_IDENTITY = 0,
    493  MC_BT709 = 1,
    494  MC_UNSPECIFIED = 2,
    495  MC_RESERVED_MIN = 3,  // 3, [15, 255] are all reserved
    496  MC_FCC = 4,
    497  MC_BT470BG = 5,
    498  MC_BT601 = 6,
    499  MC_SMPTE240 = 7,
    500  MC_YCGCO = 8,
    501  MC_BT2020_NCL = 9,
    502  MC_BT2020_CL = 10,
    503  MC_SMPTE2085 = 11,
    504  MC_CHROMAT_NCL = 12,
    505  MC_CHROMAT_CL = 13,
    506  MC_ICTCP = 14,
    507 };
    508 
    509 inline bool IsReserved(MatrixCoefficients aIn) {
    510  switch (aIn) {
    511    case MC_IDENTITY:
    512    case MC_BT709:
    513    case MC_UNSPECIFIED:
    514    case MC_RESERVED_MIN:
    515    case MC_FCC:
    516    case MC_BT470BG:
    517    case MC_BT601:
    518    case MC_SMPTE240:
    519    case MC_YCGCO:
    520    case MC_BT2020_NCL:
    521    case MC_BT2020_CL:
    522    case MC_SMPTE2085:
    523    case MC_CHROMAT_NCL:
    524    case MC_CHROMAT_CL:
    525    case MC_ICTCP:
    526      return false;
    527    default:
    528      return true;
    529  }
    530 }
    531 }  // namespace CICP
    532 
    533 // The matrix coeffiecients used for YUV to RGB conversion.
    534 enum class YUVColorSpace : uint8_t {
    535  BT601,
    536  BT709,
    537  BT2020,
    538  Identity,  // Todo: s/YUVColorSpace/ColorSpace/, s/Identity/SRGB/
    539  Default = BT709,
    540  _First = BT601,
    541  _Last = Identity,
    542 };
    543 
    544 enum class ColorDepth : uint8_t {
    545  COLOR_8,
    546  COLOR_10,
    547  COLOR_12,
    548  COLOR_16,
    549  _First = COLOR_8,
    550  _Last = COLOR_16,
    551 };
    552 
    553 std::ostream& operator<<(std::ostream& aOut, const ColorDepth& aColorDepth);
    554 
    555 enum class TransferFunction : uint8_t {
    556  BT709,
    557  SRGB,
    558  PQ,
    559  HLG,
    560  _First = BT709,
    561  _Last = HLG,
    562  Default = BT709,
    563 };
    564 
    565 enum class ColorRange : uint8_t {
    566  LIMITED,
    567  FULL,
    568  _First = LIMITED,
    569  _Last = FULL,
    570 };
    571 
    572 // Really "YcbcrColorColorSpace"
    573 enum class YUVRangedColorSpace : uint8_t {
    574  BT601_Narrow = 0,
    575  BT601_Full,
    576  BT709_Narrow,
    577  BT709_Full,
    578  BT2020_Narrow,
    579  BT2020_Full,
    580  GbrIdentity,
    581 
    582  _First = BT601_Narrow,
    583  _Last = GbrIdentity,
    584  Default = BT709_Narrow,
    585 };
    586 
    587 // I can either come up with a longer "very clever" name that doesn't conflict
    588 // with FilterSupport.h, embrace and expand FilterSupport, or rename the old
    589 // one.
    590 // Some times Worse Is Better.
    591 enum class ColorSpace2 : uint8_t {
    592  Display,
    593  UNKNOWN = Display,  // We feel sufficiently bad about this TODO.
    594  SRGB,
    595  DISPLAY_P3,
    596  BT601_525,  // aka smpte170m NTSC
    597  BT709,      // Same gamut as SRGB, but different gamma.
    598  BT601_625 =
    599      BT709,  // aka bt470bg PAL. Basically BT709, just Xg is 0.290 not 0.300.
    600  BT2020,
    601  _First = Display,
    602  _Last = BT2020,
    603 };
    604 
    605 inline ColorSpace2 ToColorSpace2(const YUVColorSpace in) {
    606  switch (in) {
    607    case YUVColorSpace::BT601:
    608      return ColorSpace2::BT601_525;
    609    case YUVColorSpace::BT709:
    610      return ColorSpace2::BT709;
    611    case YUVColorSpace::BT2020:
    612      return ColorSpace2::BT2020;
    613    case YUVColorSpace::Identity:
    614      return ColorSpace2::SRGB;
    615  }
    616  MOZ_ASSERT_UNREACHABLE();
    617 }
    618 
    619 inline YUVColorSpace ToYUVColorSpace(const ColorSpace2 in) {
    620  switch (in) {
    621    case ColorSpace2::BT601_525:
    622      return YUVColorSpace::BT601;
    623    case ColorSpace2::BT709:
    624      return YUVColorSpace::BT709;
    625    case ColorSpace2::BT2020:
    626      return YUVColorSpace::BT2020;
    627    case ColorSpace2::SRGB:
    628      return YUVColorSpace::Identity;
    629 
    630    case ColorSpace2::UNKNOWN:
    631    case ColorSpace2::DISPLAY_P3:
    632      MOZ_CRASH("Bad ColorSpace2 for ToYUVColorSpace");
    633  }
    634  MOZ_ASSERT_UNREACHABLE();
    635 }
    636 
    637 struct FromYUVRangedColorSpaceT final {
    638  const YUVColorSpace space;
    639  const ColorRange range;
    640 };
    641 
    642 inline FromYUVRangedColorSpaceT FromYUVRangedColorSpace(
    643    const YUVRangedColorSpace s) {
    644  switch (s) {
    645    case YUVRangedColorSpace::BT601_Narrow:
    646      return {YUVColorSpace::BT601, ColorRange::LIMITED};
    647    case YUVRangedColorSpace::BT601_Full:
    648      return {YUVColorSpace::BT601, ColorRange::FULL};
    649 
    650    case YUVRangedColorSpace::BT709_Narrow:
    651      return {YUVColorSpace::BT709, ColorRange::LIMITED};
    652    case YUVRangedColorSpace::BT709_Full:
    653      return {YUVColorSpace::BT709, ColorRange::FULL};
    654 
    655    case YUVRangedColorSpace::BT2020_Narrow:
    656      return {YUVColorSpace::BT2020, ColorRange::LIMITED};
    657    case YUVRangedColorSpace::BT2020_Full:
    658      return {YUVColorSpace::BT2020, ColorRange::FULL};
    659 
    660    case YUVRangedColorSpace::GbrIdentity:
    661      return {YUVColorSpace::Identity, ColorRange::FULL};
    662  }
    663  MOZ_CRASH("bad YUVRangedColorSpace");
    664 }
    665 
    666 // Todo: This should go in the CPP.
    667 inline YUVRangedColorSpace ToYUVRangedColorSpace(const YUVColorSpace space,
    668                                                 const ColorRange range) {
    669  bool narrow;
    670  switch (range) {
    671    case ColorRange::FULL:
    672      narrow = false;
    673      break;
    674    case ColorRange::LIMITED:
    675      narrow = true;
    676      break;
    677  }
    678 
    679  switch (space) {
    680    case YUVColorSpace::Identity:
    681      MOZ_ASSERT(range == ColorRange::FULL);
    682      return YUVRangedColorSpace::GbrIdentity;
    683 
    684    case YUVColorSpace::BT601:
    685      return narrow ? YUVRangedColorSpace::BT601_Narrow
    686                    : YUVRangedColorSpace::BT601_Full;
    687 
    688    case YUVColorSpace::BT709:
    689      return narrow ? YUVRangedColorSpace::BT709_Narrow
    690                    : YUVRangedColorSpace::BT709_Full;
    691 
    692    case YUVColorSpace::BT2020:
    693      return narrow ? YUVRangedColorSpace::BT2020_Narrow
    694                    : YUVRangedColorSpace::BT2020_Full;
    695  }
    696  MOZ_CRASH("bad YUVColorSpace");
    697 }
    698 
    699 template <typename DescriptorT>
    700 inline YUVRangedColorSpace GetYUVRangedColorSpace(const DescriptorT& d) {
    701  return ToYUVRangedColorSpace(d.yUVColorSpace(), d.colorRange());
    702 }
    703 
    704 static inline SurfaceFormat SurfaceFormatForColorDepth(ColorDepth aColorDepth) {
    705  SurfaceFormat format = SurfaceFormat::A8;
    706  switch (aColorDepth) {
    707    case ColorDepth::COLOR_8:
    708      break;
    709    case ColorDepth::COLOR_10:
    710    case ColorDepth::COLOR_12:
    711    case ColorDepth::COLOR_16:
    712      format = SurfaceFormat::A16;
    713      break;
    714  }
    715  return format;
    716 }
    717 
    718 static inline uint8_t BitDepthForColorDepth(ColorDepth aColorDepth) {
    719  uint8_t depth = 8;
    720  switch (aColorDepth) {
    721    case ColorDepth::COLOR_8:
    722      break;
    723    case ColorDepth::COLOR_10:
    724      depth = 10;
    725      break;
    726    case ColorDepth::COLOR_12:
    727      depth = 12;
    728      break;
    729    case ColorDepth::COLOR_16:
    730      depth = 16;
    731      break;
    732  }
    733  return depth;
    734 }
    735 
    736 static inline ColorDepth ColorDepthForBitDepth(uint8_t aBitDepth) {
    737  ColorDepth depth = ColorDepth::COLOR_8;
    738  switch (aBitDepth) {
    739    case 8:
    740      break;
    741    case 10:
    742      depth = ColorDepth::COLOR_10;
    743      break;
    744    case 12:
    745      depth = ColorDepth::COLOR_12;
    746      break;
    747    case 16:
    748      depth = ColorDepth::COLOR_16;
    749      break;
    750  }
    751  return depth;
    752 }
    753 
    754 // 10 and 12 bits color depth image are using 16 bits integers for storage
    755 // As such we need to rescale the value from 10 or 12 bits to 16.
    756 static inline uint32_t RescalingFactorForColorDepth(ColorDepth aColorDepth) {
    757  uint32_t factor = 1;
    758  switch (aColorDepth) {
    759    case ColorDepth::COLOR_8:
    760      break;
    761    case ColorDepth::COLOR_10:
    762      factor = 64;
    763      break;
    764    case ColorDepth::COLOR_12:
    765      factor = 16;
    766      break;
    767    case ColorDepth::COLOR_16:
    768      break;
    769  }
    770  return factor;
    771 }
    772 
    773 static inline bool IsHDRTransferFunction(
    774    gfx::TransferFunction aTransferFunction) {
    775  switch (aTransferFunction) {
    776    case gfx::TransferFunction::PQ:
    777    case gfx::TransferFunction::HLG:
    778      return true;
    779    case gfx::TransferFunction::BT709:
    780    case gfx::TransferFunction::SRGB:
    781      return false;
    782  }
    783  MOZ_CRASH("bad TransferFunction");
    784 }
    785 
    786 enum class ChromaSubsampling : uint8_t {
    787  FULL,
    788  HALF_WIDTH,
    789  HALF_WIDTH_AND_HEIGHT,
    790  _First = FULL,
    791  _Last = HALF_WIDTH_AND_HEIGHT,
    792 };
    793 
    794 template <typename T>
    795 static inline T ChromaSize(const T& aYSize, ChromaSubsampling aSubsampling) {
    796  switch (aSubsampling) {
    797    case ChromaSubsampling::FULL:
    798      return aYSize;
    799    case ChromaSubsampling::HALF_WIDTH:
    800      return T((aYSize.width + 1) / 2, aYSize.height);
    801    case ChromaSubsampling::HALF_WIDTH_AND_HEIGHT:
    802      return T((aYSize.width + 1) / 2, (aYSize.height + 1) / 2);
    803  }
    804  MOZ_CRASH("bad ChromaSubsampling");
    805 }
    806 
    807 enum class FilterType : int8_t {
    808  BLEND = 0,
    809  TRANSFORM,
    810  MORPHOLOGY,
    811  COLOR_MATRIX,
    812  FLOOD,
    813  TILE,
    814  TABLE_TRANSFER,
    815  DISCRETE_TRANSFER,
    816  LINEAR_TRANSFER,
    817  GAMMA_TRANSFER,
    818  CONVOLVE_MATRIX,
    819  DISPLACEMENT_MAP,
    820  TURBULENCE,
    821  ARITHMETIC_COMBINE,
    822  COMPOSITE,
    823  DIRECTIONAL_BLUR,
    824  GAUSSIAN_BLUR,
    825  POINT_DIFFUSE,
    826  POINT_SPECULAR,
    827  SPOT_DIFFUSE,
    828  SPOT_SPECULAR,
    829  DISTANT_DIFFUSE,
    830  DISTANT_SPECULAR,
    831  CROP,
    832  PREMULTIPLY,
    833  UNPREMULTIPLY,
    834  OPACITY
    835 };
    836 
    837 enum class DrawTargetType : int8_t {
    838  SOFTWARE_RASTER = 0,
    839  HARDWARE_RASTER,
    840  VECTOR
    841 };
    842 
    843 enum class BackendType : int8_t {
    844  NONE = 0,
    845  CAIRO,
    846  SKIA,
    847  RECORDING,
    848  WEBRENDER_TEXT,
    849  WEBGL,
    850 
    851  // Add new entries above this line.
    852  BACKEND_LAST
    853 };
    854 
    855 enum class RecorderType : int8_t {
    856  UNKNOWN,
    857  PRIVATE,
    858  MEMORY,
    859  CANVAS,
    860  PRFILEDESC,
    861  WEBRENDER
    862 };
    863 
    864 enum class FontType : int8_t {
    865  DWRITE,
    866  GDI,
    867  MAC,
    868  FONTCONFIG,
    869  FREETYPE,
    870  UNKNOWN
    871 };
    872 
    873 enum class NativeSurfaceType : int8_t {
    874  D3D10_TEXTURE,
    875  CAIRO_CONTEXT,
    876  CGCONTEXT,
    877  CGCONTEXT_ACCELERATED,
    878  OPENGL_TEXTURE,
    879  WEBGL_CONTEXT
    880 };
    881 
    882 enum class FontStyle : int8_t { NORMAL, ITALIC, BOLD, BOLD_ITALIC };
    883 
    884 enum class FontHinting : int8_t { NONE, LIGHT, NORMAL, FULL };
    885 
    886 enum class CompositionOp : int8_t {
    887  OP_CLEAR,
    888  OP_OVER,
    889  OP_ADD,
    890  OP_ATOP,
    891  OP_OUT,
    892  OP_IN,
    893  OP_SOURCE,
    894  OP_DEST_IN,
    895  OP_DEST_OUT,
    896  OP_DEST_OVER,
    897  OP_DEST_ATOP,
    898  OP_XOR,
    899  OP_MULTIPLY,
    900  OP_SCREEN,
    901  OP_OVERLAY,
    902  OP_DARKEN,
    903  OP_LIGHTEN,
    904  OP_COLOR_DODGE,
    905  OP_COLOR_BURN,
    906  OP_HARD_LIGHT,
    907  OP_SOFT_LIGHT,
    908  OP_DIFFERENCE,
    909  OP_EXCLUSION,
    910  OP_HUE,
    911  OP_SATURATION,
    912  OP_COLOR,
    913  OP_LUMINOSITY,
    914  OP_COUNT
    915 };
    916 
    917 enum class Axis : int8_t { X_AXIS, Y_AXIS, BOTH };
    918 
    919 enum class ExtendMode : int8_t {
    920  CLAMP,     // Do not repeat
    921  REPEAT,    // Repeat in both axis
    922  REPEAT_X,  // Only X axis
    923  REPEAT_Y,  // Only Y axis
    924  REFLECT    // Mirror the image
    925 };
    926 
    927 enum class FillRule : int8_t { FILL_WINDING, FILL_EVEN_ODD };
    928 
    929 enum class AntialiasMode : int8_t { NONE, GRAY, SUBPIXEL, DEFAULT };
    930 
    931 // See https://en.wikipedia.org/wiki/Texture_filtering
    932 enum class SamplingFilter : int8_t {
    933  GOOD,
    934  LINEAR,
    935  POINT,
    936  SENTINEL  // one past the last valid value
    937 };
    938 
    939 std::ostream& operator<<(std::ostream& aOut, const SamplingFilter& aFilter);
    940 
    941 // clang-format off
    942 MOZ_DEFINE_ENUM_CLASS_WITH_BASE(PatternType, int8_t, (
    943  COLOR,
    944  SURFACE,
    945  LINEAR_GRADIENT,
    946  RADIAL_GRADIENT,
    947  CONIC_GRADIENT
    948 ));
    949 // clang-format on
    950 
    951 enum class JoinStyle : int8_t {
    952  BEVEL,
    953  ROUND,
    954  MITER,  //!< Mitered if within the miter limit, else, if the backend supports
    955          //!< it, the miter is clamped. If the backend does not support miter
    956          //!< clamping the behavior is as for MITER_OR_BEVEL.
    957  MITER_OR_BEVEL  //!< Mitered if within the miter limit, else beveled.
    958 };
    959 
    960 enum class CapStyle : int8_t { BUTT, ROUND, SQUARE };
    961 
    962 enum class SamplingBounds : int8_t { UNBOUNDED, BOUNDED };
    963 
    964 // Moz2d version for SVG mask types
    965 enum class LuminanceType : int8_t {
    966  LUMINANCE,
    967  LINEARRGB,
    968 };
    969 
    970 /* Color is stored in non-premultiplied form in sRGB color space */
    971 struct sRGBColor {
    972 public:
    973  constexpr sRGBColor() : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {}
    974  constexpr sRGBColor(Float aR, Float aG, Float aB, Float aA)
    975      : r(aR), g(aG), b(aB), a(aA) {}
    976  constexpr sRGBColor(Float aR, Float aG, Float aB)
    977      : r(aR), g(aG), b(aB), a(1.0f) {}
    978 
    979  static constexpr sRGBColor White(float aA) {
    980    return sRGBColor(1.f, 1.f, 1.f, aA);
    981  }
    982 
    983  static constexpr sRGBColor Black(float aA) {
    984    return sRGBColor(0.f, 0.f, 0.f, aA);
    985  }
    986 
    987  static constexpr sRGBColor OpaqueWhite() { return White(1.f); }
    988 
    989  static constexpr sRGBColor OpaqueBlack() { return Black(1.f); }
    990 
    991  static constexpr sRGBColor FromU8(uint8_t aR, uint8_t aG, uint8_t aB,
    992                                    uint8_t aA) {
    993    return sRGBColor(float(aR) / 255.f, float(aG) / 255.f, float(aB) / 255.f,
    994                     float(aA) / 255.f);
    995  }
    996 
    997  static constexpr sRGBColor FromABGR(uint32_t aColor) {
    998    return sRGBColor(((aColor >> 0) & 0xff) * (1.0f / 255.0f),
    999                     ((aColor >> 8) & 0xff) * (1.0f / 255.0f),
   1000                     ((aColor >> 16) & 0xff) * (1.0f / 255.0f),
   1001                     ((aColor >> 24) & 0xff) * (1.0f / 255.0f));
   1002  }
   1003 
   1004  // The "Unusual" prefix is to avoid unintentionally using this function when
   1005  // FromABGR(), which is much more common, is needed.
   1006  static constexpr sRGBColor UnusualFromARGB(uint32_t aColor) {
   1007    return sRGBColor(((aColor >> 16) & 0xff) * (1.0f / 255.0f),
   1008                     ((aColor >> 8) & 0xff) * (1.0f / 255.0f),
   1009                     ((aColor >> 0) & 0xff) * (1.0f / 255.0f),
   1010                     ((aColor >> 24) & 0xff) * (1.0f / 255.0f));
   1011  }
   1012 
   1013  constexpr uint32_t ToABGR() const {
   1014    return uint32_t(r * 255.0f) | uint32_t(g * 255.0f) << 8 |
   1015           uint32_t(b * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
   1016  }
   1017 
   1018  constexpr sRGBColor Premultiplied() const {
   1019    return sRGBColor(r * a, g * a, b * a, a);
   1020  }
   1021 
   1022  constexpr sRGBColor Unpremultiplied() const {
   1023    return a > 0.f ? sRGBColor(r / a, g / a, b / a, a) : *this;
   1024  }
   1025 
   1026  // The "Unusual" prefix is to avoid unintentionally using this function when
   1027  // ToABGR(), which is much more common, is needed.
   1028  uint32_t UnusualToARGB() const {
   1029    return uint32_t(b * 255.0f) | uint32_t(g * 255.0f) << 8 |
   1030           uint32_t(r * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
   1031  }
   1032 
   1033  bool operator==(const sRGBColor& aColor) const {
   1034    return r == aColor.r && g == aColor.g && b == aColor.b && a == aColor.a;
   1035  }
   1036 
   1037  bool operator!=(const sRGBColor& aColor) const { return !(*this == aColor); }
   1038 
   1039  Float r, g, b, a;
   1040 };
   1041 
   1042 /* Color is stored in non-premultiplied form in device color space */
   1043 struct DeviceColor {
   1044 public:
   1045  constexpr DeviceColor() : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {}
   1046  constexpr DeviceColor(Float aR, Float aG, Float aB, Float aA)
   1047      : r(aR), g(aG), b(aB), a(aA) {}
   1048  constexpr DeviceColor(Float aR, Float aG, Float aB)
   1049      : r(aR), g(aG), b(aB), a(1.0f) {}
   1050 
   1051  /* The following Mask* variants are helpers used to make it clear when a
   1052   * particular color is being used for masking purposes. These masks should
   1053   * never be colored managed. */
   1054  static DeviceColor Mask(float aC, float aA) {
   1055    return DeviceColor(aC, aC, aC, aA);
   1056  }
   1057 
   1058  static DeviceColor MaskWhite(float aA) { return Mask(1.f, aA); }
   1059 
   1060  static DeviceColor MaskBlack(float aA) { return Mask(0.f, aA); }
   1061 
   1062  static DeviceColor MaskOpaqueWhite() { return MaskWhite(1.f); }
   1063 
   1064  static DeviceColor MaskOpaqueBlack() { return MaskBlack(1.f); }
   1065 
   1066  static DeviceColor FromU8(uint8_t aR, uint8_t aG, uint8_t aB, uint8_t aA) {
   1067    return DeviceColor(float(aR) / 255.f, float(aG) / 255.f, float(aB) / 255.f,
   1068                       float(aA) / 255.f);
   1069  }
   1070 
   1071  static DeviceColor FromABGR(uint32_t aColor) {
   1072    DeviceColor newColor(((aColor >> 0) & 0xff) * (1.0f / 255.0f),
   1073                         ((aColor >> 8) & 0xff) * (1.0f / 255.0f),
   1074                         ((aColor >> 16) & 0xff) * (1.0f / 255.0f),
   1075                         ((aColor >> 24) & 0xff) * (1.0f / 255.0f));
   1076 
   1077    return newColor;
   1078  }
   1079 
   1080  // The "Unusual" prefix is to avoid unintentionally using this function when
   1081  // FromABGR(), which is much more common, is needed.
   1082  static DeviceColor UnusualFromARGB(uint32_t aColor) {
   1083    DeviceColor newColor(((aColor >> 16) & 0xff) * (1.0f / 255.0f),
   1084                         ((aColor >> 8) & 0xff) * (1.0f / 255.0f),
   1085                         ((aColor >> 0) & 0xff) * (1.0f / 255.0f),
   1086                         ((aColor >> 24) & 0xff) * (1.0f / 255.0f));
   1087 
   1088    return newColor;
   1089  }
   1090 
   1091  uint32_t ToABGR() const {
   1092    return uint32_t(r * 255.0f) | uint32_t(g * 255.0f) << 8 |
   1093           uint32_t(b * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
   1094  }
   1095 
   1096  // The "Unusual" prefix is to avoid unintentionally using this function when
   1097  // ToABGR(), which is much more common, is needed.
   1098  uint32_t UnusualToARGB() const {
   1099    return uint32_t(b * 255.0f) | uint32_t(g * 255.0f) << 8 |
   1100           uint32_t(r * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
   1101  }
   1102 
   1103  bool operator==(const DeviceColor& aColor) const {
   1104    return r == aColor.r && g == aColor.g && b == aColor.b && a == aColor.a;
   1105  }
   1106 
   1107  bool operator!=(const DeviceColor& aColor) const {
   1108    return !(*this == aColor);
   1109  }
   1110 
   1111  friend std::ostream& operator<<(std::ostream& aOut,
   1112                                  const DeviceColor& aColor);
   1113 
   1114  Float r, g, b, a;
   1115 };
   1116 
   1117 struct GradientStop {
   1118  bool operator<(const GradientStop& aOther) const {
   1119    return offset < aOther.offset;
   1120  }
   1121 
   1122  Float offset;
   1123  DeviceColor color;
   1124 };
   1125 
   1126 enum class JobStatus { Complete, Wait, Yield, Error };
   1127 
   1128 enum class DeviceResetReason {
   1129  OK = 0,        // No reset.
   1130  HUNG,          // Windows specific, guilty device reset.
   1131  REMOVED,       // Windows specific, device removed or driver upgraded.
   1132  RESET,         // Guilty device reset.
   1133  DRIVER_ERROR,  // Innocent device reset.
   1134  INVALID_CALL,  // Windows specific, guilty device reset.
   1135  OUT_OF_MEMORY,
   1136  FORCED_RESET,  // Simulated device reset.
   1137  OTHER,         // Unrecognized reason for device reset.
   1138  NVIDIA_VIDEO,  // Linux specific, NVIDIA video memory was reset.
   1139  UNKNOWN,       // GL specific, unknown if guilty or innocent.
   1140  _First = OK,
   1141  _Last = UNKNOWN,
   1142 };
   1143 
   1144 enum class DeviceResetDetectPlace {
   1145  WR_BEGIN_FRAME = 0,
   1146  WR_WAIT_FOR_GPU,
   1147  WR_POST_UPDATE,
   1148  WR_SYNC_OBJRCT,
   1149  WR_SIMULATE,
   1150  WIDGET,
   1151  CANVAS_TRANSLATOR,
   1152  _First = WR_BEGIN_FRAME,
   1153  _Last = CANVAS_TRANSLATOR,
   1154 };
   1155 
   1156 enum class ForcedDeviceResetReason {
   1157  OPENSHAREDHANDLE = 0,
   1158  COMPOSITOR_UPDATED,
   1159 };
   1160 
   1161 }  // namespace gfx
   1162 }  // namespace mozilla
   1163 
   1164 // XXX: temporary
   1165 typedef mozilla::gfx::SurfaceFormat gfxImageFormat;
   1166 
   1167 #if defined(XP_WIN) && defined(MOZ_GFX)
   1168 #  ifdef GFX2D_INTERNAL
   1169 #    define GFX2D_API __declspec(dllexport)
   1170 #  else
   1171 #    define GFX2D_API __declspec(dllimport)
   1172 #  endif
   1173 #else
   1174 #  define GFX2D_API
   1175 #endif
   1176 
   1177 namespace mozilla {
   1178 
   1179 // Side constants for use in various places.
   1180 enum Side : uint8_t { eSideTop, eSideRight, eSideBottom, eSideLeft };
   1181 
   1182 std::ostream& operator<<(std::ostream&, const mozilla::Side&);
   1183 
   1184 constexpr auto AllPhysicalSides() {
   1185  return mozilla::MakeInclusiveEnumeratedRange(eSideTop, eSideLeft);
   1186 }
   1187 
   1188 enum class SideBits {
   1189  eNone = 0,
   1190  eTop = 1 << eSideTop,
   1191  eRight = 1 << eSideRight,
   1192  eBottom = 1 << eSideBottom,
   1193  eLeft = 1 << eSideLeft,
   1194  eTopBottom = SideBits::eTop | SideBits::eBottom,
   1195  eLeftRight = SideBits::eLeft | SideBits::eRight,
   1196  eAll = SideBits::eTopBottom | SideBits::eLeftRight
   1197 };
   1198 
   1199 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SideBits)
   1200 
   1201 inline constexpr SideBits SideToSideBit(mozilla::Side aSide) {
   1202  return SideBits(1 << aSide);
   1203 }
   1204 
   1205 enum Corner : uint8_t {
   1206  // This order is important!
   1207  eCornerTopLeft = 0,
   1208  eCornerTopRight = 1,
   1209  eCornerBottomRight = 2,
   1210  eCornerBottomLeft = 3
   1211 };
   1212 
   1213 // RectCornerRadii::radii depends on this value. It is not being added to
   1214 // Corner because we want to lift the responsibility to handle it in the
   1215 // switch-case.
   1216 constexpr int eCornerCount = 4;
   1217 
   1218 constexpr auto AllPhysicalCorners() {
   1219  return mozilla::MakeInclusiveEnumeratedRange(eCornerTopLeft,
   1220                                               eCornerBottomLeft);
   1221 }
   1222 
   1223 // Indices into "half corner" arrays (nsStyleCorners e.g.)
   1224 enum HalfCorner : uint8_t {
   1225  // This order is important!
   1226  eCornerTopLeftX = 0,
   1227  eCornerTopLeftY = 1,
   1228  eCornerTopRightX = 2,
   1229  eCornerTopRightY = 3,
   1230  eCornerBottomRightX = 4,
   1231  eCornerBottomRightY = 5,
   1232  eCornerBottomLeftX = 6,
   1233  eCornerBottomLeftY = 7
   1234 };
   1235 
   1236 constexpr auto AllPhysicalHalfCorners() {
   1237  return mozilla::MakeInclusiveEnumeratedRange(eCornerTopLeftX,
   1238                                               eCornerBottomLeftY);
   1239 }
   1240 
   1241 // The result of these conversion functions are exhaustively checked in
   1242 // nsFrame.cpp, which also serves as usage examples.
   1243 
   1244 constexpr bool HalfCornerIsX(HalfCorner aHalfCorner) {
   1245  return !(aHalfCorner % 2);
   1246 }
   1247 
   1248 constexpr Corner HalfToFullCorner(HalfCorner aHalfCorner) {
   1249  return Corner(aHalfCorner / 2);
   1250 }
   1251 
   1252 constexpr HalfCorner FullToHalfCorner(Corner aCorner, bool aIsVertical) {
   1253  return HalfCorner(aCorner * 2 + aIsVertical);
   1254 }
   1255 
   1256 constexpr bool SideIsVertical(mozilla::Side aSide) { return aSide % 2; }
   1257 
   1258 // @param aIsSecond when true, return the clockwise second of the two
   1259 // corners associated with aSide. For example, with aSide = eSideBottom the
   1260 // result is eCornerBottomRight when aIsSecond is false, and
   1261 // eCornerBottomLeft when aIsSecond is true.
   1262 constexpr Corner SideToFullCorner(mozilla::Side aSide, bool aIsSecond) {
   1263  return Corner((aSide + aIsSecond) % 4);
   1264 }
   1265 
   1266 // @param aIsSecond see SideToFullCorner.
   1267 // @param aIsParallel return the half-corner that is parallel with aSide
   1268 // when aIsParallel is true. For example with aSide=eSideTop, aIsSecond=true
   1269 // the result is eCornerTopRightX when aIsParallel is true, and
   1270 // eCornerTopRightY when aIsParallel is false (because "X" is parallel with
   1271 // eSideTop/eSideBottom, similarly "Y" is parallel with
   1272 // eSideLeft/eSideRight)
   1273 constexpr HalfCorner SideToHalfCorner(mozilla::Side aSide, bool aIsSecond,
   1274                                      bool aIsParallel) {
   1275  return HalfCorner(((aSide + aIsSecond) * 2 + (aSide + !aIsParallel) % 2) % 8);
   1276 }
   1277 
   1278 }  // namespace mozilla
   1279 
   1280 #endif /* MOZILLA_GFX_TYPES_H_ */