/* 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/. */

/* Generated with cbindgen:0.29.2 */

/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
 * To generate this file:
 *   1. Get the latest cbindgen using `cargo install --force cbindgen`
 *      a. Alternatively, you can clone `https://github.com/eqrion/cbindgen` and use a tagged release
 *   2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate webrender_bindings -o gfx/webrender_bindings/webrender_ffi_generated.h`
 */

#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

namespace mozilla {
namespace wr {

/// Special value handled in this wrapper layer to signify a redundant clip chain.
constexpr static const uint64_t ROOT_CLIP_CHAIN = ~0;

constexpr static const uintptr_t BudgetType_COUNT = 7;

/// Defined here for cbindgen
constexpr static const int32_t MAX_RENDER_TASK_SIZE = 16384;

/// Maximum number of SVGFE filters in one graph, this is constant size to avoid
/// allocating anything, and the SVG spec allows us to drop all filters on an
/// item if the graph is excessively complex - a graph this large will never be
/// a good user experience, performance-wise.
constexpr static const uintptr_t SVGFE_GRAPH_MAX = 256;

constexpr static const uintptr_t POLYGON_CLIP_VERTEX_MAX = 32;

constexpr static const uintptr_t MAX_TEXT_RUN_LENGTH = 2040;

enum class WrExternalImageType : uint32_t {
  RawData,
  NativeTexture,
  Invalid,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const WrExternalImageType& aInstance) {
  switch (aInstance) {
    case WrExternalImageType::RawData: aStream << "RawData"; break;
    case WrExternalImageType::NativeTexture: aStream << "NativeTexture"; break;
    case WrExternalImageType::Invalid: aStream << "Invalid"; break;
    case WrExternalImageType::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// Crash annotations included in crash reports.
enum class CrashAnnotation {
  CompileShader = 0,
  DrawShader = 1,
  FontFile = 2,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const CrashAnnotation& aInstance) {
  switch (aInstance) {
    case CrashAnnotation::CompileShader: aStream << "CompileShader"; break;
    case CrashAnnotation::DrawShader: aStream << "DrawShader"; break;
    case CrashAnnotation::FontFile: aStream << "FontFile"; break;
    case CrashAnnotation::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// A stage of the rendering pipeline.
enum class Checkpoint : uint32_t {
  ///
  SceneBuilt,
  ///
  FrameBuilt,
  ///
  FrameTexturesUpdated,
  ///
  FrameRendered,
  /// NotificationRequests get notified with this if they get dropped without having been
  /// notified. This provides the guarantee that if a request is created it will get notified.
  TransactionDropped,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const Checkpoint& aInstance) {
  switch (aInstance) {
    case Checkpoint::SceneBuilt: aStream << "SceneBuilt"; break;
    case Checkpoint::FrameBuilt: aStream << "FrameBuilt"; break;
    case Checkpoint::FrameTexturesUpdated: aStream << "FrameTexturesUpdated"; break;
    case Checkpoint::FrameRendered: aStream << "FrameRendered"; break;
    case Checkpoint::TransactionDropped: aStream << "TransactionDropped"; break;
    case Checkpoint::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// Specifies the format of a series of pixels, in driver terms.
enum class ImageFormat : uint8_t {
  /// One-channel, byte storage. The "red" doesn't map to the color
  /// red per se, and is just the way that OpenGL has historically referred
  /// to single-channel buffers.
  R8 = 1,
  /// One-channel, short storage
  R16 = 2,
  /// Four channels, byte storage.
  BGRA8 = 3,
  /// Four channels, float storage.
  RGBAF32 = 4,
  /// Two-channels, byte storage. Similar to `R8`, this just means
  /// "two channels" rather than "red and green".
  RG8 = 5,
  /// Two-channels, short storage. Similar to `R16`, this just means
  /// "two channels" rather than "red and green".
  RG16 = 6,
  /// Four channels, signed integer storage.
  RGBAI32 = 7,
  /// Four channels, byte storage.
  RGBA8 = 8,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const ImageFormat& aInstance) {
  switch (aInstance) {
    case ImageFormat::R8: aStream << "R8"; break;
    case ImageFormat::R16: aStream << "R16"; break;
    case ImageFormat::BGRA8: aStream << "BGRA8"; break;
    case ImageFormat::RGBAF32: aStream << "RGBAF32"; break;
    case ImageFormat::RG8: aStream << "RG8"; break;
    case ImageFormat::RG16: aStream << "RG16"; break;
    case ImageFormat::RGBAI32: aStream << "RGBAI32"; break;
    case ImageFormat::RGBA8: aStream << "RGBA8"; break;
    case ImageFormat::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class ImageRendering : uint8_t {
  Auto = 0,
  CrispEdges = 1,
  Pixelated = 2,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const ImageRendering& aInstance) {
  switch (aInstance) {
    case ImageRendering::Auto: aStream << "Auto"; break;
    case ImageRendering::CrispEdges: aStream << "CrispEdges"; break;
    case ImageRendering::Pixelated: aStream << "Pixelated"; break;
    case ImageRendering::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class YuvRangedColorSpace : uint8_t {
  Rec601Narrow = 0,
  Rec601Full = 1,
  Rec709Narrow = 2,
  Rec709Full = 3,
  Rec2020Narrow = 4,
  Rec2020Full = 5,
  GbrIdentity = 6,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const YuvRangedColorSpace& aInstance) {
  switch (aInstance) {
    case YuvRangedColorSpace::Rec601Narrow: aStream << "Rec601Narrow"; break;
    case YuvRangedColorSpace::Rec601Full: aStream << "Rec601Full"; break;
    case YuvRangedColorSpace::Rec709Narrow: aStream << "Rec709Narrow"; break;
    case YuvRangedColorSpace::Rec709Full: aStream << "Rec709Full"; break;
    case YuvRangedColorSpace::Rec2020Narrow: aStream << "Rec2020Narrow"; break;
    case YuvRangedColorSpace::Rec2020Full: aStream << "Rec2020Full"; break;
    case YuvRangedColorSpace::GbrIdentity: aStream << "GbrIdentity"; break;
    case YuvRangedColorSpace::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// Specifies the color depth of an image. Currently only used for YUV images.
enum class ColorDepth : uint8_t {
  /// 8 bits image (most common)
  Color8,
  /// 10 bits image
  Color10,
  /// 12 bits image
  Color12,
  /// 16 bits image
  Color16,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const ColorDepth& aInstance) {
  switch (aInstance) {
    case ColorDepth::Color8: aStream << "Color8"; break;
    case ColorDepth::Color10: aStream << "Color10"; break;
    case ColorDepth::Color12: aStream << "Color12"; break;
    case ColorDepth::Color16: aStream << "Color16"; break;
    case ColorDepth::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// Boolean configuration option.
enum class BoolParameter : uint32_t {
  PboUploads = 0,
  Multithreading = 1,
  BatchedUploads = 2,
  DrawCallsForTextureCopy = 3,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const BoolParameter& aInstance) {
  switch (aInstance) {
    case BoolParameter::PboUploads: aStream << "PboUploads"; break;
    case BoolParameter::Multithreading: aStream << "Multithreading"; break;
    case BoolParameter::BatchedUploads: aStream << "BatchedUploads"; break;
    case BoolParameter::DrawCallsForTextureCopy: aStream << "DrawCallsForTextureCopy"; break;
    case BoolParameter::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// Integer configuration option.
enum class IntParameter : uint32_t {
  BatchedUploadThreshold = 0,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const IntParameter& aInstance) {
  switch (aInstance) {
    case IntParameter::BatchedUploadThreshold: aStream << "BatchedUploadThreshold"; break;
    case IntParameter::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// Floating point configuration option.
enum class FloatParameter : uint32_t {
  /// The minimum time for the CPU portion of a frame to be considered slow
  SlowCpuFrameThreshold = 0,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const FloatParameter& aInstance) {
  switch (aInstance) {
    case FloatParameter::SlowCpuFrameThreshold: aStream << "SlowCpuFrameThreshold"; break;
    case FloatParameter::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// Used to indicate if an image is opaque, or has an alpha channel.
enum class OpacityType : uint8_t {
  Opaque = 0,
  HasAlphaChannel = 1,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const OpacityType& aInstance) {
  switch (aInstance) {
    case OpacityType::Opaque: aStream << "Opaque"; break;
    case OpacityType::HasAlphaChannel: aStream << "HasAlphaChannel"; break;
    case OpacityType::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// Specifies the type of texture target in driver terms.
enum class ImageBufferKind : uint8_t {
  /// Standard texture. This maps to GL_TEXTURE_2D in OpenGL.
  Texture2D = 0,
  /// Rectangle texture. This maps to GL_TEXTURE_RECTANGLE in OpenGL. This
  /// is similar to a standard texture, with a few subtle differences
  /// (no mipmaps, non-power-of-two dimensions, different coordinate space)
  /// that make it useful for representing the kinds of textures we use
  /// in WebRender. See https://www.khronos.org/opengl/wiki/Rectangle_Texture
  /// for background on Rectangle textures.
  TextureRect = 1,
  /// External texture. This maps to GL_TEXTURE_EXTERNAL_OES in OpenGL, which
  /// is an extension. This is used for image formats that OpenGL doesn't
  /// understand, particularly YUV. See
  /// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
  TextureExternal = 2,
  /// External texture which is forced to be converted from YUV to RGB using BT709 colorspace.
  /// This maps to GL_TEXTURE_EXTERNAL_OES in OpenGL, using the EXT_YUV_TARGET extension.
  /// https://registry.khronos.org/OpenGL/extensions/EXT/EXT_YUV_target.txt
  TextureExternalBT709 = 3,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const ImageBufferKind& aInstance) {
  switch (aInstance) {
    case ImageBufferKind::Texture2D: aStream << "Texture2D"; break;
    case ImageBufferKind::TextureRect: aStream << "TextureRect"; break;
    case ImageBufferKind::TextureExternal: aStream << "TextureExternal"; break;
    case ImageBufferKind::TextureExternalBT709: aStream << "TextureExternalBT709"; break;
    case ImageBufferKind::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class FontRenderMode : uint8_t {
  Mono = 0,
  Alpha,
  Subpixel,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const FontRenderMode& aInstance) {
  switch (aInstance) {
    case FontRenderMode::Mono: aStream << "Mono"; break;
    case FontRenderMode::Alpha: aStream << "Alpha"; break;
    case FontRenderMode::Subpixel: aStream << "Subpixel"; break;
    case FontRenderMode::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

#if !(defined(XP_MACOSX) || defined(XP_WIN))
enum class FontLCDFilter : uint8_t {
  None,
  Default,
  Light,
  Legacy,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const FontLCDFilter& aInstance) {
  switch (aInstance) {
    case FontLCDFilter::None: aStream << "None"; break;
    case FontLCDFilter::Default: aStream << "Default"; break;
    case FontLCDFilter::Light: aStream << "Light"; break;
    case FontLCDFilter::Legacy: aStream << "Legacy"; break;
    case FontLCDFilter::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}
#endif

#if !(defined(XP_MACOSX) || defined(XP_WIN))
enum class FontHinting : uint8_t {
  None,
  Mono,
  Light,
  Normal,
  LCD,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const FontHinting& aInstance) {
  switch (aInstance) {
    case FontHinting::None: aStream << "None"; break;
    case FontHinting::Mono: aStream << "Mono"; break;
    case FontHinting::Light: aStream << "Light"; break;
    case FontHinting::Normal: aStream << "Normal"; break;
    case FontHinting::LCD: aStream << "LCD"; break;
    case FontHinting::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}
#endif

enum class WrAnimationType : uint32_t {
  Transform = 0,
  Opacity = 1,
  BackgroundColor = 2,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const WrAnimationType& aInstance) {
  switch (aInstance) {
    case WrAnimationType::Transform: aStream << "Transform"; break;
    case WrAnimationType::Opacity: aStream << "Opacity"; break;
    case WrAnimationType::BackgroundColor: aStream << "BackgroundColor"; break;
    case WrAnimationType::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class WrRotation : uint8_t {
  Degree0,
  Degree90,
  Degree180,
  Degree270,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const WrRotation& aInstance) {
  switch (aInstance) {
    case WrRotation::Degree0: aStream << "Degree0"; break;
    case WrRotation::Degree90: aStream << "Degree90"; break;
    case WrRotation::Degree180: aStream << "Degree180"; break;
    case WrRotation::Degree270: aStream << "Degree270"; break;
    case WrRotation::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class TransformStyle : uint8_t {
  Flat = 0,
  Preserve3D = 1,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const TransformStyle& aInstance) {
  switch (aInstance) {
    case TransformStyle::Flat: aStream << "Flat"; break;
    case TransformStyle::Preserve3D: aStream << "Preserve3D"; break;
    case TransformStyle::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class WrReferenceFrameKind : uint8_t {
  Transform,
  Perspective,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const WrReferenceFrameKind& aInstance) {
  switch (aInstance) {
    case WrReferenceFrameKind::Transform: aStream << "Transform"; break;
    case WrReferenceFrameKind::Perspective: aStream << "Perspective"; break;
    case WrReferenceFrameKind::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class MixBlendMode : uint8_t {
  Normal = 0,
  Multiply = 1,
  Screen = 2,
  Overlay = 3,
  Darken = 4,
  Lighten = 5,
  ColorDodge = 6,
  ColorBurn = 7,
  HardLight = 8,
  SoftLight = 9,
  Difference = 10,
  Exclusion = 11,
  Hue = 12,
  Saturation = 13,
  Color = 14,
  Luminosity = 15,
  PlusLighter = 16,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const MixBlendMode& aInstance) {
  switch (aInstance) {
    case MixBlendMode::Normal: aStream << "Normal"; break;
    case MixBlendMode::Multiply: aStream << "Multiply"; break;
    case MixBlendMode::Screen: aStream << "Screen"; break;
    case MixBlendMode::Overlay: aStream << "Overlay"; break;
    case MixBlendMode::Darken: aStream << "Darken"; break;
    case MixBlendMode::Lighten: aStream << "Lighten"; break;
    case MixBlendMode::ColorDodge: aStream << "ColorDodge"; break;
    case MixBlendMode::ColorBurn: aStream << "ColorBurn"; break;
    case MixBlendMode::HardLight: aStream << "HardLight"; break;
    case MixBlendMode::SoftLight: aStream << "SoftLight"; break;
    case MixBlendMode::Difference: aStream << "Difference"; break;
    case MixBlendMode::Exclusion: aStream << "Exclusion"; break;
    case MixBlendMode::Hue: aStream << "Hue"; break;
    case MixBlendMode::Saturation: aStream << "Saturation"; break;
    case MixBlendMode::Color: aStream << "Color"; break;
    case MixBlendMode::Luminosity: aStream << "Luminosity"; break;
    case MixBlendMode::PlusLighter: aStream << "PlusLighter"; break;
    case MixBlendMode::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class ComponentTransferFuncType : uint8_t {
  Identity = 0,
  Table = 1,
  Discrete = 2,
  Linear = 3,
  Gamma = 4,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const ComponentTransferFuncType& aInstance) {
  switch (aInstance) {
    case ComponentTransferFuncType::Identity: aStream << "Identity"; break;
    case ComponentTransferFuncType::Table: aStream << "Table"; break;
    case ComponentTransferFuncType::Discrete: aStream << "Discrete"; break;
    case ComponentTransferFuncType::Linear: aStream << "Linear"; break;
    case ComponentTransferFuncType::Gamma: aStream << "Gamma"; break;
    case ComponentTransferFuncType::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class FillRule : uint8_t {
  Nonzero = 1,
  Evenodd = 2,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const FillRule& aInstance) {
  switch (aInstance) {
    case FillRule::Nonzero: aStream << "Nonzero"; break;
    case FillRule::Evenodd: aStream << "Evenodd"; break;
    case FillRule::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class ClipMode {
  Clip,
  ClipOut,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const ClipMode& aInstance) {
  switch (aInstance) {
    case ClipMode::Clip: aStream << "Clip"; break;
    case ClipMode::ClipOut: aStream << "ClipOut"; break;
    case ClipMode::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// A flag in each scrollable frame to represent whether the owner of the frame document
/// has any scroll-linked effect.
/// See https://firefox-source-docs.mozilla.org/performance/scroll-linked_effects.html
/// for a definition of scroll-linked effect.
enum class HasScrollLinkedEffect : uint8_t {
  Yes,
  No,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const HasScrollLinkedEffect& aInstance) {
  switch (aInstance) {
    case HasScrollLinkedEffect::Yes: aStream << "Yes"; break;
    case HasScrollLinkedEffect::No: aStream << "No"; break;
    case HasScrollLinkedEffect::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class YuvColorSpace : uint8_t {
  Rec601 = 0,
  Rec709 = 1,
  Rec2020 = 2,
  Identity = 3,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const YuvColorSpace& aInstance) {
  switch (aInstance) {
    case YuvColorSpace::Rec601: aStream << "Rec601"; break;
    case YuvColorSpace::Rec709: aStream << "Rec709"; break;
    case YuvColorSpace::Rec2020: aStream << "Rec2020"; break;
    case YuvColorSpace::Identity: aStream << "Identity"; break;
    case YuvColorSpace::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class ColorRange : uint8_t {
  Limited = 0,
  Full = 1,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const ColorRange& aInstance) {
  switch (aInstance) {
    case ColorRange::Limited: aStream << "Limited"; break;
    case ColorRange::Full: aStream << "Full"; break;
    case ColorRange::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class LineOrientation : uint8_t {
  Vertical,
  Horizontal,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const LineOrientation& aInstance) {
  switch (aInstance) {
    case LineOrientation::Vertical: aStream << "Vertical"; break;
    case LineOrientation::Horizontal: aStream << "Horizontal"; break;
    case LineOrientation::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class LineStyle : uint8_t {
  Solid,
  Dotted,
  Dashed,
  Wavy,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const LineStyle& aInstance) {
  switch (aInstance) {
    case LineStyle::Solid: aStream << "Solid"; break;
    case LineStyle::Dotted: aStream << "Dotted"; break;
    case LineStyle::Dashed: aStream << "Dashed"; break;
    case LineStyle::Wavy: aStream << "Wavy"; break;
    case LineStyle::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

/// Whether a border should be antialiased.
enum class AntialiasBorder {
  No = 0,
  Yes,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const AntialiasBorder& aInstance) {
  switch (aInstance) {
    case AntialiasBorder::No: aStream << "No"; break;
    case AntialiasBorder::Yes: aStream << "Yes"; break;
    case AntialiasBorder::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class BorderStyle : uint32_t {
  None = 0,
  Solid = 1,
  Double = 2,
  Dotted = 3,
  Dashed = 4,
  Hidden = 5,
  Groove = 6,
  Ridge = 7,
  Inset = 8,
  Outset = 9,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const BorderStyle& aInstance) {
  switch (aInstance) {
    case BorderStyle::None: aStream << "None"; break;
    case BorderStyle::Solid: aStream << "Solid"; break;
    case BorderStyle::Double: aStream << "Double"; break;
    case BorderStyle::Dotted: aStream << "Dotted"; break;
    case BorderStyle::Dashed: aStream << "Dashed"; break;
    case BorderStyle::Hidden: aStream << "Hidden"; break;
    case BorderStyle::Groove: aStream << "Groove"; break;
    case BorderStyle::Ridge: aStream << "Ridge"; break;
    case BorderStyle::Inset: aStream << "Inset"; break;
    case BorderStyle::Outset: aStream << "Outset"; break;
    case BorderStyle::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class RepeatMode : uint8_t {
  Stretch,
  Repeat,
  Round,
  Space,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const RepeatMode& aInstance) {
  switch (aInstance) {
    case RepeatMode::Stretch: aStream << "Stretch"; break;
    case RepeatMode::Repeat: aStream << "Repeat"; break;
    case RepeatMode::Round: aStream << "Round"; break;
    case RepeatMode::Space: aStream << "Space"; break;
    case RepeatMode::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class ExtendMode : uint8_t {
  Clamp,
  Repeat,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const ExtendMode& aInstance) {
  switch (aInstance) {
    case ExtendMode::Clamp: aStream << "Clamp"; break;
    case ExtendMode::Repeat: aStream << "Repeat"; break;
    case ExtendMode::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

enum class BoxShadowClipMode : uint8_t {
  Outset = 0,
  Inset = 1,
  /// Must be last for serialization purposes
  Sentinel,
};

inline std::ostream& operator<<(std::ostream& aStream, const BoxShadowClipMode& aInstance) {
  switch (aInstance) {
    case BoxShadowClipMode::Outset: aStream << "Outset"; break;
    case BoxShadowClipMode::Inset: aStream << "Inset"; break;
    case BoxShadowClipMode::Sentinel: aStream << "Sentinel"; break;
  }
  return aStream;
}

template<typename T = void>
struct Arc;

/// Features of the batch that, if not requested, may allow a fast-path.
///
/// Rather than breaking batches when primitives request different features,
/// we always request the minimum amount of features to satisfy all items in
/// the batch.
/// The goal is to let the renderer be optionally select more specialized
/// versions of a shader if the batch doesn't require code certain code paths.
/// Not all shaders necessarily implement all of these features.
struct BatchFeatures;

/// A set of flags describing why a picture may need a backing surface.
struct BlitReason;

struct Block;

/// Flags that define how the common brush shader
/// code should process this instance.
struct BrushFlags;

/// An ID for a texture that is owned by the `texture_cache` module.
///
/// This can include atlases or standalone textures allocated via the texture
/// cache (e.g.  if an image is too large to be added to an atlas). The texture
/// cache manages the allocation and freeing of these IDs, and the rendering
/// thread maintains a map from cache texture ID to native texture.
///
/// We never reuse IDs, so we use a u64 here to be safe.
struct CacheTextureId;

/// Bit flags for WR stages to store in a capture.
struct CaptureBits;

/// Mask for clearing caches in debug commands.
struct ClearCache;

struct ClipChainId;

struct ClipNodeFlags;

/// ID for a ClipTreeNode
struct ClipNodeId;

struct ClipTaskIndex;

/// A set of flags describing why a picture may need a backing surface.
struct ClusterFlags;

/// Optional features that can be opted-out of when compositing,
/// possibly allowing a fast path to be selected.
struct CompositeFeatures;

struct CompositorTransformIndex;

struct Device;

/// Geometry in the coordinate system of the render target (screen or intermediate
/// surface) in physical pixels.
struct DevicePixel;

struct DocumentHandle;

/// Each bit of the edge AA mask is:
/// 0, when the edge of the primitive needs to be considered for AA
/// 1, when the edge of the segment needs to be considered for AA
///
/// *Note*: the bit values have to match the shader logic in
/// `write_transform_vertex()` function.
struct EdgeAaSegmentMask;

struct FrameId;

/// Identifier to track a sequence of frames.
///
/// This is effectively a `FrameId` with a ridealong timestamp corresponding
/// to when advance() was called, which allows for more nuanced cache eviction
/// decisions. As such, we use the `FrameId` for equality and comparison, since
/// we should never have two `FrameStamps` with the same id but different
/// timestamps.
struct FrameStamp;

struct GpuBufferAddress;

template<typename I = void>
struct Handle;

/// Information stored an image dependency
struct ImageDependency;

/// Various flags that are part of an image descriptor.
struct ImageDescriptorFlags;

struct ImageGeneration;

template<typename T = void>
struct Index;

struct ItemFlags;

/// Geometry in a stacking context's local coordinate space (logical pixels).
struct LayoutPixel;

struct PassId;

/// Flags describing properties for a given PicturePrimitive
struct PictureFlags;

struct PictureIndex;

/// A set of bitflags that can be set in the visibility information
/// for a primitive instance. This can be used to control how primitives
/// are treated during batching.
struct PrimitiveVisibilityFlags;

struct RenderTaskId;

/// The renderer is responsible for submitting to the GPU the work prepared by the
/// RenderBackend.
///
/// We have a separate `Renderer` instance for each instance of WebRender (generally
/// one per OS window), and all instances share the same thread.
struct Renderer;

struct ResolvedExternalSurfaceIndex;

/// Flags that control how shaders are pre-cached, if at all.
struct ShaderPrecacheFlags;

/// Slice flags
struct SliceFlags;

struct SpatialNodeIndex;

/// Defines which sub-slice (effectively a z-index) a primitive exists on within
/// a picture cache instance.
struct SubSliceIndex;

/// Startup parameters for the texture cache.
///
/// Texture sizes must be at least 512.
struct TextureCacheConfig;

struct TextureFlags;

/// Unit for tile coordinates.
struct TileCoordinate;

/// A Transaction is a group of commands to apply atomically to a document.
///
/// This mechanism ensures that:
///  - no other message can be interleaved between two commands that need to be applied together.
///  - no redundant work is performed if two commands in the same transaction cause the scene or
///    the frame to be rebuilt.
struct Transaction;

struct UniformLocation;

/// The default unit.
struct UnknownUnit;

template<typename T = void>
struct Vec;

/// Geometry in the document's coordinate space (logical pixels).
struct WorldPixel;

struct WrChunkPool;

struct WrGlyphRasterThread;

struct WrProgramCache;

/// A wrapper around a strong reference to a Shaders object, and around the
/// Device object that was used to create the shaders.
///
/// We store the device to avoid repeated GL function lookups.
struct WrShaders;

struct WrState;

struct WrThreadPool;

struct WrVecU8 {
  /// `data` must always be valid for passing to Vec::from_raw_parts.
  /// In particular, it must be non-null even if capacity is zero.
  uint8_t *data;
  uintptr_t length;
  uintptr_t capacity;

  friend std::ostream& operator<<(std::ostream& aStream, const WrVecU8& aInstance) {
    return aStream << "{ " << "data=" << aInstance.data << ", "
                           << "length=" << aInstance.length << ", "
                           << "capacity=" << aInstance.capacity << " }";
  }
  bool operator==(const WrVecU8& aOther) const {
    return data == aOther.data &&
           length == aOther.length &&
           capacity == aOther.capacity;
  }
};

struct ByteSlice {
  const uint8_t *buffer;
  uintptr_t len;

  friend std::ostream& operator<<(std::ostream& aStream, const ByteSlice& aInstance) {
    return aStream << "{ " << "buffer=" << aInstance.buffer << ", "
                           << "len=" << aInstance.len << " }";
  }
  bool operator==(const ByteSlice& aOther) const {
    return buffer == aOther.buffer &&
           len == aOther.len;
  }
};

struct WrExternalImage {
  WrExternalImageType image_type;
  uint32_t handle;
  float u0;
  float v0;
  float u1;
  float v1;
  const uint8_t *buff;
  uintptr_t size;

  friend std::ostream& operator<<(std::ostream& aStream, const WrExternalImage& aInstance) {
    return aStream << "{ " << "image_type=" << aInstance.image_type << ", "
                           << "handle=" << aInstance.handle << ", "
                           << "u0=" << aInstance.u0 << ", "
                           << "v0=" << aInstance.v0 << ", "
                           << "u1=" << aInstance.u1 << ", "
                           << "v1=" << aInstance.v1 << ", "
                           << "buff=" << aInstance.buff << ", "
                           << "size=" << aInstance.size << " }";
  }
  bool operator==(const WrExternalImage& aOther) const {
    return image_type == aOther.image_type &&
           handle == aOther.handle &&
           u0 == aOther.u0 &&
           v0 == aOther.v0 &&
           u1 == aOther.u1 &&
           v1 == aOther.v1 &&
           buff == aOther.buff &&
           size == aOther.size;
  }
};

/// An arbitrary identifier for an external image provided by the
/// application. It must be a unique identifier for each external
/// image.
struct ExternalImageId {
  uint64_t _0;

  friend std::ostream& operator<<(std::ostream& aStream, const ExternalImageId& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const ExternalImageId& aOther) const {
    return _0 == aOther._0;
  }
};

struct WrWindowId {
  uint64_t mHandle;

  friend std::ostream& operator<<(std::ostream& aStream, const WrWindowId& aInstance) {
    return aStream << "{ " << "mHandle=" << aInstance.mHandle << " }";
  }
  bool operator==(const WrWindowId& aOther) const {
    return mHandle == aOther.mHandle;
  }
  bool operator<(const WrWindowId& aOther) const {
    return mHandle < aOther.mHandle;
  }
  bool operator<=(const WrWindowId& aOther) const {
    return mHandle <= aOther.mHandle;
  }
};

struct FramePublishId {
  uint64_t _0;

  friend std::ostream& operator<<(std::ostream& aStream, const FramePublishId& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const FramePublishId& aOther) const {
    return _0 == aOther._0;
  }
  static const FramePublishId INVALID;
};
/// An invalid sentinel FramePublishId, which will always compare less than
/// any valid FrameId.
constexpr inline const FramePublishId FramePublishId::INVALID = FramePublishId{
  /* ._0 = */ 0
};

struct FrameReadyParams {
  bool present;
  bool render;
  bool scrolled;
  /// Firefox uses this to indicate that the frame does not participate
  /// in the frame throttling mechanism.
  /// Frames from off-screen transactions are not tracked.
  bool tracked;

  friend std::ostream& operator<<(std::ostream& aStream, const FrameReadyParams& aInstance) {
    return aStream << "{ " << "present=" << aInstance.present << ", "
                           << "render=" << aInstance.render << ", "
                           << "scrolled=" << aInstance.scrolled << ", "
                           << "tracked=" << aInstance.tracked << " }";
  }
  bool operator==(const FrameReadyParams& aOther) const {
    return present == aOther.present &&
           render == aOther.render &&
           scrolled == aOther.scrolled &&
           tracked == aOther.tracked;
  }
};

/// Flags to track why we are rendering.
struct RenderReasons {
  uint32_t _0;

  constexpr explicit operator bool() const {
    return !!_0;
  }
  constexpr RenderReasons operator~() const {
    return RenderReasons { static_cast<decltype(_0)>(~_0) };
  }
  constexpr RenderReasons operator|(const RenderReasons& aOther) const {
    return RenderReasons { static_cast<decltype(_0)>(this->_0 | aOther._0) };
  }
  RenderReasons& operator|=(const RenderReasons& aOther) {
    *this = (*this | aOther);
    return *this;
  }
  constexpr RenderReasons operator&(const RenderReasons& aOther) const {
    return RenderReasons { static_cast<decltype(_0)>(this->_0 & aOther._0) };
  }
  RenderReasons& operator&=(const RenderReasons& aOther) {
    *this = (*this & aOther);
    return *this;
  }
  constexpr RenderReasons operator^(const RenderReasons& aOther) const {
    return RenderReasons { static_cast<decltype(_0)>(this->_0 ^ aOther._0) };
  }
  RenderReasons& operator^=(const RenderReasons& aOther) {
    *this = (*this ^ aOther);
    return *this;
  }
  friend std::ostream& operator<<(std::ostream& aStream, const RenderReasons& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const RenderReasons& aOther) const {
    return _0 == aOther._0;
  }
  static const RenderReasons NONE;
  static const RenderReasons SCENE;
  static const RenderReasons ANIMATED_PROPERTY;
  static const RenderReasons RESOURCE_UPDATE;
  static const RenderReasons ASYNC_IMAGE;
  static const RenderReasons CLEAR_RESOURCES;
  static const RenderReasons APZ;
  static const RenderReasons RESIZE;
  static const RenderReasons WIDGET;
  static const RenderReasons TEXTURE_CACHE_FLUSH;
  static const RenderReasons SNAPSHOT;
  static const RenderReasons POST_RESOURCE_UPDATES_HOOK;
  static const RenderReasons CONFIG_CHANGE;
  static const RenderReasons CONTENT_SYNC;
  static const RenderReasons FLUSH;
  static const RenderReasons TESTING;
  static const RenderReasons OTHER;
  static const RenderReasons VSYNC;
  static const RenderReasons SKIPPED_COMPOSITE;
  static const RenderReasons START_OBSERVING_VSYNC;
  static const RenderReasons ASYNC_IMAGE_COMPOSITE_UNTIL;
  static const uint32_t NUM_BITS;
};
/// Equivalent of empty() for the C++ side.
constexpr inline const RenderReasons RenderReasons::NONE = RenderReasons{
  /* ._0 = */ (uint32_t)0
};
constexpr inline const RenderReasons RenderReasons::SCENE = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 0)
};
constexpr inline const RenderReasons RenderReasons::ANIMATED_PROPERTY = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 1)
};
constexpr inline const RenderReasons RenderReasons::RESOURCE_UPDATE = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 2)
};
constexpr inline const RenderReasons RenderReasons::ASYNC_IMAGE = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 3)
};
constexpr inline const RenderReasons RenderReasons::CLEAR_RESOURCES = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 4)
};
constexpr inline const RenderReasons RenderReasons::APZ = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 5)
};
/// Window resize
constexpr inline const RenderReasons RenderReasons::RESIZE = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 6)
};
/// Various widget-related reasons
constexpr inline const RenderReasons RenderReasons::WIDGET = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 7)
};
/// See Frame::must_be_drawn
constexpr inline const RenderReasons RenderReasons::TEXTURE_CACHE_FLUSH = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 8)
};
constexpr inline const RenderReasons RenderReasons::SNAPSHOT = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 9)
};
constexpr inline const RenderReasons RenderReasons::POST_RESOURCE_UPDATES_HOOK = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 10)
};
constexpr inline const RenderReasons RenderReasons::CONFIG_CHANGE = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 11)
};
constexpr inline const RenderReasons RenderReasons::CONTENT_SYNC = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 12)
};
constexpr inline const RenderReasons RenderReasons::FLUSH = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 13)
};
constexpr inline const RenderReasons RenderReasons::TESTING = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 14)
};
constexpr inline const RenderReasons RenderReasons::OTHER = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 15)
};
/// Vsync isn't actually "why" we render but it can be useful
/// to see which frames were driven by the vsync scheduler so
/// we store a bit for it.
constexpr inline const RenderReasons RenderReasons::VSYNC = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 16)
};
constexpr inline const RenderReasons RenderReasons::SKIPPED_COMPOSITE = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 17)
};
/// Gecko does some special things when it starts observing vsync
/// so it can be useful to know what frames are associated with it.
constexpr inline const RenderReasons RenderReasons::START_OBSERVING_VSYNC = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 18)
};
constexpr inline const RenderReasons RenderReasons::ASYNC_IMAGE_COMPOSITE_UNTIL = RenderReasons{
  /* ._0 = */ (uint32_t)(1 << 19)
};
constexpr inline const uint32_t RenderReasons::NUM_BITS = 17;

/// This type carries no valuable semantics for WR. However, it reflects the fact that
/// clients (Servo) may generate pipelines by different semi-independent sources.
/// These pipelines still belong to the same `IdNamespace` and the same `DocumentId`.
/// Having this extra Id field enables them to generate `PipelineId` without collision.
using PipelineSourceId = uint32_t;

/// From the point of view of WR, `PipelineId` is completely opaque and generic as long as
/// it's clonable, serializable, comparable, and hashable.
struct PipelineId {
  PipelineSourceId mNamespace;
  uint32_t mHandle;

  friend std::ostream& operator<<(std::ostream& aStream, const PipelineId& aInstance) {
    return aStream << "{ " << "mNamespace=" << aInstance.mNamespace << ", "
                           << "mHandle=" << aInstance.mHandle << " }";
  }
  bool operator==(const PipelineId& aOther) const {
    return mNamespace == aOther.mNamespace &&
           mHandle == aOther.mHandle;
  }
  static const PipelineId INVALID;
};
constexpr inline const PipelineId PipelineId::INVALID = PipelineId{
};

using WrPipelineId = PipelineId;

/// ID namespaces uniquely identify different users of WebRender's API.
///
/// For example in Gecko each content process uses a separate id namespace.
struct IdNamespace {
  uint32_t mHandle;

  friend std::ostream& operator<<(std::ostream& aStream, const IdNamespace& aInstance) {
    return aStream << "{ " << "mHandle=" << aInstance.mHandle << " }";
  }
  bool operator==(const IdNamespace& aOther) const {
    return mHandle == aOther.mHandle;
  }
  bool operator!=(const IdNamespace& aOther) const {
    return mHandle != aOther.mHandle;
  }
  bool operator<(const IdNamespace& aOther) const {
    return mHandle < aOther.mHandle;
  }
  bool operator<=(const IdNamespace& aOther) const {
    return mHandle <= aOther.mHandle;
  }
  static const IdNamespace DEBUGGER;
};
constexpr inline const IdNamespace IdNamespace::DEBUGGER = IdNamespace{
};

/// A key uniquely identifying a WebRender document.
///
/// Instances can manage one or several documents (using the same render backend thread).
/// Each document will internally correspond to a single scene, and scenes are made of
/// one or several pipelines.
struct DocumentId {
  ///
  IdNamespace mNamespace;
  ///
  uint32_t mHandle;

  friend std::ostream& operator<<(std::ostream& aStream, const DocumentId& aInstance) {
    return aStream << "{ " << "mNamespace=" << aInstance.mNamespace << ", "
                           << "mHandle=" << aInstance.mHandle << " }";
  }
  bool operator==(const DocumentId& aOther) const {
    return mNamespace == aOther.mNamespace &&
           mHandle == aOther.mHandle;
  }
  static const DocumentId INVALID;
};
///
constexpr inline const DocumentId DocumentId::INVALID = DocumentId{
};

using WrDocumentId = DocumentId;

/// An epoch identifies the state of a pipeline in time.
///
/// This is mostly used as a synchronization mechanism to observe how/when particular pipeline
/// updates propagate through WebRender and are applied at various stages.
struct Epoch {
  uint32_t mHandle;

  friend std::ostream& operator<<(std::ostream& aStream, const Epoch& aInstance) {
    return aStream << "{ " << "mHandle=" << aInstance.mHandle << " }";
  }
  bool operator==(const Epoch& aOther) const {
    return mHandle == aOther.mHandle;
  }
  bool operator!=(const Epoch& aOther) const {
    return mHandle != aOther.mHandle;
  }
  bool operator<(const Epoch& aOther) const {
    return mHandle < aOther.mHandle;
  }
  bool operator<=(const Epoch& aOther) const {
    return mHandle <= aOther.mHandle;
  }
};

using WrEpoch = Epoch;

struct WrPipelineEpoch {
  WrPipelineId pipeline_id;
  WrDocumentId document_id;
  WrEpoch epoch;

  friend std::ostream& operator<<(std::ostream& aStream, const WrPipelineEpoch& aInstance) {
    return aStream << "{ " << "pipeline_id=" << aInstance.pipeline_id << ", "
                           << "document_id=" << aInstance.document_id << ", "
                           << "epoch=" << aInstance.epoch << " }";
  }
  bool operator==(const WrPipelineEpoch& aOther) const {
    return pipeline_id == aOther.pipeline_id &&
           document_id == aOther.document_id &&
           epoch == aOther.epoch;
  }
};

struct WrRemovedPipeline {
  WrPipelineId pipeline_id;
  WrDocumentId document_id;

  friend std::ostream& operator<<(std::ostream& aStream, const WrRemovedPipeline& aInstance) {
    return aStream << "{ " << "pipeline_id=" << aInstance.pipeline_id << ", "
                           << "document_id=" << aInstance.document_id << " }";
  }
  bool operator==(const WrRemovedPipeline& aOther) const {
    return pipeline_id == aOther.pipeline_id &&
           document_id == aOther.document_id;
  }
};

struct WrPipelineInfo {
  /// This contains an entry for each pipeline that was rendered, along with
  /// the epoch at which it was rendered. Rendered pipelines include the root
  /// pipeline and any other pipelines that were reachable via IFrame display
  /// items from the root pipeline.
  nsTArray<WrPipelineEpoch> epochs;
  /// This contains an entry for each pipeline that was removed during the
  /// last transaction. These pipelines would have been explicitly removed by
  /// calling remove_pipeline on the transaction object; the pipeline showing
  /// up in this array means that the data structures have been torn down on
  /// the webrender side, and so any remaining data structures on the caller
  /// side can now be torn down also.
  nsTArray<WrRemovedPipeline> removed_pipelines;

  friend std::ostream& operator<<(std::ostream& aStream, const WrPipelineInfo& aInstance) {
    return aStream << "{ " << "epochs=" << aInstance.epochs << ", "
                           << "removed_pipelines=" << aInstance.removed_pipelines << " }";
  }
  bool operator==(const WrPipelineInfo& aOther) const {
    return epochs == aOther.epochs &&
           removed_pipelines == aOther.removed_pipelines;
  }
};

/// Represents RGBA screen colors with floating point numbers.
///
/// All components must be between 0.0 and 1.0.
/// An alpha value of 1.0 is opaque while 0.0 is fully transparent.
struct ColorF {
  float r;
  float g;
  float b;
  float a;

  friend std::ostream& operator<<(std::ostream& aStream, const ColorF& aInstance) {
    return aStream << "{ " << "r=" << aInstance.r << ", "
                           << "g=" << aInstance.g << ", "
                           << "b=" << aInstance.b << ", "
                           << "a=" << aInstance.a << " }";
  }
  bool operator==(const ColorF& aOther) const {
    return r == aOther.r &&
           g == aOther.g &&
           b == aOther.b &&
           a == aOther.a;
  }
  static const ColorF BLACK;
  static const ColorF TRANSPARENT;
  static const ColorF WHITE;
};
constexpr inline const ColorF ColorF::BLACK = ColorF{
  /* .r = */ 0.0,
  /* .g = */ 0.0,
  /* .b = */ 0.0,
  /* .a = */ 1.0
};
constexpr inline const ColorF ColorF::TRANSPARENT = ColorF{
  /* .r = */ 0.0,
  /* .g = */ 0.0,
  /* .b = */ 0.0,
  /* .a = */ 0.0
};
constexpr inline const ColorF ColorF::WHITE = ColorF{
  /* .r = */ 1.0,
  /* .g = */ 1.0,
  /* .b = */ 1.0,
  /* .a = */ 1.0
};

struct WrExternalImageHandler {
  void *external_image_obj;

  friend std::ostream& operator<<(std::ostream& aStream, const WrExternalImageHandler& aInstance) {
    return aStream << "{ " << "external_image_obj=" << aInstance.external_image_obj << " }";
  }
  bool operator==(const WrExternalImageHandler& aOther) const {
    return external_image_obj == aOther.external_image_obj;
  }
};

/// Some basic statistics about the rendered scene, used in Gecko, as
/// well as in wrench reftests to ensure that tests are batching and/or
/// allocating on render targets as we expect them to.
struct RendererStats {
  uintptr_t total_draw_calls;
  uintptr_t alpha_target_count;
  uintptr_t color_target_count;
  double texture_upload_mb;
  double resource_upload_time;
  double gpu_cache_upload_time;
  double gecko_display_list_time;
  double wr_display_list_time;
  double scene_build_time;
  double frame_build_time;
  bool full_display_list;
  bool full_paint;

  friend std::ostream& operator<<(std::ostream& aStream, const RendererStats& aInstance) {
    return aStream << "{ " << "total_draw_calls=" << aInstance.total_draw_calls << ", "
                           << "alpha_target_count=" << aInstance.alpha_target_count << ", "
                           << "color_target_count=" << aInstance.color_target_count << ", "
                           << "texture_upload_mb=" << aInstance.texture_upload_mb << ", "
                           << "resource_upload_time=" << aInstance.resource_upload_time << ", "
                           << "gpu_cache_upload_time=" << aInstance.gpu_cache_upload_time << ", "
                           << "gecko_display_list_time=" << aInstance.gecko_display_list_time << ", "
                           << "wr_display_list_time=" << aInstance.wr_display_list_time << ", "
                           << "scene_build_time=" << aInstance.scene_build_time << ", "
                           << "frame_build_time=" << aInstance.frame_build_time << ", "
                           << "full_display_list=" << aInstance.full_display_list << ", "
                           << "full_paint=" << aInstance.full_paint << " }";
  }
  bool operator==(const RendererStats& aOther) const {
    return total_draw_calls == aOther.total_draw_calls &&
           alpha_target_count == aOther.alpha_target_count &&
           color_target_count == aOther.color_target_count &&
           texture_upload_mb == aOther.texture_upload_mb &&
           resource_upload_time == aOther.resource_upload_time &&
           gpu_cache_upload_time == aOther.gpu_cache_upload_time &&
           gecko_display_list_time == aOther.gecko_display_list_time &&
           wr_display_list_time == aOther.wr_display_list_time &&
           scene_build_time == aOther.scene_build_time &&
           frame_build_time == aOther.frame_build_time &&
           full_display_list == aOther.full_display_list &&
           full_paint == aOther.full_paint;
  }
};

/// A 2d Point tagged with a unit.
template<typename T, typename U>
struct Point2D {
  T x;
  T y;

  friend std::ostream& operator<<(std::ostream& aStream, const Point2D& aInstance) {
    return aStream << "{ " << "x=" << aInstance.x << ", "
                           << "y=" << aInstance.y << " }";
  }
  bool operator==(const Point2D& aOther) const {
    return x == aOther.x &&
           y == aOther.y;
  }
};

/// A 2d axis aligned rectangle represented by its minimum and maximum coordinates.
///
/// # Representation
///
/// This struct is similar to [`Rect`], but stores rectangle as two endpoints
/// instead of origin point and size. Such representation has several advantages over
/// [`Rect`] representation:
/// - Several operations are more efficient with `Box2D`, including [`intersection`],
///   [`union`], and point-in-rect.
/// - The representation is less susceptible to overflow. With [`Rect`], computation
///   of second point can overflow for a large range of values of origin and size.
///   However, with `Box2D`, computation of [`size`] cannot overflow if the coordinates
///   are signed and the resulting size is unsigned.
///
/// A known disadvantage of `Box2D` is that translating the rectangle requires translating
/// both points, whereas translating [`Rect`] only requires translating one point.
///
/// # Empty box
///
/// A box is considered empty (see [`is_empty`]) if any of the following is true:
/// - it's area is empty,
/// - it's area is negative (`min.x > max.x` or `min.y > max.y`),
/// - it contains NaNs.
///
/// [`Rect`]: struct.Rect.html
/// [`intersection`]: #method.intersection
/// [`is_empty`]: #method.is_empty
/// [`union`]: #method.union
/// [`size`]: #method.size
template<typename T, typename U>
struct Box2D {
  Point2D<T, U> min;
  Point2D<T, U> max;

  friend std::ostream& operator<<(std::ostream& aStream, const Box2D& aInstance) {
    return aStream << "{ " << "min=" << aInstance.min << ", "
                           << "max=" << aInstance.max << " }";
  }
  bool operator==(const Box2D& aOther) const {
    return min == aOther.min &&
           max == aOther.max;
  }
  inline T width() const { return max.x - min.x; }
  inline T height() const { return max.y - min.y; }
};

using DeviceIntRect = Box2D<int32_t, DevicePixel>;

/// A handle to a recorded frame that was captured.
struct RecordedFrameHandle {
  uintptr_t _0;

  friend std::ostream& operator<<(std::ostream& aStream, const RecordedFrameHandle& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const RecordedFrameHandle& aOther) const {
    return _0 == aOther._0;
  }
};

/// A handle to a screenshot that is being asynchronously captured and scaled.
struct AsyncScreenshotHandle {
  uintptr_t _0;

  friend std::ostream& operator<<(std::ostream& aStream, const AsyncScreenshotHandle& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const AsyncScreenshotHandle& aOther) const {
    return _0 == aOther._0;
  }
};

/// Memory report for interning-related data structures.
struct InterningMemoryReport {
  ///
  InternerSubReport interners;
  ///
  InternerSubReport data_stores;
};

/// Collection of heap sizes, in bytes.
struct MemoryReport {
  uintptr_t clip_stores;
  uintptr_t gpu_cache_metadata;
  uintptr_t gpu_cache_cpu_mirror;
  uintptr_t hit_testers;
  uintptr_t fonts;
  uintptr_t weak_fonts;
  uintptr_t images;
  uintptr_t rasterized_blobs;
  uintptr_t shader_cache;
  InterningMemoryReport interning;
  uintptr_t display_list;
  uintptr_t upload_staging_memory;
  uintptr_t swgl;
  uintptr_t frame_allocator;
  uintptr_t render_tasks;
  uintptr_t gpu_cache_textures;
  uintptr_t vertex_data_textures;
  uintptr_t render_target_textures;
  uintptr_t picture_tile_textures;
  uintptr_t atlas_textures;
  uintptr_t standalone_textures;
  uintptr_t texture_cache_structures;
  uintptr_t depth_target_textures;
  uintptr_t texture_upload_pbos;
  uintptr_t swap_chain;
  uintptr_t render_texture_hosts;
  uintptr_t upload_staging_textures;
};

/// An arbitrary identifier for a native (OS compositor) surface
struct NativeSurfaceId {
  uint64_t _0;

  friend std::ostream& operator<<(std::ostream& aStream, const NativeSurfaceId& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const NativeSurfaceId& aOther) const {
    return _0 == aOther._0;
  }
  static const NativeSurfaceId DEBUG_OVERLAY;
};
/// A special id for the native surface that is used for debug / profiler overlays.
constexpr inline const NativeSurfaceId NativeSurfaceId::DEBUG_OVERLAY = NativeSurfaceId{
  /* ._0 = */ UINT64_MAX
};

using DeviceIntPoint = Point2D<int32_t, DevicePixel>;

/// A 2d size tagged with a unit.
template<typename T, typename U>
struct Size2D {
  /// The extent of the element in the `U` units along the `x` axis (usually horizontal).
  T width;
  /// The extent of the element in the `U` units along the `y` axis (usually vertical).
  T height;

  friend std::ostream& operator<<(std::ostream& aStream, const Size2D& aInstance) {
    return aStream << "{ " << "width=" << aInstance.width << ", "
                           << "height=" << aInstance.height << " }";
  }
  bool operator==(const Size2D& aOther) const {
    return width == aOther.width &&
           height == aOther.height;
  }
};

using DeviceIntSize = Size2D<int32_t, DevicePixel>;

struct NativeTileId {
  NativeSurfaceId surface_id;
  int32_t x;
  int32_t y;

  friend std::ostream& operator<<(std::ostream& aStream, const NativeTileId& aInstance) {
    return aStream << "{ " << "surface_id=" << aInstance.surface_id << ", "
                           << "x=" << aInstance.x << ", "
                           << "y=" << aInstance.y << " }";
  }
  bool operator==(const NativeTileId& aOther) const {
    return surface_id == aOther.surface_id &&
           x == aOther.x &&
           y == aOther.y;
  }
  static const NativeTileId DEBUG_OVERLAY;
};
/// A special id for the native surface that is used for debug / profiler overlays.
constexpr inline const NativeTileId NativeTileId::DEBUG_OVERLAY = NativeTileId{
  /* .surface_id = */ NativeSurfaceId::DEBUG_OVERLAY,
  /* .x = */ 0,
  /* .y = */ 0
};

/// A 2d Vector tagged with a unit.
template<typename T, typename U>
struct Vector2D {
  /// The `x` (traditionally, horizontal) coordinate.
  T x;
  /// The `y` (traditionally, vertical) coordinate.
  T y;

  friend std::ostream& operator<<(std::ostream& aStream, const Vector2D& aInstance) {
    return aStream << "{ " << "x=" << aInstance.x << ", "
                           << "y=" << aInstance.y << " }";
  }
  bool operator==(const Vector2D& aOther) const {
    return x == aOther.x &&
           y == aOther.y;
  }
};

struct ScaleOffset {
  Vector2D<float, UnknownUnit> scale;
  Vector2D<float, UnknownUnit> offset;

  friend std::ostream& operator<<(std::ostream& aStream, const ScaleOffset& aInstance) {
    return aStream << "{ " << "scale=" << aInstance.scale << ", "
                           << "offset=" << aInstance.offset << " }";
  }
  bool operator==(const ScaleOffset& aOther) const {
    return scale == aOther.scale &&
           offset == aOther.offset;
  }
};

/// The transform type to apply to Compositor surfaces.
using CompositorSurfaceTransform = ScaleOffset;

struct ClipRadius {
  int32_t top_left;
  int32_t top_right;
  int32_t bottom_left;
  int32_t bottom_right;

  friend std::ostream& operator<<(std::ostream& aStream, const ClipRadius& aInstance) {
    return aStream << "{ " << "top_left=" << aInstance.top_left << ", "
                           << "top_right=" << aInstance.top_right << ", "
                           << "bottom_left=" << aInstance.bottom_left << ", "
                           << "bottom_right=" << aInstance.bottom_right << " }";
  }
  bool operator==(const ClipRadius& aOther) const {
    return top_left == aOther.top_left &&
           top_right == aOther.top_right &&
           bottom_left == aOther.bottom_left &&
           bottom_right == aOther.bottom_right;
  }
  static const ClipRadius EMPTY;
};
constexpr inline const ClipRadius ClipRadius::EMPTY = ClipRadius{
  /* .top_left = */ 0,
  /* .top_right = */ 0,
  /* .bottom_left = */ 0,
  /* .bottom_right = */ 0
};

struct CompositorCapabilities {
  /// The virtual surface size used by the underlying platform.
  int32_t virtual_surface_size;
  /// Whether the compositor requires redrawing on invalidation.
  bool redraw_on_invalidation;
  /// The maximum number of dirty rects that can be provided per compositor
  /// surface update. If this is zero, the entire compositor surface for
  /// a given tile will be drawn if it's dirty.
  uintptr_t max_update_rects;
  /// Whether or not this compositor will create surfaces for backdrops.
  bool supports_surface_for_backdrop;
  /// Whether external compositor surface supports negative scaling.
  bool supports_external_compositor_surface_negative_scaling;

  friend std::ostream& operator<<(std::ostream& aStream, const CompositorCapabilities& aInstance) {
    return aStream << "{ " << "virtual_surface_size=" << aInstance.virtual_surface_size << ", "
                           << "redraw_on_invalidation=" << aInstance.redraw_on_invalidation << ", "
                           << "max_update_rects=" << aInstance.max_update_rects << ", "
                           << "supports_surface_for_backdrop=" << aInstance.supports_surface_for_backdrop << ", "
                           << "supports_external_compositor_surface_negative_scaling=" << aInstance.supports_external_compositor_surface_negative_scaling << " }";
  }
  bool operator==(const CompositorCapabilities& aOther) const {
    return virtual_surface_size == aOther.virtual_surface_size &&
           redraw_on_invalidation == aOther.redraw_on_invalidation &&
           max_update_rects == aOther.max_update_rects &&
           supports_surface_for_backdrop == aOther.supports_surface_for_backdrop &&
           supports_external_compositor_surface_negative_scaling == aOther.supports_external_compositor_surface_negative_scaling;
  }
};

struct WindowVisibility {
  bool is_fully_occluded;

  friend std::ostream& operator<<(std::ostream& aStream, const WindowVisibility& aInstance) {
    return aStream << "{ " << "is_fully_occluded=" << aInstance.is_fully_occluded << " }";
  }
  bool operator==(const WindowVisibility& aOther) const {
    return is_fully_occluded == aOther.is_fully_occluded;
  }
};

struct WindowProperties {
  bool is_opaque;
  bool enable_screenshot;

  friend std::ostream& operator<<(std::ostream& aStream, const WindowProperties& aInstance) {
    return aStream << "{ " << "is_opaque=" << aInstance.is_opaque << ", "
                           << "enable_screenshot=" << aInstance.enable_screenshot << " }";
  }
  bool operator==(const WindowProperties& aOther) const {
    return is_opaque == aOther.is_opaque &&
           enable_screenshot == aOther.enable_screenshot;
  }
};

/// Descriptor for a locked surface that will be directly composited by SWGL.
struct SWGLCompositeSurfaceInfo {
  /// The number of YUV planes in the surface. 0 indicates non-YUV BGRA.
  /// 1 is interleaved YUV. 2 is NV12. 3 is planar YUV.
  uint32_t yuv_planes;
  /// Textures for planes of the surface, or 0 if not applicable.
  uint32_t textures[3];
  /// Color space of surface if using a YUV format.
  YuvRangedColorSpace color_space;
  /// Color depth of surface if using a YUV format.
  ColorDepth color_depth;
  /// The actual source surface size before transformation.
  DeviceIntSize size;

  friend std::ostream& operator<<(std::ostream& aStream, const SWGLCompositeSurfaceInfo& aInstance) {
    return aStream << "{ " << "yuv_planes=" << aInstance.yuv_planes << ", "
                           << "textures=" << aInstance.textures << ", "
                           << "color_space=" << aInstance.color_space << ", "
                           << "color_depth=" << aInstance.color_depth << ", "
                           << "size=" << aInstance.size << " }";
  }
};

/// A C function that takes a pointer to a heap allocation and returns its size.
///
/// This is borrowed from the malloc_size_of crate, upon which we want to avoid
/// a dependency from WebRender.
using VoidPtrToSizeFn = uintptr_t(*)(const void *ptr);

/// Flags to enable/disable various builtin debugging tools.
struct DebugFlags {
  uint64_t _0;

  constexpr explicit operator bool() const {
    return !!_0;
  }
  constexpr DebugFlags operator~() const {
    return DebugFlags { static_cast<decltype(_0)>(~_0) };
  }
  constexpr DebugFlags operator|(const DebugFlags& aOther) const {
    return DebugFlags { static_cast<decltype(_0)>(this->_0 | aOther._0) };
  }
  DebugFlags& operator|=(const DebugFlags& aOther) {
    *this = (*this | aOther);
    return *this;
  }
  constexpr DebugFlags operator&(const DebugFlags& aOther) const {
    return DebugFlags { static_cast<decltype(_0)>(this->_0 & aOther._0) };
  }
  DebugFlags& operator&=(const DebugFlags& aOther) {
    *this = (*this & aOther);
    return *this;
  }
  constexpr DebugFlags operator^(const DebugFlags& aOther) const {
    return DebugFlags { static_cast<decltype(_0)>(this->_0 ^ aOther._0) };
  }
  DebugFlags& operator^=(const DebugFlags& aOther) {
    *this = (*this ^ aOther);
    return *this;
  }
  friend std::ostream& operator<<(std::ostream& aStream, const DebugFlags& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const DebugFlags& aOther) const {
    return _0 == aOther._0;
  }
  static const DebugFlags PROFILER_DBG;
  static const DebugFlags RENDER_TARGET_DBG;
  static const DebugFlags TEXTURE_CACHE_DBG;
  static const DebugFlags GPU_TIME_QUERIES;
  static const DebugFlags GPU_SAMPLE_QUERIES;
  static const DebugFlags DISABLE_BATCHING;
  static const DebugFlags EPOCHS;
  static const DebugFlags ECHO_DRIVER_MESSAGES;
  static const DebugFlags SHOW_OVERDRAW;
  static const DebugFlags GPU_CACHE_DBG;
  static const DebugFlags TEXTURE_CACHE_DBG_CLEAR_EVICTED;
  static const DebugFlags PICTURE_CACHING_DBG;
  static const DebugFlags ZOOM_DBG;
  static const DebugFlags SMALL_SCREEN;
  static const DebugFlags DISABLE_OPAQUE_PASS;
  static const DebugFlags DISABLE_ALPHA_PASS;
  static const DebugFlags DISABLE_CLIP_MASKS;
  static const DebugFlags DISABLE_TEXT_PRIMS;
  static const DebugFlags DISABLE_GRADIENT_PRIMS;
  static const DebugFlags OBSCURE_IMAGES;
  static const DebugFlags GLYPH_FLASHING;
  static const DebugFlags SMART_PROFILER;
  static const DebugFlags INVALIDATION_DBG;
  static const DebugFlags PROFILER_CAPTURE;
  static const DebugFlags FORCE_PICTURE_INVALIDATION;
  static const DebugFlags WINDOW_VISIBILITY_DBG;
  static const DebugFlags RESTRICT_BLOB_SIZE;
  static const DebugFlags SURFACE_PROMOTION_LOGGING;
  static const DebugFlags PICTURE_BORDERS;
  static const DebugFlags MISSING_SNAPSHOT_PANIC;
  static const DebugFlags MISSING_SNAPSHOT_PINK;
  static const DebugFlags HIGHLIGHT_BACKDROP_FILTERS;
  static const DebugFlags EXTERNAL_COMPOSITE_BORDERS;
};
/// Display the frame profiler on screen.
constexpr inline const DebugFlags DebugFlags::PROFILER_DBG = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 0)
};
/// Display intermediate render targets on screen.
constexpr inline const DebugFlags DebugFlags::RENDER_TARGET_DBG = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 1)
};
/// Display all texture cache pages on screen.
constexpr inline const DebugFlags DebugFlags::TEXTURE_CACHE_DBG = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 2)
};
/// Display GPU timing results.
constexpr inline const DebugFlags DebugFlags::GPU_TIME_QUERIES = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 3)
};
/// Query the number of pixels that pass the depth test divided and show it
/// in the profiler as a percentage of the number of pixels in the screen
/// (window width times height).
constexpr inline const DebugFlags DebugFlags::GPU_SAMPLE_QUERIES = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 4)
};
/// Render each quad with their own draw call.
///
/// Terrible for performance but can help with understanding the drawing
/// order when inspecting renderdoc or apitrace recordings.
constexpr inline const DebugFlags DebugFlags::DISABLE_BATCHING = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 5)
};
/// Display the pipeline epochs.
constexpr inline const DebugFlags DebugFlags::EPOCHS = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 6)
};
/// Print driver messages to stdout.
constexpr inline const DebugFlags DebugFlags::ECHO_DRIVER_MESSAGES = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 7)
};
/// Show an overlay displaying overdraw amount.
constexpr inline const DebugFlags DebugFlags::SHOW_OVERDRAW = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 8)
};
/// Display the contents of GPU cache.
constexpr inline const DebugFlags DebugFlags::GPU_CACHE_DBG = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 9)
};
/// Clear evicted parts of the texture cache for debugging purposes.
constexpr inline const DebugFlags DebugFlags::TEXTURE_CACHE_DBG_CLEAR_EVICTED = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 10)
};
/// Show picture caching debug overlay
constexpr inline const DebugFlags DebugFlags::PICTURE_CACHING_DBG = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 11)
};
/// Draw a zoom widget showing part of the framebuffer zoomed in.
constexpr inline const DebugFlags DebugFlags::ZOOM_DBG = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 13)
};
/// Scale the debug renderer down for a smaller screen. This will disrupt
/// any mapping between debug display items and page content, so shouldn't
/// be used with overlays like the picture caching or primitive display.
constexpr inline const DebugFlags DebugFlags::SMALL_SCREEN = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 14)
};
/// Disable various bits of the WebRender pipeline, to help narrow
/// down where slowness might be coming from.
constexpr inline const DebugFlags DebugFlags::DISABLE_OPAQUE_PASS = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 15)
};
///
constexpr inline const DebugFlags DebugFlags::DISABLE_ALPHA_PASS = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 16)
};
///
constexpr inline const DebugFlags DebugFlags::DISABLE_CLIP_MASKS = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 17)
};
///
constexpr inline const DebugFlags DebugFlags::DISABLE_TEXT_PRIMS = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 18)
};
///
constexpr inline const DebugFlags DebugFlags::DISABLE_GRADIENT_PRIMS = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 19)
};
///
constexpr inline const DebugFlags DebugFlags::OBSCURE_IMAGES = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 20)
};
/// Taint the transparent area of the glyphs with a random opacity to easily
/// see when glyphs are re-rasterized.
constexpr inline const DebugFlags DebugFlags::GLYPH_FLASHING = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 21)
};
/// The profiler only displays information that is out of the ordinary.
constexpr inline const DebugFlags DebugFlags::SMART_PROFILER = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 22)
};
/// If set, dump picture cache invalidation debug to console.
constexpr inline const DebugFlags DebugFlags::INVALIDATION_DBG = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 23)
};
/// Collect and dump profiler statistics to captures.
constexpr inline const DebugFlags DebugFlags::PROFILER_CAPTURE = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 25)
};
/// Invalidate picture tiles every frames (useful when inspecting GPU work in external tools).
constexpr inline const DebugFlags DebugFlags::FORCE_PICTURE_INVALIDATION = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 26)
};
/// Display window visibility on screen.
constexpr inline const DebugFlags DebugFlags::WINDOW_VISIBILITY_DBG = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 27)
};
/// Render large blobs with at a smaller size (incorrectly). This is a temporary workaround for
/// fuzzing.
constexpr inline const DebugFlags DebugFlags::RESTRICT_BLOB_SIZE = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 28)
};
/// Enable surface promotion logging.
constexpr inline const DebugFlags DebugFlags::SURFACE_PROMOTION_LOGGING = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 29)
};
/// Show picture caching debug overlay.
constexpr inline const DebugFlags DebugFlags::PICTURE_BORDERS = DebugFlags{
  /* ._0 = */ (uint64_t)(1 << 30)
};
/// Panic when a attempting to display a missing stacking context snapshot.
constexpr inline const DebugFlags DebugFlags::MISSING_SNAPSHOT_PANIC = DebugFlags{
  /* ._0 = */ (uint64_t)((uint64_t)1 << 31)
};
/// Panic when a attempting to display a missing stacking context snapshot.
constexpr inline const DebugFlags DebugFlags::MISSING_SNAPSHOT_PINK = DebugFlags{
  /* ._0 = */ (uint64_t)((uint64_t)1 << 32)
};
/// Highlight backdrop filters
constexpr inline const DebugFlags DebugFlags::HIGHLIGHT_BACKDROP_FILTERS = DebugFlags{
  /* ._0 = */ (uint64_t)((uint64_t)1 << 33)
};
/// Show external composite border rects in debug overlay.
/// TODO: Add native compositor support
constexpr inline const DebugFlags DebugFlags::EXTERNAL_COMPOSITE_BORDERS = DebugFlags{
  /* ._0 = */ (uint64_t)((uint64_t)1 << 34)
};

struct GeckoDisplayListType {
  enum class Tag {
    None,
    Partial,
    Full,
    /// Must be last for serialization purposes
    Sentinel,
  };

  friend std::ostream& operator<<(std::ostream& aStream, const Tag& aInstance) {
    using Tag = GeckoDisplayListType::Tag;
    switch (aInstance) {
      case Tag::None: aStream << "None"; break;
      case Tag::Partial: aStream << "Partial"; break;
      case Tag::Full: aStream << "Full"; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  friend std::ostream& operator<<(std::ostream& aStream, const GeckoDisplayListType& aInstance) {
    using Tag = GeckoDisplayListType::Tag;
    switch (aInstance.tag) {
      case Tag::None: aStream << "None"; break;
      case Tag::Partial: aStream << "Partial" << aInstance.partial; break;
      case Tag::Full: aStream << "Full" << aInstance.full; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  struct Partial_Body {
    double _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Partial_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Partial_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct Full_Body {
    double _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Full_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Full_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  Tag tag;
  union {
    Partial_Body partial;
    Full_Body full;
  };

  static GeckoDisplayListType None() {
    GeckoDisplayListType result;
    result.tag = Tag::None;
    return result;
  }

  bool IsNone() const {
    return tag == Tag::None;
  }

  static GeckoDisplayListType Partial(const double &a0) {
    GeckoDisplayListType result;
    ::new (&result.partial._0) (double)(a0);
    result.tag = Tag::Partial;
    return result;
  }

  bool IsPartial() const {
    return tag == Tag::Partial;
  }

  static GeckoDisplayListType Full(const double &a0) {
    GeckoDisplayListType result;
    ::new (&result.full._0) (double)(a0);
    result.tag = Tag::Full;
    return result;
  }

  bool IsFull() const {
    return tag == Tag::Full;
  }

  static GeckoDisplayListType Sentinel() {
    GeckoDisplayListType result;
    result.tag = Tag::Sentinel;
    return result;
  }

  bool IsSentinel() const {
    return tag == Tag::Sentinel;
  }

  bool operator==(const GeckoDisplayListType& aOther) const {
    if (tag != aOther.tag) {
      return false;
    }
    switch (tag) {
      case Tag::Partial: return partial == aOther.partial;
      case Tag::Full: return full == aOther.full;
      default: break;
    }
    return true;
  }
};

/// Describes the memory layout of a display list.
///
/// A display list consists of some number of display list items, followed by a number of display
/// items.
struct BuiltDisplayListDescriptor {
  /// Gecko specific information about the display list.
  GeckoDisplayListType gecko_display_list_type;
  /// The first IPC time stamp: before any work has been done
  uint64_t builder_start_time;
  /// The second IPC time stamp: after serialization
  uint64_t builder_finish_time;
  /// The third IPC time stamp: just before sending
  uint64_t send_start_time;
  /// The amount of clipping nodes created while building this display list.
  uintptr_t total_clip_nodes;
  /// The amount of spatial nodes created while building this display list.
  uintptr_t total_spatial_nodes;
  /// The size of the cache for this display list.
  uintptr_t cache_size;

  friend std::ostream& operator<<(std::ostream& aStream, const BuiltDisplayListDescriptor& aInstance) {
    return aStream << "{ " << "gecko_display_list_type=" << aInstance.gecko_display_list_type << ", "
                           << "builder_start_time=" << aInstance.builder_start_time << ", "
                           << "builder_finish_time=" << aInstance.builder_finish_time << ", "
                           << "send_start_time=" << aInstance.send_start_time << ", "
                           << "total_clip_nodes=" << aInstance.total_clip_nodes << ", "
                           << "total_spatial_nodes=" << aInstance.total_spatial_nodes << ", "
                           << "cache_size=" << aInstance.cache_size << " }";
  }
  bool operator==(const BuiltDisplayListDescriptor& aOther) const {
    return gecko_display_list_type == aOther.gecko_display_list_type &&
           builder_start_time == aOther.builder_start_time &&
           builder_finish_time == aOther.builder_finish_time &&
           send_start_time == aOther.send_start_time &&
           total_clip_nodes == aOther.total_clip_nodes &&
           total_spatial_nodes == aOther.total_spatial_nodes &&
           cache_size == aOther.cache_size;
  }
};

template<typename T>
struct WrAnimationPropertyValue {
  uint64_t id;
  T value;

  friend std::ostream& operator<<(std::ostream& aStream, const WrAnimationPropertyValue& aInstance) {
    return aStream << "{ " << "id=" << aInstance.id << ", "
                           << "value=" << aInstance.value << " }";
  }
};

using WrOpacityProperty = WrAnimationPropertyValue<float>;

/// A 3d transform stored as a column-major 4 by 4 matrix.
///
/// Transforms can be parametrized over the source and destination units, to describe a
/// transformation from a space to another.
/// For example, `Transform3D<f32, WorldSpace, ScreenSpace>::transform_point3d`
/// takes a `Point3D<f32, WorldSpace>` and returns a `Point3D<f32, ScreenSpace>`.
///
/// Transforms expose a set of convenience methods for pre- and post-transformations.
/// Pre-transformations (`pre_*` methods) correspond to adding an operation that is
/// applied before the rest of the transformation, while post-transformations (`then_*`
/// methods) add an operation that is applied after.
///
/// When translating Transform3D into general matrix representations, consider that the
/// representation follows the column major notation with column vectors.
///
/// ```text
///  |x'|   | m11 m12 m13 m14 |   |x|
///  |y'|   | m21 m22 m23 m24 |   |y|
///  |z'| = | m31 m32 m33 m34 | x |y|
///  |w |   | m41 m42 m43 m44 |   |1|
/// ```
///
/// The translation terms are m41, m42 and m43.
template<typename T, typename Src, typename Dst>
struct Transform3D {
  T m11;
  T m12;
  T m13;
  T m14;
  T m21;
  T m22;
  T m23;
  T m24;
  T m31;
  T m32;
  T m33;
  T m34;
  T m41;
  T m42;
  T m43;
  T m44;

