// Generated by gmmproc 2.84.0 -- DO NOT MODIFY!
#ifndef _GSKMM_TRANSFORM_H
#define _GSKMM_TRANSFORM_H

#include <gskmmconfig.h>


#include <glibmm/ustring.h>
#include <sigc++/sigc++.h>

/* Copyright (C) 2025 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */


#include <glibmm/refptr.h>
#include <glibmm/ustring.h>
#include <gdkmm/graphene_point.h>
#include <gdkmm/graphene_rect.h>
#include <gsk/gsk.h> // For GskTransform

namespace Gsk
{
/** Describes a 3D transform.
 *
 * Unlike `graphene_matrix_t`, `%Gsk::Transform` retains the steps in how
 * a transform was constructed, and allows inspecting them. It is modeled
 * after the way CSS describes transforms.
 *
 * `%Gsk::Transform` objects are immutable and cannot be changed after creation.
 * This means code can safely expose them as properties of objects without
 * having to worry about others changing them.
 *
 * @newin{4,20}
 */
class GSKMM_API Transform final
{
  // GskTransform is registered as a boxed type, but it has custom
  // reference-counting instead of copy/free functions, so we use it via RefPtr.
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  using CppObjectType = Transform;
  using BaseObjectType = GskTransform;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

  /** Get the GType for this class, for use with the underlying GObject type system.
   */
  static GType get_type() G_GNUC_CONST;

  static Glib::RefPtr<Transform> create();

  /** Increment the reference count for this object.
   * You should never need to do this manually - use the object via a RefPtr instead.
   */
  void reference()   const;

  /** Decrement the reference count for this object.
   * You should never need to do this manually - use the object via a RefPtr instead.
   */
  void unreference() const;

  ///Provides access to the underlying C instance.
  GskTransform*       gobj();

  ///Provides access to the underlying C instance.
  const GskTransform* gobj() const;

  ///Provides access to the underlying C instance. The caller is responsible for unrefing it. Use when directly setting fields in structs.
  GskTransform* gobj_copy() const;

  Transform() = delete;

  // noncopyable
  Transform(const Transform&) = delete;
  Transform& operator=(const Transform&) = delete;

protected:
  // Do not derive this.  Gsk::Transform can neither be constructed nor deleted.

  void operator delete(void*, std::size_t);

private:

     
public:
  /** @addtogroup gskmmEnums gskmm Enums and Flags */

  /** 
   *  @var Category::UNKNOWN
   * The category of the matrix has not been
   * determined.
   * 
   *  @var Category::ANY
   * Analyzing the matrix concluded that it does
   * not fit in any other category.
   * 
   *  @var Category::CAT_3D
   * The matrix is a 3D matrix. This means that
   * the w column (the last column) has the values (0, 0, 0, 1).
   * 
   *  @var Category::CAT_2D
   * The matrix is a 2D matrix. This is equivalent
   * to graphene_matrix_is_2d() returning <tt>true</tt>. In particular, this
   * means that Cairo can deal with the matrix.
   * 
   *  @var Category::CAT_2D_AFFINE
   * The matrix is a combination of 2D scale
   * and 2D translation operations. In particular, this means that any
   * rectangle can be transformed exactly using this matrix.
   * 
   *  @var Category::CAT_2D_TRANSLATE
   * The matrix is a 2D translation.
   * 
   *  @var Category::IDENTITY
   * The matrix is the identity matrix.
   */
   /** The categories of matrices relevant for GSK and GTK.
   * 
   * Note that any category includes matrices of all later categories.
   * So if you want to for example check if a matrix is a 2D matrix,
   * `category >= GSK_TRANSFORM_CATEGORY_2D` is the way to do this.
   * 
   * Also keep in mind that rounding errors may cause matrices to not
   * conform to their categories. Otherwise, matrix operations done via
   * multiplication will not worsen categories. So for the matrix
   * multiplication `C = A * B`, `category(C) = MIN (category(A), category(B))`.
   * 
   * @newin{4,20}
   *
   * @ingroup gskmmEnums
   */
  enum class Category
  {
    UNKNOWN,
    ANY,
    CAT_3D,
    CAT_2D,
    CAT_2D_AFFINE,
    CAT_2D_TRANSLATE,
    IDENTITY
  };


  /** Converts the transform into a human-readable string.
   * 
   * The resulting string can be parsed with parse().
   * 
   * This is a wrapper around print().
   * 
   * @return A new string for @a self.
   */
  Glib::ustring to_string() const;
  

