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

/* NOTE: This file is auto-generated by pdbgen.pl. */

#include "config.h"

#include "stamp-pdbgen.h"

#include <cairo.h>
#include <string.h>

#include <gegl.h>

#include <gdk-pixbuf/gdk-pixbuf.h>

#include "libpikacolor/pikacolor.h"

#include "libpikabase/pikabase.h"

#include "pdb-types.h"

#include "core/pika.h"
#include "core/pikacontext.h"
#include "core/pikadatafactory.h"
#include "core/pikagradient.h"
#include "core/pikaparamspecs.h"

#include "pikapdb.h"
#include "pikapdb-utils.h"
#include "pikaprocedure.h"
#include "internal-procs.h"


static PikaValueArray *
gradient_new_invoker (PikaProcedure         *procedure,
                      Pika                  *pika,
                      PikaContext           *context,
                      PikaProgress          *progress,
                      const PikaValueArray  *args,
                      GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  const gchar *name;
  PikaGradient *gradient = NULL;

  name = g_value_get_string (pika_value_array_index (args, 0));

  if (success)
    {
      gradient = (PikaGradient*) pika_data_factory_data_new (pika->gradient_factory,
                                                             context, name);

      if (!gradient)
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), gradient);

  return return_vals;
}

static PikaValueArray *
gradient_get_by_name_invoker (PikaProcedure         *procedure,
                              Pika                  *pika,
                              PikaContext           *context,
                              PikaProgress          *progress,
                              const PikaValueArray  *args,
                              GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  const gchar *name;
  PikaGradient *gradient = NULL;

  name = g_value_get_string (pika_value_array_index (args, 0));

  if (success)
    {
      gradient = PIKA_GRADIENT (pika_pdb_get_resource (pika, PIKA_TYPE_GRADIENT, name,
                                                       PIKA_PDB_DATA_ACCESS_READ, error));

      if (! gradient)
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_object (pika_value_array_index (return_vals, 1), gradient);

  return return_vals;
}

static PikaValueArray *
gradient_get_number_of_segments_invoker (PikaProcedure         *procedure,
                                         Pika                  *pika,
                                         PikaContext           *context,
                                         PikaProgress          *progress,
                                         const PikaValueArray  *args,
                                         GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint num_segments = 0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));

  if (success)
    {
      if (gradient)
        {
          for (PikaGradientSegment *seg = gradient->segments; seg; seg = seg->next)
            num_segments++;
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_int (pika_value_array_index (return_vals, 1), num_segments);

  return return_vals;
}

static PikaValueArray *
gradient_get_uniform_samples_invoker (PikaProcedure         *procedure,
                                      Pika                  *pika,
                                      PikaContext           *context,
                                      PikaProgress          *progress,
                                      const PikaValueArray  *args,
                                      GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint num_samples;
  gboolean reverse;
  gint num_color_samples = 0;
  gdouble *color_samples = NULL;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  num_samples = g_value_get_int (pika_value_array_index (args, 1));
  reverse = g_value_get_boolean (pika_value_array_index (args, 2));

  if (success)
    {
      if (gradient)
        {
          PikaGradientSegment *seg   = NULL;
          gdouble              pos   = 0.0;
          gdouble              delta = 1.0 / (num_samples - 1);
          gdouble             *sample;

          num_color_samples = num_samples * 4;

          sample = color_samples = g_new (gdouble, num_color_samples);

          while (num_samples--)
            {
              PikaRGB color;

              seg = pika_gradient_get_color_at (gradient, context, seg,
                                                pos, reverse,
                                                PIKA_GRADIENT_BLEND_RGB_PERCEPTUAL,
                                                &color);

              *sample++ = color.r;
              *sample++ = color.g;
              *sample++ = color.b;
              *sample++ = color.a;

              pos += delta;
            }
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), num_color_samples);
      pika_value_take_float_array (pika_value_array_index (return_vals, 2), color_samples, num_color_samples);
    }

  return return_vals;
}