  friend std::ostream& operator<<(std::ostream& aStream, const Transform3D& aInstance) {
    return aStream << "{ " << "m11=" << aInstance.m11 << ", "
                           << "m12=" << aInstance.m12 << ", "
                           << "m13=" << aInstance.m13 << ", "
                           << "m14=" << aInstance.m14 << ", "
                           << "m21=" << aInstance.m21 << ", "
                           << "m22=" << aInstance.m22 << ", "
                           << "m23=" << aInstance.m23 << ", "
                           << "m24=" << aInstance.m24 << ", "
                           << "m31=" << aInstance.m31 << ", "
                           << "m32=" << aInstance.m32 << ", "
                           << "m33=" << aInstance.m33 << ", "
                           << "m34=" << aInstance.m34 << ", "
                           << "m41=" << aInstance.m41 << ", "
                           << "m42=" << aInstance.m42 << ", "
                           << "m43=" << aInstance.m43 << ", "
                           << "m44=" << aInstance.m44 << " }";
  }
  bool operator==(const Transform3D& aOther) const {
    return m11 == aOther.m11 &&
           m12 == aOther.m12 &&
           m13 == aOther.m13 &&
           m14 == aOther.m14 &&
           m21 == aOther.m21 &&
           m22 == aOther.m22 &&
           m23 == aOther.m23 &&
           m24 == aOther.m24 &&
           m31 == aOther.m31 &&
           m32 == aOther.m32 &&
           m33 == aOther.m33 &&
           m34 == aOther.m34 &&
           m41 == aOther.m41 &&
           m42 == aOther.m42 &&
           m43 == aOther.m43 &&
           m44 == aOther.m44;
  }
};