  /** Parses a given string into a transform.
   *
   * Strings printed via to_string()
   * can be read in again successfully using this function.
   *
   * If @a string does not describe a valid transform,
   * an empty RefPtr is returned.
   *
   * @param string The string to parse.
   * @return A new transform, or an empty RefPtr.
   */
  static Glib::RefPtr<Transform> create(const Glib::ustring& string);
  

  /** Converts a transform to a 2D transformation matrix.
   * 
   *  @a self must be a 2D transformation. If you are not
   * sure, use
   * 
   * get_category() >= GSK_TRANSFORM_CATEGORY_2D
   * 
   * to check.
   * 
   * The returned values are a subset of the full 4x4 matrix that
   * is computed by to_matrix() and have the
   * following layout:
   * 
   * ```
   * | xx yx |   |  a  b  0 |
   * | xy yy | = |  c  d  0 |
   * | dx dy |   | tx ty  1 |
   * ```
   * 
   * This function can be used to convert between a `Gsk::Transform`
   * and a matrix type from other 2D drawing libraries, in particular
   * Cairo.
   * 
   * @param out_xx Return location for the xx member.
   * @param out_yx Return location for the yx member.
   * @param out_xy Return location for the xy member.
   * @param out_yy Return location for the yy member.
   * @param out_dx Return location for the x0 member.
   * @param out_dy Return location for the y0 member.
   */
  void to_2d(float& out_xx, float& out_yx, float& out_xy, float& out_yy, float& out_dx, float& out_dy) const;
  
  /** Converts a transform to 2D transformation factors.
   * 
   * To recreate an equivalent transform from the factors returned
   * by this function, use
   * 
   * gsk_transform_skew (
   * gsk_transform_scale (
   * gsk_transform_rotate (
   * gsk_transform_translate (<tt>nullptr</tt>, &GRAPHENE_POINT_INIT (dx, dy)),
   * angle),
   * scale_x, scale_y),
   * skew_x, skew_y)
   * 
   *  @a self must be a 2D transformation. If you are not sure, use
   * 
   * get_category() >= GSK_TRANSFORM_CATEGORY_2D
   * 
   * to check.
   * 
   * @newin{4,20}
   * 
   * @param out_skew_x Return location for the skew factor
   * in the  x direction.
   * @param out_skew_y Return location for the skew factor
   * in the  y direction.
   * @param out_scale_x Return location for the scale
   * factor in the x direction.
   * @param out_scale_y Return location for the scale
   * factor in the y direction.
   * @param out_angle Return location for the rotation angle.
   * @param out_dx Return location for the translation
   * in the x direction.
   * @param out_dy Return location for the translation
   * in the y direction.
   */
  void to_2d_components(float& out_skew_x, float& out_skew_y, float& out_scale_x, float& out_scale_y, float& out_angle, float& out_dx, float& out_dy) const;
  
  /** Converts a transform to 2D affine transformation factors.
   * 
   * To recreate an equivalent transform from the factors returned
   * by this function, use
   * 
   * gsk_transform_scale (
   * gsk_transform_translate (
   * <tt>nullptr</tt>,
   * &GRAPHENE_POINT_T (dx, dy)),
   * sx, sy)
   * 
   *  @a self must be a 2D affine transformation. If you are not
   * sure, use
   * 
   * get_category() >= GSK_TRANSFORM_CATEGORY_2D_AFFINE
   * 
   * to check.
   * 
   * @param out_scale_x Return location for the scale
   * factor in the x direction.
   * @param out_scale_y Return location for the scale
   * factor in the y direction.
   * @param out_dx Return location for the translation
   * in the x direction.
   * @param out_dy Return location for the translation
   * in the y direction.
   */
  void to_affine(float& out_scale_x, float& out_scale_y, float& out_dx, float& out_dy) const;
  
  /** Converts a transform to a translation operation.
   * 
   *  @a self must be a 2D transformation. If you are not
   * sure, use
   * 
   * get_category() >= GSK_TRANSFORM_CATEGORY_2D_TRANSLATE
   * 
   * to check.
   * 
   * @param out_dx Return location for the translation
   * in the x direction.
   * @param out_dy Return location for the translation
   * in the y direction.
   */
  void to_translate(float& out_dx, float& out_dy) const;

  
  /** Returns the category this transform belongs to.
   * 
   * @return The category of the transform.
   */
  Category get_category() const;
  
  /** Checks two transforms for equality.
   * 
   * @param second The second transform.
   * @return True if the two transforms perform the same operation.
   */
  bool equal(const Glib::RefPtr<const Transform>& second) const;