static PikaValueArray *
gradient_get_custom_samples_invoker (PikaProcedure         *procedure,
                                     Pika                  *pika,
                                     PikaContext           *context,
                                     PikaProgress          *progress,
                                     const PikaValueArray  *args,
                                     GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint num_samples;
  const gdouble *positions;
  gboolean reverse;
  gint num_color_samples = 0;
  gdouble *color_samples = NULL;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  num_samples = g_value_get_int (pika_value_array_index (args, 1));
  positions = pika_value_get_float_array (pika_value_array_index (args, 2));
  reverse = g_value_get_boolean (pika_value_array_index (args, 3));

  if (success)
    {
      if (gradient)
        {
          PikaGradientSegment *seg = NULL;
          gdouble             *sample;

          num_color_samples = num_samples * 4;

          sample = color_samples = g_new (gdouble, num_color_samples);

          while (num_samples--)
            {
              PikaRGB color;

              seg = pika_gradient_get_color_at (gradient, context,
                                                seg, *positions,
                                                reverse,
                                                PIKA_GRADIENT_BLEND_RGB_PERCEPTUAL,
                                                &color);

              *sample++ = color.r;
              *sample++ = color.g;
              *sample++ = color.b;
              *sample++ = color.a;

              positions++;
            }
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      g_value_set_int (pika_value_array_index (return_vals, 1), num_color_samples);
      pika_value_take_float_array (pika_value_array_index (return_vals, 2), color_samples, num_color_samples);
    }

  return return_vals;
}

static PikaValueArray *
gradient_segment_get_left_color_invoker (PikaProcedure         *procedure,
                                         Pika                  *pika,
                                         PikaContext           *context,
                                         PikaProgress          *progress,
                                         const PikaValueArray  *args,
                                         GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint segment;
  PikaRGB color = { 0.0, 0.0, 0.0, 1.0 };
  gdouble opacity = 0.0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));

  if (success)
    {
      PikaGradientSegment *seg;

      seg = pika_gradient_segment_get_nth (gradient->segments, segment);

      if (seg)
        {
          pika_gradient_segment_get_left_color (gradient, seg, &color);
          opacity = color.a * 100.0;
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      pika_value_set_rgb (pika_value_array_index (return_vals, 1), &color);
      g_value_set_double (pika_value_array_index (return_vals, 2), opacity);
    }

  return return_vals;
}

static PikaValueArray *
gradient_segment_set_left_color_invoker (PikaProcedure         *procedure,
                                         Pika                  *pika,
                                         PikaContext           *context,
                                         PikaProgress          *progress,
                                         const PikaValueArray  *args,
                                         GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint segment;
  PikaRGB color;
  gdouble opacity;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));
  pika_value_get_rgb (pika_value_array_index (args, 2), &color);
  opacity = g_value_get_double (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
        PikaGradientSegment *seg = pika_gradient_segment_get_nth (gradient->segments, segment);

        if (seg)
          {
            color.a = opacity / 100.0;
            pika_gradient_segment_set_left_color (gradient, seg, &color);
          }
        else
          {
            success = FALSE;
          }
        }
      else
        {
          success = FALSE;
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_get_right_color_invoker (PikaProcedure         *procedure,
                                          Pika                  *pika,
                                          PikaContext           *context,
                                          PikaProgress          *progress,
                                          const PikaValueArray  *args,
                                          GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint segment;
  PikaRGB color = { 0.0, 0.0, 0.0, 1.0 };
  gdouble opacity = 0.0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));

  if (success)
    {
      PikaGradientSegment *seg;

      seg = pika_gradient_segment_get_nth (gradient->segments, segment);

      if (seg)
        {
          pika_gradient_segment_get_right_color (gradient, seg, &color);
          opacity = color.a * 100.0;
        }
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    {
      pika_value_set_rgb (pika_value_array_index (return_vals, 1), &color);
      g_value_set_double (pika_value_array_index (return_vals, 2), opacity);
    }

  return return_vals;
}

static PikaValueArray *
gradient_segment_set_right_color_invoker (PikaProcedure         *procedure,
                                          Pika                  *pika,
                                          PikaContext           *context,
                                          PikaProgress          *progress,
                                          const PikaValueArray  *args,
                                          GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint segment;
  PikaRGB color;
  gdouble opacity;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));
  pika_value_get_rgb (pika_value_array_index (args, 2), &color);
  opacity = g_value_get_double (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *seg = pika_gradient_segment_get_nth (gradient->segments, segment);

          if (seg)
            {
              color.a = opacity / 100.0;
              pika_gradient_segment_set_right_color (gradient, seg, &color);
            }
          else
            success = FALSE;
        }
      else
        {
          success = FALSE;
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_get_left_pos_invoker (PikaProcedure         *procedure,
                                       Pika                  *pika,
                                       PikaContext           *context,
                                       PikaProgress          *progress,
                                       const PikaValueArray  *args,
                                       GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint segment;
  gdouble pos = 0.0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));

  if (success)
    {
      PikaGradientSegment *seg = pika_gradient_segment_get_nth (gradient->segments, segment);

      if (seg)
        pos = pika_gradient_segment_get_left_pos (gradient, seg);
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_double (pika_value_array_index (return_vals, 1), pos);

  return return_vals;
}