using LayoutTransform = Transform3D<float, LayoutPixel, LayoutPixel>;

using WrTransformProperty = WrAnimationPropertyValue<LayoutTransform>;

using WrColorProperty = WrAnimationPropertyValue<ColorF>;

/// An external identifier that uniquely identifies a scroll frame independent of its ClipId, which
/// may change from frame to frame. This should be unique within a pipeline. WebRender makes no
/// attempt to ensure uniqueness. The zero value is reserved for use by the root scroll node of
/// every pipeline, which always has an external id.
///
/// When setting display lists with the `preserve_frame_state` this id is used to preserve scroll
/// offsets between different sets of SpatialNodes which are ScrollFrames.
struct ExternalScrollId {
  uint64_t _0;
  PipelineId _1;

  friend std::ostream& operator<<(std::ostream& aStream, const ExternalScrollId& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << ", "
                           << "_1=" << aInstance._1 << " }";
  }
  bool operator==(const ExternalScrollId& aOther) const {
    return _0 == aOther._0 &&
           _1 == aOther._1;
  }
};

using LayoutVector2D = Vector2D<float, LayoutPixel>;

using APZScrollGeneration = uint64_t;

struct SampledScrollOffset {
  LayoutVector2D offset;
  APZScrollGeneration generation;

  friend std::ostream& operator<<(std::ostream& aStream, const SampledScrollOffset& aInstance) {
    return aStream << "{ " << "offset=" << aInstance.offset << ", "
                           << "generation=" << aInstance.generation << " }";
  }
  bool operator==(const SampledScrollOffset& aOther) const {
    return offset == aOther.offset &&
           generation == aOther.generation;
  }
};

using LayoutRect = Box2D<float, LayoutPixel>;

struct MinimapData {
  bool is_root_content;
  LayoutRect visual_viewport;
  LayoutRect layout_viewport;
  LayoutRect scrollable_rect;
  LayoutRect displayport;
  LayoutTransform zoom_transform;
  PipelineId root_content_pipeline_id;
  uint64_t root_content_scroll_id;

  friend std::ostream& operator<<(std::ostream& aStream, const MinimapData& aInstance) {
    return aStream << "{ " << "is_root_content=" << aInstance.is_root_content << ", "
                           << "visual_viewport=" << aInstance.visual_viewport << ", "
                           << "layout_viewport=" << aInstance.layout_viewport << ", "
                           << "scrollable_rect=" << aInstance.scrollable_rect << ", "
                           << "displayport=" << aInstance.displayport << ", "
                           << "zoom_transform=" << aInstance.zoom_transform << ", "
                           << "root_content_pipeline_id=" << aInstance.root_content_pipeline_id << ", "
                           << "root_content_scroll_id=" << aInstance.root_content_scroll_id << " }";
  }
  bool operator==(const MinimapData& aOther) const {
    return is_root_content == aOther.is_root_content &&
           visual_viewport == aOther.visual_viewport &&
           layout_viewport == aOther.layout_viewport &&
           scrollable_rect == aOther.scrollable_rect &&
           displayport == aOther.displayport &&
           zoom_transform == aOther.zoom_transform &&
           root_content_pipeline_id == aOther.root_content_pipeline_id &&
           root_content_scroll_id == aOther.root_content_scroll_id;
  }
};

/// An opaque identifier describing an image registered with WebRender.
/// This is used as a handle to reference images, and is used as the
/// hash map key for the actual image storage in the `ResourceCache`.
struct ImageKey {
  IdNamespace mNamespace;
  uint32_t mHandle;

  friend std::ostream& operator<<(std::ostream& aStream, const ImageKey& aInstance) {
    return aStream << "{ " << "mNamespace=" << aInstance.mNamespace << ", "
                           << "mHandle=" << aInstance.mHandle << " }";
  }
  bool operator==(const ImageKey& aOther) const {
    return mNamespace == aOther.mNamespace &&
           mHandle == aOther.mHandle;
  }
  bool operator!=(const ImageKey& aOther) const {
    return mNamespace != aOther.mNamespace ||
           mHandle != aOther.mHandle;
  }
  static const ImageKey DUMMY;
};


using WrImageKey = ImageKey;

struct WrImageDescriptor {
  ImageFormat format;
  int32_t width;
  int32_t height;
  int32_t stride;
  OpacityType opacity;
  bool prefer_compositor_surface;

  friend std::ostream& operator<<(std::ostream& aStream, const WrImageDescriptor& aInstance) {
    return aStream << "{ " << "format=" << aInstance.format << ", "
                           << "width=" << aInstance.width << ", "
                           << "height=" << aInstance.height << ", "
                           << "stride=" << aInstance.stride << ", "
                           << "opacity=" << aInstance.opacity << ", "
                           << "prefer_compositor_surface=" << aInstance.prefer_compositor_surface << " }";
  }
  bool operator==(const WrImageDescriptor& aOther) const {
    return format == aOther.format &&
           width == aOther.width &&
           height == aOther.height &&
           stride == aOther.stride &&
           opacity == aOther.opacity &&
           prefer_compositor_surface == aOther.prefer_compositor_surface;
  }
};

/// An opaque identifier describing a blob image registered with WebRender.
/// This is used as a handle to reference blob images, and can be used as an
/// image in display items.
struct BlobImageKey {
  ImageKey _0;

  friend std::ostream& operator<<(std::ostream& aStream, const BlobImageKey& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const BlobImageKey& aOther) const {
    return _0 == aOther._0;
  }
};

/// Storage format identifier for externally-managed images.
union ExternalImageType {
  enum class Tag : uint8_t {
    /// The image is texture-backed.
    TextureHandle,
    /// The image is heap-allocated by the embedding.
    Buffer,
    /// Must be last for serialization purposes
    Sentinel,
  };

  friend std::ostream& operator<<(std::ostream& aStream, const Tag& aInstance) {
    using Tag = ExternalImageType::Tag;
    switch (aInstance) {
      case Tag::TextureHandle: aStream << "TextureHandle"; break;
      case Tag::Buffer: aStream << "Buffer"; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  friend std::ostream& operator<<(std::ostream& aStream, const ExternalImageType& aInstance) {
    using Tag = ExternalImageType::Tag;
    switch (aInstance.tag) {
      case Tag::TextureHandle: aStream << aInstance.texture_handle; break;
      case Tag::Buffer: aStream << "Buffer"; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  struct TextureHandle_Body {
    Tag tag;
    ImageBufferKind _0;

    friend std::ostream& operator<<(std::ostream& aStream, const TextureHandle_Body& aInstance) {
      return aStream << "{ " << "tag=" << aInstance.tag << ", "
                             << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const TextureHandle_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct {
    Tag tag;
  };
  TextureHandle_Body texture_handle;

  static ExternalImageType TextureHandle(const ImageBufferKind &a0) {
    ExternalImageType result;
    ::new (&result.texture_handle._0) (ImageBufferKind)(a0);
    result.tag = Tag::TextureHandle;
    return result;
  }

  bool IsTextureHandle() const {
    return tag == Tag::TextureHandle;
  }

  static ExternalImageType Buffer() {
    ExternalImageType result;
    result.tag = Tag::Buffer;
    return result;
  }

  bool IsBuffer() const {
    return tag == Tag::Buffer;
  }

  static ExternalImageType Sentinel() {
    ExternalImageType result;
    result.tag = Tag::Sentinel;
    return result;
  }

  bool IsSentinel() const {
    return tag == Tag::Sentinel;
  }

  bool operator==(const ExternalImageType& aOther) const {
    if (tag != aOther.tag) {
      return false;
    }
    switch (tag) {
      case Tag::TextureHandle: return texture_handle == aOther.texture_handle;
      default: break;
    }
    return true;
  }
};

using LayoutIntRect = Box2D<int32_t, LayoutPixel>;

/// An opaque identifier describing a snapshot image registered with WebRender.
/// This is used as a handle to reference snapshot images, and can be used as an
/// image in display items.
struct SnapshotImageKey {
  ImageKey _0;

  friend std::ostream& operator<<(std::ostream& aStream, const SnapshotImageKey& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const SnapshotImageKey& aOther) const {
    return _0 == aOther._0;
  }
};

struct FontKey {
  IdNamespace mNamespace;
  uint32_t mHandle;

  friend std::ostream& operator<<(std::ostream& aStream, const FontKey& aInstance) {
    return aStream << "{ " << "mNamespace=" << aInstance.mNamespace << ", "
                           << "mHandle=" << aInstance.mHandle << " }";
  }
  bool operator==(const FontKey& aOther) const {
    return mNamespace == aOther.mNamespace &&
           mHandle == aOther.mHandle;
  }
};

using WrFontKey = FontKey;

struct FontInstanceKey {
  IdNamespace mNamespace;
  uint32_t mHandle;

  friend std::ostream& operator<<(std::ostream& aStream, const FontInstanceKey& aInstance) {
    return aStream << "{ " << "mNamespace=" << aInstance.mNamespace << ", "
                           << "mHandle=" << aInstance.mHandle << " }";
  }
  bool operator==(const FontInstanceKey& aOther) const {
    return mNamespace == aOther.mNamespace &&
           mHandle == aOther.mHandle;
  }
};

using WrFontInstanceKey = FontInstanceKey;

struct FontInstanceFlags {
  uint32_t _0;

  constexpr explicit operator bool() const {
    return !!_0;
  }
  constexpr FontInstanceFlags operator~() const {
    return FontInstanceFlags { static_cast<decltype(_0)>(~_0) };
  }
  constexpr FontInstanceFlags operator|(const FontInstanceFlags& aOther) const {
    return FontInstanceFlags { static_cast<decltype(_0)>(this->_0 | aOther._0) };
  }
  FontInstanceFlags& operator|=(const FontInstanceFlags& aOther) {
    *this = (*this | aOther);
    return *this;
  }
  constexpr FontInstanceFlags operator&(const FontInstanceFlags& aOther) const {
    return FontInstanceFlags { static_cast<decltype(_0)>(this->_0 & aOther._0) };
  }
  FontInstanceFlags& operator&=(const FontInstanceFlags& aOther) {
    *this = (*this & aOther);
    return *this;
  }
  constexpr FontInstanceFlags operator^(const FontInstanceFlags& aOther) const {
    return FontInstanceFlags { static_cast<decltype(_0)>(this->_0 ^ aOther._0) };
  }
  FontInstanceFlags& operator^=(const FontInstanceFlags& aOther) {
    *this = (*this ^ aOther);
    return *this;
  }
  friend std::ostream& operator<<(std::ostream& aStream, const FontInstanceFlags& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const FontInstanceFlags& aOther) const {
    return _0 == aOther._0;
  }
  static const FontInstanceFlags SYNTHETIC_BOLD;
  static const FontInstanceFlags EMBEDDED_BITMAPS;
  static const FontInstanceFlags SUBPIXEL_BGR;
  static const FontInstanceFlags TRANSPOSE;
  static const FontInstanceFlags FLIP_X;
  static const FontInstanceFlags FLIP_Y;
  static const FontInstanceFlags SUBPIXEL_POSITION;
  static const FontInstanceFlags VERTICAL;
  static const FontInstanceFlags MULTISTRIKE_BOLD;
  static const FontInstanceFlags TRANSFORM_GLYPHS;
  static const FontInstanceFlags TEXTURE_PADDING;
  static const FontInstanceFlags FORCE_GDI;
  static const FontInstanceFlags FORCE_SYMMETRIC;
  static const FontInstanceFlags NO_SYMMETRIC;
  static const FontInstanceFlags FONT_SMOOTHING;
  static const FontInstanceFlags FORCE_AUTOHINT;
  static const FontInstanceFlags NO_AUTOHINT;
  static const FontInstanceFlags VERTICAL_LAYOUT;
  static const FontInstanceFlags LCD_VERTICAL;
};
constexpr inline const FontInstanceFlags FontInstanceFlags::SYNTHETIC_BOLD = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 1)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::EMBEDDED_BITMAPS = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 2)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::SUBPIXEL_BGR = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 3)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::TRANSPOSE = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 4)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::FLIP_X = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 5)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::FLIP_Y = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 6)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::SUBPIXEL_POSITION = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 7)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::VERTICAL = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 8)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::MULTISTRIKE_BOLD = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 9)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::TRANSFORM_GLYPHS = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 12)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::TEXTURE_PADDING = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 13)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::FORCE_GDI = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 16)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::FORCE_SYMMETRIC = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 17)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::NO_SYMMETRIC = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 18)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::FONT_SMOOTHING = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 16)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::FORCE_AUTOHINT = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 16)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::NO_AUTOHINT = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 17)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::VERTICAL_LAYOUT = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 18)
};
constexpr inline const FontInstanceFlags FontInstanceFlags::LCD_VERTICAL = FontInstanceFlags{
  /* ._0 = */ (uint32_t)(1 << 19)
};

struct SyntheticItalics {
  int16_t angle;

  friend std::ostream& operator<<(std::ostream& aStream, const SyntheticItalics& aInstance) {
    return aStream << "{ " << "angle=" << aInstance.angle << " }";
  }
  bool operator==(const SyntheticItalics& aOther) const {
    return angle == aOther.angle;
  }
  static const float ANGLE_SCALE;
};
constexpr inline const float SyntheticItalics::ANGLE_SCALE = 256.0;

struct FontInstanceOptions {
  FontInstanceFlags flags;
  SyntheticItalics synthetic_italics;
  FontRenderMode render_mode;
  uint8_t _padding;

  friend std::ostream& operator<<(std::ostream& aStream, const FontInstanceOptions& aInstance) {
    return aStream << "{ " << "flags=" << aInstance.flags << ", "
                           << "synthetic_italics=" << aInstance.synthetic_italics << ", "
                           << "render_mode=" << aInstance.render_mode << ", "
                           << "_padding=" << aInstance._padding << " }";
  }
  bool operator==(const FontInstanceOptions& aOther) const {
    return flags == aOther.flags &&
           synthetic_italics == aOther.synthetic_italics &&
           render_mode == aOther.render_mode &&
           _padding == aOther._padding;
  }
};

#if defined(XP_WIN)
struct FontInstancePlatformOptions {
  uint16_t gamma;
  uint8_t contrast;
  uint8_t cleartype_level;

  friend std::ostream& operator<<(std::ostream& aStream, const FontInstancePlatformOptions& aInstance) {
    return aStream << "{ " << "gamma=" << aInstance.gamma << ", "
                           << "contrast=" << aInstance.contrast << ", "
                           << "cleartype_level=" << aInstance.cleartype_level << " }";
  }
  bool operator==(const FontInstancePlatformOptions& aOther) const {
    return gamma == aOther.gamma &&
           contrast == aOther.contrast &&
           cleartype_level == aOther.cleartype_level;
  }
};
#endif

#if defined(XP_MACOSX)
struct FontInstancePlatformOptions {
  uint32_t unused;

  friend std::ostream& operator<<(std::ostream& aStream, const FontInstancePlatformOptions& aInstance) {
    return aStream << "{ " << "unused=" << aInstance.unused << " }";
  }
  bool operator==(const FontInstancePlatformOptions& aOther) const {
    return unused == aOther.unused;
  }
};
#endif

#if !(defined(XP_MACOSX) || defined(XP_WIN))
struct FontInstancePlatformOptions {
  FontLCDFilter lcd_filter;
  FontHinting hinting;

  friend std::ostream& operator<<(std::ostream& aStream, const FontInstancePlatformOptions& aInstance) {
    return aStream << "{ " << "lcd_filter=" << aInstance.lcd_filter << ", "
                           << "hinting=" << aInstance.hinting << " }";
  }
  bool operator==(const FontInstancePlatformOptions& aOther) const {
    return lcd_filter == aOther.lcd_filter &&
           hinting == aOther.hinting;
  }
};
#endif

using WrIdNamespace = IdNamespace;

struct WrSpatialId {
  uintptr_t id;

  friend std::ostream& operator<<(std::ostream& aStream, const WrSpatialId& aInstance) {
    return aStream << "{ " << "id=" << aInstance.id << " }";
  }
  bool operator==(const WrSpatialId& aOther) const {
    return id == aOther.id;
  }
};

struct WrStackingContextClip {
  enum class Tag {
    None,
    ClipChain,
    /// Must be last for serialization purposes
    Sentinel,
  };

