/* PIKA - Photo and Image Kooker Application
 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
 *
 * Original copyright, applying to most contents (license remains unchanged): 
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef __PIKA_CHANNEL_H__
#define __PIKA_CHANNEL_H__

#include "pikadrawable.h"


#define PIKA_TYPE_CHANNEL            (pika_channel_get_type ())
#define PIKA_CHANNEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_CHANNEL, PikaChannel))
#define PIKA_CHANNEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_CHANNEL, PikaChannelClass))
#define PIKA_IS_CHANNEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_CHANNEL))
#define PIKA_IS_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_CHANNEL))
#define PIKA_CHANNEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_CHANNEL, PikaChannelClass))


typedef struct _PikaChannelClass PikaChannelClass;

struct _PikaChannel
{
  PikaDrawable  parent_instance;

  PikaRGB       color;             /*  Also stores the opacity        */
  gboolean      show_masked;       /*  Show masked areas--as          */
                                   /*  opposed to selected areas      */

  GeglNode     *color_node;
  GeglNode     *invert_node;
  GeglNode     *mask_node;

  /*  Selection mask variables  */
  gboolean      boundary_known;    /*  is the current boundary valid  */
  PikaBoundSeg *segs_in;           /*  outline of selected region     */
  PikaBoundSeg *segs_out;          /*  outline of selected region     */
  gint          num_segs_in;       /*  number of lines in boundary    */
  gint          num_segs_out;      /*  number of lines in boundary    */
  gboolean      empty;             /*  is the region empty?           */
  gboolean      bounds_known;      /*  recalculate the bounds?        */
  gint          x1, y1;            /*  coordinates for bounding box   */
  gint          x2, y2;            /*  lower right hand coordinate    */
};

struct _PikaChannelClass
{
  PikaDrawableClass  parent_class;

  /*  signals  */
  void     (* color_changed) (PikaChannel             *channel);

  /*  virtual functions  */
  gboolean (* boundary)      (PikaChannel             *channel,
                              const PikaBoundSeg     **segs_in,
                              const PikaBoundSeg     **segs_out,
                              gint                    *num_segs_in,
                              gint                    *num_segs_out,
                              gint                     x1,
                              gint                     y1,
                              gint                     x2,
                              gint                     y2);
  gboolean (* is_empty)      (PikaChannel             *channel);
  gboolean (* is_full)       (PikaChannel             *channel);

  void     (* feather)       (PikaChannel             *channel,
                              gdouble                  radius_x,
                              gdouble                  radius_y,
                              gboolean                 edge_lock,
                              gboolean                 push_undo);
  void     (* sharpen)       (PikaChannel             *channel,
                              gboolean                 push_undo);
  void     (* clear)         (PikaChannel             *channel,
                              const gchar             *undo_desc,
                              gboolean                 push_undo);
  void     (* all)           (PikaChannel             *channel,
                              gboolean                 push_undo);
  void     (* invert)        (PikaChannel             *channel,
                              gboolean                 push_undo);
  void     (* border)        (PikaChannel             *channel,
                              gint                     radius_x,
                              gint                     radius_y,
                              PikaChannelBorderStyle   style,
                              gboolean                 edge_lock,
                              gboolean                 push_undo);
  void     (* grow)          (PikaChannel             *channel,
                              gint                     radius_x,
                              gint                     radius_y,
                              gboolean                 push_undo);
  void     (* shrink)        (PikaChannel             *channel,
                              gint                     radius_x,
                              gint                     radius_y,
                              gboolean                 edge_lock,
                              gboolean                 push_undo);
  void     (* flood)         (PikaChannel             *channel,
                              gboolean                 push_undo);

  const gchar *feather_desc;
  const gchar *sharpen_desc;
  const gchar *clear_desc;
  const gchar *all_desc;
  const gchar *invert_desc;
  const gchar *border_desc;
  const gchar *grow_desc;
  const gchar *shrink_desc;
  const gchar *flood_desc;
};


/*  function declarations  */

GType         pika_channel_get_type           (void) G_GNUC_CONST;

PikaChannel * pika_channel_new                (PikaImage         *image,
                                               gint               width,
                                               gint               height,
                                               const gchar       *name,
                                               const PikaRGB     *color);
PikaChannel * pika_channel_new_from_buffer    (PikaImage         *image,
                                               GeglBuffer        *buffer,
                                               const gchar       *name,
                                               const PikaRGB     *color);
PikaChannel * pika_channel_new_from_alpha     (PikaImage         *image,
                                               PikaDrawable      *drawable,
                                               const gchar       *name,
                                               const PikaRGB     *color);
PikaChannel * pika_channel_new_from_component (PikaImage         *image,
                                               PikaChannelType    type,
                                               const gchar       *name,
                                               const PikaRGB     *color);

PikaChannel * pika_channel_get_parent         (PikaChannel       *channel);

gdouble       pika_channel_get_opacity        (PikaChannel       *channel);
void          pika_channel_set_opacity        (PikaChannel       *channel,
                                               gdouble            opacity,
                                               gboolean           push_undo);

void          pika_channel_get_color          (PikaChannel       *channel,
                                               PikaRGB           *color);
void          pika_channel_set_color          (PikaChannel       *channel,
                                               const PikaRGB     *color,
                                               gboolean           push_undo);

gboolean      pika_channel_get_show_masked    (PikaChannel       *channel);
void          pika_channel_set_show_masked    (PikaChannel       *channel,
                                               gboolean           show_masked);

void          pika_channel_push_undo          (PikaChannel       *mask,
                                               const gchar       *undo_desc);


/*  selection mask functions  */

PikaChannel * pika_channel_new_mask           (PikaImage              *image,
                                               gint                    width,
                                               gint                    height);

gboolean      pika_channel_boundary           (PikaChannel            *mask,
                                               const PikaBoundSeg    **segs_in,
                                               const PikaBoundSeg    **segs_out,
                                               gint                   *num_segs_in,
                                               gint                   *num_segs_out,
                                               gint                    x1,
                                               gint                    y1,
                                               gint                    x2,
                                               gint                    y2);
gboolean      pika_channel_is_empty           (PikaChannel            *mask);

gboolean      pika_channel_is_full            (PikaChannel            *mask);

void          pika_channel_feather            (PikaChannel            *mask,
                                               gdouble                 radius_x,
                                               gdouble                 radius_y,
                                               gboolean                edge_lock,
                                               gboolean                push_undo);
void          pika_channel_sharpen            (PikaChannel            *mask,
                                               gboolean                push_undo);

void          pika_channel_clear              (PikaChannel            *mask,
                                               const gchar            *undo_desc,
                                               gboolean                push_undo);
void          pika_channel_all                (PikaChannel            *mask,
                                               gboolean                push_undo);
void          pika_channel_invert             (PikaChannel            *mask,
                                               gboolean                push_undo);

void          pika_channel_border             (PikaChannel            *mask,
                                               gint                    radius_x,
                                               gint                    radius_y,
                                               PikaChannelBorderStyle  style,
                                               gboolean                edge_lock,
                                               gboolean                push_undo);
void          pika_channel_grow               (PikaChannel            *mask,
                                               gint                    radius_x,
                                               gint                    radius_y,
                                               gboolean                push_undo);
void          pika_channel_shrink             (PikaChannel            *mask,
                                               gint                    radius_x,
                                               gint                    radius_y,
                                               gboolean                edge_lock,
                                               gboolean                push_undo);
void          pika_channel_flood              (PikaChannel            *mask,
                                               gboolean                push_undo);


#endif /* __PIKA_CHANNEL_H__ */
