summaryrefslogtreecommitdiffstats
path: root/gfx/2d/Types.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /gfx/2d/Types.h
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/2d/Types.h')
-rw-r--r--gfx/2d/Types.h1135
1 files changed, 1135 insertions, 0 deletions
diff --git a/gfx/2d/Types.h b/gfx/2d/Types.h
new file mode 100644
index 0000000000..e6f73eac3a
--- /dev/null
+++ b/gfx/2d/Types.h
@@ -0,0 +1,1135 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_GFX_TYPES_H_
+#define MOZILLA_GFX_TYPES_H_
+
+#include "mozilla/DefineEnum.h" // for MOZ_DEFINE_ENUM_CLASS_WITH_BASE
+#include "mozilla/EndianUtils.h"
+#include "mozilla/EnumeratedRange.h"
+#include "mozilla/MacroArgs.h" // for MOZ_CONCAT
+#include "mozilla/TypedEnumBits.h"
+
+#include <iosfwd> // for ostream
+#include <stddef.h>
+#include <stdint.h>
+#include <optional>
+
+namespace mozilla {
+namespace gfx {
+
+typedef float Float;
+typedef double Double;
+
+enum class SurfaceType : int8_t {
+ DATA, /* Data surface - bitmap in memory */
+ D2D1_BITMAP, /* Surface wrapping a ID2D1Bitmap */
+ D2D1_DRAWTARGET, /* Surface made from a D2D draw target */
+ CAIRO, /* Surface wrapping a cairo surface */
+ CAIRO_IMAGE, /* Data surface wrapping a cairo image surface */
+ COREGRAPHICS_IMAGE, /* Surface wrapping a CoreGraphics Image */
+ COREGRAPHICS_CGCONTEXT, /* Surface wrapping a CG context */
+ SKIA, /* Surface wrapping a Skia bitmap */
+ D2D1_1_IMAGE, /* A D2D 1.1 ID2D1Image SourceSurface */
+ RECORDING, /* Surface used for recording */
+ DATA_SHARED, /* Data surface using shared memory */
+ DATA_RECYCLING_SHARED, /* Data surface using shared memory */
+ OFFSET, /* Offset */
+ DATA_ALIGNED, /* Data surface using aligned heap memory */
+ DATA_SHARED_WRAPPER, /* Shared memory mapped in from another process */
+ BLOB_IMAGE, /* Recorded blob image */
+ DATA_MAPPED, /* Data surface wrapping a ScopedMap */
+ WEBGL, /* Surface wrapping a DrawTargetWebgl texture */
+};
+
+enum class SurfaceFormat : int8_t {
+ // The following values are named to reflect layout of colors in memory, from
+ // lowest byte to highest byte. The 32-bit value layout depends on machine
+ // endianness.
+ // in-memory 32-bit LE value 32-bit BE value
+ B8G8R8A8, // [BB, GG, RR, AA] 0xAARRGGBB 0xBBGGRRAA
+ B8G8R8X8, // [BB, GG, RR, 00] 0x00RRGGBB 0xBBGGRR00
+ R8G8B8A8, // [RR, GG, BB, AA] 0xAABBGGRR 0xRRGGBBAA
+ R8G8B8X8, // [RR, GG, BB, 00] 0x00BBGGRR 0xRRGGBB00
+ A8R8G8B8, // [AA, RR, GG, BB] 0xBBGGRRAA 0xAARRGGBB
+ X8R8G8B8, // [00, RR, GG, BB] 0xBBGGRR00 0x00RRGGBB
+
+ R8G8B8,
+ B8G8R8,
+
+ // The _UINT16 suffix here indicates that the name reflects the layout when
+ // viewed as a uint16_t value. In memory these values are stored using native
+ // endianness.
+ R5G6B5_UINT16, // 0bRRRRRGGGGGGBBBBB
+
+ // This one is a single-byte, so endianness isn't an issue.
+ A8,
+ A16,
+
+ R8G8,
+ R16G16,
+
+ // These ones are their own special cases.
+ YUV,
+ NV12, // YUV 4:2:0 image with a plane of 8 bit Y samples followed by
+ // an interleaved U/V plane containing 8 bit 2x2 subsampled
+ // colour difference samples.
+ P016, // Similar to NV12, but with 16 bits plane values
+ P010, // Identical to P016 but the 6 least significant bits are 0.
+ // With DXGI in theory entirely compatible, however practice has
+ // shown that it's not the case.
+ YUV422, // Single plane YUV 4:2:2 interleaved as Y`0 Cb Y`1 Cr.
+ HSV,
+ Lab,
+ Depth,
+
+ // This represents the unknown format.
+ UNKNOWN, // TODO: Replace uses with Maybe<SurfaceFormat>.
+
+// The following values are endian-independent synonyms. The _UINT32 suffix
+// indicates that the name reflects the layout when viewed as a uint32_t
+// value.
+#if MOZ_LITTLE_ENDIAN()
+ A8R8G8B8_UINT32 = B8G8R8A8, // 0xAARRGGBB
+ X8R8G8B8_UINT32 = B8G8R8X8, // 0x00RRGGBB
+#elif MOZ_BIG_ENDIAN()
+ A8R8G8B8_UINT32 = A8R8G8B8, // 0xAARRGGBB
+ X8R8G8B8_UINT32 = X8R8G8B8, // 0x00RRGGBB
+#else
+# error "bad endianness"
+#endif
+
+ // The following values are OS and endian-independent synonyms.
+ //
+ // TODO(aosmond): When everything blocking bug 1581828 has been resolved, we
+ // can make this use R8B8G8A8 and R8B8G8X8 for non-Windows platforms.
+ OS_RGBA = A8R8G8B8_UINT32,
+ OS_RGBX = X8R8G8B8_UINT32
+};
+
+struct SurfaceFormatInfo {
+ bool hasColor;
+ bool hasAlpha;
+ bool isYuv;
+ std::optional<uint8_t> bytesPerPixel;
+};
+inline std::optional<SurfaceFormatInfo> Info(const SurfaceFormat aFormat) {
+ auto info = SurfaceFormatInfo{};
+
+ switch (aFormat) {
+ case SurfaceFormat::B8G8R8A8:
+ case SurfaceFormat::R8G8B8A8:
+ case SurfaceFormat::A8R8G8B8:
+ info.hasColor = true;
+ info.hasAlpha = true;
+ break;
+
+ case SurfaceFormat::B8G8R8X8:
+ case SurfaceFormat::R8G8B8X8:
+ case SurfaceFormat::X8R8G8B8:
+ case SurfaceFormat::R8G8B8:
+ case SurfaceFormat::B8G8R8:
+ case SurfaceFormat::R5G6B5_UINT16:
+ case SurfaceFormat::R8G8:
+ case SurfaceFormat::R16G16:
+ case SurfaceFormat::HSV:
+ case SurfaceFormat::Lab:
+ info.hasColor = true;
+ info.hasAlpha = false;
+ break;
+
+ case SurfaceFormat::A8:
+ case SurfaceFormat::A16:
+ info.hasColor = false;
+ info.hasAlpha = true;
+ break;
+
+ case SurfaceFormat::YUV:
+ case SurfaceFormat::NV12:
+ case SurfaceFormat::P016:
+ case SurfaceFormat::P010:
+ case SurfaceFormat::YUV422:
+ info.hasColor = true;
+ info.hasAlpha = false;
+ info.isYuv = true;
+ break;
+
+ case SurfaceFormat::Depth:
+ info.hasColor = false;
+ info.hasAlpha = false;
+ info.isYuv = false;
+ break;
+
+ case SurfaceFormat::UNKNOWN:
+ break;
+ }
+
+ // -
+ // bytesPerPixel
+
+ switch (aFormat) {
+ case SurfaceFormat::B8G8R8A8:
+ case SurfaceFormat::R8G8B8A8:
+ case SurfaceFormat::A8R8G8B8:
+ case SurfaceFormat::B8G8R8X8:
+ case SurfaceFormat::R8G8B8X8:
+ case SurfaceFormat::X8R8G8B8:
+ case SurfaceFormat::R16G16:
+ info.bytesPerPixel = 4;
+ break;
+
+ case SurfaceFormat::R8G8B8:
+ case SurfaceFormat::B8G8R8:
+ info.bytesPerPixel = 3;
+ break;
+
+ case SurfaceFormat::R5G6B5_UINT16:
+ case SurfaceFormat::R8G8:
+ case SurfaceFormat::A16:
+ case SurfaceFormat::Depth: // uint16_t
+ info.bytesPerPixel = 2;
+ break;
+
+ case SurfaceFormat::A8:
+ info.bytesPerPixel = 1;
+ break;
+
+ case SurfaceFormat::HSV:
+ case SurfaceFormat::Lab:
+ info.bytesPerPixel = 3 * sizeof(float);
+ break;
+
+ case SurfaceFormat::YUV:
+ case SurfaceFormat::NV12:
+ case SurfaceFormat::P016:
+ case SurfaceFormat::P010:
+ case SurfaceFormat::YUV422:
+ case SurfaceFormat::UNKNOWN:
+ break; // No bytesPerPixel per se.
+ }
+
+ // -
+
+ if (aFormat == SurfaceFormat::UNKNOWN) {
+ return {};
+ }
+ return info;
+}
+
+std::ostream& operator<<(std::ostream& aOut, const SurfaceFormat& aFormat);
+
+// Represents the bit-shifts required to access color channels when the layout
+// is viewed as a uint32_t value.
+enum class SurfaceFormatBit : uint32_t {
+#if MOZ_LITTLE_ENDIAN()
+ R8G8B8A8_R = 0,
+ R8G8B8A8_G = 8,
+ R8G8B8A8_B = 16,
+ R8G8B8A8_A = 24,
+#elif MOZ_BIG_ENDIAN()
+ R8G8B8A8_A = 0,
+ R8G8B8A8_B = 8,
+ R8G8B8A8_G = 16,
+ R8G8B8A8_R = 24,
+#else
+# error "bad endianness"
+#endif
+
+ // The following values are endian-independent for A8R8G8B8_UINT32.
+ A8R8G8B8_UINT32_B = 0,
+ A8R8G8B8_UINT32_G = 8,
+ A8R8G8B8_UINT32_R = 16,
+ A8R8G8B8_UINT32_A = 24,
+
+ // The following values are OS and endian-independent.
+ //
+ // TODO(aosmond): When everything blocking bug 1581828 has been resolved, we
+ // can make this use R8G8B8A8_X for non-Windows platforms.
+ OS_R = A8R8G8B8_UINT32_R,
+ OS_G = A8R8G8B8_UINT32_G,
+ OS_B = A8R8G8B8_UINT32_B,
+ OS_A = A8R8G8B8_UINT32_A,
+};
+
+inline uint32_t operator<<(uint8_t a, SurfaceFormatBit b) {
+ return a << static_cast<uint32_t>(b);
+}
+
+inline uint32_t operator>>(uint32_t a, SurfaceFormatBit b) {
+ return a >> static_cast<uint32_t>(b);
+}
+
+static inline int BytesPerPixel(SurfaceFormat aFormat) {
+ // TODO: return Info(aFormat).value().bytesPerPixel.value();
+ switch (aFormat) {
+ case SurfaceFormat::A8:
+ return 1;
+ case SurfaceFormat::R5G6B5_UINT16:
+ case SurfaceFormat::A16:
+ return 2;
+ case SurfaceFormat::R8G8B8:
+ case SurfaceFormat::B8G8R8:
+ return 3;
+ case SurfaceFormat::HSV:
+ case SurfaceFormat::Lab:
+ return 3 * sizeof(float);
+ case SurfaceFormat::Depth:
+ return sizeof(uint16_t);
+ default:
+ return 4;
+ }
+}
+
+inline bool IsOpaque(SurfaceFormat aFormat) {
+ // TODO: return Info(aFormat).value().hasAlpha;
+ switch (aFormat) {
+ case SurfaceFormat::B8G8R8X8:
+ case SurfaceFormat::R8G8B8X8:
+ case SurfaceFormat::X8R8G8B8:
+ case SurfaceFormat::R5G6B5_UINT16:
+ case SurfaceFormat::R8G8B8:
+ case SurfaceFormat::B8G8R8:
+ case SurfaceFormat::R8G8:
+ case SurfaceFormat::HSV:
+ case SurfaceFormat::Lab:
+ case SurfaceFormat::Depth:
+ case SurfaceFormat::YUV:
+ case SurfaceFormat::NV12:
+ case SurfaceFormat::P010:
+ case SurfaceFormat::P016:
+ case SurfaceFormat::YUV422:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// These are standardized Coding-independent Code Points
+// See [Rec. ITU-T H.273
+// (12/2016)](https://www.itu.int/rec/T-REC-H.273-201612-I/en)
+//
+// We deliberately use an unscoped enum with fixed uint8_t representation since
+// all possible values [0, 255] are legal, but it's unwieldy to declare 200+
+// "RESERVED" enumeration values. Having a fixed underlying type avoids any
+// potential UB and avoids the need for a cast when passing these values across
+// FFI to functions like qcms_profile_create_cicp.
+namespace CICP {
+enum ColourPrimaries : uint8_t {
+ CP_RESERVED_MIN = 0, // 0, 3, [13, 21], [23, 255] are all reserved
+ CP_BT709 = 1,
+ CP_UNSPECIFIED = 2,
+ CP_BT470M = 4,
+ CP_BT470BG = 5,
+ CP_BT601 = 6,
+ CP_SMPTE240 = 7,
+ CP_GENERIC_FILM = 8,
+ CP_BT2020 = 9,
+ CP_XYZ = 10,
+ CP_SMPTE431 = 11,
+ CP_SMPTE432 = 12,
+ CP_EBU3213 = 22,
+};
+
+inline bool IsReserved(ColourPrimaries aIn) {
+ switch (aIn) {
+ case CP_BT709:
+ case CP_UNSPECIFIED:
+ case CP_BT470M:
+ case CP_BT470BG:
+ case CP_BT601:
+ case CP_SMPTE240:
+ case CP_GENERIC_FILM:
+ case CP_BT2020:
+ case CP_XYZ:
+ case CP_SMPTE431:
+ case CP_SMPTE432:
+ case CP_EBU3213:
+ return false;
+ default:
+ return true;
+ }
+}
+
+enum TransferCharacteristics : uint8_t {
+ TC_RESERVED_MIN = 0, // 0, 3, [19, 255] are all reserved
+ TC_BT709 = 1,
+ TC_UNSPECIFIED = 2,
+ TC_BT470M = 4,
+ TC_BT470BG = 5,
+ TC_BT601 = 6,
+ TC_SMPTE240 = 7,
+ TC_LINEAR = 8,
+ TC_LOG_100 = 9,
+ TC_LOG_100_SQRT10 = 10,
+ TC_IEC61966 = 11,
+ TC_BT_1361 = 12,
+ TC_SRGB = 13,
+ TC_BT2020_10BIT = 14,
+ TC_BT2020_12BIT = 15,
+ TC_SMPTE2084 = 16,
+ TC_SMPTE428 = 17,
+ TC_HLG = 18,
+};
+
+inline bool IsReserved(TransferCharacteristics aIn) {
+ switch (aIn) {
+ case TC_BT709:
+ case TC_UNSPECIFIED:
+ case TC_BT470M:
+ case TC_BT470BG:
+ case TC_BT601:
+ case TC_SMPTE240:
+ case TC_LINEAR:
+ case TC_LOG_100:
+ case TC_LOG_100_SQRT10:
+ case TC_IEC61966:
+ case TC_BT_1361:
+ case TC_SRGB:
+ case TC_BT2020_10BIT:
+ case TC_BT2020_12BIT:
+ case TC_SMPTE2084:
+ case TC_SMPTE428:
+ case TC_HLG:
+ return false;
+ default:
+ return true;
+ }
+}
+
+enum MatrixCoefficients : uint8_t {
+ MC_IDENTITY = 0,
+ MC_BT709 = 1,
+ MC_UNSPECIFIED = 2,
+ MC_RESERVED_MIN = 3, // 3, [15, 255] are all reserved
+ MC_FCC = 4,
+ MC_BT470BG = 5,
+ MC_BT601 = 6,
+ MC_SMPTE240 = 7,
+ MC_YCGCO = 8,
+ MC_BT2020_NCL = 9,
+ MC_BT2020_CL = 10,
+ MC_SMPTE2085 = 11,
+ MC_CHROMAT_NCL = 12,
+ MC_CHROMAT_CL = 13,
+ MC_ICTCP = 14,
+};
+
+inline bool IsReserved(MatrixCoefficients aIn) {
+ switch (aIn) {
+ case MC_IDENTITY:
+ case MC_BT709:
+ case MC_UNSPECIFIED:
+ case MC_RESERVED_MIN:
+ case MC_FCC:
+ case MC_BT470BG:
+ case MC_BT601:
+ case MC_SMPTE240:
+ case MC_YCGCO:
+ case MC_BT2020_NCL:
+ case MC_BT2020_CL:
+ case MC_SMPTE2085:
+ case MC_CHROMAT_NCL:
+ case MC_CHROMAT_CL:
+ case MC_ICTCP:
+ return false;
+ default:
+ return true;
+ }
+}
+} // namespace CICP
+
+// The matrix coeffiecients used for YUV to RGB conversion.
+enum class YUVColorSpace : uint8_t {
+ BT601,
+ BT709,
+ BT2020,
+ Identity, // Todo: s/YUVColorSpace/ColorSpace/, s/Identity/SRGB/
+ Default = BT709,
+ _First = BT601,
+ _Last = Identity,
+};
+
+enum class ColorDepth : uint8_t {
+ COLOR_8,
+ COLOR_10,
+ COLOR_12,
+ COLOR_16,
+ _First = COLOR_8,
+ _Last = COLOR_16,
+};
+
+enum class TransferFunction : uint8_t {
+ BT709,
+ SRGB,
+ PQ,
+ HLG,
+ _First = BT709,
+ _Last = HLG,
+ Default = BT709,
+};
+
+enum class ColorRange : uint8_t {
+ LIMITED,
+ FULL,
+ _First = LIMITED,
+ _Last = FULL,
+};
+
+// Really "YcbcrColorColorSpace"
+enum class YUVRangedColorSpace : uint8_t {
+ BT601_Narrow = 0,
+ BT601_Full,
+ BT709_Narrow,
+ BT709_Full,
+ BT2020_Narrow,
+ BT2020_Full,
+ GbrIdentity,
+
+ _First = BT601_Narrow,
+ _Last = GbrIdentity,
+ Default = BT709_Narrow,
+};
+
+// I can either come up with a longer "very clever" name that doesn't conflict
+// with FilterSupport.h, embrace and expand FilterSupport, or rename the old
+// one.
+// Some times Worse Is Better.
+enum class ColorSpace2 : uint8_t {
+ Display,
+ UNKNOWN = Display, // We feel sufficiently bad about this TODO.
+ SRGB,
+ DISPLAY_P3,
+ BT601_525, // aka smpte170m NTSC
+ BT709, // Same gamut as SRGB, but different gamma.
+ BT601_625 =
+ BT709, // aka bt470bg PAL. Basically BT709, just Xg is 0.290 not 0.300.
+ BT2020,
+ _First = Display,
+ _Last = BT2020,
+};
+
+inline ColorSpace2 ToColorSpace2(const YUVColorSpace in) {
+ switch (in) {
+ case YUVColorSpace::BT601:
+ return ColorSpace2::BT601_525;
+ case YUVColorSpace::BT709:
+ return ColorSpace2::BT709;
+ case YUVColorSpace::BT2020:
+ return ColorSpace2::BT2020;
+ case YUVColorSpace::Identity:
+ return ColorSpace2::SRGB;
+ }
+ MOZ_ASSERT_UNREACHABLE();
+}
+
+inline YUVColorSpace ToYUVColorSpace(const ColorSpace2 in) {
+ switch (in) {
+ case ColorSpace2::BT601_525:
+ return YUVColorSpace::BT601;
+ case ColorSpace2::BT709:
+ return YUVColorSpace::BT709;
+ case ColorSpace2::BT2020:
+ return YUVColorSpace::BT2020;
+ case ColorSpace2::SRGB:
+ return YUVColorSpace::Identity;
+
+ case ColorSpace2::UNKNOWN:
+ case ColorSpace2::DISPLAY_P3:
+ MOZ_CRASH("Bad ColorSpace2 for ToYUVColorSpace");
+ }
+ MOZ_ASSERT_UNREACHABLE();
+}
+
+struct FromYUVRangedColorSpaceT final {
+ const YUVColorSpace space;
+ const ColorRange range;
+};
+
+inline FromYUVRangedColorSpaceT FromYUVRangedColorSpace(
+ const YUVRangedColorSpace s) {
+ switch (s) {
+ case YUVRangedColorSpace::BT601_Narrow:
+ return {YUVColorSpace::BT601, ColorRange::LIMITED};
+ case YUVRangedColorSpace::BT601_Full:
+ return {YUVColorSpace::BT601, ColorRange::FULL};
+
+ case YUVRangedColorSpace::BT709_Narrow:
+ return {YUVColorSpace::BT709, ColorRange::LIMITED};
+ case YUVRangedColorSpace::BT709_Full:
+ return {YUVColorSpace::BT709, ColorRange::FULL};
+
+ case YUVRangedColorSpace::BT2020_Narrow:
+ return {YUVColorSpace::BT2020, ColorRange::LIMITED};
+ case YUVRangedColorSpace::BT2020_Full:
+ return {YUVColorSpace::BT2020, ColorRange::FULL};
+
+ case YUVRangedColorSpace::GbrIdentity:
+ return {YUVColorSpace::Identity, ColorRange::FULL};
+ }
+ MOZ_CRASH("bad YUVRangedColorSpace");
+}
+
+// Todo: This should go in the CPP.
+inline YUVRangedColorSpace ToYUVRangedColorSpace(const YUVColorSpace space,
+ const ColorRange range) {
+ bool narrow;
+ switch (range) {
+ case ColorRange::FULL:
+ narrow = false;
+ break;
+ case ColorRange::LIMITED:
+ narrow = true;
+ break;
+ }
+
+ switch (space) {
+ case YUVColorSpace::Identity:
+ MOZ_ASSERT(range == ColorRange::FULL);
+ return YUVRangedColorSpace::GbrIdentity;
+
+ case YUVColorSpace::BT601:
+ return narrow ? YUVRangedColorSpace::BT601_Narrow
+ : YUVRangedColorSpace::BT601_Full;
+
+ case YUVColorSpace::BT709:
+ return narrow ? YUVRangedColorSpace::BT709_Narrow
+ : YUVRangedColorSpace::BT709_Full;
+
+ case YUVColorSpace::BT2020:
+ return narrow ? YUVRangedColorSpace::BT2020_Narrow
+ : YUVRangedColorSpace::BT2020_Full;
+ }
+ MOZ_CRASH("bad YUVColorSpace");
+}
+
+template <typename DescriptorT>
+inline YUVRangedColorSpace GetYUVRangedColorSpace(const DescriptorT& d) {
+ return ToYUVRangedColorSpace(d.yUVColorSpace(), d.colorRange());
+}
+
+static inline SurfaceFormat SurfaceFormatForColorDepth(ColorDepth aColorDepth) {
+ SurfaceFormat format = SurfaceFormat::A8;
+ switch (aColorDepth) {
+ case ColorDepth::COLOR_8:
+ break;
+ case ColorDepth::COLOR_10:
+ case ColorDepth::COLOR_12:
+ case ColorDepth::COLOR_16:
+ format = SurfaceFormat::A16;
+ break;
+ }
+ return format;
+}
+
+static inline uint8_t BitDepthForColorDepth(ColorDepth aColorDepth) {
+ uint8_t depth = 8;
+ switch (aColorDepth) {
+ case ColorDepth::COLOR_8:
+ break;
+ case ColorDepth::COLOR_10:
+ depth = 10;
+ break;
+ case ColorDepth::COLOR_12:
+ depth = 12;
+ break;
+ case ColorDepth::COLOR_16:
+ depth = 16;
+ break;
+ }
+ return depth;
+}
+
+static inline ColorDepth ColorDepthForBitDepth(uint8_t aBitDepth) {
+ ColorDepth depth = ColorDepth::COLOR_8;
+ switch (aBitDepth) {
+ case 8:
+ break;
+ case 10:
+ depth = ColorDepth::COLOR_10;
+ break;
+ case 12:
+ depth = ColorDepth::COLOR_12;
+ break;
+ case 16:
+ depth = ColorDepth::COLOR_16;
+ break;
+ }
+ return depth;
+}
+
+// 10 and 12 bits color depth image are using 16 bits integers for storage
+// As such we need to rescale the value from 10 or 12 bits to 16.
+static inline uint32_t RescalingFactorForColorDepth(ColorDepth aColorDepth) {
+ uint32_t factor = 1;
+ switch (aColorDepth) {
+ case ColorDepth::COLOR_8:
+ break;
+ case ColorDepth::COLOR_10:
+ factor = 64;
+ break;
+ case ColorDepth::COLOR_12:
+ factor = 16;
+ break;
+ case ColorDepth::COLOR_16:
+ break;
+ }
+ return factor;
+}
+
+enum class ChromaSubsampling : uint8_t {
+ FULL,
+ HALF_WIDTH,
+ HALF_WIDTH_AND_HEIGHT,
+ _First = FULL,
+ _Last = HALF_WIDTH_AND_HEIGHT,
+};
+
+template <typename T>
+static inline T ChromaSize(const T& aYSize, ChromaSubsampling aSubsampling) {
+ switch (aSubsampling) {
+ case ChromaSubsampling::FULL:
+ return aYSize;
+ case ChromaSubsampling::HALF_WIDTH:
+ return T((aYSize.width + 1) / 2, aYSize.height);
+ case ChromaSubsampling::HALF_WIDTH_AND_HEIGHT:
+ return T((aYSize.width + 1) / 2, (aYSize.height + 1) / 2);
+ }
+ MOZ_CRASH("bad ChromaSubsampling");
+}
+
+enum class FilterType : int8_t {
+ BLEND = 0,
+ TRANSFORM,
+ MORPHOLOGY,
+ COLOR_MATRIX,
+ FLOOD,
+ TILE,
+ TABLE_TRANSFER,
+ DISCRETE_TRANSFER,
+ LINEAR_TRANSFER,
+ GAMMA_TRANSFER,
+ CONVOLVE_MATRIX,
+ DISPLACEMENT_MAP,
+ TURBULENCE,
+ ARITHMETIC_COMBINE,
+ COMPOSITE,
+ DIRECTIONAL_BLUR,
+ GAUSSIAN_BLUR,
+ POINT_DIFFUSE,
+ POINT_SPECULAR,
+ SPOT_DIFFUSE,
+ SPOT_SPECULAR,
+ DISTANT_DIFFUSE,
+ DISTANT_SPECULAR,
+ CROP,
+ PREMULTIPLY,
+ UNPREMULTIPLY,
+ OPACITY
+};
+
+enum class DrawTargetType : int8_t {
+ SOFTWARE_RASTER = 0,
+ HARDWARE_RASTER,
+ VECTOR
+};
+
+enum class BackendType : int8_t {
+ NONE = 0,
+ DIRECT2D, // Used for version independent D2D objects.
+ CAIRO,
+ SKIA,
+ RECORDING,
+ DIRECT2D1_1,
+ WEBRENDER_TEXT,
+ WEBGL,
+
+ // Add new entries above this line.
+ BACKEND_LAST
+};
+
+enum class FontType : int8_t {
+ DWRITE,
+ GDI,
+ MAC,
+ FONTCONFIG,
+ FREETYPE,
+ UNKNOWN
+};
+
+enum class NativeSurfaceType : int8_t {
+ D3D10_TEXTURE,
+ CAIRO_CONTEXT,
+ CGCONTEXT,
+ CGCONTEXT_ACCELERATED,
+ OPENGL_TEXTURE,
+ WEBGL_CONTEXT
+};
+
+enum class FontStyle : int8_t { NORMAL, ITALIC, BOLD, BOLD_ITALIC };
+
+enum class FontHinting : int8_t { NONE, LIGHT, NORMAL, FULL };
+
+enum class CompositionOp : int8_t {
+ OP_CLEAR,
+ OP_OVER,
+ OP_ADD,
+ OP_ATOP,
+ OP_OUT,
+ OP_IN,
+ OP_SOURCE,
+ OP_DEST_IN,
+ OP_DEST_OUT,
+ OP_DEST_OVER,
+ OP_DEST_ATOP,
+ OP_XOR,
+ OP_MULTIPLY,
+ OP_SCREEN,
+ OP_OVERLAY,
+ OP_DARKEN,
+ OP_LIGHTEN,
+ OP_COLOR_DODGE,
+ OP_COLOR_BURN,
+ OP_HARD_LIGHT,
+ OP_SOFT_LIGHT,
+ OP_DIFFERENCE,
+ OP_EXCLUSION,
+ OP_HUE,
+ OP_SATURATION,
+ OP_COLOR,
+ OP_LUMINOSITY,
+ OP_COUNT
+};
+
+enum class Axis : int8_t { X_AXIS, Y_AXIS, BOTH };
+
+enum class ExtendMode : int8_t {
+ CLAMP, // Do not repeat
+ REPEAT, // Repeat in both axis
+ REPEAT_X, // Only X axis
+ REPEAT_Y, // Only Y axis
+ REFLECT // Mirror the image
+};
+
+enum class FillRule : int8_t { FILL_WINDING, FILL_EVEN_ODD };
+
+enum class AntialiasMode : int8_t { NONE, GRAY, SUBPIXEL, DEFAULT };
+
+// See https://en.wikipedia.org/wiki/Texture_filtering
+enum class SamplingFilter : int8_t {
+ GOOD,
+ LINEAR,
+ POINT,
+ SENTINEL // one past the last valid value
+};
+
+std::ostream& operator<<(std::ostream& aOut, const SamplingFilter& aFilter);
+
+// clang-format off
+MOZ_DEFINE_ENUM_CLASS_WITH_BASE(PatternType, int8_t, (
+ COLOR,
+ SURFACE,
+ LINEAR_GRADIENT,
+ RADIAL_GRADIENT,
+ CONIC_GRADIENT
+));
+// clang-format on
+
+enum class JoinStyle : int8_t {
+ BEVEL,
+ ROUND,
+ MITER, //!< Mitered if within the miter limit, else, if the backed supports
+ //!< it (D2D), the miter is clamped. If the backend does not support
+ //!< miter clamping the behavior is as for MITER_OR_BEVEL.
+ MITER_OR_BEVEL //!< Mitered if within the miter limit, else beveled.
+};
+
+enum class CapStyle : int8_t { BUTT, ROUND, SQUARE };
+
+enum class SamplingBounds : int8_t { UNBOUNDED, BOUNDED };
+
+// Moz2d version for SVG mask types
+enum class LuminanceType : int8_t {
+ LUMINANCE,
+ LINEARRGB,
+};
+
+/* Color is stored in non-premultiplied form in sRGB color space */
+struct sRGBColor {
+ public:
+ constexpr sRGBColor() : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {}
+ constexpr sRGBColor(Float aR, Float aG, Float aB, Float aA)
+ : r(aR), g(aG), b(aB), a(aA) {}
+ constexpr sRGBColor(Float aR, Float aG, Float aB)
+ : r(aR), g(aG), b(aB), a(1.0f) {}
+
+ static constexpr sRGBColor White(float aA) {
+ return sRGBColor(1.f, 1.f, 1.f, aA);
+ }
+
+ static constexpr sRGBColor Black(float aA) {
+ return sRGBColor(0.f, 0.f, 0.f, aA);
+ }
+
+ static constexpr sRGBColor OpaqueWhite() { return White(1.f); }
+
+ static constexpr sRGBColor OpaqueBlack() { return Black(1.f); }
+
+ static constexpr sRGBColor FromU8(uint8_t aR, uint8_t aG, uint8_t aB,
+ uint8_t aA) {
+ return sRGBColor(float(aR) / 255.f, float(aG) / 255.f, float(aB) / 255.f,
+ float(aA) / 255.f);
+ }
+
+ static constexpr sRGBColor FromABGR(uint32_t aColor) {
+ return sRGBColor(((aColor >> 0) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 8) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 16) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 24) & 0xff) * (1.0f / 255.0f));
+ }
+
+ // The "Unusual" prefix is to avoid unintentionally using this function when
+ // FromABGR(), which is much more common, is needed.
+ static constexpr sRGBColor UnusualFromARGB(uint32_t aColor) {
+ return sRGBColor(((aColor >> 16) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 8) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 0) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 24) & 0xff) * (1.0f / 255.0f));
+ }
+
+ constexpr uint32_t ToABGR() const {
+ return uint32_t(r * 255.0f) | uint32_t(g * 255.0f) << 8 |
+ uint32_t(b * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
+ }
+
+ constexpr sRGBColor Premultiplied() const {
+ return sRGBColor(r * a, g * a, b * a, a);
+ }
+
+ constexpr sRGBColor Unpremultiplied() const {
+ return a > 0.f ? sRGBColor(r / a, g / a, b / a, a) : *this;
+ }
+
+ // The "Unusual" prefix is to avoid unintentionally using this function when
+ // ToABGR(), which is much more common, is needed.
+ uint32_t UnusualToARGB() const {
+ return uint32_t(b * 255.0f) | uint32_t(g * 255.0f) << 8 |
+ uint32_t(r * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
+ }
+
+ bool operator==(const sRGBColor& aColor) const {
+ return r == aColor.r && g == aColor.g && b == aColor.b && a == aColor.a;
+ }
+
+ bool operator!=(const sRGBColor& aColor) const { return !(*this == aColor); }
+
+ Float r, g, b, a;
+};
+
+/* Color is stored in non-premultiplied form in device color space */
+struct DeviceColor {
+ public:
+ DeviceColor() : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {}
+ DeviceColor(Float aR, Float aG, Float aB, Float aA)
+ : r(aR), g(aG), b(aB), a(aA) {}
+ DeviceColor(Float aR, Float aG, Float aB) : r(aR), g(aG), b(aB), a(1.0f) {}
+
+ /* The following Mask* variants are helpers used to make it clear when a
+ * particular color is being used for masking purposes. These masks should
+ * never be colored managed. */
+ static DeviceColor Mask(float aC, float aA) {
+ return DeviceColor(aC, aC, aC, aA);
+ }
+
+ static DeviceColor MaskWhite(float aA) { return Mask(1.f, aA); }
+
+ static DeviceColor MaskBlack(float aA) { return Mask(0.f, aA); }
+
+ static DeviceColor MaskOpaqueWhite() { return MaskWhite(1.f); }
+
+ static DeviceColor MaskOpaqueBlack() { return MaskBlack(1.f); }
+
+ static DeviceColor FromU8(uint8_t aR, uint8_t aG, uint8_t aB, uint8_t aA) {
+ return DeviceColor(float(aR) / 255.f, float(aG) / 255.f, float(aB) / 255.f,
+ float(aA) / 255.f);
+ }
+
+ static DeviceColor FromABGR(uint32_t aColor) {
+ DeviceColor newColor(((aColor >> 0) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 8) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 16) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 24) & 0xff) * (1.0f / 255.0f));
+
+ return newColor;
+ }
+
+ // The "Unusual" prefix is to avoid unintentionally using this function when
+ // FromABGR(), which is much more common, is needed.
+ static DeviceColor UnusualFromARGB(uint32_t aColor) {
+ DeviceColor newColor(((aColor >> 16) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 8) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 0) & 0xff) * (1.0f / 255.0f),
+ ((aColor >> 24) & 0xff) * (1.0f / 255.0f));
+
+ return newColor;
+ }
+
+ uint32_t ToABGR() const {
+ return uint32_t(r * 255.0f) | uint32_t(g * 255.0f) << 8 |
+ uint32_t(b * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
+ }
+
+ // The "Unusual" prefix is to avoid unintentionally using this function when
+ // ToABGR(), which is much more common, is needed.
+ uint32_t UnusualToARGB() const {
+ return uint32_t(b * 255.0f) | uint32_t(g * 255.0f) << 8 |
+ uint32_t(r * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
+ }
+
+ bool operator==(const DeviceColor& aColor) const {
+ return r == aColor.r && g == aColor.g && b == aColor.b && a == aColor.a;
+ }
+
+ bool operator!=(const DeviceColor& aColor) const {
+ return !(*this == aColor);
+ }
+
+ friend std::ostream& operator<<(std::ostream& aOut,
+ const DeviceColor& aColor);
+
+ Float r, g, b, a;
+};
+
+struct GradientStop {
+ bool operator<(const GradientStop& aOther) const {
+ return offset < aOther.offset;
+ }
+
+ Float offset;
+ DeviceColor color;
+};
+
+enum class JobStatus { Complete, Wait, Yield, Error };
+
+} // namespace gfx
+} // namespace mozilla
+
+// XXX: temporary
+typedef mozilla::gfx::SurfaceFormat gfxImageFormat;
+
+#if defined(XP_WIN) && defined(MOZ_GFX)
+# ifdef GFX2D_INTERNAL
+# define GFX2D_API __declspec(dllexport)
+# else
+# define GFX2D_API __declspec(dllimport)
+# endif
+#else
+# define GFX2D_API
+#endif
+
+namespace mozilla {
+
+// Side constants for use in various places.
+enum Side : uint8_t { eSideTop, eSideRight, eSideBottom, eSideLeft };
+
+std::ostream& operator<<(std::ostream&, const mozilla::Side&);
+
+constexpr auto AllPhysicalSides() {
+ return mozilla::MakeInclusiveEnumeratedRange(eSideTop, eSideLeft);
+}
+
+enum class SideBits {
+ eNone = 0,
+ eTop = 1 << eSideTop,
+ eRight = 1 << eSideRight,
+ eBottom = 1 << eSideBottom,
+ eLeft = 1 << eSideLeft,
+ eTopBottom = SideBits::eTop | SideBits::eBottom,
+ eLeftRight = SideBits::eLeft | SideBits::eRight,
+ eAll = SideBits::eTopBottom | SideBits::eLeftRight
+};
+
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SideBits)
+
+inline constexpr SideBits SideToSideBit(mozilla::Side aSide) {
+ return SideBits(1 << aSide);
+}
+
+enum Corner : uint8_t {
+ // This order is important!
+ eCornerTopLeft = 0,
+ eCornerTopRight = 1,
+ eCornerBottomRight = 2,
+ eCornerBottomLeft = 3
+};
+
+// RectCornerRadii::radii depends on this value. It is not being added to
+// Corner because we want to lift the responsibility to handle it in the
+// switch-case.
+constexpr int eCornerCount = 4;
+
+constexpr auto AllPhysicalCorners() {
+ return mozilla::MakeInclusiveEnumeratedRange(eCornerTopLeft,
+ eCornerBottomLeft);
+}
+
+// Indices into "half corner" arrays (nsStyleCorners e.g.)
+enum HalfCorner : uint8_t {
+ // This order is important!
+ eCornerTopLeftX = 0,
+ eCornerTopLeftY = 1,
+ eCornerTopRightX = 2,
+ eCornerTopRightY = 3,
+ eCornerBottomRightX = 4,
+ eCornerBottomRightY = 5,
+ eCornerBottomLeftX = 6,
+ eCornerBottomLeftY = 7
+};
+
+constexpr auto AllPhysicalHalfCorners() {
+ return mozilla::MakeInclusiveEnumeratedRange(eCornerTopLeftX,
+ eCornerBottomLeftY);
+}
+
+// The result of these conversion functions are exhaustively checked in
+// nsFrame.cpp, which also serves as usage examples.
+
+constexpr bool HalfCornerIsX(HalfCorner aHalfCorner) {
+ return !(aHalfCorner % 2);
+}
+
+constexpr Corner HalfToFullCorner(HalfCorner aHalfCorner) {
+ return Corner(aHalfCorner / 2);
+}
+
+constexpr HalfCorner FullToHalfCorner(Corner aCorner, bool aIsVertical) {
+ return HalfCorner(aCorner * 2 + aIsVertical);
+}
+
+constexpr bool SideIsVertical(mozilla::Side aSide) { return aSide % 2; }
+
+// @param aIsSecond when true, return the clockwise second of the two
+// corners associated with aSide. For example, with aSide = eSideBottom the
+// result is eCornerBottomRight when aIsSecond is false, and
+// eCornerBottomLeft when aIsSecond is true.
+constexpr Corner SideToFullCorner(mozilla::Side aSide, bool aIsSecond) {
+ return Corner((aSide + aIsSecond) % 4);
+}
+
+// @param aIsSecond see SideToFullCorner.
+// @param aIsParallel return the half-corner that is parallel with aSide
+// when aIsParallel is true. For example with aSide=eSideTop, aIsSecond=true
+// the result is eCornerTopRightX when aIsParallel is true, and
+// eCornerTopRightY when aIsParallel is false (because "X" is parallel with
+// eSideTop/eSideBottom, similarly "Y" is parallel with
+// eSideLeft/eSideRight)
+constexpr HalfCorner SideToHalfCorner(mozilla::Side aSide, bool aIsSecond,
+ bool aIsParallel) {
+ return HalfCorner(((aSide + aIsSecond) * 2 + (aSide + !aIsParallel) % 2) % 8);
+}
+
+} // namespace mozilla
+
+#endif /* MOZILLA_GFX_TYPES_H_ */