  friend std::ostream& operator<<(std::ostream& aStream, const Tag& aInstance) {
    using Tag = WrStackingContextClip::Tag;
    switch (aInstance) {
      case Tag::None: aStream << "None"; break;
      case Tag::ClipChain: aStream << "ClipChain"; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  friend std::ostream& operator<<(std::ostream& aStream, const WrStackingContextClip& aInstance) {
    using Tag = WrStackingContextClip::Tag;
    switch (aInstance.tag) {
      case Tag::None: aStream << "None"; break;
      case Tag::ClipChain: aStream << "ClipChain" << aInstance.clip_chain; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  struct ClipChain_Body {
    uint64_t _0;

    friend std::ostream& operator<<(std::ostream& aStream, const ClipChain_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const ClipChain_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  Tag tag;
  union {
    ClipChain_Body clip_chain;
  };

  static WrStackingContextClip None() {
    WrStackingContextClip result;
    result.tag = Tag::None;
    return result;
  }

  bool IsNone() const {
    return tag == Tag::None;
  }

  static WrStackingContextClip ClipChain(const uint64_t &a0) {
    WrStackingContextClip result;
    ::new (&result.clip_chain._0) (uint64_t)(a0);
    result.tag = Tag::ClipChain;
    return result;
  }

  bool IsClipChain() const {
    return tag == Tag::ClipChain;
  }

  static WrStackingContextClip Sentinel() {
    WrStackingContextClip result;
    result.tag = Tag::Sentinel;
    return result;
  }

  bool IsSentinel() const {
    return tag == Tag::Sentinel;
  }

  bool operator==(const WrStackingContextClip& aOther) const {
    if (tag != aOther.tag) {
      return false;
    }
    switch (tag) {
      case Tag::ClipChain: return clip_chain == aOther.clip_chain;
      default: break;
    }
    return true;
  }
};

/// Defines a caller provided key that is unique for a given spatial node, and is stable across
/// display lists. WR uses this to determine which spatial nodes are added / removed for a new
/// display list. The content itself is arbitrary and opaque to WR, the only thing that matters
/// is that it's unique and stable between display lists.
struct SpatialTreeItemKey {
  uint64_t key0;
  uint64_t key1;

  friend std::ostream& operator<<(std::ostream& aStream, const SpatialTreeItemKey& aInstance) {
    return aStream << "{ " << "key0=" << aInstance.key0 << ", "
                           << "key1=" << aInstance.key1 << " }";
  }
  bool operator==(const SpatialTreeItemKey& aOther) const {
    return key0 == aOther.key0 &&
           key1 == aOther.key1;
  }
};

struct WrAnimationProperty {
  WrAnimationType effect_type;
  uint64_t id;
  SpatialTreeItemKey key;

  friend std::ostream& operator<<(std::ostream& aStream, const WrAnimationProperty& aInstance) {
    return aStream << "{ " << "effect_type=" << aInstance.effect_type << ", "
                           << "id=" << aInstance.id << ", "
                           << "key=" << aInstance.key << " }";
  }
  bool operator==(const WrAnimationProperty& aOther) const {
    return effect_type == aOther.effect_type &&
           id == aOther.id &&
           key == aOther.key;
  }
};

using LayoutSize = Size2D<float, LayoutPixel>;

struct WrComputedTransformData {
  LayoutSize scale_from;
  bool vertical_flip;
  WrRotation rotation;
  SpatialTreeItemKey key;

  friend std::ostream& operator<<(std::ostream& aStream, const WrComputedTransformData& aInstance) {
    return aStream << "{ " << "scale_from=" << aInstance.scale_from << ", "
                           << "vertical_flip=" << aInstance.vertical_flip << ", "
                           << "rotation=" << aInstance.rotation << ", "
                           << "key=" << aInstance.key << " }";
  }
  bool operator==(const WrComputedTransformData& aOther) const {
    return scale_from == aOther.scale_from &&
           vertical_flip == aOther.vertical_flip &&
           rotation == aOther.rotation &&
           key == aOther.key;
  }
};

/// If passed in a stacking context display item, inform WebRender that
/// the contents of the stacking context should be retained into a texture
/// and associated to an image key.
///
/// Image display items can then display the cached snapshot using the
/// same image key.
///
/// The flow for creating/using/deleting snapshots is the same as with
/// regular images:
///  - The image key must have been created with `Transaction::add_snapshot_image`.
///  - The current scene must not contain references to the snapshot when
///    `Transaction::delete_snapshot_image` is called.
struct SnapshotInfo {
  /// The image key to associate the snapshot with.
  SnapshotImageKey key;
  /// The bounds of the snapshot in local space.
  ///
  /// This rectangle is relative to the same coordinate space as the
  /// child items of the stacking context.
  LayoutRect area;
  /// If true, detach the stacking context from the scene and only
  /// render it into the snapshot.
  /// If false, the stacking context rendered in the frame normally
  /// in addition to being cached into the snapshot.
  bool detached;

  friend std::ostream& operator<<(std::ostream& aStream, const SnapshotInfo& aInstance) {
    return aStream << "{ " << "key=" << aInstance.key << ", "
                           << "area=" << aInstance.area << ", "
                           << "detached=" << aInstance.detached << " }";
  }
  bool operator==(const SnapshotInfo& aOther) const {
    return key == aOther.key &&
           area == aOther.area &&
           detached == aOther.detached;
  }
};

struct PrimitiveFlags {
  uint8_t _0;

  constexpr explicit operator bool() const {
    return !!_0;
  }
  constexpr PrimitiveFlags operator~() const {
    return PrimitiveFlags { static_cast<decltype(_0)>(~_0) };
  }
  constexpr PrimitiveFlags operator|(const PrimitiveFlags& aOther) const {
    return PrimitiveFlags { static_cast<decltype(_0)>(this->_0 | aOther._0) };
  }
  PrimitiveFlags& operator|=(const PrimitiveFlags& aOther) {
    *this = (*this | aOther);
    return *this;
  }
  constexpr PrimitiveFlags operator&(const PrimitiveFlags& aOther) const {
    return PrimitiveFlags { static_cast<decltype(_0)>(this->_0 & aOther._0) };
  }
  PrimitiveFlags& operator&=(const PrimitiveFlags& aOther) {
    *this = (*this & aOther);
    return *this;
  }
  constexpr PrimitiveFlags operator^(const PrimitiveFlags& aOther) const {
    return PrimitiveFlags { static_cast<decltype(_0)>(this->_0 ^ aOther._0) };
  }
  PrimitiveFlags& operator^=(const PrimitiveFlags& aOther) {
    *this = (*this ^ aOther);
    return *this;
  }
  friend std::ostream& operator<<(std::ostream& aStream, const PrimitiveFlags& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const PrimitiveFlags& aOther) const {
    return _0 == aOther._0;
  }
  static const PrimitiveFlags IS_BACKFACE_VISIBLE;
  static const PrimitiveFlags IS_SCROLLBAR_CONTAINER;
  static const PrimitiveFlags PREFER_COMPOSITOR_SURFACE;
  static const PrimitiveFlags SUPPORTS_EXTERNAL_COMPOSITOR_SURFACE;
  static const PrimitiveFlags ANTIALISED;
  static const PrimitiveFlags CHECKERBOARD_BACKGROUND;
};
/// The CSS backface-visibility property (yes, it can be really granular)
constexpr inline const PrimitiveFlags PrimitiveFlags::IS_BACKFACE_VISIBLE = PrimitiveFlags{
  /* ._0 = */ (uint8_t)(1 << 0)
};
/// If set, this primitive represents a scroll bar container
constexpr inline const PrimitiveFlags PrimitiveFlags::IS_SCROLLBAR_CONTAINER = PrimitiveFlags{
  /* ._0 = */ (uint8_t)(1 << 1)
};
/// This is used as a performance hint - this primitive may be promoted to a native
/// compositor surface under certain (implementation specific) conditions. This
/// is typically used for large videos, and canvas elements.
constexpr inline const PrimitiveFlags PrimitiveFlags::PREFER_COMPOSITOR_SURFACE = PrimitiveFlags{
  /* ._0 = */ (uint8_t)(1 << 2)
};
/// If set, this primitive can be passed directly to the compositor via its
/// ExternalImageId, and the compositor will use the native image directly.
/// Used as a further extension on top of PREFER_COMPOSITOR_SURFACE.
constexpr inline const PrimitiveFlags PrimitiveFlags::SUPPORTS_EXTERNAL_COMPOSITOR_SURFACE = PrimitiveFlags{
  /* ._0 = */ (uint8_t)(1 << 3)
};
/// This flags disables snapping and forces anti-aliasing even if the primitive is axis-aligned.
constexpr inline const PrimitiveFlags PrimitiveFlags::ANTIALISED = PrimitiveFlags{
  /* ._0 = */ (uint8_t)(1 << 4)
};
/// If true, this primitive is used as a background for checkerboarding
constexpr inline const PrimitiveFlags PrimitiveFlags::CHECKERBOARD_BACKGROUND = PrimitiveFlags{
  /* ._0 = */ (uint8_t)(1 << 5)
};

struct StackingContextFlags {
  uint8_t _0;

  constexpr explicit operator bool() const {
    return !!_0;
  }
  constexpr StackingContextFlags operator~() const {
    return StackingContextFlags { static_cast<decltype(_0)>(~_0) };
  }
  constexpr StackingContextFlags operator|(const StackingContextFlags& aOther) const {
    return StackingContextFlags { static_cast<decltype(_0)>(this->_0 | aOther._0) };
  }
  StackingContextFlags& operator|=(const StackingContextFlags& aOther) {
    *this = (*this | aOther);
    return *this;
  }
  constexpr StackingContextFlags operator&(const StackingContextFlags& aOther) const {
    return StackingContextFlags { static_cast<decltype(_0)>(this->_0 & aOther._0) };
  }
  StackingContextFlags& operator&=(const StackingContextFlags& aOther) {
    *this = (*this & aOther);
    return *this;
  }
  constexpr StackingContextFlags operator^(const StackingContextFlags& aOther) const {
    return StackingContextFlags { static_cast<decltype(_0)>(this->_0 ^ aOther._0) };
  }
  StackingContextFlags& operator^=(const StackingContextFlags& aOther) {
    *this = (*this ^ aOther);
    return *this;
  }
  friend std::ostream& operator<<(std::ostream& aStream, const StackingContextFlags& aInstance) {
    return aStream << "{ " << "_0=" << aInstance._0 << " }";
  }
  bool operator==(const StackingContextFlags& aOther) const {
    return _0 == aOther._0;
  }
  static const StackingContextFlags IS_BLEND_CONTAINER;
  static const StackingContextFlags WRAPS_BACKDROP_FILTER;
  static const StackingContextFlags FORCED_ISOLATION;
};
/// If true, this stacking context is a blend container than contains
/// mix-blend-mode children (and should thus be isolated).
constexpr inline const StackingContextFlags StackingContextFlags::IS_BLEND_CONTAINER = StackingContextFlags{
  /* ._0 = */ (uint8_t)(1 << 0)
};
/// If true, this stacking context is a wrapper around a backdrop-filter (e.g. for
/// a clip-mask). This is needed to allow the correct selection of a backdrop root
/// since a clip-mask stacking context creates a parent surface.
constexpr inline const StackingContextFlags StackingContextFlags::WRAPS_BACKDROP_FILTER = StackingContextFlags{
  /* ._0 = */ (uint8_t)(1 << 1)
};
/// If true, this stacking context must be isolated from parent by a surface.
constexpr inline const StackingContextFlags StackingContextFlags::FORCED_ISOLATION = StackingContextFlags{
  /* ._0 = */ (uint8_t)(1 << 2)
};

/// IMPORTANT: If you add fields to this struct, you need to also add initializers
/// for those fields in WebRenderAPI.h.
struct WrStackingContextParams {
  WrStackingContextClip clip;
  const WrAnimationProperty *animation;
  const float *opacity;
  const WrComputedTransformData *computed_transform;
  const SnapshotInfo *snapshot;
  TransformStyle transform_style;
  WrReferenceFrameKind reference_frame_kind;
  bool is_2d_scale_translation;
  bool should_snap;
  bool paired_with_perspective;
  const uint64_t *scrolling_relative_to;
  PrimitiveFlags prim_flags;
  MixBlendMode mix_blend_mode;
  StackingContextFlags flags;

  friend std::ostream& operator<<(std::ostream& aStream, const WrStackingContextParams& aInstance) {
    return aStream << "{ " << "clip=" << aInstance.clip << ", "
                           << "animation=" << aInstance.animation << ", "
                           << "opacity=" << aInstance.opacity << ", "
                           << "computed_transform=" << aInstance.computed_transform << ", "
                           << "snapshot=" << aInstance.snapshot << ", "
                           << "transform_style=" << aInstance.transform_style << ", "
                           << "reference_frame_kind=" << aInstance.reference_frame_kind << ", "
                           << "is_2d_scale_translation=" << aInstance.is_2d_scale_translation << ", "
                           << "should_snap=" << aInstance.should_snap << ", "
                           << "paired_with_perspective=" << aInstance.paired_with_perspective << ", "
                           << "scrolling_relative_to=" << aInstance.scrolling_relative_to << ", "
                           << "prim_flags=" << aInstance.prim_flags << ", "
                           << "mix_blend_mode=" << aInstance.mix_blend_mode << ", "
                           << "flags=" << aInstance.flags << " }";
  }
  bool operator==(const WrStackingContextParams& aOther) const {
    return clip == aOther.clip &&
           animation == aOther.animation &&
           opacity == aOther.opacity &&
           computed_transform == aOther.computed_transform &&
           snapshot == aOther.snapshot &&
           transform_style == aOther.transform_style &&
           reference_frame_kind == aOther.reference_frame_kind &&
           is_2d_scale_translation == aOther.is_2d_scale_translation &&
           should_snap == aOther.should_snap &&
           paired_with_perspective == aOther.paired_with_perspective &&
           scrolling_relative_to == aOther.scrolling_relative_to &&
           prim_flags == aOther.prim_flags &&
           mix_blend_mode == aOther.mix_blend_mode &&
           flags == aOther.flags;
  }
};

struct WrTransformInfo {
  LayoutTransform transform;
  SpatialTreeItemKey key;

  friend std::ostream& operator<<(std::ostream& aStream, const WrTransformInfo& aInstance) {
    return aStream << "{ " << "transform=" << aInstance.transform << ", "
                           << "key=" << aInstance.key << " }";
  }
  bool operator==(const WrTransformInfo& aOther) const {
    return transform == aOther.transform &&
           key == aOther.key;
  }
};

/// A key to identify an animated property binding.
struct PropertyBindingId {
  IdNamespace namespace_;
  uint32_t uid;

  friend std::ostream& operator<<(std::ostream& aStream, const PropertyBindingId& aInstance) {
    return aStream << "{ " << "namespace_=" << aInstance.namespace_ << ", "
                           << "uid=" << aInstance.uid << " }";
  }
  bool operator==(const PropertyBindingId& aOther) const {
    return namespace_ == aOther.namespace_ &&
           uid == aOther.uid;
  }
};

/// A unique key that is used for connecting animated property
/// values to bindings in the display list.
template<typename T>
struct PropertyBindingKey {
  ///
  PropertyBindingId id;

  friend std::ostream& operator<<(std::ostream& aStream, const PropertyBindingKey& aInstance) {
    return aStream << "{ " << "id=" << aInstance.id << " }";
  }
  bool operator==(const PropertyBindingKey& aOther) const {
    return id == aOther.id;
  }
};

/// A binding property can either be a specific value
/// (the normal, non-animated case) or point to a binding location
/// to fetch the current value from.
/// Note that Binding has also a non-animated value, the value is
/// used for the case where the animation is still in-delay phase
/// (i.e. the animation doesn't produce any animation values).
template<typename T>
struct PropertyBinding {
  enum class Tag {
    /// Non-animated value.
    Value,
    /// Animated binding.
    Binding,
    /// Must be last for serialization purposes
    Sentinel,
  };

  friend std::ostream& operator<<(std::ostream& aStream, const Tag& aInstance) {
    using Tag = PropertyBinding::Tag;
    switch (aInstance) {
      case Tag::Value: aStream << "Value"; break;
      case Tag::Binding: aStream << "Binding"; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  friend std::ostream& operator<<(std::ostream& aStream, const PropertyBinding& aInstance) {
    using Tag = PropertyBinding::Tag;
    switch (aInstance.tag) {
      case Tag::Value: aStream << "Value" << aInstance.value; break;
      case Tag::Binding: aStream << "Binding" << aInstance.binding; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  struct Value_Body {
    T _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Value_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Value_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct Binding_Body {
    PropertyBindingKey<T> _0;
    T _1;

    friend std::ostream& operator<<(std::ostream& aStream, const Binding_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << ", "
                             << "_1=" << aInstance._1 << " }";
    }
    bool operator==(const Binding_Body& aOther) const {
      return _0 == aOther._0 &&
             _1 == aOther._1;
    }
  };

  Tag tag;
  union {
    Value_Body value;
    Binding_Body binding;
  };

  static PropertyBinding Value(const T &a0) {
    PropertyBinding result;
    ::new (&result.value._0) (T)(a0);
    result.tag = Tag::Value;
    return result;
  }

  bool IsValue() const {
    return tag == Tag::Value;
  }

  static PropertyBinding Binding(const PropertyBindingKey<T> &a0,
                                 const T &a1) {
    PropertyBinding result;
    ::new (&result.binding._0) (PropertyBindingKey<T>)(a0);
    ::new (&result.binding._1) (T)(a1);
    result.tag = Tag::Binding;
    return result;
  }

  bool IsBinding() const {
    return tag == Tag::Binding;
  }

  static PropertyBinding Sentinel() {
    PropertyBinding result;
    result.tag = Tag::Sentinel;
    return result;
  }

  bool IsSentinel() const {
    return tag == Tag::Sentinel;
  }

  bool operator==(const PropertyBinding& aOther) const {
    if (tag != aOther.tag) {
      return false;
    }
    switch (tag) {
      case Tag::Value: return value == aOther.value;
      case Tag::Binding: return binding == aOther.binding;
      default: break;
    }
    return true;
  }
};

struct Shadow {
  LayoutVector2D offset;
  ColorF color;
  float blur_radius;

  friend std::ostream& operator<<(std::ostream& aStream, const Shadow& aInstance) {
    return aStream << "{ " << "offset=" << aInstance.offset << ", "
                           << "color=" << aInstance.color << ", "
                           << "blur_radius=" << aInstance.blur_radius << " }";
  }
  bool operator==(const Shadow& aOther) const {
    return offset == aOther.offset &&
           color == aOther.color &&
           blur_radius == aOther.blur_radius;
  }
};

struct FilterOpGraphPictureBufferId {
  enum class Tag {
    /// empty slot in feMerge inputs
    None,
    /// reference to another (earlier) node in filter graph
    BufferId,
    /// Must be last for serialization purposes
    Sentinel,
  };

  friend std::ostream& operator<<(std::ostream& aStream, const Tag& aInstance) {
    using Tag = FilterOpGraphPictureBufferId::Tag;
    switch (aInstance) {
      case Tag::None: aStream << "None"; break;
      case Tag::BufferId: aStream << "BufferId"; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  friend std::ostream& operator<<(std::ostream& aStream, const FilterOpGraphPictureBufferId& aInstance) {
    using Tag = FilterOpGraphPictureBufferId::Tag;
    switch (aInstance.tag) {
      case Tag::None: aStream << "None"; break;
      case Tag::BufferId: aStream << "BufferId" << aInstance.buffer_id; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  struct BufferId_Body {
    int16_t _0;

    friend std::ostream& operator<<(std::ostream& aStream, const BufferId_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const BufferId_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  Tag tag;
  union {
    BufferId_Body buffer_id;
  };

  static FilterOpGraphPictureBufferId None() {
    FilterOpGraphPictureBufferId result;
    result.tag = Tag::None;
    return result;
  }

  bool IsNone() const {
    return tag == Tag::None;
  }

  static FilterOpGraphPictureBufferId BufferId(const int16_t &a0) {
    FilterOpGraphPictureBufferId result;
    ::new (&result.buffer_id._0) (int16_t)(a0);
    result.tag = Tag::BufferId;
    return result;
  }

  bool IsBufferId() const {
    return tag == Tag::BufferId;
  }

  static FilterOpGraphPictureBufferId Sentinel() {
    FilterOpGraphPictureBufferId result;
    result.tag = Tag::Sentinel;
    return result;
  }

  bool IsSentinel() const {
    return tag == Tag::Sentinel;
  }

  bool operator==(const FilterOpGraphPictureBufferId& aOther) const {
    if (tag != aOther.tag) {
      return false;
    }
    switch (tag) {
      case Tag::BufferId: return buffer_id == aOther.buffer_id;
      default: break;
    }
    return true;
  }
};

struct FilterOpGraphPictureReference {
  /// Id of the picture in question in a namespace unique to this filter DAG
  FilterOpGraphPictureBufferId buffer_id;

  friend std::ostream& operator<<(std::ostream& aStream, const FilterOpGraphPictureReference& aInstance) {
    return aStream << "{ " << "buffer_id=" << aInstance.buffer_id << " }";
  }
  bool operator==(const FilterOpGraphPictureReference& aOther) const {
    return buffer_id == aOther.buffer_id;
  }
};

struct FilterOpGraphNode {
  /// True if color_interpolation_filter == LinearRgb; shader will convert
  /// sRGB texture pixel colors on load and convert back on store, for correct
  /// interpolation
  bool linear;
  /// virtualized picture input binding 1 (i.e. texture source), typically
  /// this is used, but certain filters do not use it
  FilterOpGraphPictureReference input;
  /// virtualized picture input binding 2 (i.e. texture sources), only certain
  /// filters use this
  FilterOpGraphPictureReference input2;
  /// rect this node will render into, in filter space
  LayoutRect subregion;

  friend std::ostream& operator<<(std::ostream& aStream, const FilterOpGraphNode& aInstance) {
    return aStream << "{ " << "linear=" << aInstance.linear << ", "
                           << "input=" << aInstance.input << ", "
                           << "input2=" << aInstance.input2 << ", "
                           << "subregion=" << aInstance.subregion << " }";
  }
  bool operator==(const FilterOpGraphNode& aOther) const {
    return linear == aOther.linear &&
           input == aOther.input &&
           input2 == aOther.input2 &&
           subregion == aOther.subregion;
  }
};

struct FilterOp {
  enum class Tag {
    /// Filter that does no transformation of the colors, needed for
    /// debug purposes, and is the default value in impl_default_for_enums.
    /// parameters: none
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Identity,
    /// apply blur effect
    /// parameters: stdDeviationX, stdDeviationY
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Blur,
    /// apply brightness effect
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Brightness,
    /// apply contrast effect
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Contrast,
    /// fade image toward greyscale version of image
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Grayscale,
    /// fade image toward hue-rotated version of image (rotate RGB around color wheel)
    /// parameters: angle
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    HueRotate,
    /// fade image toward inverted image (1 - RGB)
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Invert,
    /// multiplies color and alpha by opacity
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Opacity,
    /// multiply saturation of colors
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Saturate,
    /// fade image toward sepia tone version of image
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Sepia,
    /// add drop shadow version of image to the image
    /// parameters: shadow
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    DropShadow,
    /// transform color and alpha in image through 4x5 color matrix (transposed for efficiency)
    /// parameters: matrix[5][4]
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    ColorMatrix,
    /// internal use - convert sRGB input to linear output
    /// parameters: none
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    SrgbToLinear,
    /// internal use - convert linear input to sRGB output
    /// parameters: none
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    LinearToSrgb,
    /// remap RGBA with color gradients and component swizzle
    /// parameters: FilterData
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    ComponentTransfer,
    /// replace image with a solid color
    /// NOTE: UNUSED; Gecko never produces this filter
    /// parameters: color
    /// CSS filter semantics - operates on previous picture,uses sRGB space (non-linear)
    Flood,
    /// Filter that copies the SourceGraphic image into the specified subregion,
    /// This is intentionally the only way to get SourceGraphic into the graph,
    /// as the filter region must be applied before it is used.
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - no inputs, no linear
    SVGFESourceGraphic,
    /// Filter that copies the SourceAlpha image into the specified subregion,
    /// This is intentionally the only way to get SourceGraphic into the graph,
    /// as the filter region must be applied before it is used.
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - no inputs, no linear
    SVGFESourceAlpha,
    /// Filter that does no transformation of the colors, used for subregion
    /// cropping only.
    SVGFEIdentity,
    /// represents CSS opacity property as a graph node like the rest of the SVGFE* filters
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    SVGFEOpacity,
    /// convert a color image to an alpha channel - internal use; generated by
    /// SVGFilterInstance::GetOrCreateSourceAlphaIndex().
    SVGFEToAlpha,
    /// combine 2 images with SVG_FEBLEND_MODE_DARKEN
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
    SVGFEBlendDarken,
    /// combine 2 images with SVG_FEBLEND_MODE_LIGHTEN
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
    SVGFEBlendLighten,
    /// combine 2 images with SVG_FEBLEND_MODE_MULTIPLY
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
    SVGFEBlendMultiply,
    /// combine 2 images with SVG_FEBLEND_MODE_NORMAL
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
    SVGFEBlendNormal,
    /// combine 2 images with SVG_FEBLEND_MODE_SCREEN
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
    SVGFEBlendScreen,
    /// combine 2 images with SVG_FEBLEND_MODE_OVERLAY
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendOverlay,
    /// combine 2 images with SVG_FEBLEND_MODE_COLOR_DODGE
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendColorDodge,
    /// combine 2 images with SVG_FEBLEND_MODE_COLOR_BURN
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendColorBurn,
    /// combine 2 images with SVG_FEBLEND_MODE_HARD_LIGHT
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendHardLight,
    /// combine 2 images with SVG_FEBLEND_MODE_SOFT_LIGHT
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendSoftLight,
    /// combine 2 images with SVG_FEBLEND_MODE_DIFFERENCE
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendDifference,
    /// combine 2 images with SVG_FEBLEND_MODE_EXCLUSION
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendExclusion,
    /// combine 2 images with SVG_FEBLEND_MODE_HUE
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendHue,
    /// combine 2 images with SVG_FEBLEND_MODE_SATURATION
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendSaturation,
    /// combine 2 images with SVG_FEBLEND_MODE_COLOR
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendColor,
    /// combine 2 images with SVG_FEBLEND_MODE_LUMINOSITY
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendLuminosity,
    /// transform colors of image through 5x4 color matrix (transposed for efficiency)
    /// parameters: FilterOpGraphNode, matrix[5][4]
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
    SVGFEColorMatrix,
    /// transform colors of image through configurable gradients with component swizzle
    /// parameters: FilterOpGraphNode, FilterData
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feComponentTransferElement
    SVGFEComponentTransfer,
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode, k1, k2, k3, k4
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeArithmetic,
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeATop,
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeIn,
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Docs: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComposite
    SVGFECompositeLighter,
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeOut,
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeOver,
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeXOR,
    /// transform image through convolution matrix of up to 25 values (spec
    /// allows more but for performance reasons we do not)
    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
    ///  divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
    ///  preserveAlpha
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
    SVGFEConvolveMatrixEdgeModeDuplicate,
    /// transform image through convolution matrix of up to 25 values (spec
    /// allows more but for performance reasons we do not)
    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
    ///  divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
    ///  preserveAlpha
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
    SVGFEConvolveMatrixEdgeModeNone,
    /// transform image through convolution matrix of up to 25 values (spec
    /// allows more but for performance reasons we do not)
    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
    ///  divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
    /// preserveAlpha
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
    SVGFEConvolveMatrixEdgeModeWrap,
    /// calculate lighting based on heightmap image with provided values for a
    /// distant light source with specified direction
    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
    ///  kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
    SVGFEDiffuseLightingDistant,
    /// calculate lighting based on heightmap image with provided values for a
    /// point light source at specified location
    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
    ///  kernelUnitLengthX, kernelUnitLengthY, x, y, z
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
    SVGFEDiffuseLightingPoint,
    /// calculate lighting based on heightmap image with provided values for a
    /// spot light source at specified location pointing at specified target
    /// location with specified hotspot sharpness and cone angle
    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
    ///  kernelUnitLengthX, kernelUnitLengthY, x, y, z, pointsAtX, pointsAtY,
    ///  pointsAtZ, specularExponent, limitingConeAngle
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
    /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
    SVGFEDiffuseLightingSpot,
    /// calculate a distorted version of first input image using offset values
    /// from second input image at specified intensity
    /// parameters: FilterOpGraphNode, scale, xChannelSelector, yChannelSelector
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDisplacementMapElement
    SVGFEDisplacementMap,
    /// create and merge a dropshadow version of the specified image's alpha
    /// channel with specified offset and blur radius
    /// parameters: FilterOpGraphNode, flood_color, flood_opacity, dx, dy,
    ///  stdDeviationX, stdDeviationY
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDropShadowElement
    SVGFEDropShadow,
    /// synthesize a new image of specified size containing a solid color
    /// parameters: FilterOpGraphNode, color
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEFloodElement
    SVGFEFlood,
    /// create a blurred version of the input image
    /// parameters: FilterOpGraphNode, stdDeviationX, stdDeviationY
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEGaussianBlurElement
    SVGFEGaussianBlur,
    /// synthesize a new image based on a url (i.e. blob image source)
    /// parameters: FilterOpGraphNode, sampling_filter (see SamplingFilter in Types.h), transform
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEImageElement
    SVGFEImage,
    /// create a new image based on the input image with the contour stretched
    /// outward (dilate operator)
    /// parameters: FilterOpGraphNode, radiusX, radiusY
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
    SVGFEMorphologyDilate,
    /// create a new image based on the input image with the contour shrunken
    /// inward (erode operator)
    /// parameters: FilterOpGraphNode, radiusX, radiusY
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
    SVGFEMorphologyErode,
    /// create a new image that is a scrolled version of the input image, this
    /// is basically a no-op as we support offset in the graph node
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEOffsetElement
    SVGFEOffset,
    /// calculate lighting based on heightmap image with provided values for a
    /// distant light source with specified direction
    /// parameters: FilerData, surfaceScale, specularConstant, specularExponent,
    ///  kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
    /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
    SVGFESpecularLightingDistant,
    /// calculate lighting based on heightmap image with provided values for a
    /// point light source at specified location
    /// parameters: FilterOpGraphNode, surfaceScale, specularConstant,
    ///  specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
    SVGFESpecularLightingPoint,
    /// calculate lighting based on heightmap image with provided values for a
    /// spot light source at specified location pointing at specified target
    /// location with specified hotspot sharpness and cone angle
    /// parameters: FilterOpGraphNode, surfaceScale, specularConstant,
    ///  specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z,
    ///  pointsAtX, pointsAtY, pointsAtZ, specularExponent, limitingConeAngle
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
    SVGFESpecularLightingSpot,
    /// create a new image based on the input image, repeated throughout the
    /// output rectangle
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETileElement
    SVGFETile,
    /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
    /// stitching mode
    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
    ///  numOctaves, seed
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
    SVGFETurbulenceWithFractalNoiseWithNoStitching,
    /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
    /// stitching mode
    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
    ///  numOctaves, seed
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
    SVGFETurbulenceWithFractalNoiseWithStitching,
    /// synthesize a new image based on Turbulence Noise (offset vectors)
    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
    ///  numOctaves, seed
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
    SVGFETurbulenceWithTurbulenceNoiseWithNoStitching,
    /// synthesize a new image based on Turbulence Noise (offset vectors)
    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
    ///  numOctaves, seed
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
    SVGFETurbulenceWithTurbulenceNoiseWithStitching,
    /// Must be last for serialization purposes
    Sentinel,
  };

  friend std::ostream& operator<<(std::ostream& aStream, const Tag& aInstance) {
    using Tag = FilterOp::Tag;
    switch (aInstance) {
      case Tag::Identity: aStream << "Identity"; break;
      case Tag::Blur: aStream << "Blur"; break;
      case Tag::Brightness: aStream << "Brightness"; break;
      case Tag::Contrast: aStream << "Contrast"; break;
      case Tag::Grayscale: aStream << "Grayscale"; break;
      case Tag::HueRotate: aStream << "HueRotate"; break;
      case Tag::Invert: aStream << "Invert"; break;
      case Tag::Opacity: aStream << "Opacity"; break;
      case Tag::Saturate: aStream << "Saturate"; break;
      case Tag::Sepia: aStream << "Sepia"; break;
      case Tag::DropShadow: aStream << "DropShadow"; break;
      case Tag::ColorMatrix: aStream << "ColorMatrix"; break;
      case Tag::SrgbToLinear: aStream << "SrgbToLinear"; break;
      case Tag::LinearToSrgb: aStream << "LinearToSrgb"; break;
      case Tag::ComponentTransfer: aStream << "ComponentTransfer"; break;
      case Tag::Flood: aStream << "Flood"; break;
      case Tag::SVGFESourceGraphic: aStream << "SVGFESourceGraphic"; break;
      case Tag::SVGFESourceAlpha: aStream << "SVGFESourceAlpha"; break;
      case Tag::SVGFEIdentity: aStream << "SVGFEIdentity"; break;
      case Tag::SVGFEOpacity: aStream << "SVGFEOpacity"; break;
      case Tag::SVGFEToAlpha: aStream << "SVGFEToAlpha"; break;
      case Tag::SVGFEBlendDarken: aStream << "SVGFEBlendDarken"; break;
      case Tag::SVGFEBlendLighten: aStream << "SVGFEBlendLighten"; break;
      case Tag::SVGFEBlendMultiply: aStream << "SVGFEBlendMultiply"; break;
      case Tag::SVGFEBlendNormal: aStream << "SVGFEBlendNormal"; break;
      case Tag::SVGFEBlendScreen: aStream << "SVGFEBlendScreen"; break;
      case Tag::SVGFEBlendOverlay: aStream << "SVGFEBlendOverlay"; break;
      case Tag::SVGFEBlendColorDodge: aStream << "SVGFEBlendColorDodge"; break;
      case Tag::SVGFEBlendColorBurn: aStream << "SVGFEBlendColorBurn"; break;
      case Tag::SVGFEBlendHardLight: aStream << "SVGFEBlendHardLight"; break;
      case Tag::SVGFEBlendSoftLight: aStream << "SVGFEBlendSoftLight"; break;
      case Tag::SVGFEBlendDifference: aStream << "SVGFEBlendDifference"; break;
      case Tag::SVGFEBlendExclusion: aStream << "SVGFEBlendExclusion"; break;
      case Tag::SVGFEBlendHue: aStream << "SVGFEBlendHue"; break;
      case Tag::SVGFEBlendSaturation: aStream << "SVGFEBlendSaturation"; break;
      case Tag::SVGFEBlendColor: aStream << "SVGFEBlendColor"; break;
      case Tag::SVGFEBlendLuminosity: aStream << "SVGFEBlendLuminosity"; break;
      case Tag::SVGFEColorMatrix: aStream << "SVGFEColorMatrix"; break;
      case Tag::SVGFEComponentTransfer: aStream << "SVGFEComponentTransfer"; break;
      case Tag::SVGFECompositeArithmetic: aStream << "SVGFECompositeArithmetic"; break;
      case Tag::SVGFECompositeATop: aStream << "SVGFECompositeATop"; break;
      case Tag::SVGFECompositeIn: aStream << "SVGFECompositeIn"; break;
      case Tag::SVGFECompositeLighter: aStream << "SVGFECompositeLighter"; break;
      case Tag::SVGFECompositeOut: aStream << "SVGFECompositeOut"; break;
      case Tag::SVGFECompositeOver: aStream << "SVGFECompositeOver"; break;
      case Tag::SVGFECompositeXOR: aStream << "SVGFECompositeXOR"; break;
      case Tag::SVGFEConvolveMatrixEdgeModeDuplicate: aStream << "SVGFEConvolveMatrixEdgeModeDuplicate"; break;
      case Tag::SVGFEConvolveMatrixEdgeModeNone: aStream << "SVGFEConvolveMatrixEdgeModeNone"; break;
      case Tag::SVGFEConvolveMatrixEdgeModeWrap: aStream << "SVGFEConvolveMatrixEdgeModeWrap"; break;
      case Tag::SVGFEDiffuseLightingDistant: aStream << "SVGFEDiffuseLightingDistant"; break;
      case Tag::SVGFEDiffuseLightingPoint: aStream << "SVGFEDiffuseLightingPoint"; break;
      case Tag::SVGFEDiffuseLightingSpot: aStream << "SVGFEDiffuseLightingSpot"; break;
      case Tag::SVGFEDisplacementMap: aStream << "SVGFEDisplacementMap"; break;
      case Tag::SVGFEDropShadow: aStream << "SVGFEDropShadow"; break;
      case Tag::SVGFEFlood: aStream << "SVGFEFlood"; break;
      case Tag::SVGFEGaussianBlur: aStream << "SVGFEGaussianBlur"; break;
      case Tag::SVGFEImage: aStream << "SVGFEImage"; break;
      case Tag::SVGFEMorphologyDilate: aStream << "SVGFEMorphologyDilate"; break;
      case Tag::SVGFEMorphologyErode: aStream << "SVGFEMorphologyErode"; break;
      case Tag::SVGFEOffset: aStream << "SVGFEOffset"; break;
      case Tag::SVGFESpecularLightingDistant: aStream << "SVGFESpecularLightingDistant"; break;
      case Tag::SVGFESpecularLightingPoint: aStream << "SVGFESpecularLightingPoint"; break;
      case Tag::SVGFESpecularLightingSpot: aStream << "SVGFESpecularLightingSpot"; break;
      case Tag::SVGFETile: aStream << "SVGFETile"; break;
      case Tag::SVGFETurbulenceWithFractalNoiseWithNoStitching: aStream << "SVGFETurbulenceWithFractalNoiseWithNoStitching"; break;
      case Tag::SVGFETurbulenceWithFractalNoiseWithStitching: aStream << "SVGFETurbulenceWithFractalNoiseWithStitching"; break;
      case Tag::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching: aStream << "SVGFETurbulenceWithTurbulenceNoiseWithNoStitching"; break;
      case Tag::SVGFETurbulenceWithTurbulenceNoiseWithStitching: aStream << "SVGFETurbulenceWithTurbulenceNoiseWithStitching"; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  friend std::ostream& operator<<(std::ostream& aStream, const FilterOp& aInstance) {
    using Tag = FilterOp::Tag;
    switch (aInstance.tag) {
      case Tag::Identity: aStream << "Identity"; break;
      case Tag::Blur: aStream << "Blur" << aInstance.blur; break;
      case Tag::Brightness: aStream << "Brightness" << aInstance.brightness; break;
      case Tag::Contrast: aStream << "Contrast" << aInstance.contrast; break;
      case Tag::Grayscale: aStream << "Grayscale" << aInstance.grayscale; break;
      case Tag::HueRotate: aStream << "HueRotate" << aInstance.hue_rotate; break;
      case Tag::Invert: aStream << "Invert" << aInstance.invert; break;
      case Tag::Opacity: aStream << "Opacity" << aInstance.opacity; break;
      case Tag::Saturate: aStream << "Saturate" << aInstance.saturate; break;
      case Tag::Sepia: aStream << "Sepia" << aInstance.sepia; break;
      case Tag::DropShadow: aStream << "DropShadow" << aInstance.drop_shadow; break;
      case Tag::ColorMatrix: aStream << "ColorMatrix" << aInstance.color_matrix; break;
      case Tag::SrgbToLinear: aStream << "SrgbToLinear"; break;
      case Tag::LinearToSrgb: aStream << "LinearToSrgb"; break;
      case Tag::ComponentTransfer: aStream << "ComponentTransfer"; break;
      case Tag::Flood: aStream << "Flood" << aInstance.flood; break;
      case Tag::SVGFESourceGraphic: aStream << "SVGFESourceGraphic" << aInstance.svgfe_source_graphic; break;
      case Tag::SVGFESourceAlpha: aStream << "SVGFESourceAlpha" << aInstance.svgfe_source_alpha; break;
      case Tag::SVGFEIdentity: aStream << "SVGFEIdentity" << aInstance.svgfe_identity; break;
      case Tag::SVGFEOpacity: aStream << "SVGFEOpacity" << aInstance.svgfe_opacity; break;
      case Tag::SVGFEToAlpha: aStream << "SVGFEToAlpha" << aInstance.svgfe_to_alpha; break;
      case Tag::SVGFEBlendDarken: aStream << "SVGFEBlendDarken" << aInstance.svgfe_blend_darken; break;
      case Tag::SVGFEBlendLighten: aStream << "SVGFEBlendLighten" << aInstance.svgfe_blend_lighten; break;
      case Tag::SVGFEBlendMultiply: aStream << "SVGFEBlendMultiply" << aInstance.svgfe_blend_multiply; break;
      case Tag::SVGFEBlendNormal: aStream << "SVGFEBlendNormal" << aInstance.svgfe_blend_normal; break;
      case Tag::SVGFEBlendScreen: aStream << "SVGFEBlendScreen" << aInstance.svgfe_blend_screen; break;
      case Tag::SVGFEBlendOverlay: aStream << "SVGFEBlendOverlay" << aInstance.svgfe_blend_overlay; break;
      case Tag::SVGFEBlendColorDodge: aStream << "SVGFEBlendColorDodge" << aInstance.svgfe_blend_color_dodge; break;
      case Tag::SVGFEBlendColorBurn: aStream << "SVGFEBlendColorBurn" << aInstance.svgfe_blend_color_burn; break;
      case Tag::SVGFEBlendHardLight: aStream << "SVGFEBlendHardLight" << aInstance.svgfe_blend_hard_light; break;
      case Tag::SVGFEBlendSoftLight: aStream << "SVGFEBlendSoftLight" << aInstance.svgfe_blend_soft_light; break;
      case Tag::SVGFEBlendDifference: aStream << "SVGFEBlendDifference" << aInstance.svgfe_blend_difference; break;
      case Tag::SVGFEBlendExclusion: aStream << "SVGFEBlendExclusion" << aInstance.svgfe_blend_exclusion; break;
      case Tag::SVGFEBlendHue: aStream << "SVGFEBlendHue" << aInstance.svgfe_blend_hue; break;
      case Tag::SVGFEBlendSaturation: aStream << "SVGFEBlendSaturation" << aInstance.svgfe_blend_saturation; break;
      case Tag::SVGFEBlendColor: aStream << "SVGFEBlendColor" << aInstance.svgfe_blend_color; break;
      case Tag::SVGFEBlendLuminosity: aStream << "SVGFEBlendLuminosity" << aInstance.svgfe_blend_luminosity; break;
      case Tag::SVGFEColorMatrix: aStream << "SVGFEColorMatrix" << aInstance.svgfe_color_matrix; break;
      case Tag::SVGFEComponentTransfer: aStream << "SVGFEComponentTransfer" << aInstance.svgfe_component_transfer; break;
      case Tag::SVGFECompositeArithmetic: aStream << "SVGFECompositeArithmetic" << aInstance.svgfe_composite_arithmetic; break;
      case Tag::SVGFECompositeATop: aStream << "SVGFECompositeATop" << aInstance.svgfe_composite_a_top; break;
      case Tag::SVGFECompositeIn: aStream << "SVGFECompositeIn" << aInstance.svgfe_composite_in; break;
      case Tag::SVGFECompositeLighter: aStream << "SVGFECompositeLighter" << aInstance.svgfe_composite_lighter; break;
      case Tag::SVGFECompositeOut: aStream << "SVGFECompositeOut" << aInstance.svgfe_composite_out; break;
      case Tag::SVGFECompositeOver: aStream << "SVGFECompositeOver" << aInstance.svgfe_composite_over; break;
      case Tag::SVGFECompositeXOR: aStream << "SVGFECompositeXOR" << aInstance.svgfe_composite_xor; break;
      case Tag::SVGFEConvolveMatrixEdgeModeDuplicate: aStream << "SVGFEConvolveMatrixEdgeModeDuplicate" << aInstance.svgfe_convolve_matrix_edge_mode_duplicate; break;
      case Tag::SVGFEConvolveMatrixEdgeModeNone: aStream << "SVGFEConvolveMatrixEdgeModeNone" << aInstance.svgfe_convolve_matrix_edge_mode_none; break;
      case Tag::SVGFEConvolveMatrixEdgeModeWrap: aStream << "SVGFEConvolveMatrixEdgeModeWrap" << aInstance.svgfe_convolve_matrix_edge_mode_wrap; break;
      case Tag::SVGFEDiffuseLightingDistant: aStream << "SVGFEDiffuseLightingDistant" << aInstance.svgfe_diffuse_lighting_distant; break;
      case Tag::SVGFEDiffuseLightingPoint: aStream << "SVGFEDiffuseLightingPoint" << aInstance.svgfe_diffuse_lighting_point; break;
      case Tag::SVGFEDiffuseLightingSpot: aStream << "SVGFEDiffuseLightingSpot" << aInstance.svgfe_diffuse_lighting_spot; break;
      case Tag::SVGFEDisplacementMap: aStream << "SVGFEDisplacementMap" << aInstance.svgfe_displacement_map; break;
      case Tag::SVGFEDropShadow: aStream << "SVGFEDropShadow" << aInstance.svgfe_drop_shadow; break;
      case Tag::SVGFEFlood: aStream << "SVGFEFlood" << aInstance.svgfe_flood; break;
      case Tag::SVGFEGaussianBlur: aStream << "SVGFEGaussianBlur" << aInstance.svgfe_gaussian_blur; break;
      case Tag::SVGFEImage: aStream << "SVGFEImage" << aInstance.svgfe_image; break;
      case Tag::SVGFEMorphologyDilate: aStream << "SVGFEMorphologyDilate" << aInstance.svgfe_morphology_dilate; break;
      case Tag::SVGFEMorphologyErode: aStream << "SVGFEMorphologyErode" << aInstance.svgfe_morphology_erode; break;
      case Tag::SVGFEOffset: aStream << "SVGFEOffset" << aInstance.svgfe_offset; break;
      case Tag::SVGFESpecularLightingDistant: aStream << "SVGFESpecularLightingDistant" << aInstance.svgfe_specular_lighting_distant; break;
      case Tag::SVGFESpecularLightingPoint: aStream << "SVGFESpecularLightingPoint" << aInstance.svgfe_specular_lighting_point; break;
      case Tag::SVGFESpecularLightingSpot: aStream << "SVGFESpecularLightingSpot" << aInstance.svgfe_specular_lighting_spot; break;
      case Tag::SVGFETile: aStream << "SVGFETile" << aInstance.svgfe_tile; break;
      case Tag::SVGFETurbulenceWithFractalNoiseWithNoStitching: aStream << "SVGFETurbulenceWithFractalNoiseWithNoStitching" << aInstance.svgfe_turbulence_with_fractal_noise_with_no_stitching; break;
      case Tag::SVGFETurbulenceWithFractalNoiseWithStitching: aStream << "SVGFETurbulenceWithFractalNoiseWithStitching" << aInstance.svgfe_turbulence_with_fractal_noise_with_stitching; break;
      case Tag::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching: aStream << "SVGFETurbulenceWithTurbulenceNoiseWithNoStitching" << aInstance.svgfe_turbulence_with_turbulence_noise_with_no_stitching; break;
      case Tag::SVGFETurbulenceWithTurbulenceNoiseWithStitching: aStream << "SVGFETurbulenceWithTurbulenceNoiseWithStitching" << aInstance.svgfe_turbulence_with_turbulence_noise_with_stitching; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  struct Blur_Body {
    float _0;
    float _1;

    friend std::ostream& operator<<(std::ostream& aStream, const Blur_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << ", "
                             << "_1=" << aInstance._1 << " }";
    }
    bool operator==(const Blur_Body& aOther) const {
      return _0 == aOther._0 &&
             _1 == aOther._1;
    }
  };

  struct Brightness_Body {
    float _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Brightness_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Brightness_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct Contrast_Body {
    float _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Contrast_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Contrast_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct Grayscale_Body {
    float _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Grayscale_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Grayscale_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct HueRotate_Body {
    float _0;

    friend std::ostream& operator<<(std::ostream& aStream, const HueRotate_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const HueRotate_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct Invert_Body {
    float _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Invert_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Invert_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct Opacity_Body {
    PropertyBinding<float> _0;
    float _1;

    friend std::ostream& operator<<(std::ostream& aStream, const Opacity_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << ", "
                             << "_1=" << aInstance._1 << " }";
    }
    bool operator==(const Opacity_Body& aOther) const {
      return _0 == aOther._0 &&
             _1 == aOther._1;
    }
  };

  struct Saturate_Body {
    float _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Saturate_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Saturate_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct Sepia_Body {
    float _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Sepia_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Sepia_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct DropShadow_Body {
    Shadow _0;

    friend std::ostream& operator<<(std::ostream& aStream, const DropShadow_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const DropShadow_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct ColorMatrix_Body {
    float _0[20];

    friend std::ostream& operator<<(std::ostream& aStream, const ColorMatrix_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
  };

  struct Flood_Body {
    ColorF _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Flood_Body& aInstance) {
      return aStream << "{ " << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Flood_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct SVGFESourceGraphic_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFESourceGraphic_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFESourceGraphic_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFESourceAlpha_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFESourceAlpha_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFESourceAlpha_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEIdentity_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEIdentity_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEIdentity_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEOpacity_Body {
    FilterOpGraphNode node;
    PropertyBinding<float> valuebinding;
    float value;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEOpacity_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "valuebinding=" << aInstance.valuebinding << ", "
                             << "value=" << aInstance.value << " }";
    }
    bool operator==(const SVGFEOpacity_Body& aOther) const {
      return node == aOther.node &&
             valuebinding == aOther.valuebinding &&
             value == aOther.value;
    }
  };

  struct SVGFEToAlpha_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEToAlpha_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEToAlpha_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendDarken_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendDarken_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendDarken_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendLighten_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendLighten_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendLighten_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendMultiply_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendMultiply_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendMultiply_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendNormal_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendNormal_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendNormal_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendScreen_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendScreen_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendScreen_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendOverlay_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendOverlay_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendOverlay_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendColorDodge_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendColorDodge_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendColorDodge_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendColorBurn_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendColorBurn_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendColorBurn_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendHardLight_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendHardLight_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendHardLight_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendSoftLight_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendSoftLight_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendSoftLight_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendDifference_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendDifference_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendDifference_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendExclusion_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendExclusion_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendExclusion_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendHue_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendHue_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendHue_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendSaturation_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendSaturation_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendSaturation_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendColor_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendColor_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendColor_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEBlendLuminosity_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEBlendLuminosity_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEBlendLuminosity_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEColorMatrix_Body {
    FilterOpGraphNode node;
    float values[20];

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEColorMatrix_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "values=" << aInstance.values << " }";
    }
  };

  struct SVGFEComponentTransfer_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEComponentTransfer_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFEComponentTransfer_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFECompositeArithmetic_Body {
    FilterOpGraphNode node;
    float k1;
    float k2;
    float k3;
    float k4;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFECompositeArithmetic_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "k1=" << aInstance.k1 << ", "
                             << "k2=" << aInstance.k2 << ", "
                             << "k3=" << aInstance.k3 << ", "
                             << "k4=" << aInstance.k4 << " }";
    }
    bool operator==(const SVGFECompositeArithmetic_Body& aOther) const {
      return node == aOther.node &&
             k1 == aOther.k1 &&
             k2 == aOther.k2 &&
             k3 == aOther.k3 &&
             k4 == aOther.k4;
    }
  };

  struct SVGFECompositeATop_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFECompositeATop_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFECompositeATop_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFECompositeIn_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFECompositeIn_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFECompositeIn_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFECompositeLighter_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFECompositeLighter_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFECompositeLighter_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFECompositeOut_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFECompositeOut_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFECompositeOut_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFECompositeOver_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFECompositeOver_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFECompositeOver_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFECompositeXOR_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFECompositeXOR_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFECompositeXOR_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFEConvolveMatrixEdgeModeDuplicate_Body {
    FilterOpGraphNode node;
    int32_t order_x;
    int32_t order_y;
    float kernel[25];
    float divisor;
    float bias;
    int32_t target_x;
    int32_t target_y;
    float kernel_unit_length_x;
    float kernel_unit_length_y;
    int32_t preserve_alpha;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEConvolveMatrixEdgeModeDuplicate_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "order_x=" << aInstance.order_x << ", "
                             << "order_y=" << aInstance.order_y << ", "
                             << "kernel=" << aInstance.kernel << ", "
                             << "divisor=" << aInstance.divisor << ", "
                             << "bias=" << aInstance.bias << ", "
                             << "target_x=" << aInstance.target_x << ", "
                             << "target_y=" << aInstance.target_y << ", "
                             << "kernel_unit_length_x=" << aInstance.kernel_unit_length_x << ", "
                             << "kernel_unit_length_y=" << aInstance.kernel_unit_length_y << ", "
                             << "preserve_alpha=" << aInstance.preserve_alpha << " }";
    }
  };

  struct SVGFEConvolveMatrixEdgeModeNone_Body {
    FilterOpGraphNode node;
    int32_t order_x;
    int32_t order_y;
    float kernel[25];
    float divisor;
    float bias;
    int32_t target_x;
    int32_t target_y;
    float kernel_unit_length_x;
    float kernel_unit_length_y;
    int32_t preserve_alpha;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEConvolveMatrixEdgeModeNone_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "order_x=" << aInstance.order_x << ", "
                             << "order_y=" << aInstance.order_y << ", "
                             << "kernel=" << aInstance.kernel << ", "
                             << "divisor=" << aInstance.divisor << ", "
                             << "bias=" << aInstance.bias << ", "
                             << "target_x=" << aInstance.target_x << ", "
                             << "target_y=" << aInstance.target_y << ", "
                             << "kernel_unit_length_x=" << aInstance.kernel_unit_length_x << ", "
                             << "kernel_unit_length_y=" << aInstance.kernel_unit_length_y << ", "
                             << "preserve_alpha=" << aInstance.preserve_alpha << " }";
    }
  };

  struct SVGFEConvolveMatrixEdgeModeWrap_Body {
    FilterOpGraphNode node;
    int32_t order_x;
    int32_t order_y;
    float kernel[25];
    float divisor;
    float bias;
    int32_t target_x;
    int32_t target_y;
    float kernel_unit_length_x;
    float kernel_unit_length_y;
    int32_t preserve_alpha;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEConvolveMatrixEdgeModeWrap_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "order_x=" << aInstance.order_x << ", "
                             << "order_y=" << aInstance.order_y << ", "
                             << "kernel=" << aInstance.kernel << ", "
                             << "divisor=" << aInstance.divisor << ", "
                             << "bias=" << aInstance.bias << ", "
                             << "target_x=" << aInstance.target_x << ", "
                             << "target_y=" << aInstance.target_y << ", "
                             << "kernel_unit_length_x=" << aInstance.kernel_unit_length_x << ", "
                             << "kernel_unit_length_y=" << aInstance.kernel_unit_length_y << ", "
                             << "preserve_alpha=" << aInstance.preserve_alpha << " }";
    }
  };

  struct SVGFEDiffuseLightingDistant_Body {
    FilterOpGraphNode node;
    float surface_scale;
    float diffuse_constant;
    float kernel_unit_length_x;
    float kernel_unit_length_y;
    float azimuth;
    float elevation;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEDiffuseLightingDistant_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "surface_scale=" << aInstance.surface_scale << ", "
                             << "diffuse_constant=" << aInstance.diffuse_constant << ", "
                             << "kernel_unit_length_x=" << aInstance.kernel_unit_length_x << ", "
                             << "kernel_unit_length_y=" << aInstance.kernel_unit_length_y << ", "
                             << "azimuth=" << aInstance.azimuth << ", "
                             << "elevation=" << aInstance.elevation << " }";
    }
    bool operator==(const SVGFEDiffuseLightingDistant_Body& aOther) const {
      return node == aOther.node &&
             surface_scale == aOther.surface_scale &&
             diffuse_constant == aOther.diffuse_constant &&
             kernel_unit_length_x == aOther.kernel_unit_length_x &&
             kernel_unit_length_y == aOther.kernel_unit_length_y &&
             azimuth == aOther.azimuth &&
             elevation == aOther.elevation;
    }
  };

  struct SVGFEDiffuseLightingPoint_Body {
    FilterOpGraphNode node;
    float surface_scale;
    float diffuse_constant;
    float kernel_unit_length_x;
    float kernel_unit_length_y;
    float x;
    float y;
    float z;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEDiffuseLightingPoint_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "surface_scale=" << aInstance.surface_scale << ", "
                             << "diffuse_constant=" << aInstance.diffuse_constant << ", "
                             << "kernel_unit_length_x=" << aInstance.kernel_unit_length_x << ", "
                             << "kernel_unit_length_y=" << aInstance.kernel_unit_length_y << ", "
                             << "x=" << aInstance.x << ", "
                             << "y=" << aInstance.y << ", "
                             << "z=" << aInstance.z << " }";
    }
    bool operator==(const SVGFEDiffuseLightingPoint_Body& aOther) const {
      return node == aOther.node &&
             surface_scale == aOther.surface_scale &&
             diffuse_constant == aOther.diffuse_constant &&
             kernel_unit_length_x == aOther.kernel_unit_length_x &&
             kernel_unit_length_y == aOther.kernel_unit_length_y &&
             x == aOther.x &&
             y == aOther.y &&
             z == aOther.z;
    }
  };

  struct SVGFEDiffuseLightingSpot_Body {
    FilterOpGraphNode node;
    float surface_scale;
    float diffuse_constant;
    float kernel_unit_length_x;
    float kernel_unit_length_y;
    float x;
    float y;
    float z;
    float points_at_x;
    float points_at_y;
    float points_at_z;
    float cone_exponent;
    float limiting_cone_angle;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEDiffuseLightingSpot_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "surface_scale=" << aInstance.surface_scale << ", "
                             << "diffuse_constant=" << aInstance.diffuse_constant << ", "
                             << "kernel_unit_length_x=" << aInstance.kernel_unit_length_x << ", "
                             << "kernel_unit_length_y=" << aInstance.kernel_unit_length_y << ", "
                             << "x=" << aInstance.x << ", "
                             << "y=" << aInstance.y << ", "
                             << "z=" << aInstance.z << ", "
                             << "points_at_x=" << aInstance.points_at_x << ", "
                             << "points_at_y=" << aInstance.points_at_y << ", "
                             << "points_at_z=" << aInstance.points_at_z << ", "
                             << "cone_exponent=" << aInstance.cone_exponent << ", "
                             << "limiting_cone_angle=" << aInstance.limiting_cone_angle << " }";
    }
    bool operator==(const SVGFEDiffuseLightingSpot_Body& aOther) const {
      return node == aOther.node &&
             surface_scale == aOther.surface_scale &&
             diffuse_constant == aOther.diffuse_constant &&
             kernel_unit_length_x == aOther.kernel_unit_length_x &&
             kernel_unit_length_y == aOther.kernel_unit_length_y &&
             x == aOther.x &&
             y == aOther.y &&
             z == aOther.z &&
             points_at_x == aOther.points_at_x &&
             points_at_y == aOther.points_at_y &&
             points_at_z == aOther.points_at_z &&
             cone_exponent == aOther.cone_exponent &&
             limiting_cone_angle == aOther.limiting_cone_angle;
    }
  };

  struct SVGFEDisplacementMap_Body {
    FilterOpGraphNode node;
    float scale;
    uint32_t x_channel_selector;
    uint32_t y_channel_selector;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEDisplacementMap_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "scale=" << aInstance.scale << ", "
                             << "x_channel_selector=" << aInstance.x_channel_selector << ", "
                             << "y_channel_selector=" << aInstance.y_channel_selector << " }";
    }
    bool operator==(const SVGFEDisplacementMap_Body& aOther) const {
      return node == aOther.node &&
             scale == aOther.scale &&
             x_channel_selector == aOther.x_channel_selector &&
             y_channel_selector == aOther.y_channel_selector;
    }
  };

  struct SVGFEDropShadow_Body {
    FilterOpGraphNode node;
    ColorF color;
    float dx;
    float dy;
    float std_deviation_x;
    float std_deviation_y;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEDropShadow_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "color=" << aInstance.color << ", "
                             << "dx=" << aInstance.dx << ", "
                             << "dy=" << aInstance.dy << ", "
                             << "std_deviation_x=" << aInstance.std_deviation_x << ", "
                             << "std_deviation_y=" << aInstance.std_deviation_y << " }";
    }
    bool operator==(const SVGFEDropShadow_Body& aOther) const {
      return node == aOther.node &&
             color == aOther.color &&
             dx == aOther.dx &&
             dy == aOther.dy &&
             std_deviation_x == aOther.std_deviation_x &&
             std_deviation_y == aOther.std_deviation_y;
    }
  };

  struct SVGFEFlood_Body {
    FilterOpGraphNode node;
    ColorF color;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEFlood_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "color=" << aInstance.color << " }";
    }
    bool operator==(const SVGFEFlood_Body& aOther) const {
      return node == aOther.node &&
             color == aOther.color;
    }
  };

  struct SVGFEGaussianBlur_Body {
    FilterOpGraphNode node;
    float std_deviation_x;
    float std_deviation_y;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEGaussianBlur_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "std_deviation_x=" << aInstance.std_deviation_x << ", "
                             << "std_deviation_y=" << aInstance.std_deviation_y << " }";
    }
    bool operator==(const SVGFEGaussianBlur_Body& aOther) const {
      return node == aOther.node &&
             std_deviation_x == aOther.std_deviation_x &&
             std_deviation_y == aOther.std_deviation_y;
    }
  };

  struct SVGFEImage_Body {
    FilterOpGraphNode node;
    uint32_t sampling_filter;
    float matrix[6];

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEImage_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "sampling_filter=" << aInstance.sampling_filter << ", "
                             << "matrix=" << aInstance.matrix << " }";
    }
  };

  struct SVGFEMorphologyDilate_Body {
    FilterOpGraphNode node;
    float radius_x;
    float radius_y;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEMorphologyDilate_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "radius_x=" << aInstance.radius_x << ", "
                             << "radius_y=" << aInstance.radius_y << " }";
    }
    bool operator==(const SVGFEMorphologyDilate_Body& aOther) const {
      return node == aOther.node &&
             radius_x == aOther.radius_x &&
             radius_y == aOther.radius_y;
    }
  };

  struct SVGFEMorphologyErode_Body {
    FilterOpGraphNode node;
    float radius_x;
    float radius_y;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEMorphologyErode_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "radius_x=" << aInstance.radius_x << ", "
                             << "radius_y=" << aInstance.radius_y << " }";
    }
    bool operator==(const SVGFEMorphologyErode_Body& aOther) const {
      return node == aOther.node &&
             radius_x == aOther.radius_x &&
             radius_y == aOther.radius_y;
    }
  };

  struct SVGFEOffset_Body {
    FilterOpGraphNode node;
    float offset_x;
    float offset_y;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFEOffset_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "offset_x=" << aInstance.offset_x << ", "
                             << "offset_y=" << aInstance.offset_y << " }";
    }
    bool operator==(const SVGFEOffset_Body& aOther) const {
      return node == aOther.node &&
             offset_x == aOther.offset_x &&
             offset_y == aOther.offset_y;
    }
  };

  struct SVGFESpecularLightingDistant_Body {
    FilterOpGraphNode node;
    float surface_scale;
    float specular_constant;
    float specular_exponent;
    float kernel_unit_length_x;
    float kernel_unit_length_y;
    float azimuth;
    float elevation;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFESpecularLightingDistant_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "surface_scale=" << aInstance.surface_scale << ", "
                             << "specular_constant=" << aInstance.specular_constant << ", "
                             << "specular_exponent=" << aInstance.specular_exponent << ", "
                             << "kernel_unit_length_x=" << aInstance.kernel_unit_length_x << ", "
                             << "kernel_unit_length_y=" << aInstance.kernel_unit_length_y << ", "
                             << "azimuth=" << aInstance.azimuth << ", "
                             << "elevation=" << aInstance.elevation << " }";
    }
    bool operator==(const SVGFESpecularLightingDistant_Body& aOther) const {
      return node == aOther.node &&
             surface_scale == aOther.surface_scale &&
             specular_constant == aOther.specular_constant &&
             specular_exponent == aOther.specular_exponent &&
             kernel_unit_length_x == aOther.kernel_unit_length_x &&
             kernel_unit_length_y == aOther.kernel_unit_length_y &&
             azimuth == aOther.azimuth &&
             elevation == aOther.elevation;
    }
  };

  struct SVGFESpecularLightingPoint_Body {
    FilterOpGraphNode node;
    float surface_scale;
    float specular_constant;
    float specular_exponent;
    float kernel_unit_length_x;
    float kernel_unit_length_y;
    float x;
    float y;
    float z;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFESpecularLightingPoint_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "surface_scale=" << aInstance.surface_scale << ", "
                             << "specular_constant=" << aInstance.specular_constant << ", "
                             << "specular_exponent=" << aInstance.specular_exponent << ", "
                             << "kernel_unit_length_x=" << aInstance.kernel_unit_length_x << ", "
                             << "kernel_unit_length_y=" << aInstance.kernel_unit_length_y << ", "
                             << "x=" << aInstance.x << ", "
                             << "y=" << aInstance.y << ", "
                             << "z=" << aInstance.z << " }";
    }
    bool operator==(const SVGFESpecularLightingPoint_Body& aOther) const {
      return node == aOther.node &&
             surface_scale == aOther.surface_scale &&
             specular_constant == aOther.specular_constant &&
             specular_exponent == aOther.specular_exponent &&
             kernel_unit_length_x == aOther.kernel_unit_length_x &&
             kernel_unit_length_y == aOther.kernel_unit_length_y &&
             x == aOther.x &&
             y == aOther.y &&
             z == aOther.z;
    }
  };

  struct SVGFESpecularLightingSpot_Body {
    FilterOpGraphNode node;
    float surface_scale;
    float specular_constant;
    float specular_exponent;
    float kernel_unit_length_x;
    float kernel_unit_length_y;
    float x;
    float y;
    float z;
    float points_at_x;
    float points_at_y;
    float points_at_z;
    float cone_exponent;
    float limiting_cone_angle;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFESpecularLightingSpot_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "surface_scale=" << aInstance.surface_scale << ", "
                             << "specular_constant=" << aInstance.specular_constant << ", "
                             << "specular_exponent=" << aInstance.specular_exponent << ", "
                             << "kernel_unit_length_x=" << aInstance.kernel_unit_length_x << ", "
                             << "kernel_unit_length_y=" << aInstance.kernel_unit_length_y << ", "
                             << "x=" << aInstance.x << ", "
                             << "y=" << aInstance.y << ", "
                             << "z=" << aInstance.z << ", "
                             << "points_at_x=" << aInstance.points_at_x << ", "
                             << "points_at_y=" << aInstance.points_at_y << ", "
                             << "points_at_z=" << aInstance.points_at_z << ", "
                             << "cone_exponent=" << aInstance.cone_exponent << ", "
                             << "limiting_cone_angle=" << aInstance.limiting_cone_angle << " }";
    }
    bool operator==(const SVGFESpecularLightingSpot_Body& aOther) const {
      return node == aOther.node &&
             surface_scale == aOther.surface_scale &&
             specular_constant == aOther.specular_constant &&
             specular_exponent == aOther.specular_exponent &&
             kernel_unit_length_x == aOther.kernel_unit_length_x &&
             kernel_unit_length_y == aOther.kernel_unit_length_y &&
             x == aOther.x &&
             y == aOther.y &&
             z == aOther.z &&
             points_at_x == aOther.points_at_x &&
             points_at_y == aOther.points_at_y &&
             points_at_z == aOther.points_at_z &&
             cone_exponent == aOther.cone_exponent &&
             limiting_cone_angle == aOther.limiting_cone_angle;
    }
  };

  struct SVGFETile_Body {
    FilterOpGraphNode node;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFETile_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << " }";
    }
    bool operator==(const SVGFETile_Body& aOther) const {
      return node == aOther.node;
    }
  };

  struct SVGFETurbulenceWithFractalNoiseWithNoStitching_Body {
    FilterOpGraphNode node;
    float base_frequency_x;
    float base_frequency_y;
    uint32_t num_octaves;
    uint32_t seed;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFETurbulenceWithFractalNoiseWithNoStitching_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "base_frequency_x=" << aInstance.base_frequency_x << ", "
                             << "base_frequency_y=" << aInstance.base_frequency_y << ", "
                             << "num_octaves=" << aInstance.num_octaves << ", "
                             << "seed=" << aInstance.seed << " }";
    }
    bool operator==(const SVGFETurbulenceWithFractalNoiseWithNoStitching_Body& aOther) const {
      return node == aOther.node &&
             base_frequency_x == aOther.base_frequency_x &&
             base_frequency_y == aOther.base_frequency_y &&
             num_octaves == aOther.num_octaves &&
             seed == aOther.seed;
    }
  };

  struct SVGFETurbulenceWithFractalNoiseWithStitching_Body {
    FilterOpGraphNode node;
    float base_frequency_x;
    float base_frequency_y;
    uint32_t num_octaves;
    uint32_t seed;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFETurbulenceWithFractalNoiseWithStitching_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "base_frequency_x=" << aInstance.base_frequency_x << ", "
                             << "base_frequency_y=" << aInstance.base_frequency_y << ", "
                             << "num_octaves=" << aInstance.num_octaves << ", "
                             << "seed=" << aInstance.seed << " }";
    }
    bool operator==(const SVGFETurbulenceWithFractalNoiseWithStitching_Body& aOther) const {
      return node == aOther.node &&
             base_frequency_x == aOther.base_frequency_x &&
             base_frequency_y == aOther.base_frequency_y &&
             num_octaves == aOther.num_octaves &&
             seed == aOther.seed;
    }
  };

  struct SVGFETurbulenceWithTurbulenceNoiseWithNoStitching_Body {
    FilterOpGraphNode node;
    float base_frequency_x;
    float base_frequency_y;
    uint32_t num_octaves;
    uint32_t seed;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFETurbulenceWithTurbulenceNoiseWithNoStitching_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "base_frequency_x=" << aInstance.base_frequency_x << ", "
                             << "base_frequency_y=" << aInstance.base_frequency_y << ", "
                             << "num_octaves=" << aInstance.num_octaves << ", "
                             << "seed=" << aInstance.seed << " }";
    }
    bool operator==(const SVGFETurbulenceWithTurbulenceNoiseWithNoStitching_Body& aOther) const {
      return node == aOther.node &&
             base_frequency_x == aOther.base_frequency_x &&
             base_frequency_y == aOther.base_frequency_y &&
             num_octaves == aOther.num_octaves &&
             seed == aOther.seed;
    }
  };

  struct SVGFETurbulenceWithTurbulenceNoiseWithStitching_Body {
    FilterOpGraphNode node;
    float base_frequency_x;
    float base_frequency_y;
    uint32_t num_octaves;
    uint32_t seed;

    friend std::ostream& operator<<(std::ostream& aStream, const SVGFETurbulenceWithTurbulenceNoiseWithStitching_Body& aInstance) {
      return aStream << "{ " << "node=" << aInstance.node << ", "
                             << "base_frequency_x=" << aInstance.base_frequency_x << ", "
                             << "base_frequency_y=" << aInstance.base_frequency_y << ", "
                             << "num_octaves=" << aInstance.num_octaves << ", "
                             << "seed=" << aInstance.seed << " }";
    }
    bool operator==(const SVGFETurbulenceWithTurbulenceNoiseWithStitching_Body& aOther) const {
      return node == aOther.node &&
             base_frequency_x == aOther.base_frequency_x &&
             base_frequency_y == aOther.base_frequency_y &&
             num_octaves == aOther.num_octaves &&
             seed == aOther.seed;
    }
  };

  Tag tag;
  union {
    Blur_Body blur;
    Brightness_Body brightness;
    Contrast_Body contrast;
    Grayscale_Body grayscale;
    HueRotate_Body hue_rotate;
    Invert_Body invert;
    Opacity_Body opacity;
    Saturate_Body saturate;
    Sepia_Body sepia;
    DropShadow_Body drop_shadow;
    ColorMatrix_Body color_matrix;
    Flood_Body flood;
    SVGFESourceGraphic_Body svgfe_source_graphic;
    SVGFESourceAlpha_Body svgfe_source_alpha;
    SVGFEIdentity_Body svgfe_identity;
    SVGFEOpacity_Body svgfe_opacity;
    SVGFEToAlpha_Body svgfe_to_alpha;
    SVGFEBlendDarken_Body svgfe_blend_darken;
    SVGFEBlendLighten_Body svgfe_blend_lighten;
    SVGFEBlendMultiply_Body svgfe_blend_multiply;
    SVGFEBlendNormal_Body svgfe_blend_normal;
    SVGFEBlendScreen_Body svgfe_blend_screen;
    SVGFEBlendOverlay_Body svgfe_blend_overlay;
    SVGFEBlendColorDodge_Body svgfe_blend_color_dodge;
    SVGFEBlendColorBurn_Body svgfe_blend_color_burn;
    SVGFEBlendHardLight_Body svgfe_blend_hard_light;
    SVGFEBlendSoftLight_Body svgfe_blend_soft_light;
    SVGFEBlendDifference_Body svgfe_blend_difference;
    SVGFEBlendExclusion_Body svgfe_blend_exclusion;
    SVGFEBlendHue_Body svgfe_blend_hue;
    SVGFEBlendSaturation_Body svgfe_blend_saturation;
    SVGFEBlendColor_Body svgfe_blend_color;
    SVGFEBlendLuminosity_Body svgfe_blend_luminosity;
    SVGFEColorMatrix_Body svgfe_color_matrix;
    SVGFEComponentTransfer_Body svgfe_component_transfer;
    SVGFECompositeArithmetic_Body svgfe_composite_arithmetic;
    SVGFECompositeATop_Body svgfe_composite_a_top;
    SVGFECompositeIn_Body svgfe_composite_in;
    SVGFECompositeLighter_Body svgfe_composite_lighter;
    SVGFECompositeOut_Body svgfe_composite_out;
    SVGFECompositeOver_Body svgfe_composite_over;
    SVGFECompositeXOR_Body svgfe_composite_xor;
    SVGFEConvolveMatrixEdgeModeDuplicate_Body svgfe_convolve_matrix_edge_mode_duplicate;
    SVGFEConvolveMatrixEdgeModeNone_Body svgfe_convolve_matrix_edge_mode_none;
    SVGFEConvolveMatrixEdgeModeWrap_Body svgfe_convolve_matrix_edge_mode_wrap;
    SVGFEDiffuseLightingDistant_Body svgfe_diffuse_lighting_distant;
    SVGFEDiffuseLightingPoint_Body svgfe_diffuse_lighting_point;
    SVGFEDiffuseLightingSpot_Body svgfe_diffuse_lighting_spot;
    SVGFEDisplacementMap_Body svgfe_displacement_map;
    SVGFEDropShadow_Body svgfe_drop_shadow;
    SVGFEFlood_Body svgfe_flood;
    SVGFEGaussianBlur_Body svgfe_gaussian_blur;
    SVGFEImage_Body svgfe_image;
    SVGFEMorphologyDilate_Body svgfe_morphology_dilate;
    SVGFEMorphologyErode_Body svgfe_morphology_erode;
    SVGFEOffset_Body svgfe_offset;
    SVGFESpecularLightingDistant_Body svgfe_specular_lighting_distant;
    SVGFESpecularLightingPoint_Body svgfe_specular_lighting_point;
    SVGFESpecularLightingSpot_Body svgfe_specular_lighting_spot;
    SVGFETile_Body svgfe_tile;
    SVGFETurbulenceWithFractalNoiseWithNoStitching_Body svgfe_turbulence_with_fractal_noise_with_no_stitching;
    SVGFETurbulenceWithFractalNoiseWithStitching_Body svgfe_turbulence_with_fractal_noise_with_stitching;
    SVGFETurbulenceWithTurbulenceNoiseWithNoStitching_Body svgfe_turbulence_with_turbulence_noise_with_no_stitching;
    SVGFETurbulenceWithTurbulenceNoiseWithStitching_Body svgfe_turbulence_with_turbulence_noise_with_stitching;
  };

  static FilterOp Identity() {
    FilterOp result;
    result.tag = Tag::Identity;
    return result;
  }

  bool IsIdentity() const {
    return tag == Tag::Identity;
  }

  static FilterOp Blur(const float &a0,
                       const float &a1) {
    FilterOp result;
    ::new (&result.blur._0) (float)(a0);
    ::new (&result.blur._1) (float)(a1);
    result.tag = Tag::Blur;
    return result;
  }

  bool IsBlur() const {
    return tag == Tag::Blur;
  }

  static FilterOp Brightness(const float &a0) {
    FilterOp result;
    ::new (&result.brightness._0) (float)(a0);
    result.tag = Tag::Brightness;
    return result;
  }

  bool IsBrightness() const {
    return tag == Tag::Brightness;
  }

  static FilterOp Contrast(const float &a0) {
    FilterOp result;
    ::new (&result.contrast._0) (float)(a0);
    result.tag = Tag::Contrast;
    return result;
  }

  bool IsContrast() const {
    return tag == Tag::Contrast;
  }

  static FilterOp Grayscale(const float &a0) {
    FilterOp result;
    ::new (&result.grayscale._0) (float)(a0);
    result.tag = Tag::Grayscale;
    return result;
  }

  bool IsGrayscale() const {
    return tag == Tag::Grayscale;
  }

  static FilterOp HueRotate(const float &a0) {
    FilterOp result;
    ::new (&result.hue_rotate._0) (float)(a0);
    result.tag = Tag::HueRotate;
    return result;
  }

  bool IsHueRotate() const {
    return tag == Tag::HueRotate;
  }

  static FilterOp Invert(const float &a0) {
    FilterOp result;
    ::new (&result.invert._0) (float)(a0);
    result.tag = Tag::Invert;
    return result;
  }

  bool IsInvert() const {
    return tag == Tag::Invert;
  }

  static FilterOp Opacity(const PropertyBinding<float> &a0,
                          const float &a1) {
    FilterOp result;
    ::new (&result.opacity._0) (PropertyBinding<float>)(a0);
    ::new (&result.opacity._1) (float)(a1);
    result.tag = Tag::Opacity;
    return result;
  }

  bool IsOpacity() const {
    return tag == Tag::Opacity;
  }

  static FilterOp Saturate(const float &a0) {
    FilterOp result;
    ::new (&result.saturate._0) (float)(a0);
    result.tag = Tag::Saturate;
    return result;
  }

  bool IsSaturate() const {
    return tag == Tag::Saturate;
  }

  static FilterOp Sepia(const float &a0) {
    FilterOp result;
    ::new (&result.sepia._0) (float)(a0);
    result.tag = Tag::Sepia;
    return result;
  }

  bool IsSepia() const {
    return tag == Tag::Sepia;
  }

  static FilterOp DropShadow(const Shadow &a0) {
    FilterOp result;
    ::new (&result.drop_shadow._0) (Shadow)(a0);
    result.tag = Tag::DropShadow;
    return result;
  }

  bool IsDropShadow() const {
    return tag == Tag::DropShadow;
  }

  static FilterOp ColorMatrix(const float (&a0)[20]) {
    FilterOp result;
    for (int i = 0; i < 20; i++) {
      ::new (&result.color_matrix._0[i]) (float)(a0[i]);
    }
    result.tag = Tag::ColorMatrix;
    return result;
  }

  bool IsColorMatrix() const {
    return tag == Tag::ColorMatrix;
  }

  static FilterOp SrgbToLinear() {
    FilterOp result;
    result.tag = Tag::SrgbToLinear;
    return result;
  }

  bool IsSrgbToLinear() const {
    return tag == Tag::SrgbToLinear;
  }

  static FilterOp LinearToSrgb() {
    FilterOp result;
    result.tag = Tag::LinearToSrgb;
    return result;
  }

  bool IsLinearToSrgb() const {
    return tag == Tag::LinearToSrgb;
  }

  static FilterOp ComponentTransfer() {
    FilterOp result;
    result.tag = Tag::ComponentTransfer;
    return result;
  }

  bool IsComponentTransfer() const {
    return tag == Tag::ComponentTransfer;
  }

  static FilterOp Flood(const ColorF &a0) {
    FilterOp result;
    ::new (&result.flood._0) (ColorF)(a0);
    result.tag = Tag::Flood;
    return result;
  }

  bool IsFlood() const {
    return tag == Tag::Flood;
  }

  static FilterOp SVGFESourceGraphic(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_source_graphic.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFESourceGraphic;
    return result;
  }

  bool IsSVGFESourceGraphic() const {
    return tag == Tag::SVGFESourceGraphic;
  }

  static FilterOp SVGFESourceAlpha(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_source_alpha.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFESourceAlpha;
    return result;
  }

  bool IsSVGFESourceAlpha() const {
    return tag == Tag::SVGFESourceAlpha;
  }

  static FilterOp SVGFEIdentity(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_identity.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEIdentity;
    return result;
  }

  bool IsSVGFEIdentity() const {
    return tag == Tag::SVGFEIdentity;
  }

  static FilterOp SVGFEOpacity(const FilterOpGraphNode &aNode,
                               const PropertyBinding<float> &aValuebinding,
                               const float &aValue) {
    FilterOp result;
    ::new (&result.svgfe_opacity.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_opacity.valuebinding) (PropertyBinding<float>)(aValuebinding);
    ::new (&result.svgfe_opacity.value) (float)(aValue);
    result.tag = Tag::SVGFEOpacity;
    return result;
  }

  bool IsSVGFEOpacity() const {
    return tag == Tag::SVGFEOpacity;
  }

  static FilterOp SVGFEToAlpha(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_to_alpha.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEToAlpha;
    return result;
  }

  bool IsSVGFEToAlpha() const {
    return tag == Tag::SVGFEToAlpha;
  }

  static FilterOp SVGFEBlendDarken(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_darken.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendDarken;
    return result;
  }

  bool IsSVGFEBlendDarken() const {
    return tag == Tag::SVGFEBlendDarken;
  }

  static FilterOp SVGFEBlendLighten(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_lighten.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendLighten;
    return result;
  }

  bool IsSVGFEBlendLighten() const {
    return tag == Tag::SVGFEBlendLighten;
  }

  static FilterOp SVGFEBlendMultiply(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_multiply.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendMultiply;
    return result;
  }

  bool IsSVGFEBlendMultiply() const {
    return tag == Tag::SVGFEBlendMultiply;
  }

  static FilterOp SVGFEBlendNormal(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_normal.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendNormal;
    return result;
  }

  bool IsSVGFEBlendNormal() const {
    return tag == Tag::SVGFEBlendNormal;
  }

  static FilterOp SVGFEBlendScreen(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_screen.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendScreen;
    return result;
  }

  bool IsSVGFEBlendScreen() const {
    return tag == Tag::SVGFEBlendScreen;
  }

  static FilterOp SVGFEBlendOverlay(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_overlay.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendOverlay;
    return result;
  }

  bool IsSVGFEBlendOverlay() const {
    return tag == Tag::SVGFEBlendOverlay;
  }

  static FilterOp SVGFEBlendColorDodge(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_color_dodge.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendColorDodge;
    return result;
  }

  bool IsSVGFEBlendColorDodge() const {
    return tag == Tag::SVGFEBlendColorDodge;
  }

  static FilterOp SVGFEBlendColorBurn(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_color_burn.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendColorBurn;
    return result;
  }

  bool IsSVGFEBlendColorBurn() const {
    return tag == Tag::SVGFEBlendColorBurn;
  }

  static FilterOp SVGFEBlendHardLight(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_hard_light.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendHardLight;
    return result;
  }

  bool IsSVGFEBlendHardLight() const {
    return tag == Tag::SVGFEBlendHardLight;
  }

  static FilterOp SVGFEBlendSoftLight(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_soft_light.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendSoftLight;
    return result;
  }

  bool IsSVGFEBlendSoftLight() const {
    return tag == Tag::SVGFEBlendSoftLight;
  }

  static FilterOp SVGFEBlendDifference(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_difference.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendDifference;
    return result;
  }

  bool IsSVGFEBlendDifference() const {
    return tag == Tag::SVGFEBlendDifference;
  }

  static FilterOp SVGFEBlendExclusion(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_exclusion.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendExclusion;
    return result;
  }

  bool IsSVGFEBlendExclusion() const {
    return tag == Tag::SVGFEBlendExclusion;
  }

  static FilterOp SVGFEBlendHue(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_hue.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendHue;
    return result;
  }

  bool IsSVGFEBlendHue() const {
    return tag == Tag::SVGFEBlendHue;
  }

  static FilterOp SVGFEBlendSaturation(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_saturation.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendSaturation;
    return result;
  }

  bool IsSVGFEBlendSaturation() const {
    return tag == Tag::SVGFEBlendSaturation;
  }

  static FilterOp SVGFEBlendColor(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_color.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendColor;
    return result;
  }

  bool IsSVGFEBlendColor() const {
    return tag == Tag::SVGFEBlendColor;
  }

  static FilterOp SVGFEBlendLuminosity(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_blend_luminosity.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEBlendLuminosity;
    return result;
  }

  bool IsSVGFEBlendLuminosity() const {
    return tag == Tag::SVGFEBlendLuminosity;
  }

  static FilterOp SVGFEColorMatrix(const FilterOpGraphNode &aNode,
                                   const float (&aValues)[20]) {
    FilterOp result;
    ::new (&result.svgfe_color_matrix.node) (FilterOpGraphNode)(aNode);
    for (int i = 0; i < 20; i++) {
      ::new (&result.svgfe_color_matrix.values[i]) (float)(aValues[i]);
    }
    result.tag = Tag::SVGFEColorMatrix;
    return result;
  }

  bool IsSVGFEColorMatrix() const {
    return tag == Tag::SVGFEColorMatrix;
  }

  static FilterOp SVGFEComponentTransfer(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_component_transfer.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFEComponentTransfer;
    return result;
  }

  bool IsSVGFEComponentTransfer() const {
    return tag == Tag::SVGFEComponentTransfer;
  }

  static FilterOp SVGFECompositeArithmetic(const FilterOpGraphNode &aNode,
                                           const float &aK1,
                                           const float &aK2,
                                           const float &aK3,
                                           const float &aK4) {
    FilterOp result;
    ::new (&result.svgfe_composite_arithmetic.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_composite_arithmetic.k1) (float)(aK1);
    ::new (&result.svgfe_composite_arithmetic.k2) (float)(aK2);
    ::new (&result.svgfe_composite_arithmetic.k3) (float)(aK3);
    ::new (&result.svgfe_composite_arithmetic.k4) (float)(aK4);
    result.tag = Tag::SVGFECompositeArithmetic;
    return result;
  }

  bool IsSVGFECompositeArithmetic() const {
    return tag == Tag::SVGFECompositeArithmetic;
  }

  static FilterOp SVGFECompositeATop(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_composite_a_top.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFECompositeATop;
    return result;
  }

  bool IsSVGFECompositeATop() const {
    return tag == Tag::SVGFECompositeATop;
  }

  static FilterOp SVGFECompositeIn(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_composite_in.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFECompositeIn;
    return result;
  }

  bool IsSVGFECompositeIn() const {
    return tag == Tag::SVGFECompositeIn;
  }

  static FilterOp SVGFECompositeLighter(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_composite_lighter.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFECompositeLighter;
    return result;
  }

  bool IsSVGFECompositeLighter() const {
    return tag == Tag::SVGFECompositeLighter;
  }

  static FilterOp SVGFECompositeOut(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_composite_out.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFECompositeOut;
    return result;
  }

  bool IsSVGFECompositeOut() const {
    return tag == Tag::SVGFECompositeOut;
  }

  static FilterOp SVGFECompositeOver(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_composite_over.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFECompositeOver;
    return result;
  }

  bool IsSVGFECompositeOver() const {
    return tag == Tag::SVGFECompositeOver;
  }

  static FilterOp SVGFECompositeXOR(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_composite_xor.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFECompositeXOR;
    return result;
  }

  bool IsSVGFECompositeXOR() const {
    return tag == Tag::SVGFECompositeXOR;
  }

  static FilterOp SVGFEConvolveMatrixEdgeModeDuplicate(const FilterOpGraphNode &aNode,
                                                       const int32_t &aOrderX,
                                                       const int32_t &aOrderY,
                                                       const float (&aKernel)[25],
                                                       const float &aDivisor,
                                                       const float &aBias,
                                                       const int32_t &aTargetX,
                                                       const int32_t &aTargetY,
                                                       const float &aKernelUnitLengthX,
                                                       const float &aKernelUnitLengthY,
                                                       const int32_t &aPreserveAlpha) {
    FilterOp result;
    ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.order_x) (int32_t)(aOrderX);
    ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.order_y) (int32_t)(aOrderY);
    for (int i = 0; i < 25; i++) {
      ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.kernel[i]) (float)(aKernel[i]);
    }
    ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.divisor) (float)(aDivisor);
    ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.bias) (float)(aBias);
    ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.target_x) (int32_t)(aTargetX);
    ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.target_y) (int32_t)(aTargetY);
    ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.kernel_unit_length_x) (float)(aKernelUnitLengthX);
    ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.kernel_unit_length_y) (float)(aKernelUnitLengthY);
    ::new (&result.svgfe_convolve_matrix_edge_mode_duplicate.preserve_alpha) (int32_t)(aPreserveAlpha);
    result.tag = Tag::SVGFEConvolveMatrixEdgeModeDuplicate;
    return result;
  }