static PikaValueArray *
gradient_segment_set_left_pos_invoker (PikaProcedure         *procedure,
                                       Pika                  *pika,
                                       PikaContext           *context,
                                       PikaProgress          *progress,
                                       const PikaValueArray  *args,
                                       GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint segment;
  gdouble pos;
  gdouble final_pos = 0.0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));
  pos = g_value_get_double (pika_value_array_index (args, 2));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *seg = pika_gradient_segment_get_nth (gradient->segments, segment);

          if (seg)
            final_pos = pika_gradient_segment_set_left_pos (gradient, seg, pos);
          else
            success = FALSE;
        }
      else
        {
          success = FALSE;
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_double (pika_value_array_index (return_vals, 1), final_pos);

  return return_vals;
}

static PikaValueArray *
gradient_segment_get_middle_pos_invoker (PikaProcedure         *procedure,
                                         Pika                  *pika,
                                         PikaContext           *context,
                                         PikaProgress          *progress,
                                         const PikaValueArray  *args,
                                         GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint segment;
  gdouble pos = 0.0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));

  if (success)
    {
      PikaGradientSegment *seg = pika_gradient_segment_get_nth (gradient->segments, segment);

      if (seg)
        pos = pika_gradient_segment_get_middle_pos (gradient, seg);
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_double (pika_value_array_index (return_vals, 1), pos);

  return return_vals;
}

static PikaValueArray *
gradient_segment_set_middle_pos_invoker (PikaProcedure         *procedure,
                                         Pika                  *pika,
                                         PikaContext           *context,
                                         PikaProgress          *progress,
                                         const PikaValueArray  *args,
                                         GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint segment;
  gdouble pos;
  gdouble final_pos = 0.0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));
  pos = g_value_get_double (pika_value_array_index (args, 2));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *seg = pika_gradient_segment_get_nth (gradient->segments, segment);

          if (seg)
            final_pos = pika_gradient_segment_set_middle_pos (gradient, seg, pos);
          else
            success = FALSE;
        }
      else
        {
          success = FALSE;
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_double (pika_value_array_index (return_vals, 1), final_pos);

  return return_vals;
}

static PikaValueArray *
gradient_segment_get_right_pos_invoker (PikaProcedure         *procedure,
                                        Pika                  *pika,
                                        PikaContext           *context,
                                        PikaProgress          *progress,
                                        const PikaValueArray  *args,
                                        GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint segment;
  gdouble pos = 0.0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));

  if (success)
    {
      PikaGradientSegment *seg = pika_gradient_segment_get_nth (gradient->segments, segment);

      if (seg)
        pos = pika_gradient_segment_get_right_pos (gradient, seg);
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_double (pika_value_array_index (return_vals, 1), pos);

  return return_vals;
}

static PikaValueArray *
gradient_segment_set_right_pos_invoker (PikaProcedure         *procedure,
                                        Pika                  *pika,
                                        PikaContext           *context,
                                        PikaProgress          *progress,
                                        const PikaValueArray  *args,
                                        GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint segment;
  gdouble pos;
  gdouble final_pos = 0.0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));
  pos = g_value_get_double (pika_value_array_index (args, 2));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *seg = pika_gradient_segment_get_nth (gradient->segments, segment);

          if (seg)
            final_pos = pika_gradient_segment_set_right_pos (gradient, seg, pos);
          else
            success = FALSE;
        }
      else
        {
          success = FALSE;
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_double (pika_value_array_index (return_vals, 1), final_pos);

  return return_vals;
}

static PikaValueArray *
gradient_segment_get_blending_function_invoker (PikaProcedure         *procedure,
                                                Pika                  *pika,
                                                PikaContext           *context,
                                                PikaProgress          *progress,
                                                const PikaValueArray  *args,
                                                GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint segment;
  gint blend_func = 0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));

  if (success)
    {
      PikaGradientSegment *seg = pika_gradient_segment_get_nth (gradient->segments, segment);

      if (seg)
        blend_func = pika_gradient_segment_get_blending_function (gradient, seg);
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_enum (pika_value_array_index (return_vals, 1), blend_func);

  return return_vals;
}

