text: /*
   * Copyright (c) 2020-2022 Gustavo Valiente gustavo.valiente@protonmail.com
   * zlib License, see LICENSE file.
   */
  
  #ifndef BN_BLENDING_TRANSPARENCY_ATTRIBUTES_H
  #define BN_BLENDING_TRANSPARENCY_ATTRIBUTES_H
  
  /**
   * @file
   * bn::blending_transparency_attributes header file.
   *
   * @ingroup blending
   */
  
  #include "bn_fixed.h"
  #include "bn_assert.h"
  
  namespace bn
  {
  
  /**
   * @brief Manages the attributes to commit to the GBA transparency and intensity blendings register.
   *
   * @ingroup blending
   */
  class blending_transparency_attributes
  {
  
  public:
      /**
       * @brief Default constructor.
       */
      constexpr blending_transparency_attributes() = default;
  
      /**
       * @brief Constructor.
       * @param transparency_top_weight Transparency weight in the range [0..1] for the top layers,
       * with 0 being fully transparent and 1 being fully visible.
       * @param transparency_bottom_weight Transparency weight in the range [0..1] for the bottom layers,
       * with 0 being fully transparent and 1 being fully visible.
       */
      constexpr blending_transparency_attributes(fixed transparency_top_weight, fixed transparency_bottom_weight) :
          _transparency_top_weight(transparency_top_weight),
          _transparency_bottom_weight(transparency_bottom_weight)
      {
          BN_ASSERT(transparency_top_weight >= 0 && transparency_top_weight <= 1,
                    "Invalid transparency top weight: ", transparency_top_weight);
          BN_ASSERT(transparency_bottom_weight >= 0 && transparency_bottom_weight <= 1,
                    "Invalid transparency bottom weight: ", transparency_bottom_weight);
      }
  
      /**
       * @brief Returns the weight of the transparency blending for the top layers,
       * with 0 being fully transparent and 1 being fully visible.
       */
      [[nodiscard]] constexpr fixed transparency_top_weight() const
      {
          return _transparency_top_weight;
      }
  
      /**
       * @brief Sets the weight of the transparency blending for the top layers,
       * with 0 being fully transparent and 1 being fully visible.
       * @param transparency_top_weight Transparency weight in the range [0..1].
       */
      constexpr void set_transparency_top_weight(fixed transparency_top_weight)
      {
          BN_ASSERT(transparency_top_weight >= 0 && transparency_top_weight <= 1,
                    "Invalid transparency top weight: ", transparency_top_weight);
  
          _transparency_top_weight = transparency_top_weight;
      }
  
      /**
       * @brief Returns the weight of the transparency blending for the bottom layers,
       * with 0 being fully transparent and 1 being fully visible.
       */
      [[nodiscard]] constexpr fixed transparency_bottom_weight() const
      {
          return _transparency_bottom_weight;
      }
  
      /**
       * @brief Sets the weight of the transparency blending for the bottom layers,
       * with 0 being fully transparent and 1 being fully visible.
       * @param transparency_bottom_weight Transparency weight in the range [0..1].
       */
      constexpr void set_transparency_bottom_weight(fixed transparency_bottom_weight)
      {
          BN_ASSERT(transparency_bottom_weight >= 0 && transparency_bottom_weight <= 1,
                    "Invalid transparency bottom weight: ", transparency_bottom_weight);
  
          _transparency_bottom_weight = transparency_bottom_weight;
      }
  
      /**
       * @brief Sets the weight of the transparency blending,
       * with 0 being fully transparent and 1 being fully visible.
       * @param transparency_alpha Transparency weight in the range [0..1].
       */
      constexpr void set_transparency_alpha(fixed transparency_alpha)
      {
          BN_ASSERT(transparency_alpha >= 0 && transparency_alpha <= 1,
                    "Invalid transparency alpha: ", transparency_alpha);
  
          _transparency_top_weight = transparency_alpha;
          _transparency_bottom_weight = 1 - transparency_alpha;
      }
  
      /**
       * @brief Sets the weight of the intensity blending, with 0 being disabled and 1 being fully applied.
       * @param intensity_alpha Intensity weight in the range [0..1].
       */
      constexpr void set_intensity_alpha(fixed intensity_alpha)
      {
          BN_ASSERT(intensity_alpha >= 0 && intensity_alpha <= 1,
                    "Invalid intensity alpha: ", intensity_alpha);
  
          _transparency_top_weight = 1;
          _transparency_bottom_weight = intensity_alpha;
      }
  
      /**
       * @brief Sets the weights of the transparency and the the intensity blendings.
       * @param transparency_alpha Transparency weight in the range [0..1],
       * with 0 being fully transparent and 1 being fully visible.
       * @param intensity_alpha Intensity weight in the range [0..1],
       * with 0 being disabled and 1 being fully applied.
       */
      constexpr void set_transparency_and_intensity_alphas(fixed transparency_alpha, fixed intensity_alpha)
      {
          BN_ASSERT(transparency_alpha >= 0 && transparency_alpha <= 1,
                    "Invalid transparency alpha: ", transparency_alpha);
          BN_ASSERT(intensity_alpha >= 0 && intensity_alpha <= 1,
                    "Invalid intensity alpha: ", intensity_alpha);
  
          _transparency_top_weight = transparency_alpha;
          _transparency_bottom_weight = max(1 - transparency_alpha, intensity_alpha);
      }
  
      /**
       * @brief Default equal operator.
       */
      [[nodiscard]] constexpr friend bool operator==(const blending_transparency_attributes& a,
                                                     const blending_transparency_attributes& b) = default;
  
  private:
      fixed _transparency_top_weight = 1;
      fixed _transparency_bottom_weight = 0;
  };
  
  }
  
  #endif
  
  