  bool IsSVGFEConvolveMatrixEdgeModeDuplicate() const {
    return tag == Tag::SVGFEConvolveMatrixEdgeModeDuplicate;
  }

  static FilterOp SVGFEConvolveMatrixEdgeModeNone(const FilterOpGraphNode &aNode,
                                                  const int32_t &aOrderX,
                                                  const int32_t &aOrderY,
                                                  const float (&aKernel)[25],
                                                  const float &aDivisor,
                                                  const float &aBias,
                                                  const int32_t &aTargetX,
                                                  const int32_t &aTargetY,
                                                  const float &aKernelUnitLengthX,
                                                  const float &aKernelUnitLengthY,
                                                  const int32_t &aPreserveAlpha) {
    FilterOp result;
    ::new (&result.svgfe_convolve_matrix_edge_mode_none.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_convolve_matrix_edge_mode_none.order_x) (int32_t)(aOrderX);
    ::new (&result.svgfe_convolve_matrix_edge_mode_none.order_y) (int32_t)(aOrderY);
    for (int i = 0; i < 25; i++) {
      ::new (&result.svgfe_convolve_matrix_edge_mode_none.kernel[i]) (float)(aKernel[i]);
    }
    ::new (&result.svgfe_convolve_matrix_edge_mode_none.divisor) (float)(aDivisor);
    ::new (&result.svgfe_convolve_matrix_edge_mode_none.bias) (float)(aBias);
    ::new (&result.svgfe_convolve_matrix_edge_mode_none.target_x) (int32_t)(aTargetX);
    ::new (&result.svgfe_convolve_matrix_edge_mode_none.target_y) (int32_t)(aTargetY);
    ::new (&result.svgfe_convolve_matrix_edge_mode_none.kernel_unit_length_x) (float)(aKernelUnitLengthX);
    ::new (&result.svgfe_convolve_matrix_edge_mode_none.kernel_unit_length_y) (float)(aKernelUnitLengthY);
    ::new (&result.svgfe_convolve_matrix_edge_mode_none.preserve_alpha) (int32_t)(aPreserveAlpha);
    result.tag = Tag::SVGFEConvolveMatrixEdgeModeNone;
    return result;
  }