static PikaValueArray *
gradient_segment_get_coloring_type_invoker (PikaProcedure         *procedure,
                                            Pika                  *pika,
                                            PikaContext           *context,
                                            PikaProgress          *progress,
                                            const PikaValueArray  *args,
                                            GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint segment;
  gint coloring_type = 0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  segment = g_value_get_int (pika_value_array_index (args, 1));

  if (success)
    {
      PikaGradientSegment *seg = pika_gradient_segment_get_nth (gradient->segments, segment);

      if (seg)
        coloring_type = pika_gradient_segment_get_coloring_type (gradient, seg);
      else
        success = FALSE;
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_enum (pika_value_array_index (return_vals, 1), coloring_type);

  return return_vals;
}

static PikaValueArray *
gradient_segment_range_set_blending_function_invoker (PikaProcedure         *procedure,
                                                      Pika                  *pika,
                                                      PikaContext           *context,
                                                      PikaProgress          *progress,
                                                      const PikaValueArray  *args,
                                                      GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;
  gint blending_function;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));
  blending_function = g_value_get_enum (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            pika_gradient_segment_range_set_blending_function (gradient,
                                                               start_seg, end_seg,
                                                               blending_function);
          else
            success = FALSE;
        }
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_range_set_coloring_type_invoker (PikaProcedure         *procedure,
                                                  Pika                  *pika,
                                                  PikaContext           *context,
                                                  PikaProgress          *progress,
                                                  const PikaValueArray  *args,
                                                  GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;
  gint coloring_type;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));
  coloring_type = g_value_get_enum (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            pika_gradient_segment_range_set_coloring_type (gradient,
                                                           start_seg, end_seg,
                                                           coloring_type);
          else
            success = FALSE;
        }
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_range_flip_invoker (PikaProcedure         *procedure,
                                     Pika                  *pika,
                                     PikaContext           *context,
                                     PikaProgress          *progress,
                                     const PikaValueArray  *args,
                                     GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            pika_gradient_segment_range_flip (gradient,
                                              start_seg, end_seg,
                                              NULL, NULL);
          else
            success = FALSE;
        }
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_range_replicate_invoker (PikaProcedure         *procedure,
                                          Pika                  *pika,
                                          PikaContext           *context,
                                          PikaProgress          *progress,
                                          const PikaValueArray  *args,
                                          GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;
  gint replicate_times;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));
  replicate_times = g_value_get_int (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            pika_gradient_segment_range_replicate (gradient,
                                                   start_seg, end_seg,
                                                   replicate_times,
                                                   NULL, NULL);
          else
            success = FALSE;
        }
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_range_split_midpoint_invoker (PikaProcedure         *procedure,
                                               Pika                  *pika,
                                               PikaContext           *context,
                                               PikaProgress          *progress,
                                               const PikaValueArray  *args,
                                               GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            pika_gradient_segment_range_split_midpoint (gradient, context,
                                                        start_seg, end_seg,
                                                        PIKA_GRADIENT_BLEND_RGB_PERCEPTUAL,
                                                        NULL, NULL);
          else
            success = FALSE;
        }
      else
        success = FALSE;
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_range_split_uniform_invoker (PikaProcedure         *procedure,
                                              Pika                  *pika,
                                              PikaContext           *context,
                                              PikaProgress          *progress,
                                              const PikaValueArray  *args,
                                              GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;
  gint split_parts;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));
  split_parts = g_value_get_int (pika_value_array_index (args, 3));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            pika_gradient_segment_range_split_uniform (gradient, context,
                                                       start_seg, end_seg,
                                                       split_parts,
                                                       PIKA_GRADIENT_BLEND_RGB_PERCEPTUAL,
                                                       NULL, NULL);
          else
            success = FALSE;
        }
      else
        {
          success = FALSE;
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_range_delete_invoker (PikaProcedure         *procedure,
                                       Pika                  *pika,
                                       PikaContext           *context,
                                       PikaProgress          *progress,
                                       const PikaValueArray  *args,
                                       GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            pika_gradient_segment_range_delete (gradient,
                                                start_seg, end_seg,
                                                NULL, NULL);
          else
            success = FALSE;
        }
      else
        {
          success = FALSE;
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_range_redistribute_handles_invoker (PikaProcedure         *procedure,
                                                     Pika                  *pika,
                                                     PikaContext           *context,
                                                     PikaProgress          *progress,
                                                     const PikaValueArray  *args,
                                                     GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            pika_gradient_segment_range_redistribute_handles (gradient,
                                                              start_seg, end_seg);
          else
            success = FALSE;
        }
      else
        {
          success = FALSE;
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_range_blend_colors_invoker (PikaProcedure         *procedure,
                                             Pika                  *pika,
                                             PikaContext           *context,
                                             PikaProgress          *progress,
                                             const PikaValueArray  *args,
                                             GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            pika_gradient_segment_range_blend (gradient,
                                               start_seg, end_seg,
                                               &start_seg->left_color,
                                               &end_seg->right_color,
                                               TRUE, FALSE);
          else
            success = FALSE;
        }
      else
        {
          success = FALSE;
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_range_blend_opacity_invoker (PikaProcedure         *procedure,
                                              Pika                  *pika,
                                              PikaContext           *context,
                                              PikaProgress          *progress,
                                              const PikaValueArray  *args,
                                              GError               **error)
{
  gboolean success = TRUE;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            pika_gradient_segment_range_blend (gradient,
                                               start_seg, end_seg,
                                               &start_seg->left_color,
                                               &end_seg->right_color,
                                               FALSE, TRUE);
          else
            success = FALSE;
        }
      else
        {
          success = FALSE;
        }
    }

  return pika_procedure_get_return_values (procedure, success,
                                           error ? *error : NULL);
}

static PikaValueArray *
gradient_segment_range_move_invoker (PikaProcedure         *procedure,
                                     Pika                  *pika,
                                     PikaContext           *context,
                                     PikaProgress          *progress,
                                     const PikaValueArray  *args,
                                     GError               **error)
{
  gboolean success = TRUE;
  PikaValueArray *return_vals;
  PikaGradient *gradient;
  gint start_segment;
  gint end_segment;
  gdouble delta;
  gboolean control_compress;
  gdouble final_delta = 0.0;

  gradient = g_value_get_object (pika_value_array_index (args, 0));
  start_segment = g_value_get_int (pika_value_array_index (args, 1));
  end_segment = g_value_get_int (pika_value_array_index (args, 2));
  delta = g_value_get_double (pika_value_array_index (args, 3));
  control_compress = g_value_get_boolean (pika_value_array_index (args, 4));

  if (success)
    {
      if (pika_data_is_writable (PIKA_DATA (gradient)))
        {
          PikaGradientSegment *start_seg;
          PikaGradientSegment *end_seg;

          start_seg = pika_gradient_segment_get_nth (gradient->segments, start_segment);
          end_seg   = pika_gradient_segment_get_nth (gradient->segments, end_segment);

          if (start_seg && end_seg)
            final_delta = pika_gradient_segment_range_move (gradient,
                                                            start_seg, end_seg,
                                                            delta,
                                                            control_compress);
          else
            success = FALSE;
        }
      else
        {
          success = FALSE;
        }
    }

  return_vals = pika_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_set_double (pika_value_array_index (return_vals, 1), final_delta);

  return return_vals;
}

void
register_gradient_procs (PikaPDB *pdb)
{
  PikaProcedure *procedure;

  /*
   * pika-gradient-new
   */
  procedure = pika_procedure_new (gradient_new_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-new");
  pika_procedure_set_static_help (procedure,
                                  "Creates a new gradient",
                                  "Creates a new gradient having no segments.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("name",
                                                       "name",
                                                       "The requested name of the new gradient",
                                                       FALSE, FALSE, TRUE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_gradient ("gradient",
                                                             "gradient",
                                                             "The gradient",
                                                             FALSE,
                                                             PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-get-by-name
   */
  procedure = pika_procedure_new (gradient_get_by_name_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-get-by-name");
  pika_procedure_set_static_help (procedure,
                                  "Returns the gradient with the given name.",
                                  "Returns the gradient with the given name.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Michael Natterer <mitch@gimp.org>",
                                         "Michael Natterer",
                                         "2023");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_string ("name",
                                                       "name",
                                                       "The name of the gradient",
                                                       FALSE, FALSE, TRUE,
                                                       NULL,
                                                       PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_gradient ("gradient",
                                                             "gradient",
                                                             "The gradient",
                                                             FALSE,
                                                             PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-get-number-of-segments
   */
  procedure = pika_procedure_new (gradient_get_number_of_segments_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-get-number-of-segments");
  pika_procedure_set_static_help (procedure,
                                  "Gets the number of segments of the gradient",
                                  "Gets the number of segments of the gradient",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Lars-Peter Clausen <lars@metafoo.de>",
                                         "Lars-Peter Clausen",
                                         "2008");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-segments",
                                                     "num segments",
                                                     "Number of segments",
                                                     G_MININT32, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-get-uniform-samples
   */
  procedure = pika_procedure_new (gradient_get_uniform_samples_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-get-uniform-samples");
  pika_procedure_set_static_help (procedure,
                                  "Sample the gradient in uniform parts.",
                                  "Samples colors uniformly across the gradient. It returns a list of floating-point values which correspond to the RGBA values for each sample. The minimum number of samples to take is 2, in which case the returned colors will correspond to the { 0.0, 1.0 } positions in the gradient. For example, if the number of samples is 3, the procedure will return the colors at positions { 0.0, 0.5, 1.0 }.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Federico Mena Quintero",
                                         "Federico Mena Quintero",
                                         "1997");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("num-samples",
                                                 "num samples",
                                                 "The number of samples to take",
                                                 2, G_MAXINT32, 2,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("reverse",
                                                     "reverse",
                                                     "Use the reverse gradient",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-color-samples",
                                                     "num color samples",
                                                     "Length of the color_samples array (4 * num_samples)",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_float_array ("color-samples",
                                                                "color samples",
                                                                "Color samples: { R1, G1, B1, A1, ..., Rn, Gn, Bn, An }",
                                                                PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-get-custom-samples
   */
  procedure = pika_procedure_new (gradient_get_custom_samples_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-get-custom-samples");
  pika_procedure_set_static_help (procedure,
                                  "Sample the gradient in custom positions.",
                                  "Samples the color of the gradient at positions from a list. The left endpoint of the gradient corresponds to position 0.0, and the right endpoint corresponds to 1.0. Returns a list of floating-point values, four for each sample (RGBA.)",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Federico Mena Quintero",
                                         "Federico Mena Quintero",
                                         "1997");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("num-samples",
                                                 "num samples",
                                                 "The number of samples to take",
                                                 1, G_MAXINT32, 1,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_float_array ("positions",
                                                            "positions",
                                                            "The list of positions to sample along the gradient",
                                                            PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("reverse",
                                                     "reverse",
                                                     "Use the reverse gradient",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_int ("num-color-samples",
                                                     "num color samples",
                                                     "Length of the color_samples array (4 * num_samples)",
                                                     0, G_MAXINT32, 0,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_float_array ("color-samples",
                                                                "color samples",
                                                                "Color samples: { R1, G1, B1, A1, ..., Rn, Gn, Bn, An }",
                                                                PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-get-left-color
   */
  procedure = pika_procedure_new (gradient_segment_get_left_color_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-get-left-color");
  pika_procedure_set_static_help (procedure,
                                  "Gets the left endpoint color of the segment",
                                  "Gets the left endpoint color of the indexed segment of the gradient.\n"
                                  "Returns an error when the segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_rgb ("color",
                                                        "color",
                                                        "The return color",
                                                        FALSE,
                                                        NULL,
                                                        PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("opacity",
                                                        "opacity",
                                                        "The opacity of the endpoint",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-set-left-color
   */
  procedure = pika_procedure_new (gradient_segment_set_left_color_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-set-left-color");
  pika_procedure_set_static_help (procedure,
                                  "Sets the left endpoint color of a segment",
                                  "Sets the color of the left endpoint the indexed segment of the gradient.\n"
                                  "Returns an error when gradient is not editable or index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_rgb ("color",
                                                    "color",
                                                    "The color to set",
                                                    FALSE,
                                                    NULL,
                                                    PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("opacity",
                                                    "opacity",
                                                    "The opacity to set for the endpoint",
                                                    0, 100.0, 0,
                                                    PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-get-right-color
   */
  procedure = pika_procedure_new (gradient_segment_get_right_color_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-get-right-color");
  pika_procedure_set_static_help (procedure,
                                  "Gets the right endpoint color of the segment",
                                  "Gets the color of the right endpoint color of the segment of the gradient.\n"
                                  "Returns an error when the segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   pika_param_spec_rgb ("color",
                                                        "color",
                                                        "The return color",
                                                        FALSE,
                                                        NULL,
                                                        PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("opacity",
                                                        "opacity",
                                                        "The opacity of the endpoint",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-set-right-color
   */
  procedure = pika_procedure_new (gradient_segment_set_right_color_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-set-right-color");
  pika_procedure_set_static_help (procedure,
                                  "Sets the right endpoint color of the segment",
                                  "Sets the right endpoint color of the segment of the gradient.\n"
                                  "Returns an error when gradient is not editable or segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               pika_param_spec_rgb ("color",
                                                    "color",
                                                    "The color to set",
                                                    FALSE,
                                                    NULL,
                                                    PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("opacity",
                                                    "opacity",
                                                    "The opacity to set for the endpoint",
                                                    0, 100.0, 0,
                                                    PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-get-left-pos
   */
  procedure = pika_procedure_new (gradient_segment_get_left_pos_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-get-left-pos");
  pika_procedure_set_static_help (procedure,
                                  "Gets the left endpoint position of a segment",
                                  "Gets the position of the left endpoint of the segment of the gradient.\n"
                                  "Returns an error when the segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("pos",
                                                        "pos",
                                                        "The return position",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-set-left-pos
   */
  procedure = pika_procedure_new (gradient_segment_set_left_pos_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-set-left-pos");
  pika_procedure_set_static_help (procedure,
                                  "Sets the left endpoint position of the segment",
                                  "Sets the position of the left endpoint of the segment of the gradient. The final position will be the given fraction from the midpoint to the left to the midpoint of the current segment.\n"
                                  "Returns the final position. Returns an error when gradient is not editable or segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("pos",
                                                    "pos",
                                                    "The position to set the guidepoint to",
                                                    0.0, 1.0, 0.0,
                                                    PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("final-pos",
                                                        "final pos",
                                                        "The return position",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-get-middle-pos
   */
  procedure = pika_procedure_new (gradient_segment_get_middle_pos_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-get-middle-pos");
  pika_procedure_set_static_help (procedure,
                                  "Gets the midpoint position of the segment",
                                  "Gets the position of the midpoint of the segment of the gradient.\n"
                                  "Returns an error when the segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("pos",
                                                        "pos",
                                                        "The return position",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-set-middle-pos
   */
  procedure = pika_procedure_new (gradient_segment_set_middle_pos_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-set-middle-pos");
  pika_procedure_set_static_help (procedure,
                                  "Sets the midpoint position of the segment",
                                  "Sets the midpoint position of the segment of the gradient. The final position will be the given fraction between the two endpoints of the segment.\n"
                                  "Returns the final position. Returns an error when gradient is not editable or segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("pos",
                                                    "pos",
                                                    "The position to set the guidepoint to",
                                                    0.0, 1.0, 0.0,
                                                    PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("final-pos",
                                                        "final pos",
                                                        "The return position",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-get-right-pos
   */
  procedure = pika_procedure_new (gradient_segment_get_right_pos_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-get-right-pos");
  pika_procedure_set_static_help (procedure,
                                  "Gets the right endpoint position of the segment",
                                  "Gets the position of the right endpoint of the segment of the gradient.\n"
                                  "Returns an error when the segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("pos",
                                                        "pos",
                                                        "The return position",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-set-right-pos
   */
  procedure = pika_procedure_new (gradient_segment_set_right_pos_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-set-right-pos");
  pika_procedure_set_static_help (procedure,
                                  "Sets the right endpoint position of the segment",
                                  "Sets the right endpoint position of the segment of the gradient. The final position will be the given fraction from the midpoint of the current segment to the midpoint of the segment to the right.\n"
                                  "Returns the final position. Returns an error when gradient is not editable or segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("pos",
                                                    "pos",
                                                    "The position to set the right endpoint to",
                                                    0.0, 1.0, 0.0,
                                                    PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("final-pos",
                                                        "final pos",
                                                        "The return position",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-get-blending-function
   */
  procedure = pika_procedure_new (gradient_segment_get_blending_function_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-get-blending-function");
  pika_procedure_set_static_help (procedure,
                                  "Gets the gradient segment's blending function",
                                  "Gets the blending function of the segment at the index.\n"
                                  "Returns an error when the segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_enum ("blend-func",
                                                      "blend func",
                                                      "The blending function of the segment",
                                                      PIKA_TYPE_GRADIENT_SEGMENT_TYPE,
                                                      PIKA_GRADIENT_SEGMENT_LINEAR,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-get-coloring-type
   */
  procedure = pika_procedure_new (gradient_segment_get_coloring_type_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-get-coloring-type");
  pika_procedure_set_static_help (procedure,
                                  "Gets the gradient segment's coloring type",
                                  "Gets the coloring type of the segment at the index.\n"
                                  "Returns an error when the segment index is out of range.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("segment",
                                                 "segment",
                                                 "The index of a segment within the gradient",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_enum ("coloring-type",
                                                      "coloring type",
                                                      "The coloring type of the segment",
                                                      PIKA_TYPE_GRADIENT_SEGMENT_COLOR,
                                                      PIKA_GRADIENT_SEGMENT_RGB,
                                                      PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-set-blending-function
   */
  procedure = pika_procedure_new (gradient_segment_range_set_blending_function_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-set-blending-function");
  pika_procedure_set_static_help (procedure,
                                  "Sets the blending function of a range of segments",
                                  "Sets the blending function of a range of segments.\n"
                                  "Returns an error when a segment index is out of range, or gradient is not editable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_enum ("blending-function",
                                                  "blending function",
                                                  "The blending function",
                                                  PIKA_TYPE_GRADIENT_SEGMENT_TYPE,
                                                  PIKA_GRADIENT_SEGMENT_LINEAR,
                                                  PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-set-coloring-type
   */
  procedure = pika_procedure_new (gradient_segment_range_set_coloring_type_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-set-coloring-type");
  pika_procedure_set_static_help (procedure,
                                  "Sets the coloring type of a range of segments",
                                  "Sets the coloring type of a range of segments.\n"
                                  "Returns an error when a segment index is out of range, or gradient is not editable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_enum ("coloring-type",
                                                  "coloring type",
                                                  "The coloring type",
                                                  PIKA_TYPE_GRADIENT_SEGMENT_COLOR,
                                                  PIKA_GRADIENT_SEGMENT_RGB,
                                                  PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-flip
   */
  procedure = pika_procedure_new (gradient_segment_range_flip_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-flip");
  pika_procedure_set_static_help (procedure,
                                  "Flip the segment range",
                                  "Reverses the order of segments in a range, and swaps the left and right colors in each segment. As if the range as a 1D line were rotated in a plane.\n"
                                  "Returns an error when a segment index is out of range, or gradient is not editable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-replicate
   */
  procedure = pika_procedure_new (gradient_segment_range_replicate_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-replicate");
  pika_procedure_set_static_help (procedure,
                                  "Replicate the segment range",
                                  "Replicates a segment range a given number of times. Instead of the original segment range, several smaller scaled copies of it will appear in equal widths.\n"
                                  "Returns an error when a segment index is out of range, or gradient is not editable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("replicate-times",
                                                 "replicate times",
                                                 "The number of replicas for each segment",
                                                 2, 20, 2,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-split-midpoint
   */
  procedure = pika_procedure_new (gradient_segment_range_split_midpoint_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-split-midpoint");
  pika_procedure_set_static_help (procedure,
                                  "Splits each segment in the segment range at midpoint",
                                  "Splits each segment in the segment range at its midpoint.\n"
                                  "Returns an error when a segment index is out of range, or gradient is not editable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-split-uniform
   */
  procedure = pika_procedure_new (gradient_segment_range_split_uniform_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-split-uniform");
  pika_procedure_set_static_help (procedure,
                                  "Splits each segment in the segment range uniformly",
                                  "Splits each segment in the segment range uniformly into to the number of parts given.\n"
                                  "Returns an error when a segment index is out of range, or gradient is not editable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("split-parts",
                                                 "split parts",
                                                 "The number of uniform divisions to split each segment to",
                                                 2, 1024, 2,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-delete
   */
  procedure = pika_procedure_new (gradient_segment_range_delete_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-delete");
  pika_procedure_set_static_help (procedure,
                                  "Delete the segment range",
                                  "Deletes a range of segments.\n"
                                  "Returns an error when a segment index is out of range, or gradient is not editable. Deleting all the segments is undefined behavior.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-redistribute-handles
   */
  procedure = pika_procedure_new (gradient_segment_range_redistribute_handles_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-redistribute-handles");
  pika_procedure_set_static_help (procedure,
                                  "Uniformly redistribute the segment range's handles",
                                  "Redistributes the handles of the segment range of the gradient, so they'll be evenly spaced. A handle is where two segments meet. Segments will then have the same width.\n"
                                  "Returns an error when a segment index is out of range, or gradient is not editable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-blend-colors
   */
  procedure = pika_procedure_new (gradient_segment_range_blend_colors_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-blend-colors");
  pika_procedure_set_static_help (procedure,
                                  "Blend the colors of the segment range.",
                                  "Blends the colors (but not the opacity) of the range of segments. The colors' transition will then be uniform across the range.\n"
                                  "Returns an error when a segment index is out of range, or gradient is not editable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-blend-opacity
   */
  procedure = pika_procedure_new (gradient_segment_range_blend_opacity_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-blend-opacity");
  pika_procedure_set_static_help (procedure,
                                  "Blend the opacity of the segment range.",
                                  "Blends the opacity (but not the colors) of the range of segments. The opacity's transition will then be uniform across the range.\n"
                                  "Returns an error when a segment index is out of range, or gradient is not editable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);

  /*
   * pika-gradient-segment-range-move
   */
  procedure = pika_procedure_new (gradient_segment_range_move_invoker);
  pika_object_set_static_name (PIKA_OBJECT (procedure),
                               "pika-gradient-segment-range-move");
  pika_procedure_set_static_help (procedure,
                                  "Move the position of an entire segment range by a delta.",
                                  "Moves the position of an entire segment range by a delta. The actual delta (which is returned) will be limited by the control points of the neighboring segments.\n"
                                  "Returns the actual delta. Returns an error when a segment index is out of range, or gradient is not editable.",
                                  NULL);
  pika_procedure_set_static_attribution (procedure,
                                         "Shlomi Fish <shlomif@iglu.org.il>",
                                         "Shlomi Fish",
                                         "2003");
  pika_procedure_add_argument (procedure,
                               pika_param_spec_gradient ("gradient",
                                                         "gradient",
                                                         "The gradient",
                                                         FALSE,
                                                         PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("start-segment",
                                                 "start segment",
                                                 "Index of the first segment to operate on",
                                                 0, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_int ("end-segment",
                                                 "end segment",
                                                 "Index of the last segment to operate on. If negative, the range will extend to the end segment.",
                                                 G_MININT32, G_MAXINT32, 0,
                                                 PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_double ("delta",
                                                    "delta",
                                                    "The delta to move the segment range",
                                                    -1.0, 1.0, -1.0,
                                                    PIKA_PARAM_READWRITE));
  pika_procedure_add_argument (procedure,
                               g_param_spec_boolean ("control-compress",
                                                     "control compress",
                                                     "Whether or not to compress the neighboring segments",
                                                     FALSE,
                                                     PIKA_PARAM_READWRITE));
  pika_procedure_add_return_value (procedure,
                                   g_param_spec_double ("final-delta",
                                                        "final delta",
                                                        "The final delta by which the range moved",
                                                        -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                                        PIKA_PARAM_READWRITE));
  pika_pdb_register_procedure (pdb, procedure);
  g_object_unref (procedure);
}