  /** Applies all the operations from @a other to this transform.
   *
   * @param other Transform to apply.
   * @return The new transform.
   */
  Glib::RefPtr<Transform> transform(const Glib::RefPtr<const Transform>& other) const;

  /** Inverts the given transform.
   *
   * If this transform is not invertible, an empty RefPtr is returned.
   *
   * @return The inverted transform.
   */
  Glib::RefPtr<Transform> invert() const;

  /** Multiplies this transform with the matrix [ xx yx x0; xy yy y0; 0 0 1 ].
   *
   * The result of calling to_2d() on the returned
   * %Gsk::Transform should match the input passed to this function.
   *
   * @newin{4,20}
   *
   * @param xx The xx member.
   * @param yx The yx member.
   * @param xy The xy member.
   * @param yy The yy member.
   * @param dx The x0 member.
   * @param dy The y0 member.
   * @return The new transform.
   */
  Glib::RefPtr<Transform> matrix_2d(float xx, float yx, float xy, float yy, float dx, float dy) const;

  /** Translates this transform in 2-dimensional space by @a point.
   *
   * @param point The point to translate the transform by.
   * @return The new transform.
   */
  Glib::RefPtr<Transform> translate(const Gdk::Graphene::Point& point) const;

  /** Applies a skew transform.
   *
   * @param skew_x Skew factor, in degrees, on the X axis.
   * @param skew_y Skew factor, in degrees, on the Y axis.
   * @return The new transform.
   */
  Glib::RefPtr<Transform> skew(float skew_x, float skew_y) const;

  /** Rotates this transform by an angle around the Z axis.
   *
   * The rotation happens around the origin point of (0, 0).
   *
   * @param angle The rotation angle, in degrees (clockwise).
   * @return The new transform.
   */
  Glib::RefPtr<Transform> rotate(float angle) const;

  /** Scales this transform in 2-dimensional space by the given factors.
   *
   * Use scale_3d() to scale in all 3 dimensions.
   *
   * @param factor_x Scaling factor on the X axis.
   * @param factor_y Scaling factor on the Y axis.
   * @return The new transform.
   */
  Glib::RefPtr<Transform> scale(float factor_x, float factor_y) const;

  /** Scales this transform by the given factors.
   *
   * @param factor_x Scaling factor on the X axis.
   * @param factor_y Scaling factor on the Y axis.
   * @param factor_z Scaling factor on the Z axis.
   * @return The new transform.
   */
  Glib::RefPtr<Transform> scale_3d(float factor_x, float factor_y, float factor_z) const;

  /** Applies a perspective projection transform.
   *
   * This transform scales points in X and Y based on their Z value,
   * scaling points with positive Z values away from the origin, and
   * those with negative Z values towards the origin. Points
   * on the z=0 plane are unchanged.
   *
   * @param depth Distance of the z=0 plane. Lower values give a more
   *        flattened pyramid and therefore a more pronounced perspective effect.
   * @return The new transform.
   */
  Glib::RefPtr<Transform> perspective(float depth) const;
  

  /** Transforms a rectangle using the given transform.
   *
   * The result is the bounding box containing the coplanar quad.
   *
   * @param rect The rectangle to transform.
   * @return The transformed rectangle.
   */
  Gdk::Graphene::Rect transform_bounds(const Gdk::Graphene::Rect& rect) const;

  /** Transforms a point using the given transform.
   *
   * @param point The point to transform.
   * @return The transformed point.
   */
  Gdk::Graphene::Point transform_point(const Gdk::Graphene::Point& point) const;
  

};
} // namespace Gsk


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

template <>
class GSKMM_API Value<Gsk::Transform::Category> : public Glib::Value_Enum<Gsk::Transform::Category>
{
public:
  static GType value_type() G_GNUC_CONST;
};

} // namespace Glib
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Glib
{

/** A Glib::wrap() method for this object.
 *
 * @param object The C instance.
 * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref.
 * @result A C++ instance that wraps this C instance.
 *
 * @relates Gsk::Transform
 */
GSKMM_API
Glib::RefPtr<Gsk::Transform> wrap(GskTransform* object, bool take_copy = false);

#ifndef DOXYGEN_SHOULD_SKIP_THIS
template <>
class GSKMM_API Value<Glib::RefPtr<Gsk::Transform>> : public Glib::Value_RefPtrBoxed<Gsk::Transform>
{
public:
  CppType get() const { return Glib::wrap(static_cast<GskTransform*>(get_boxed()), true); }
};
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

} // namespace Glib


#endif /* _GSKMM_TRANSFORM_H */