  bool IsSVGFEConvolveMatrixEdgeModeNone() const {
    return tag == Tag::SVGFEConvolveMatrixEdgeModeNone;
  }

  static FilterOp SVGFEConvolveMatrixEdgeModeWrap(const FilterOpGraphNode &aNode,
                                                  const int32_t &aOrderX,
                                                  const int32_t &aOrderY,
                                                  const float (&aKernel)[25],
                                                  const float &aDivisor,
                                                  const float &aBias,
                                                  const int32_t &aTargetX,
                                                  const int32_t &aTargetY,
                                                  const float &aKernelUnitLengthX,
                                                  const float &aKernelUnitLengthY,
                                                  const int32_t &aPreserveAlpha) {
    FilterOp result;
    ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.order_x) (int32_t)(aOrderX);
    ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.order_y) (int32_t)(aOrderY);
    for (int i = 0; i < 25; i++) {
      ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.kernel[i]) (float)(aKernel[i]);
    }
    ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.divisor) (float)(aDivisor);
    ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.bias) (float)(aBias);
    ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.target_x) (int32_t)(aTargetX);
    ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.target_y) (int32_t)(aTargetY);
    ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.kernel_unit_length_x) (float)(aKernelUnitLengthX);
    ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.kernel_unit_length_y) (float)(aKernelUnitLengthY);
    ::new (&result.svgfe_convolve_matrix_edge_mode_wrap.preserve_alpha) (int32_t)(aPreserveAlpha);
    result.tag = Tag::SVGFEConvolveMatrixEdgeModeWrap;
    return result;
  }

  bool IsSVGFEConvolveMatrixEdgeModeWrap() const {
    return tag == Tag::SVGFEConvolveMatrixEdgeModeWrap;
  }

  static FilterOp SVGFEDiffuseLightingDistant(const FilterOpGraphNode &aNode,
                                              const float &aSurfaceScale,
                                              const float &aDiffuseConstant,
                                              const float &aKernelUnitLengthX,
                                              const float &aKernelUnitLengthY,
                                              const float &aAzimuth,
                                              const float &aElevation) {
    FilterOp result;
    ::new (&result.svgfe_diffuse_lighting_distant.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_diffuse_lighting_distant.surface_scale) (float)(aSurfaceScale);
    ::new (&result.svgfe_diffuse_lighting_distant.diffuse_constant) (float)(aDiffuseConstant);
    ::new (&result.svgfe_diffuse_lighting_distant.kernel_unit_length_x) (float)(aKernelUnitLengthX);
    ::new (&result.svgfe_diffuse_lighting_distant.kernel_unit_length_y) (float)(aKernelUnitLengthY);
    ::new (&result.svgfe_diffuse_lighting_distant.azimuth) (float)(aAzimuth);
    ::new (&result.svgfe_diffuse_lighting_distant.elevation) (float)(aElevation);
    result.tag = Tag::SVGFEDiffuseLightingDistant;
    return result;
  }

  bool IsSVGFEDiffuseLightingDistant() const {
    return tag == Tag::SVGFEDiffuseLightingDistant;
  }

  static FilterOp SVGFEDiffuseLightingPoint(const FilterOpGraphNode &aNode,
                                            const float &aSurfaceScale,
                                            const float &aDiffuseConstant,
                                            const float &aKernelUnitLengthX,
                                            const float &aKernelUnitLengthY,
                                            const float &aX,
                                            const float &aY,
                                            const float &aZ) {
    FilterOp result;
    ::new (&result.svgfe_diffuse_lighting_point.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_diffuse_lighting_point.surface_scale) (float)(aSurfaceScale);
    ::new (&result.svgfe_diffuse_lighting_point.diffuse_constant) (float)(aDiffuseConstant);
    ::new (&result.svgfe_diffuse_lighting_point.kernel_unit_length_x) (float)(aKernelUnitLengthX);
    ::new (&result.svgfe_diffuse_lighting_point.kernel_unit_length_y) (float)(aKernelUnitLengthY);
    ::new (&result.svgfe_diffuse_lighting_point.x) (float)(aX);
    ::new (&result.svgfe_diffuse_lighting_point.y) (float)(aY);
    ::new (&result.svgfe_diffuse_lighting_point.z) (float)(aZ);
    result.tag = Tag::SVGFEDiffuseLightingPoint;
    return result;
  }

  bool IsSVGFEDiffuseLightingPoint() const {
    return tag == Tag::SVGFEDiffuseLightingPoint;
  }

  static FilterOp SVGFEDiffuseLightingSpot(const FilterOpGraphNode &aNode,
                                           const float &aSurfaceScale,
                                           const float &aDiffuseConstant,
                                           const float &aKernelUnitLengthX,
                                           const float &aKernelUnitLengthY,
                                           const float &aX,
                                           const float &aY,
                                           const float &aZ,
                                           const float &aPointsAtX,
                                           const float &aPointsAtY,
                                           const float &aPointsAtZ,
                                           const float &aConeExponent,
                                           const float &aLimitingConeAngle) {
    FilterOp result;
    ::new (&result.svgfe_diffuse_lighting_spot.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_diffuse_lighting_spot.surface_scale) (float)(aSurfaceScale);
    ::new (&result.svgfe_diffuse_lighting_spot.diffuse_constant) (float)(aDiffuseConstant);
    ::new (&result.svgfe_diffuse_lighting_spot.kernel_unit_length_x) (float)(aKernelUnitLengthX);
    ::new (&result.svgfe_diffuse_lighting_spot.kernel_unit_length_y) (float)(aKernelUnitLengthY);
    ::new (&result.svgfe_diffuse_lighting_spot.x) (float)(aX);
    ::new (&result.svgfe_diffuse_lighting_spot.y) (float)(aY);
    ::new (&result.svgfe_diffuse_lighting_spot.z) (float)(aZ);
    ::new (&result.svgfe_diffuse_lighting_spot.points_at_x) (float)(aPointsAtX);
    ::new (&result.svgfe_diffuse_lighting_spot.points_at_y) (float)(aPointsAtY);
    ::new (&result.svgfe_diffuse_lighting_spot.points_at_z) (float)(aPointsAtZ);
    ::new (&result.svgfe_diffuse_lighting_spot.cone_exponent) (float)(aConeExponent);
    ::new (&result.svgfe_diffuse_lighting_spot.limiting_cone_angle) (float)(aLimitingConeAngle);
    result.tag = Tag::SVGFEDiffuseLightingSpot;
    return result;
  }

  bool IsSVGFEDiffuseLightingSpot() const {
    return tag == Tag::SVGFEDiffuseLightingSpot;
  }

  static FilterOp SVGFEDisplacementMap(const FilterOpGraphNode &aNode,
                                       const float &aScale,
                                       const uint32_t &aXChannelSelector,
                                       const uint32_t &aYChannelSelector) {
    FilterOp result;
    ::new (&result.svgfe_displacement_map.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_displacement_map.scale) (float)(aScale);
    ::new (&result.svgfe_displacement_map.x_channel_selector) (uint32_t)(aXChannelSelector);
    ::new (&result.svgfe_displacement_map.y_channel_selector) (uint32_t)(aYChannelSelector);
    result.tag = Tag::SVGFEDisplacementMap;
    return result;
  }

  bool IsSVGFEDisplacementMap() const {
    return tag == Tag::SVGFEDisplacementMap;
  }

  static FilterOp SVGFEDropShadow(const FilterOpGraphNode &aNode,
                                  const ColorF &aColor,
                                  const float &aDx,
                                  const float &aDy,
                                  const float &aStdDeviationX,
                                  const float &aStdDeviationY) {
    FilterOp result;
    ::new (&result.svgfe_drop_shadow.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_drop_shadow.color) (ColorF)(aColor);
    ::new (&result.svgfe_drop_shadow.dx) (float)(aDx);
    ::new (&result.svgfe_drop_shadow.dy) (float)(aDy);
    ::new (&result.svgfe_drop_shadow.std_deviation_x) (float)(aStdDeviationX);
    ::new (&result.svgfe_drop_shadow.std_deviation_y) (float)(aStdDeviationY);
    result.tag = Tag::SVGFEDropShadow;
    return result;
  }

  bool IsSVGFEDropShadow() const {
    return tag == Tag::SVGFEDropShadow;
  }

  static FilterOp SVGFEFlood(const FilterOpGraphNode &aNode,
                             const ColorF &aColor) {
    FilterOp result;
    ::new (&result.svgfe_flood.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_flood.color) (ColorF)(aColor);
    result.tag = Tag::SVGFEFlood;
    return result;
  }

  bool IsSVGFEFlood() const {
    return tag == Tag::SVGFEFlood;
  }

  static FilterOp SVGFEGaussianBlur(const FilterOpGraphNode &aNode,
                                    const float &aStdDeviationX,
                                    const float &aStdDeviationY) {
    FilterOp result;
    ::new (&result.svgfe_gaussian_blur.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_gaussian_blur.std_deviation_x) (float)(aStdDeviationX);
    ::new (&result.svgfe_gaussian_blur.std_deviation_y) (float)(aStdDeviationY);
    result.tag = Tag::SVGFEGaussianBlur;
    return result;
  }

  bool IsSVGFEGaussianBlur() const {
    return tag == Tag::SVGFEGaussianBlur;
  }

  static FilterOp SVGFEImage(const FilterOpGraphNode &aNode,
                             const uint32_t &aSamplingFilter,
                             const float (&aMatrix)[6]) {
    FilterOp result;
    ::new (&result.svgfe_image.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_image.sampling_filter) (uint32_t)(aSamplingFilter);
    for (int i = 0; i < 6; i++) {
      ::new (&result.svgfe_image.matrix[i]) (float)(aMatrix[i]);
    }
    result.tag = Tag::SVGFEImage;
    return result;
  }

  bool IsSVGFEImage() const {
    return tag == Tag::SVGFEImage;
  }

  static FilterOp SVGFEMorphologyDilate(const FilterOpGraphNode &aNode,
                                        const float &aRadiusX,
                                        const float &aRadiusY) {
    FilterOp result;
    ::new (&result.svgfe_morphology_dilate.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_morphology_dilate.radius_x) (float)(aRadiusX);
    ::new (&result.svgfe_morphology_dilate.radius_y) (float)(aRadiusY);
    result.tag = Tag::SVGFEMorphologyDilate;
    return result;
  }

  bool IsSVGFEMorphologyDilate() const {
    return tag == Tag::SVGFEMorphologyDilate;
  }

  static FilterOp SVGFEMorphologyErode(const FilterOpGraphNode &aNode,
                                       const float &aRadiusX,
                                       const float &aRadiusY) {
    FilterOp result;
    ::new (&result.svgfe_morphology_erode.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_morphology_erode.radius_x) (float)(aRadiusX);
    ::new (&result.svgfe_morphology_erode.radius_y) (float)(aRadiusY);
    result.tag = Tag::SVGFEMorphologyErode;
    return result;
  }

  bool IsSVGFEMorphologyErode() const {
    return tag == Tag::SVGFEMorphologyErode;
  }

  static FilterOp SVGFEOffset(const FilterOpGraphNode &aNode,
                              const float &aOffsetX,
                              const float &aOffsetY) {
    FilterOp result;
    ::new (&result.svgfe_offset.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_offset.offset_x) (float)(aOffsetX);
    ::new (&result.svgfe_offset.offset_y) (float)(aOffsetY);
    result.tag = Tag::SVGFEOffset;
    return result;
  }

  bool IsSVGFEOffset() const {
    return tag == Tag::SVGFEOffset;
  }

  static FilterOp SVGFESpecularLightingDistant(const FilterOpGraphNode &aNode,
                                               const float &aSurfaceScale,
                                               const float &aSpecularConstant,
                                               const float &aSpecularExponent,
                                               const float &aKernelUnitLengthX,
                                               const float &aKernelUnitLengthY,
                                               const float &aAzimuth,
                                               const float &aElevation) {
    FilterOp result;
    ::new (&result.svgfe_specular_lighting_distant.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_specular_lighting_distant.surface_scale) (float)(aSurfaceScale);
    ::new (&result.svgfe_specular_lighting_distant.specular_constant) (float)(aSpecularConstant);
    ::new (&result.svgfe_specular_lighting_distant.specular_exponent) (float)(aSpecularExponent);
    ::new (&result.svgfe_specular_lighting_distant.kernel_unit_length_x) (float)(aKernelUnitLengthX);
    ::new (&result.svgfe_specular_lighting_distant.kernel_unit_length_y) (float)(aKernelUnitLengthY);
    ::new (&result.svgfe_specular_lighting_distant.azimuth) (float)(aAzimuth);
    ::new (&result.svgfe_specular_lighting_distant.elevation) (float)(aElevation);
    result.tag = Tag::SVGFESpecularLightingDistant;
    return result;
  }

  bool IsSVGFESpecularLightingDistant() const {
    return tag == Tag::SVGFESpecularLightingDistant;
  }

  static FilterOp SVGFESpecularLightingPoint(const FilterOpGraphNode &aNode,
                                             const float &aSurfaceScale,
                                             const float &aSpecularConstant,
                                             const float &aSpecularExponent,
                                             const float &aKernelUnitLengthX,
                                             const float &aKernelUnitLengthY,
                                             const float &aX,
                                             const float &aY,
                                             const float &aZ) {
    FilterOp result;
    ::new (&result.svgfe_specular_lighting_point.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_specular_lighting_point.surface_scale) (float)(aSurfaceScale);
    ::new (&result.svgfe_specular_lighting_point.specular_constant) (float)(aSpecularConstant);
    ::new (&result.svgfe_specular_lighting_point.specular_exponent) (float)(aSpecularExponent);
    ::new (&result.svgfe_specular_lighting_point.kernel_unit_length_x) (float)(aKernelUnitLengthX);
    ::new (&result.svgfe_specular_lighting_point.kernel_unit_length_y) (float)(aKernelUnitLengthY);
    ::new (&result.svgfe_specular_lighting_point.x) (float)(aX);
    ::new (&result.svgfe_specular_lighting_point.y) (float)(aY);
    ::new (&result.svgfe_specular_lighting_point.z) (float)(aZ);
    result.tag = Tag::SVGFESpecularLightingPoint;
    return result;
  }

  bool IsSVGFESpecularLightingPoint() const {
    return tag == Tag::SVGFESpecularLightingPoint;
  }

  static FilterOp SVGFESpecularLightingSpot(const FilterOpGraphNode &aNode,
                                            const float &aSurfaceScale,
                                            const float &aSpecularConstant,
                                            const float &aSpecularExponent,
                                            const float &aKernelUnitLengthX,
                                            const float &aKernelUnitLengthY,
                                            const float &aX,
                                            const float &aY,
                                            const float &aZ,
                                            const float &aPointsAtX,
                                            const float &aPointsAtY,
                                            const float &aPointsAtZ,
                                            const float &aConeExponent,
                                            const float &aLimitingConeAngle) {
    FilterOp result;
    ::new (&result.svgfe_specular_lighting_spot.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_specular_lighting_spot.surface_scale) (float)(aSurfaceScale);
    ::new (&result.svgfe_specular_lighting_spot.specular_constant) (float)(aSpecularConstant);
    ::new (&result.svgfe_specular_lighting_spot.specular_exponent) (float)(aSpecularExponent);
    ::new (&result.svgfe_specular_lighting_spot.kernel_unit_length_x) (float)(aKernelUnitLengthX);
    ::new (&result.svgfe_specular_lighting_spot.kernel_unit_length_y) (float)(aKernelUnitLengthY);
    ::new (&result.svgfe_specular_lighting_spot.x) (float)(aX);
    ::new (&result.svgfe_specular_lighting_spot.y) (float)(aY);
    ::new (&result.svgfe_specular_lighting_spot.z) (float)(aZ);
    ::new (&result.svgfe_specular_lighting_spot.points_at_x) (float)(aPointsAtX);
    ::new (&result.svgfe_specular_lighting_spot.points_at_y) (float)(aPointsAtY);
    ::new (&result.svgfe_specular_lighting_spot.points_at_z) (float)(aPointsAtZ);
    ::new (&result.svgfe_specular_lighting_spot.cone_exponent) (float)(aConeExponent);
    ::new (&result.svgfe_specular_lighting_spot.limiting_cone_angle) (float)(aLimitingConeAngle);
    result.tag = Tag::SVGFESpecularLightingSpot;
    return result;
  }

  bool IsSVGFESpecularLightingSpot() const {
    return tag == Tag::SVGFESpecularLightingSpot;
  }

  static FilterOp SVGFETile(const FilterOpGraphNode &aNode) {
    FilterOp result;
    ::new (&result.svgfe_tile.node) (FilterOpGraphNode)(aNode);
    result.tag = Tag::SVGFETile;
    return result;
  }

  bool IsSVGFETile() const {
    return tag == Tag::SVGFETile;
  }

  static FilterOp SVGFETurbulenceWithFractalNoiseWithNoStitching(const FilterOpGraphNode &aNode,
                                                                 const float &aBaseFrequencyX,
                                                                 const float &aBaseFrequencyY,
                                                                 const uint32_t &aNumOctaves,
                                                                 const uint32_t &aSeed) {
    FilterOp result;
    ::new (&result.svgfe_turbulence_with_fractal_noise_with_no_stitching.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_turbulence_with_fractal_noise_with_no_stitching.base_frequency_x) (float)(aBaseFrequencyX);
    ::new (&result.svgfe_turbulence_with_fractal_noise_with_no_stitching.base_frequency_y) (float)(aBaseFrequencyY);
    ::new (&result.svgfe_turbulence_with_fractal_noise_with_no_stitching.num_octaves) (uint32_t)(aNumOctaves);
    ::new (&result.svgfe_turbulence_with_fractal_noise_with_no_stitching.seed) (uint32_t)(aSeed);
    result.tag = Tag::SVGFETurbulenceWithFractalNoiseWithNoStitching;
    return result;
  }

  bool IsSVGFETurbulenceWithFractalNoiseWithNoStitching() const {
    return tag == Tag::SVGFETurbulenceWithFractalNoiseWithNoStitching;
  }

  static FilterOp SVGFETurbulenceWithFractalNoiseWithStitching(const FilterOpGraphNode &aNode,
                                                               const float &aBaseFrequencyX,
                                                               const float &aBaseFrequencyY,
                                                               const uint32_t &aNumOctaves,
                                                               const uint32_t &aSeed) {
    FilterOp result;
    ::new (&result.svgfe_turbulence_with_fractal_noise_with_stitching.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_turbulence_with_fractal_noise_with_stitching.base_frequency_x) (float)(aBaseFrequencyX);
    ::new (&result.svgfe_turbulence_with_fractal_noise_with_stitching.base_frequency_y) (float)(aBaseFrequencyY);
    ::new (&result.svgfe_turbulence_with_fractal_noise_with_stitching.num_octaves) (uint32_t)(aNumOctaves);
    ::new (&result.svgfe_turbulence_with_fractal_noise_with_stitching.seed) (uint32_t)(aSeed);
    result.tag = Tag::SVGFETurbulenceWithFractalNoiseWithStitching;
    return result;
  }

  bool IsSVGFETurbulenceWithFractalNoiseWithStitching() const {
    return tag == Tag::SVGFETurbulenceWithFractalNoiseWithStitching;
  }

  static FilterOp SVGFETurbulenceWithTurbulenceNoiseWithNoStitching(const FilterOpGraphNode &aNode,
                                                                    const float &aBaseFrequencyX,
                                                                    const float &aBaseFrequencyY,
                                                                    const uint32_t &aNumOctaves,
                                                                    const uint32_t &aSeed) {
    FilterOp result;
    ::new (&result.svgfe_turbulence_with_turbulence_noise_with_no_stitching.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_turbulence_with_turbulence_noise_with_no_stitching.base_frequency_x) (float)(aBaseFrequencyX);
    ::new (&result.svgfe_turbulence_with_turbulence_noise_with_no_stitching.base_frequency_y) (float)(aBaseFrequencyY);
    ::new (&result.svgfe_turbulence_with_turbulence_noise_with_no_stitching.num_octaves) (uint32_t)(aNumOctaves);
    ::new (&result.svgfe_turbulence_with_turbulence_noise_with_no_stitching.seed) (uint32_t)(aSeed);
    result.tag = Tag::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching;
    return result;
  }

  bool IsSVGFETurbulenceWithTurbulenceNoiseWithNoStitching() const {
    return tag == Tag::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching;
  }

  static FilterOp SVGFETurbulenceWithTurbulenceNoiseWithStitching(const FilterOpGraphNode &aNode,
                                                                  const float &aBaseFrequencyX,
                                                                  const float &aBaseFrequencyY,
                                                                  const uint32_t &aNumOctaves,
                                                                  const uint32_t &aSeed) {
    FilterOp result;
    ::new (&result.svgfe_turbulence_with_turbulence_noise_with_stitching.node) (FilterOpGraphNode)(aNode);
    ::new (&result.svgfe_turbulence_with_turbulence_noise_with_stitching.base_frequency_x) (float)(aBaseFrequencyX);
    ::new (&result.svgfe_turbulence_with_turbulence_noise_with_stitching.base_frequency_y) (float)(aBaseFrequencyY);
    ::new (&result.svgfe_turbulence_with_turbulence_noise_with_stitching.num_octaves) (uint32_t)(aNumOctaves);
    ::new (&result.svgfe_turbulence_with_turbulence_noise_with_stitching.seed) (uint32_t)(aSeed);
    result.tag = Tag::SVGFETurbulenceWithTurbulenceNoiseWithStitching;
    return result;
  }

  bool IsSVGFETurbulenceWithTurbulenceNoiseWithStitching() const {
    return tag == Tag::SVGFETurbulenceWithTurbulenceNoiseWithStitching;
  }

  static FilterOp Sentinel() {
    FilterOp result;
    result.tag = Tag::Sentinel;
    return result;
  }

  bool IsSentinel() const {
    return tag == Tag::Sentinel;
  }
};

