/* Copyright (C) 2026 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/>.
 */

_CONFIGINCLUDE(gskmmconfig.h)

_DEFS(gskmm,gsk)

#include <glibmm/refptr.h>
#include <gdkmm/graphene_point.h>
#include <gdkmm/graphene_rect.h>
#include <gskmm/path.h>
#include <gskmm/pathpoint.h>
#include <gskmm/roundedrect.h>
#include <cairomm/path.h>
#include <pangomm/layout.h>
#include <gsk/gsk.h> // GskPathBuilder

namespace Gsk
{
/** Constructs `Gsk::Path` objects.
 *
 * Adding contours to the path can be done in two ways.
 * The easiest option is to use the `add_*` group of functions that add
 * predefined contours to the current path, either common shapes like
 * add_circle() or by adding from other paths like add_path().
 *
 * The `add_*` methods always add complete contours,
 * and do not use or modify the current point.
 *
 * The other option is to define each line and curve manually with
 * the `*_to` group of functions. You start with
 * a call to move_to() to set the starting point
 * and then use multiple calls to any of the drawing functions to
 * move the pen along the plane. Once you are done, you can call
 * close() to close the path by connecting it
 * back with a line to the starting point.
 *
 * This is similar to how paths are drawn in Cairo.
 *
 * Note that %Gsk::PathBuilder will reduce the degree of added Bézier
 * curves as much as possible, to simplify rendering.
 *
 * @newin{4,24}
 */
class GSKMM_API PathBuilder final
{
  // GskPathBuilder is registered as a boxed type, but it has custom
  // reference-counting instead of copy/free functions, so we use it via RefPtr.
  _CLASS_OPAQUE_REFCOUNTED(PathBuilder, GskPathBuilder, gsk_path_builder_new, gsk_path_builder_ref, gsk_path_builder_unref, GSKMM_API)
  // Necessary if used in _WRAP_PROPERTY: _IS_REFCOUNTED_BOXEDTYPE dnl// Generate a Glib::Value specialization
  _IGNORE(gsk_path_builder_ref, gsk_path_builder_unref)

public:
  _WRAP_METHOD(Glib::RefPtr<Path> to_path(), gsk_path_builder_to_path, newin "4,24")
  _IGNORE(gsk_path_builder_free_to_path)
  _WRAP_METHOD(Gdk::Graphene::Point get_current_point() const,
    gsk_path_builder_get_current_point, newin "4,24")
  _WRAP_METHOD(void add_path(const Glib::RefPtr<const Path>& path),
    gsk_path_builder_add_path, newin "4,24")
  _WRAP_METHOD(void add_reverse_path(const Glib::RefPtr<const Path>& path),
    gsk_path_builder_add_reverse_path, newin "4,24")
  _WRAP_METHOD(void add_cairo_path(const Cairo::RefPtr<const Cairo::Path>& path),
    gsk_path_builder_add_cairo_path, newin "4,24")
  _WRAP_METHOD(void add_layout(const Glib::RefPtr<const Pango::Layout>& layout),
    gsk_path_builder_add_layout, newin "4,24")
  _WRAP_METHOD(void add_rect(const Gdk::Graphene::Rect& rect),
    gsk_path_builder_add_rect, newin "4,24")
  _WRAP_METHOD(void add_rounded_rect(const Gsk::RoundedRect& rect),
    gsk_path_builder_add_rounded_rect, newin "4,24")
  _WRAP_METHOD( void add_circle(const Gdk::Graphene::Point& center, float radius),
    gsk_path_builder_add_circle, newin "4,24")
  _WRAP_METHOD(void add_segment(const Glib::RefPtr<const Path>& path,
    const PathPoint& start, const PathPoint& end), gsk_path_builder_add_segment, newin "4,24")
  _WRAP_METHOD(void move_to(float x, float y), gsk_path_builder_move_to, newin "4,24")
  _WRAP_METHOD(void rel_move_to(float x, float y), gsk_path_builder_rel_move_to, newin "4,24")
  _WRAP_METHOD(void line_to(float x, float y), gsk_path_builder_line_to, newin "4,24")
  _WRAP_METHOD(void rel_line_to(float x, float y), gsk_path_builder_rel_line_to, newin "4,24")
  _WRAP_METHOD(void quad_to(float x1, float y1, float x2, float y2),
    gsk_path_builder_quad_to, newin "4,24")
  _WRAP_METHOD(void rel_quad_to(float x1, float y1, float x2, float y2),
    gsk_path_builder_rel_quad_to, newin "4,24")
  _WRAP_METHOD(void cubic_to(float x1, float y1, float x2, float y2, float x3, float y3),
    gsk_path_builder_cubic_to, newin "4,24")
  _WRAP_METHOD(void rel_cubic_to(float x1, float y1, float x2, float y2, float x3, float y3),
    gsk_path_builder_rel_cubic_to, newin "4,24")
  _WRAP_METHOD(void conic_to(float x1, float y1, float x2, float y2, float weight),
    gsk_path_builder_conic_to, newin "4,24")
  _WRAP_METHOD(void rel_conic_to(float x1, float y1, float x2, float y2, float weight),
    gsk_path_builder_rel_conic_to, newin "4,24")
  _WRAP_METHOD(void arc_to(float x1, float y1, float x2, float y2),
    gsk_path_builder_arc_to, newin "4,24")
  _WRAP_METHOD(void rel_arc_to(float x1, float y1, float x2, float y2),
    gsk_path_builder_rel_arc_to, newin "4,24")
  _WRAP_METHOD(void svg_arc_to(float rx, float ry, float x_axis_rotation, bool large_arc,
    bool positive_sweep, float x, float y), gsk_path_builder_svg_arc_to, newin "4,24")
  _WRAP_METHOD(void rel_svg_arc_to(float rx, float ry, float x_axis_rotation, bool large_arc,
    bool positive_sweep, float x, float y), gsk_path_builder_rel_svg_arc_to, newin "4,24")
  _WRAP_METHOD(void html_arc_to(float x1, float y1, float x2, float y2, float radius),
    gsk_path_builder_html_arc_to, newin "4,24")
  _WRAP_METHOD(void rel_html_arc_to(float x1, float y1, float x2, float y2, float radius),
    gsk_path_builder_rel_html_arc_to, newin "4,24")
  _WRAP_METHOD(void close(), gsk_path_builder_close, newin "4,24")
};

} // namespace Gsk