struct WrFilterData {
  ComponentTransferFuncType funcR_type;
  float *R_values;
  uintptr_t R_values_count;
  ComponentTransferFuncType funcG_type;
  float *G_values;
  uintptr_t G_values_count;
  ComponentTransferFuncType funcB_type;
  float *B_values;
  uintptr_t B_values_count;
  ComponentTransferFuncType funcA_type;
  float *A_values;
  uintptr_t A_values_count;

  friend std::ostream& operator<<(std::ostream& aStream, const WrFilterData& aInstance) {
    return aStream << "{ " << "funcR_type=" << aInstance.funcR_type << ", "
                           << "R_values=" << aInstance.R_values << ", "
                           << "R_values_count=" << aInstance.R_values_count << ", "
                           << "funcG_type=" << aInstance.funcG_type << ", "
                           << "G_values=" << aInstance.G_values << ", "
                           << "G_values_count=" << aInstance.G_values_count << ", "
                           << "funcB_type=" << aInstance.funcB_type << ", "
                           << "B_values=" << aInstance.B_values << ", "
                           << "B_values_count=" << aInstance.B_values_count << ", "
                           << "funcA_type=" << aInstance.funcA_type << ", "
                           << "A_values=" << aInstance.A_values << ", "
                           << "A_values_count=" << aInstance.A_values_count << " }";
  }
  bool operator==(const WrFilterData& aOther) const {
    return funcR_type == aOther.funcR_type &&
           R_values == aOther.R_values &&
           R_values_count == aOther.R_values_count &&
           funcG_type == aOther.funcG_type &&
           G_values == aOther.G_values &&
           G_values_count == aOther.G_values_count &&
           funcB_type == aOther.funcB_type &&
           B_values == aOther.B_values &&
           B_values_count == aOther.B_values_count &&
           funcA_type == aOther.funcA_type &&
           A_values == aOther.A_values &&
           A_values_count == aOther.A_values_count;
  }
};

/// Configure whether the contents of a stacking context
/// should be rasterized in local space or screen space.
/// Local space rasterized pictures are typically used
/// when we want to cache the output, and performance is
/// important. Note that this is a performance hint only,
/// which WR may choose to ignore.
union RasterSpace {
  enum class Tag : uint8_t {
    Local,
    Screen,
    /// Must be last for serialization purposes
    Sentinel,
  };

  friend std::ostream& operator<<(std::ostream& aStream, const Tag& aInstance) {
    using Tag = RasterSpace::Tag;
    switch (aInstance) {
      case Tag::Local: aStream << "Local"; break;
      case Tag::Screen: aStream << "Screen"; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  friend std::ostream& operator<<(std::ostream& aStream, const RasterSpace& aInstance) {
    using Tag = RasterSpace::Tag;
    switch (aInstance.tag) {
      case Tag::Local: aStream << aInstance.local; break;
      case Tag::Screen: aStream << "Screen"; break;
      case Tag::Sentinel: aStream << "Sentinel"; break;
    }
    return aStream;
  }

  struct Local_Body {
    Tag tag;
    float _0;

    friend std::ostream& operator<<(std::ostream& aStream, const Local_Body& aInstance) {
      return aStream << "{ " << "tag=" << aInstance.tag << ", "
                             << "_0=" << aInstance._0 << " }";
    }
    bool operator==(const Local_Body& aOther) const {
      return _0 == aOther._0;
    }
  };

  struct {
    Tag tag;
  };
  Local_Body local;

  static RasterSpace Local(const float &a0) {
    RasterSpace result;
    ::new (&result.local._0) (float)(a0);
    result.tag = Tag::Local;
    return result;
  }

  bool IsLocal() const {
    return tag == Tag::Local;
  }

  static RasterSpace Screen() {
    RasterSpace result;
    result.tag = Tag::Screen;
    return result;
  }

  bool IsScreen() const {
    return tag == Tag::Screen;
  }

  static RasterSpace Sentinel() {
    RasterSpace result;
    result.tag = Tag::Sentinel;
    return result;
  }

  bool IsSentinel() const {
    return tag == Tag::Sentinel;
  }

  bool operator==(const RasterSpace& aOther) const {
    if (tag != aOther.tag) {
      return false;
    }
    switch (tag) {
      case Tag::Local: return local == aOther.local;
      default: break;
    }
    return true;
  }
};

struct WrClipId {
  uintptr_t id;

  friend std::ostream& operator<<(std::ostream& aStream, const WrClipId& aInstance) {
    return aStream << "{ " << "id=" << aInstance.id << " }";
  }
  bool operator==(const WrClipId& aOther) const {
    return id == aOther.id;
  }
};

struct ImageMask {
  ImageKey image;
  LayoutRect rect;

  friend std::ostream& operator<<(std::ostream& aStream, const ImageMask& aInstance) {
    return aStream << "{ " << "image=" << aInstance.image << ", "
                           << "rect=" << aInstance.rect << " }";
  }
  bool operator==(const ImageMask& aOther) const {
    return image == aOther.image &&
           rect == aOther.rect;
  }
};

using LayoutPoint = Point2D<float, LayoutPixel>;

struct BorderRadius {
  LayoutSize top_left;
  LayoutSize top_right;
  LayoutSize bottom_left;
  LayoutSize bottom_right;

  friend std::ostream& operator<<(std::ostream& aStream, const BorderRadius& aInstance) {
    return aStream << "{ " << "top_left=" << aInstance.top_left << ", "
                           << "top_right=" << aInstance.top_right << ", "
                           << "bottom_left=" << aInstance.bottom_left << ", "
                           << "bottom_right=" << aInstance.bottom_right << " }";
  }
  bool operator==(const BorderRadius& aOther) const {
    return top_left == aOther.top_left &&
           top_right == aOther.top_right &&
           bottom_left == aOther.bottom_left &&
           bottom_right == aOther.bottom_right;
  }
};

struct ComplexClipRegion {
  /// The boundaries of the rectangle.
  LayoutRect rect;
  /// Border radii of this rectangle.
  BorderRadius radii;
  /// Whether we are clipping inside or outside
  /// the region.
  ClipMode mode;

  friend std::ostream& operator<<(std::ostream& aStream, const ComplexClipRegion& aInstance) {
    return aStream << "{ " << "rect=" << aInstance.rect << ", "
                           << "radii=" << aInstance.radii << ", "
                           << "mode=" << aInstance.mode << " }";
  }
  bool operator==(const ComplexClipRegion& aOther) const {
    return rect == aOther.rect &&
           radii == aOther.radii &&
           mode == aOther.mode;
  }
};

/// The minimum and maximum allowable offset for a sticky frame in a single dimension.
struct StickyOffsetBounds {
  /// The minimum offset for this frame, typically a negative value, which specifies how
  /// far in the negative direction the sticky frame can offset its contents in this
  /// dimension.
  float min;
  /// The maximum offset for this frame, typically a positive value, which specifies how
  /// far in the positive direction the sticky frame can offset its contents in this
  /// dimension.
  float max;

  friend std::ostream& operator<<(std::ostream& aStream, const StickyOffsetBounds& aInstance) {
    return aStream << "{ " << "min=" << aInstance.min << ", "
                           << "max=" << aInstance.max << " }";
  }
  bool operator==(const StickyOffsetBounds& aOther) const {
    return min == aOther.min &&
           max == aOther.max;
  }
};

struct WrSpaceAndClipChain {
  WrSpatialId space;
  uint64_t clip_chain;

  friend std::ostream& operator<<(std::ostream& aStream, const WrSpaceAndClipChain& aInstance) {
    return aStream << "{ " << "space=" << aInstance.space << ", "
                           << "clip_chain=" << aInstance.clip_chain << " }";
  }
  bool operator==(const WrSpaceAndClipChain& aOther) const {
    return space == aOther.space &&
           clip_chain == aOther.clip_chain;
  }
};

using WrColorDepth = ColorDepth;

using WrYuvColorSpace = YuvColorSpace;

using WrColorRange = ColorRange;

using GlyphIndex = uint32_t;

struct GlyphInstance {
  GlyphIndex index;
  LayoutPoint point;

  friend std::ostream& operator<<(std::ostream& aStream, const GlyphInstance& aInstance) {
    return aStream << "{ " << "index=" << aInstance.index << ", "
                           << "point=" << aInstance.point << " }";
  }
  bool operator==(const GlyphInstance& aOther) const {
    return index == aOther.index &&
           point == aOther.point;
  }
};

struct GlyphOptions {
  FontRenderMode render_mode;
  FontInstanceFlags flags;

  friend std::ostream& operator<<(std::ostream& aStream, const GlyphOptions& aInstance) {
    return aStream << "{ " << "render_mode=" << aInstance.render_mode << ", "
                           << "flags=" << aInstance.flags << " }";
  }
  bool operator==(const GlyphOptions& aOther) const {
    return render_mode == aOther.render_mode &&
           flags == aOther.flags;
  }
};

/// A group of 2D side offsets, which correspond to top/right/bottom/left for borders, padding,
/// and margins in CSS, optionally tagged with a unit.
template<typename T, typename U>
struct SideOffsets2D {
  T top;
  T right;
  T bottom;
  T left;

  friend std::ostream& operator<<(std::ostream& aStream, const SideOffsets2D& aInstance) {
    return aStream << "{ " << "top=" << aInstance.top << ", "
                           << "right=" << aInstance.right << ", "
                           << "bottom=" << aInstance.bottom << ", "
                           << "left=" << aInstance.left << " }";
  }
  bool operator==(const SideOffsets2D& aOther) const {
    return top == aOther.top &&
           right == aOther.right &&
           bottom == aOther.bottom &&
           left == aOther.left;
  }
};

using LayoutSideOffsets = SideOffsets2D<float, LayoutPixel>;

struct BorderSide {
  ColorF color;
  BorderStyle style;

  friend std::ostream& operator<<(std::ostream& aStream, const BorderSide& aInstance) {
    return aStream << "{ " << "color=" << aInstance.color << ", "
                           << "style=" << aInstance.style << " }";
  }
  bool operator==(const BorderSide& aOther) const {
    return color == aOther.color &&
           style == aOther.style;
  }
};

using DeviceIntSideOffsets = SideOffsets2D<int32_t, DevicePixel>;

struct WrBorderImage {
  LayoutSideOffsets widths;
  WrImageKey image;
  ImageRendering image_rendering;
  int32_t width;
  int32_t height;
  bool fill;
  DeviceIntSideOffsets slice;
  RepeatMode repeat_horizontal;
  RepeatMode repeat_vertical;

  friend std::ostream& operator<<(std::ostream& aStream, const WrBorderImage& aInstance) {
    return aStream << "{ " << "widths=" << aInstance.widths << ", "
                           << "image=" << aInstance.image << ", "
                           << "image_rendering=" << aInstance.image_rendering << ", "
                           << "width=" << aInstance.width << ", "
                           << "height=" << aInstance.height << ", "
                           << "fill=" << aInstance.fill << ", "
                           << "slice=" << aInstance.slice << ", "
                           << "repeat_horizontal=" << aInstance.repeat_horizontal << ", "
                           << "repeat_vertical=" << aInstance.repeat_vertical << " }";
  }
  bool operator==(const WrBorderImage& aOther) const {
    return widths == aOther.widths &&
           image == aOther.image &&
           image_rendering == aOther.image_rendering &&
           width == aOther.width &&
           height == aOther.height &&
           fill == aOther.fill &&
           slice == aOther.slice &&
           repeat_horizontal == aOther.repeat_horizontal &&
           repeat_vertical == aOther.repeat_vertical;
  }
};

struct GradientStop {
  float offset;
  ColorF color;

  friend std::ostream& operator<<(std::ostream& aStream, const GradientStop& aInstance) {
    return aStream << "{ " << "offset=" << aInstance.offset << ", "
                           << "color=" << aInstance.color << " }";
  }
  bool operator==(const GradientStop& aOther) const {
    return offset == aOther.offset &&
           color == aOther.color;
  }
};

/// An identifier used to refer to previously sent display items. Currently it
/// refers to individual display items, but this may change later.
using ItemKey = uint16_t;

using WorldPoint = Point2D<float, WorldPixel>;

struct HitResult {
  WrPipelineId pipeline_id;
  uint64_t scroll_id;
  uint64_t animation_id;
  uint16_t hit_info;

  friend std::ostream& operator<<(std::ostream& aStream, const HitResult& aInstance) {
    return aStream << "{ " << "pipeline_id=" << aInstance.pipeline_id << ", "
                           << "scroll_id=" << aInstance.scroll_id << ", "
                           << "animation_id=" << aInstance.animation_id << ", "
                           << "hit_info=" << aInstance.hit_info << " }";
  }
  bool operator==(const HitResult& aOther) const {
    return pipeline_id == aOther.pipeline_id &&
           scroll_id == aOther.scroll_id &&
           animation_id == aOther.animation_id &&
           hit_info == aOther.hit_info;
  }
};

using VecU8 = Vec<uint8_t>;

using ArcVecU8 = Arc<VecU8>;

using TileOffset = Point2D<int32_t, TileCoordinate>;

struct MutByteSlice {
  uint8_t *buffer;
  uintptr_t len;

  friend std::ostream& operator<<(std::ostream& aStream, const MutByteSlice& aInstance) {
    return aStream << "{ " << "buffer=" << aInstance.buffer << ", "
                           << "len=" << aInstance.len << " }";
  }
  bool operator==(const MutByteSlice& aOther) const {
    return buffer == aOther.buffer &&
           len == aOther.len;
  }
};

struct FontVariation {
  uint32_t tag;
  float value;

  friend std::ostream& operator<<(std::ostream& aStream, const FontVariation& aInstance) {
    return aStream << "{ " << "tag=" << aInstance.tag << ", "
                           << "value=" << aInstance.value << " }";
  }
  bool operator==(const FontVariation& aOther) const {
    return tag == aOther.tag &&
           value == aOther.value;
  }
};

struct GpuCacheAddress {
  uint16_t u;
  uint16_t v;

  friend std::ostream& operator<<(std::ostream& aStream, const GpuCacheAddress& aInstance) {
    return aStream << "{ " << "u=" << aInstance.u << ", "
                           << "v=" << aInstance.v << " }";
  }
  bool operator==(const GpuCacheAddress& aOther) const {
    return u == aOther.u &&
           v == aOther.v;
  }
  static const GpuCacheAddress INVALID;
};
constexpr inline const GpuCacheAddress GpuCacheAddress::INVALID = GpuCacheAddress{
  /* .u = */ UINT16_MAX,
  /* .v = */ UINT16_MAX
};

/// Width and height in device pixels of image tiles.
using TileSize = uint16_t;



































































































































































/// The default tile size for blob images and regular images larger than
/// the maximum texture size.
constexpr static const TileSize DEFAULT_TILE_SIZE = 512;





extern "C" {

#if defined(ANDROID)
extern int __android_log_write(int aPrio,
                               const char *aTag,
                               const char *aText);
#endif

void wr_vec_u8_push_bytes(WrVecU8 *aV,
                          ByteSlice aBytes);

void wr_vec_u8_reserve(WrVecU8 *aV,
                       uintptr_t aLen);

void wr_vec_u8_free(WrVecU8 aV);

extern WrExternalImage wr_renderer_lock_external_image(void *aRenderer,
                                                       ExternalImageId aExternalImageId,
                                                       uint8_t aChannelIndex,
                                                       bool aIsComposited);

extern void wr_renderer_unlock_external_image(void *aRenderer,
                                              ExternalImageId aExternalImageId,
                                              uint8_t aChannelIndex);

extern bool is_in_compositor_thread();

extern bool is_in_render_thread();

extern bool is_in_main_thread();

extern bool is_glcontext_gles(void *aGlcontextPtr);

extern bool is_glcontext_angle(void *aGlcontextPtr);

extern const char *gfx_wr_resource_path_override();

extern bool gfx_wr_use_optimized_shaders();

extern void gfx_critical_error(const char *aMsg);

extern void gfx_critical_note(const char *aMsg);

extern void gfx_wr_set_crash_annotation(CrashAnnotation aAnnotation,
                                        const char *aValue);

extern void gfx_wr_clear_crash_annotation(CrashAnnotation aAnnotation);

extern void wr_notifier_wake_up(WrWindowId aWindowId,
                                bool aCompositeNeeded);

extern void wr_notifier_new_frame_ready(WrWindowId aWindowId,
                                        FramePublishId aPublishId,
                                        const FrameReadyParams *aParams);

extern void wr_notifier_external_event(WrWindowId aWindowId,
                                       uintptr_t aRawEvent);

extern void wr_schedule_render(WrWindowId aWindowId,
                               RenderReasons aReasons);

extern void wr_schedule_frame_after_scene_build(WrWindowId aWindowId,
                                                WrPipelineInfo *aPipelineInfo);

extern void wr_transaction_notification_notified(uintptr_t aHandler,
                                                 Checkpoint aWhen);

void wr_renderer_set_clear_color(Renderer *aRenderer,
                                 ColorF aColor);

void wr_renderer_set_external_image_handler(Renderer *aRenderer,
                                            WrExternalImageHandler *aExternalImageHandler);

void wr_renderer_update(Renderer *aRenderer);

void wr_renderer_set_target_frame_publish_id(Renderer *aRenderer,
                                             FramePublishId aPublishId);

bool wr_renderer_render(Renderer *aRenderer,
                        int32_t aWidth,
                        int32_t aHeight,
                        uintptr_t aBufferAge,
                        RendererStats *aOutStats,
                        nsTArray<DeviceIntRect> *aOutDirtyRects);

void wr_renderer_force_redraw(Renderer *aRenderer);

bool wr_renderer_record_frame(Renderer *aRenderer,
                              ImageFormat aImageFormat,
                              RecordedFrameHandle *aOutHandle,
                              int32_t *aOutWidth,
                              int32_t *aOutHeight);

bool wr_renderer_map_recorded_frame(Renderer *aRenderer,
                                    RecordedFrameHandle aHandle,
                                    uint8_t *aDstBuffer,
                                    uintptr_t aDstBufferLen,
                                    uintptr_t aDstStride);

void wr_renderer_release_composition_recorder_structures(Renderer *aRenderer);

AsyncScreenshotHandle wr_renderer_get_screenshot_async(Renderer *aRenderer,
                                                       int32_t aWindowX,
                                                       int32_t aWindowY,
                                                       int32_t aWindowWidth,
                                                       int32_t aWindowHeight,
                                                       int32_t aBufferWidth,
                                                       int32_t aBufferHeight,
                                                       ImageFormat aImageFormat,
                                                       int32_t *aScreenshotWidth,
                                                       int32_t *aScreenshotHeight);

bool wr_renderer_map_and_recycle_screenshot(Renderer *aRenderer,
                                            AsyncScreenshotHandle aHandle,
                                            uint8_t *aDstBuffer,
                                            uintptr_t aDstBufferLen,
                                            uintptr_t aDstStride);

void wr_renderer_release_profiler_structures(Renderer *aRenderer);

void wr_renderer_readback(Renderer *aRenderer,
                          int32_t aWidth,
                          int32_t aHeight,
                          ImageFormat aFormat,
                          uint8_t *aDstBuffer,
                          uintptr_t aBufferSize);

void wr_renderer_set_profiler_ui(Renderer *aRenderer,
                                 const uint8_t *aUiStr,
                                 uintptr_t aUiStrLen);

void wr_renderer_delete(Renderer *aRenderer);

void wr_renderer_accumulate_memory_report(Renderer *aRenderer,
                                          MemoryReport *aReport,
                                          void *aSwgl);

void wr_renderer_flush_pipeline_info(Renderer *aRenderer,
                                     WrPipelineInfo *aOut);

extern bool gecko_profiler_thread_is_being_profiled();

extern void apz_register_updater(WrWindowId aWindowId);

extern void apz_pre_scene_swap(WrWindowId aWindowId);

extern void apz_post_scene_swap(WrWindowId aWindowId,
                                const WrPipelineInfo *aPipelineInfo);

extern void apz_run_updater(WrWindowId aWindowId);

extern void apz_deregister_updater(WrWindowId aWindowId);

extern void apz_register_sampler(WrWindowId aWindowId);

extern void apz_sample_transforms(WrWindowId aWindowId,
                                  const uint64_t *aGeneratedFrameId,
                                  Transaction *aTransaction);

extern void apz_deregister_sampler(WrWindowId aWindowId);

extern void omta_register_sampler(WrWindowId aWindowId);

extern void omta_sample(WrWindowId aWindowId,
                        Transaction *aTransaction);

extern void omta_deregister_sampler(WrWindowId aWindowId);

extern void wr_register_thread_local_arena();

WrThreadPool *wr_thread_pool_new(bool aLowPriority);

void wr_thread_pool_delete(WrThreadPool *aThreadPool);

WrChunkPool *wr_chunk_pool_new();

void wr_chunk_pool_delete(WrChunkPool *aPool);

void wr_chunk_pool_purge(const WrChunkPool *aPool);

WrProgramCache *wr_program_cache_new(const nsAString *aProfPath,
                                     WrThreadPool *aThreadPool);

void wr_program_cache_delete(WrProgramCache *aProgramCache);

void wr_try_load_startup_shaders_from_disk(WrProgramCache *aProgramCache);

bool remove_program_binary_disk_cache(const nsAString *aProfPath);

extern void wr_compositor_create_surface(void *aCompositor,
                                         NativeSurfaceId aId,
                                         DeviceIntPoint aVirtualOffset,
                                         DeviceIntSize aTileSize,
                                         bool aIsOpaque);

extern void wr_compositor_create_swapchain_surface(void *aCompositor,
                                                   NativeSurfaceId aId,
                                                   DeviceIntSize aSize,
                                                   bool aIsOpaque,
                                                   bool aNeedsSyncDcompCommit);

extern void wr_compositor_resize_swapchain(void *aCompositor,
                                           NativeSurfaceId aId,
                                           DeviceIntSize aSize);

extern void wr_compositor_create_external_surface(void *aCompositor,
                                                  NativeSurfaceId aId,
                                                  bool aIsOpaque);

extern void wr_compositor_create_backdrop_surface(void *aCompositor,
                                                  NativeSurfaceId aId,
                                                  ColorF aColor);

extern void wr_compositor_destroy_surface(void *aCompositor,
                                          NativeSurfaceId aId);

extern void wr_compositor_create_tile(void *aCompositor,
                                      NativeSurfaceId aId,
                                      int32_t aX,
                                      int32_t aY);

extern void wr_compositor_destroy_tile(void *aCompositor,
                                       NativeSurfaceId aId,
                                       int32_t aX,
                                       int32_t aY);

extern void wr_compositor_attach_external_image(void *aCompositor,
                                                NativeSurfaceId aId,
                                                ExternalImageId aExternalImage);

extern void wr_compositor_bind(void *aCompositor,
                               NativeTileId aId,
                               DeviceIntPoint *aOffset,
                               uint32_t *aFboId,
                               DeviceIntRect aDirtyRect,
                               DeviceIntRect aValidRect);

extern void wr_compositor_unbind(void *aCompositor);

extern void wr_compositor_begin_frame(void *aCompositor);

extern void wr_compositor_add_surface(void *aCompositor,
                                      NativeSurfaceId aId,
                                      const CompositorSurfaceTransform *aTransform,
                                      DeviceIntRect aClipRect,
                                      ImageRendering aImageRendering,
                                      DeviceIntRect aRoundedClipRect,
                                      ClipRadius aRoundedClipRadii);

extern void wr_compositor_start_compositing(void *aCompositor,
                                            ColorF aClearColor,
                                            const DeviceIntRect *aDirtyRects,
                                            uintptr_t aNumDirtyRects,
                                            const DeviceIntRect *aOpaqueRects,
                                            uintptr_t aNumOpaqueRects);

extern void wr_compositor_end_frame(void *aCompositor);

extern void wr_compositor_enable_native_compositor(void *aCompositor,
                                                   bool aEnable);

extern void wr_compositor_deinit(void *aCompositor);

extern void wr_compositor_get_capabilities(void *aCompositor,
                                           CompositorCapabilities *aCaps);

extern void wr_compositor_get_window_visibility(void *aCompositor,
                                                WindowVisibility *aCaps);

extern void wr_compositor_get_window_properties(void *aCompositor,
                                                WindowProperties *aProps);

extern void wr_compositor_bind_swapchain(void *aCompositor,
                                         NativeSurfaceId aId,
                                         const DeviceIntRect *aDirtyRects,
                                         uintptr_t aNumDirtyRects);

extern void wr_compositor_present_swapchain(void *aCompositor,
                                            NativeSurfaceId aId,
                                            const DeviceIntRect *aDirtyRects,
                                            uintptr_t aNumDirtyRects);

extern void wr_compositor_map_tile(void *aCompositor,
                                   NativeTileId aId,
                                   DeviceIntRect aDirtyRect,
                                   DeviceIntRect aValidRect,
                                   void **aData,
                                   int32_t *aStride);

extern void wr_compositor_unmap_tile(void *aCompositor);

extern void wr_partial_present_compositor_set_buffer_damage_region(void *aCompositor,
                                                                   const DeviceIntRect *aRects,
                                                                   uintptr_t aNRects);

extern bool wr_swgl_lock_composite_surface(void *aCtx,
                                           ExternalImageId aExternalImageId,
                                           SWGLCompositeSurfaceInfo *aCompositeInfo);

extern void wr_swgl_unlock_composite_surface(void *aCtx,
                                             ExternalImageId aExternalImageId);

WrGlyphRasterThread *wr_glyph_raster_thread_new();

void wr_glyph_raster_thread_delete(WrGlyphRasterThread *aThread);

bool wr_window_new(WrWindowId aWindowId,
                   int32_t aWindowWidth,
                   int32_t aWindowHeight,
                   bool aIsMainWindow,
                   bool aSupportLowPriorityTransactions,
                   bool aSupportLowPriorityThreadpool,
                   bool aAllowTextureSwizzling,
                   bool aAllowScissoredCacheClears,
                   void *aSwglContext,
                   void *aGlContext,
                   bool aSurfaceOriginIsTopLeft,
                   WrProgramCache *aProgramCache,
                   WrShaders *aShaders,
                   WrThreadPool *aThreadPool,
                   WrThreadPool *aThreadPoolLowPriority,
                   const WrChunkPool *aChunkPool,
                   const WrGlyphRasterThread *aGlyphRasterThread,
                   VoidPtrToSizeFn aSizeOfOp,
                   VoidPtrToSizeFn aEnclosingSizeOfOp,
                   uint32_t aDocumentId,
                   void *aCompositor,
                   bool aUseNativeCompositor,
                   bool aUsePartialPresent,
                   uintptr_t aMaxPartialPresentRects,
                   bool aDrawPreviousPartialPresentRegions,
                   DocumentHandle **aOutHandle,
                   Renderer **aOutRenderer,
                   int32_t *aOutMaxTextureSize,
                   char **aOutErr,
                   bool aEnableGpuMarkers,
                   bool aPanicOnGlError,
                   int32_t aPictureTileWidth,
                   int32_t aPictureTileHeight,
                   bool aRejectSoftwareRasterizer,
                   bool aLowQualityPinchZoom,
                   int32_t aMaxSharedSurfaceSize,
                   bool aEnableSubpixelAa,
                   bool aUseLayerCompositor);

void wr_api_free_error_msg(char *aMsg);

void wr_api_delete_document(DocumentHandle *aDh);

void wr_api_clone(DocumentHandle *aDh,
                  DocumentHandle **aOutHandle);

void wr_api_delete(DocumentHandle *aDh);

void wr_api_stop_render_backend(DocumentHandle *aDh);

void wr_api_shut_down(DocumentHandle *aDh);

void wr_api_notify_memory_pressure(DocumentHandle *aDh);

void wr_api_set_debug_flags(DocumentHandle *aDh,
                            DebugFlags aFlags);

void wr_api_set_bool(DocumentHandle *aDh,
                     BoolParameter aParamName,
                     bool aVal);

void wr_api_set_int(DocumentHandle *aDh,
                    IntParameter aParamName,
                    int32_t aVal);

void wr_api_set_float(DocumentHandle *aDh,
                      FloatParameter aParamName,
                      float aVal);

void wr_api_accumulate_memory_report(DocumentHandle *aDh,
                                     MemoryReport *aReport,
                                     uintptr_t (*aSizeOfOp)(const void *ptr),
                                     uintptr_t (*aEnclosingSizeOfOp)(const void *ptr));

void wr_api_clear_all_caches(DocumentHandle *aDh);

void wr_api_enable_native_compositor(DocumentHandle *aDh,
                                     bool aEnable);

void wr_api_set_batching_lookback(DocumentHandle *aDh,
                                  uint32_t aCount);

Transaction *wr_transaction_new(bool aDoAsync);

void wr_transaction_delete(Transaction *aTxn);

void wr_transaction_set_low_priority(Transaction *aTxn,
                                     bool aLowPriority);

bool wr_transaction_is_empty(const Transaction *aTxn);

bool wr_transaction_resource_updates_is_empty(const Transaction *aTxn);

bool wr_transaction_is_rendered_frame_invalidated(const Transaction *aTxn);

void wr_transaction_notify(Transaction *aTxn,
                           Checkpoint aWhen,
                           uintptr_t aEvent);

void wr_transaction_update_epoch(Transaction *aTxn,
                                 WrPipelineId aPipelineId,
                                 WrEpoch aEpoch);

void wr_transaction_set_root_pipeline(Transaction *aTxn,
                                      WrPipelineId aPipelineId);

void wr_transaction_remove_pipeline(Transaction *aTxn,
                                    WrPipelineId aPipelineId);

void wr_transaction_set_display_list(Transaction *aTxn,
                                     WrEpoch aEpoch,
                                     WrPipelineId aPipelineId,
                                     BuiltDisplayListDescriptor aDlDescriptor,
                                     WrVecU8 *aDlItemsData,
                                     WrVecU8 *aDlCacheData,
                                     WrVecU8 *aDlSpatialTreeData);

void wr_transaction_set_document_view(Transaction *aTxn,
                                      const DeviceIntRect *aDocRect);

void wr_transaction_generate_frame(Transaction *aTxn,
                                   uint64_t aId,
                                   bool aPresent,
                                   bool aTracked,
                                   RenderReasons aReasons);

void wr_transaction_invalidate_rendered_frame(Transaction *aTxn,
                                              RenderReasons aReasons);

void wr_transaction_render_offscreen(Transaction *aTxn,
                                     WrPipelineId aPipelineId);

void wr_transaction_append_dynamic_properties(Transaction *aTxn,
                                              const WrOpacityProperty *aOpacityArray,
                                              uintptr_t aOpacityCount,
                                              const WrTransformProperty *aTransformArray,
                                              uintptr_t aTransformCount,
                                              const WrColorProperty *aColorArray,
                                              uintptr_t aColorCount);

void wr_transaction_append_transform_properties(Transaction *aTxn,
                                                const WrTransformProperty *aTransformArray,
                                                uintptr_t aTransformCount);

void wr_transaction_scroll_layer(Transaction *aTxn,
                                 ExternalScrollId aScrollId,
                                 const nsTArray<SampledScrollOffset> *aSampledScrollOffsets);

void wr_transaction_set_is_transform_async_zooming(Transaction *aTxn,
                                                   uint64_t aAnimationId,
                                                   bool aIsZooming);

void wr_transaction_add_minimap_data(Transaction *aTxn,
                                     ExternalScrollId aScrollId,
                                     MinimapData aMinimapData);

void wr_transaction_set_quality_settings(Transaction *aTxn,
                                         bool aForceSubpixelAaWherePossible);

void wr_resource_updates_add_image(Transaction *aTxn,
                                   WrImageKey aImageKey,
                                   const WrImageDescriptor *aDescriptor,
                                   WrVecU8 *aBytes);

void wr_resource_updates_add_blob_image(Transaction *aTxn,
                                        BlobImageKey aImageKey,
                                        const WrImageDescriptor *aDescriptor,
                                        uint16_t aTileSize,
                                        WrVecU8 *aBytes,
                                        DeviceIntRect aVisibleRect);

void wr_resource_updates_add_external_image(Transaction *aTxn,
                                            WrImageKey aImageKey,
                                            const WrImageDescriptor *aDescriptor,
                                            ExternalImageId aExternalImageId,
                                            const ExternalImageType *aImageType,
                                            uint8_t aChannelIndex,
                                            bool aNormalizedUvs);

void wr_resource_updates_update_image(Transaction *aTxn,
                                      WrImageKey aKey,
                                      const WrImageDescriptor *aDescriptor,
                                      WrVecU8 *aBytes);

void wr_resource_updates_set_blob_image_visible_area(Transaction *aTxn,
                                                     BlobImageKey aKey,
                                                     const DeviceIntRect *aArea);

void wr_resource_updates_update_external_image(Transaction *aTxn,
                                               WrImageKey aKey,
                                               const WrImageDescriptor *aDescriptor,
                                               ExternalImageId aExternalImageId,
                                               const ExternalImageType *aImageType,
                                               uint8_t aChannelIndex,
                                               bool aNormalizedUvs);

void wr_resource_updates_update_external_image_with_dirty_rect(Transaction *aTxn,
                                                               WrImageKey aKey,
                                                               const WrImageDescriptor *aDescriptor,
                                                               ExternalImageId aExternalImageId,
                                                               const ExternalImageType *aImageType,
                                                               uint8_t aChannelIndex,
                                                               bool aNormalizedUvs,
                                                               DeviceIntRect aDirtyRect);

void wr_resource_updates_update_blob_image(Transaction *aTxn,
                                           BlobImageKey aImageKey,
                                           const WrImageDescriptor *aDescriptor,
                                           WrVecU8 *aBytes,
                                           DeviceIntRect aVisibleRect,
                                           LayoutIntRect aDirtyRect);

void wr_resource_updates_delete_image(Transaction *aTxn,
                                      WrImageKey aKey);

void wr_resource_updates_delete_blob_image(Transaction *aTxn,
                                           BlobImageKey aKey);

void wr_resource_updates_add_snapshot_image(Transaction *aTxn,
                                            SnapshotImageKey aImageKey);

void wr_resource_updates_delete_snapshot_image(Transaction *aTxn,
                                               SnapshotImageKey aKey);

void wr_api_send_transaction(DocumentHandle *aDh,
                             Transaction *aTransaction,
                             bool aIsAsync);

void wr_transaction_clear_display_list(Transaction *aTxn,
                                       WrEpoch aEpoch,
                                       WrPipelineId aPipelineId);

void wr_api_send_external_event(DocumentHandle *aDh,
                                uintptr_t aEvt);

void wr_resource_updates_add_raw_font(Transaction *aTxn,
                                      WrFontKey aKey,
                                      WrVecU8 *aBytes,
                                      uint32_t aIndex);

void wr_api_capture(DocumentHandle *aDh,
                    const char *aPath,
                    const char *aMozRevision,
                    uint32_t aBitsRaw);

void wr_api_start_capture_sequence(DocumentHandle *aDh,
                                   const char *aPath,
                                   const char *aMozRevision,
                                   uint32_t aBitsRaw);

void wr_api_stop_capture_sequence(DocumentHandle *aDh);

void wr_resource_updates_add_font_descriptor(Transaction *aTxn,
                                             WrFontKey aKey,
                                             WrVecU8 *aBytes,
                                             uint32_t aIndex);

void wr_resource_updates_delete_font(Transaction *aTxn,
                                     WrFontKey aKey);

void wr_resource_updates_add_font_instance(Transaction *aTxn,
                                           WrFontInstanceKey aKey,
                                           WrFontKey aFontKey,
                                           float aGlyphSize,
                                           const FontInstanceOptions *aOptions,
                                           const FontInstancePlatformOptions *aPlatformOptions,
                                           WrVecU8 *aVariations);

void wr_resource_updates_delete_font_instance(Transaction *aTxn,
                                              WrFontInstanceKey aKey);

void wr_resource_updates_clear(Transaction *aTxn);

WrIdNamespace wr_api_get_namespace(DocumentHandle *aDh);

void wr_api_wake_scene_builder(DocumentHandle *aDh);

void wr_api_flush_scene_builder(DocumentHandle *aDh);

WrState *wr_state_new(WrPipelineId aPipelineId);

void wr_state_delete(WrState *aState);

void wr_dp_save(WrState *aState);

void wr_dp_restore(WrState *aState);

void wr_dp_clear_save(WrState *aState);

WrSpatialId wr_dp_push_stacking_context(WrState *aState,
                                        LayoutRect aBounds,
                                        WrSpatialId aSpatialId,
                                        const WrStackingContextParams *aParams,
                                        const WrTransformInfo *aTransform,
                                        const FilterOp *aFilters,
                                        uintptr_t aFilterCount,
                                        const WrFilterData *aFilterDatas,
                                        uintptr_t aFilterDatasCount,
                                        RasterSpace aGlyphRasterSpace);

void wr_dp_push_debug(WrState *aState,
                      uint32_t aVal);

void wr_dp_pop_stacking_context(WrState *aState,
                                bool aIsReferenceFrame);

uint64_t wr_dp_define_clipchain(WrState *aState,
                                const uint64_t *aParentClipchainId,
                                const WrClipId *aClips,
                                uintptr_t aClipsCount);

WrClipId wr_dp_define_image_mask_clip_with_parent_clip_chain(WrState *aState,
                                                             WrSpatialId aSpace,
                                                             ImageMask aMask,
                                                             const LayoutPoint *aPoints,
                                                             uintptr_t aPointCount,
                                                             FillRule aFillRule);

WrClipId wr_dp_define_rounded_rect_clip(WrState *aState,
                                        WrSpatialId aSpace,
                                        ComplexClipRegion aComplex);

WrClipId wr_dp_define_rect_clip(WrState *aState,
                                WrSpatialId aSpace,
                                LayoutRect aClipRect);

WrSpatialId wr_dp_define_sticky_frame(WrState *aState,
                                      WrSpatialId aParentSpatialId,
                                      LayoutRect aContentRect,
                                      const float *aTopMargin,
                                      const float *aRightMargin,
                                      const float *aBottomMargin,
                                      const float *aLeftMargin,
                                      StickyOffsetBounds aVerticalBounds,
                                      StickyOffsetBounds aHorizontalBounds,
                                      LayoutVector2D aAppliedOffset,
                                      SpatialTreeItemKey aKey,
                                      const WrAnimationProperty *aAnimation);

WrSpatialId wr_dp_define_scroll_layer(WrState *aState,
                                      uint64_t aExternalScrollId,
                                      const WrSpatialId *aParent,
                                      LayoutRect aContentRect,
                                      LayoutRect aClipRect,
                                      LayoutVector2D aScrollOffset,
                                      APZScrollGeneration aScrollOffsetGeneration,
                                      HasScrollLinkedEffect aHasScrollLinkedEffect,
                                      SpatialTreeItemKey aKey);

void wr_dp_push_iframe(WrState *aState,
                       LayoutRect aRect,
                       LayoutRect aClip,
                       bool aIsBackfaceVisible,
                       const WrSpaceAndClipChain *aParent,
                       WrPipelineId aPipelineId,
                       bool aIgnoreMissingPipeline);

void wr_dp_push_rect(WrState *aState,
                     LayoutRect aRect,
                     LayoutRect aClip,
                     bool aIsBackfaceVisible,
                     bool aForceAntialiasing,
                     bool aIsCheckerboard,
                     const WrSpaceAndClipChain *aParent,
                     ColorF aColor);

void wr_dp_push_rect_with_animation(WrState *aState,
                                    LayoutRect aRect,
                                    LayoutRect aClip,
                                    bool aIsBackfaceVisible,
                                    const WrSpaceAndClipChain *aParent,
                                    ColorF aColor,
                                    const WrAnimationProperty *aAnimation);

void wr_dp_push_backdrop_filter(WrState *aState,
                                LayoutRect aRect,
                                LayoutRect aClip,
                                bool aIsBackfaceVisible,
                                const WrSpaceAndClipChain *aParent,
                                const FilterOp *aFilters,
                                uintptr_t aFilterCount,
                                const WrFilterData *aFilterDatas,
                                uintptr_t aFilterDatasCount);

void wr_dp_push_clear_rect(WrState *aState,
                           LayoutRect aRect,
                           LayoutRect aClipRect,
                           const WrSpaceAndClipChain *aParent);

void wr_dp_push_hit_test(WrState *aState,
                         LayoutRect aRect,
                         LayoutRect aClip,
                         bool aIsBackfaceVisible,
                         const WrSpaceAndClipChain *aParent,
                         uint64_t aScrollId,
                         uint16_t aHitInfo);

void wr_dp_push_image(WrState *aState,
                      LayoutRect aBounds,
                      LayoutRect aClip,
                      bool aIsBackfaceVisible,
                      bool aForceAntialiasing,
                      const WrSpaceAndClipChain *aParent,
                      ImageRendering aImageRendering,
                      WrImageKey aKey,
                      bool aPremultipliedAlpha,
                      ColorF aColor,
                      bool aPreferCompositorSurface,
                      bool aSupportsExternalCompositing);

void wr_dp_push_repeating_image(WrState *aState,
                                LayoutRect aBounds,
                                LayoutRect aClip,
                                bool aIsBackfaceVisible,
                                const WrSpaceAndClipChain *aParent,
                                LayoutSize aStretchSize,
                                LayoutSize aTileSpacing,
                                ImageRendering aImageRendering,
                                WrImageKey aKey,
                                bool aPremultipliedAlpha,
                                ColorF aColor);

/// Push a 3 planar yuv image.
void wr_dp_push_yuv_planar_image(WrState *aState,
                                 LayoutRect aBounds,
                                 LayoutRect aClip,
                                 bool aIsBackfaceVisible,
                                 const WrSpaceAndClipChain *aParent,
                                 WrImageKey aImageKey0,
                                 WrImageKey aImageKey1,
                                 WrImageKey aImageKey2,
                                 WrColorDepth aColorDepth,
                                 WrYuvColorSpace aColorSpace,
                                 WrColorRange aColorRange,
                                 ImageRendering aImageRendering,
                                 bool aPreferCompositorSurface,
                                 bool aSupportsExternalCompositing);

/// Push a 2 planar NV12 image.
void wr_dp_push_yuv_NV12_image(WrState *aState,
                               LayoutRect aBounds,
                               LayoutRect aClip,
                               bool aIsBackfaceVisible,
                               const WrSpaceAndClipChain *aParent,
                               WrImageKey aImageKey0,
                               WrImageKey aImageKey1,
                               WrColorDepth aColorDepth,
                               WrYuvColorSpace aColorSpace,
                               WrColorRange aColorRange,
                               ImageRendering aImageRendering,
                               bool aPreferCompositorSurface,
                               bool aSupportsExternalCompositing);

/// Push a 2 planar P010 image.
void wr_dp_push_yuv_P010_image(WrState *aState,
                               LayoutRect aBounds,
                               LayoutRect aClip,
                               bool aIsBackfaceVisible,
                               const WrSpaceAndClipChain *aParent,
                               WrImageKey aImageKey0,
                               WrImageKey aImageKey1,
                               WrColorDepth aColorDepth,
                               WrYuvColorSpace aColorSpace,
                               WrColorRange aColorRange,
                               ImageRendering aImageRendering,
                               bool aPreferCompositorSurface,
                               bool aSupportsExternalCompositing);

/// Push a 2 planar NV16 image.
void wr_dp_push_yuv_NV16_image(WrState *aState,
                               LayoutRect aBounds,
                               LayoutRect aClip,
                               bool aIsBackfaceVisible,
                               const WrSpaceAndClipChain *aParent,
                               WrImageKey aImageKey0,
                               WrImageKey aImageKey1,
                               WrColorDepth aColorDepth,
                               WrYuvColorSpace aColorSpace,
                               WrColorRange aColorRange,
                               ImageRendering aImageRendering,
                               bool aPreferCompositorSurface,
                               bool aSupportsExternalCompositing);

/// Push a yuv interleaved image.
void wr_dp_push_yuv_interleaved_image(WrState *aState,
                                      LayoutRect aBounds,
                                      LayoutRect aClip,
                                      bool aIsBackfaceVisible,
                                      const WrSpaceAndClipChain *aParent,
                                      WrImageKey aImageKey0,
                                      WrColorDepth aColorDepth,
                                      WrYuvColorSpace aColorSpace,
                                      WrColorRange aColorRange,
                                      ImageRendering aImageRendering,
                                      bool aPreferCompositorSurface,
                                      bool aSupportsExternalCompositing);

void wr_dp_push_text(WrState *aState,
                     LayoutRect aBounds,
                     LayoutRect aClip,
                     bool aIsBackfaceVisible,
                     const WrSpaceAndClipChain *aParent,
                     ColorF aColor,
                     WrFontInstanceKey aFontKey,
                     const GlyphInstance *aGlyphs,
                     uint32_t aGlyphCount,
                     const GlyphOptions *aGlyphOptions);

void wr_dp_push_shadow(WrState *aState,
                       LayoutRect aBounds,
                       LayoutRect aClip,
                       bool aIsBackfaceVisible,
                       const WrSpaceAndClipChain *aParent,
                       Shadow aShadow,
                       bool aShouldInflate);

void wr_dp_pop_all_shadows(WrState *aState);

void wr_dp_push_line(WrState *aState,
                     const LayoutRect *aClip,
                     bool aIsBackfaceVisible,
                     const WrSpaceAndClipChain *aParent,
                     const LayoutRect *aBounds,
                     float aWavyLineThickness,
                     LineOrientation aOrientation,
                     const ColorF *aColor,
                     LineStyle aStyle);

void wr_dp_push_border(WrState *aState,
                       LayoutRect aRect,
                       LayoutRect aClip,
                       bool aIsBackfaceVisible,
                       const WrSpaceAndClipChain *aParent,
                       AntialiasBorder aDoAa,
                       LayoutSideOffsets aWidths,
                       BorderSide aTop,
                       BorderSide aRight,
                       BorderSide aBottom,
                       BorderSide aLeft,
                       BorderRadius aRadius);

void wr_dp_push_border_image(WrState *aState,
                             LayoutRect aRect,
                             LayoutRect aClip,
                             bool aIsBackfaceVisible,
                             const WrSpaceAndClipChain *aParent,
                             const WrBorderImage *aParams);

void wr_dp_push_border_gradient(WrState *aState,
                                LayoutRect aRect,
                                LayoutRect aClip,
                                bool aIsBackfaceVisible,
                                const WrSpaceAndClipChain *aParent,
                                LayoutSideOffsets aWidths,
                                int32_t aWidth,
                                int32_t aHeight,
                                bool aFill,
                                DeviceIntSideOffsets aSlice,
                                LayoutPoint aStartPoint,
                                LayoutPoint aEndPoint,
                                const GradientStop *aStops,
                                uintptr_t aStopsCount,
                                ExtendMode aExtendMode);

void wr_dp_push_border_radial_gradient(WrState *aState,
                                       LayoutRect aRect,
                                       LayoutRect aClip,
                                       bool aIsBackfaceVisible,
                                       const WrSpaceAndClipChain *aParent,
                                       LayoutSideOffsets aWidths,
                                       bool aFill,
                                       LayoutPoint aCenter,
                                       LayoutSize aRadius,
                                       const GradientStop *aStops,
                                       uintptr_t aStopsCount,
                                       ExtendMode aExtendMode);

void wr_dp_push_border_conic_gradient(WrState *aState,
                                      LayoutRect aRect,
                                      LayoutRect aClip,
                                      bool aIsBackfaceVisible,
                                      const WrSpaceAndClipChain *aParent,
                                      LayoutSideOffsets aWidths,
                                      bool aFill,
                                      LayoutPoint aCenter,
                                      float aAngle,
                                      const GradientStop *aStops,
                                      uintptr_t aStopsCount,
                                      ExtendMode aExtendMode);

void wr_dp_push_linear_gradient(WrState *aState,
                                LayoutRect aRect,
                                LayoutRect aClip,
                                bool aIsBackfaceVisible,
                                const WrSpaceAndClipChain *aParent,
                                LayoutPoint aStartPoint,
                                LayoutPoint aEndPoint,
                                const GradientStop *aStops,
                                uintptr_t aStopsCount,
                                ExtendMode aExtendMode,
                                LayoutSize aTileSize,
                                LayoutSize aTileSpacing);

void wr_dp_push_radial_gradient(WrState *aState,
                                LayoutRect aRect,
                                LayoutRect aClip,
                                bool aIsBackfaceVisible,
                                const WrSpaceAndClipChain *aParent,
                                LayoutPoint aCenter,
                                LayoutSize aRadius,
                                const GradientStop *aStops,
                                uintptr_t aStopsCount,
                                ExtendMode aExtendMode,
                                LayoutSize aTileSize,
                                LayoutSize aTileSpacing);

void wr_dp_push_conic_gradient(WrState *aState,
                               LayoutRect aRect,
                               LayoutRect aClip,
                               bool aIsBackfaceVisible,
                               const WrSpaceAndClipChain *aParent,
                               LayoutPoint aCenter,
                               float aAngle,
                               const GradientStop *aStops,
                               uintptr_t aStopsCount,
                               ExtendMode aExtendMode,
                               LayoutSize aTileSize,
                               LayoutSize aTileSpacing);

void wr_dp_push_box_shadow(WrState *aState,
                           LayoutRect aRect,
                           LayoutRect aClip,
                           bool aIsBackfaceVisible,
                           const WrSpaceAndClipChain *aParent,
                           LayoutRect aBoxBounds,
                           LayoutVector2D aOffset,
                           ColorF aColor,
                           float aBlurRadius,
                           float aSpreadRadius,
                           BorderRadius aBorderRadius,
                           BoxShadowClipMode aClipMode);

void wr_dp_start_item_group(WrState *aState);

void wr_dp_cancel_item_group(WrState *aState,
                             bool aDiscard);

bool wr_dp_finish_item_group(WrState *aState,
                             ItemKey aKey);

void wr_dp_push_reuse_items(WrState *aState,
                            ItemKey aKey);

void wr_dp_set_cache_size(WrState *aState,
                          uintptr_t aCacheSize);

uintptr_t wr_dump_display_list(WrState *aState,
                               uintptr_t aIndent,
                               const uintptr_t *aStart,
                               const uintptr_t *aEnd);

void wr_dump_serialized_display_list(WrState *aState);

void wr_api_begin_builder(WrState *aState);

void wr_api_end_builder(WrState *aState,
                        BuiltDisplayListDescriptor *aDlDescriptor,
                        WrVecU8 *aDlItemsData,
                        WrVecU8 *aDlCacheData,
                        WrVecU8 *aDlSpatialTree);

void wr_api_hit_test(DocumentHandle *aDh,
                     WorldPoint aPoint,
                     nsTArray<HitResult> *aOutResults);

const VecU8 *wr_add_ref_arc(const ArcVecU8 *aArc);

void wr_dec_ref_arc(const VecU8 *aArc);

extern bool wr_moz2d_render_cb(ByteSlice aBlob,
                               ImageFormat aFormat,
                               const LayoutIntRect *aRenderRect,
                               const DeviceIntRect *aVisibleRect,
                               uint16_t aTileSize,
                               const TileOffset *aTileOffset,
                               const LayoutIntRect *aDirtyRect,
                               MutByteSlice aOutput);

WrSpatialId wr_root_scroll_node_id();

WrClipId wr_root_clip_id();

void wr_device_delete(Device *aDevice);

WrShaders *wr_shaders_new(void *aGlContext,
                          WrProgramCache *aProgramCache,
                          bool aPrecacheShaders);

void wr_shaders_delete(WrShaders *aShaders);

/// Perform one step of shader warmup.
///
/// Returns true if another call is needed, false if warmup is finished.
bool wr_shaders_resume_warmup(WrShaders *aShaders);

uintptr_t wr_program_cache_report_memory(const WrProgramCache *aCache,
                                         VoidPtrToSizeFn aSizeOfOp);

extern bool HasFontData(WrFontKey aKey);

extern void AddFontData(WrFontKey aKey,
                        const uint8_t *aData,
                        uintptr_t aSize,
                        uint32_t aIndex,
                        const ArcVecU8 *aVec);

extern void AddNativeFontHandle(WrFontKey aKey,
                                void *aHandle,
                                uint32_t aIndex);

extern void DeleteFontData(WrFontKey aKey);

extern void AddBlobFont(WrFontInstanceKey aInstanceKey,
                        WrFontKey aFontKey,
                        float aSize,
                        const FontInstanceOptions *aOptions,
                        const FontInstancePlatformOptions *aPlatformOptions,
                        const FontVariation *aVariations,
                        uintptr_t aNumVariations);

extern void DeleteBlobFont(WrFontInstanceKey aKey);

extern void ClearBlobImageResources(WrIdNamespace aNamespace);

#if defined(XP_WIN)
extern void gfx_wr_set_crash_annotation(CrashAnnotation aAnnotation,
                                        const char *aValue);
#endif

void *wr_swgl_create_context();

void wr_swgl_reference_context(void *aCtx);

void wr_swgl_destroy_context(void *aCtx);

void wr_swgl_make_current(void *aCtx);

void wr_swgl_init_default_framebuffer(void *aCtx,
                                      int32_t aX,
                                      int32_t aY,
                                      int32_t aWidth,
                                      int32_t aHeight,
                                      int32_t aStride,
                                      void *aBuf);

void wr_swgl_resolve_framebuffer(void *aCtx,
                                 uint32_t aFbo);

uint32_t wr_swgl_gen_texture(void *aCtx);

void wr_swgl_delete_texture(void *aCtx,
                            uint32_t aTex);

void wr_swgl_set_texture_parameter(void *aCtx,
                                   uint32_t aTex,
                                   uint32_t aPname,
                                   int32_t aParam);

void wr_swgl_set_texture_buffer(void *aCtx,
                                uint32_t aTex,
                                uint32_t aInternalFormat,
                                int32_t aWidth,
                                int32_t aHeight,
                                int32_t aStride,
                                void *aBuf,
                                int32_t aMinWidth,
                                int32_t aMinHeight);

void wr_swgl_clear_color_rect(void *aCtx,
                              uint32_t aFbo,
                              int32_t aX,
                              int32_t aY,
                              int32_t aWidth,
                              int32_t aHeight,
                              float aR,
                              float aG,
                              float aB,
                              float aA);

}  // extern "C"

}  // namespace wr
}  // namespace mozilla
