2006-12-09 21:33:38 +00:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
2003-11-06 15:27:05 +00:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
1999-08-24 18:36:38 +00:00
|
|
|
*
|
2009-01-17 22:28:01 +00:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
2003-11-06 15:27:05 +00:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-17 22:28:01 +00:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2003-11-06 15:27:05 +00:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
1999-08-24 18:36:38 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2003-11-06 15:27:05 +00:00
|
|
|
* 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
|
2018-07-11 23:27:07 +02:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
1999-08-24 18:36:38 +00:00
|
|
|
*/
|
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
/* Original plug-in coded by Tim Newsome.
|
|
|
|
*
|
1999-08-24 18:36:38 +00:00
|
|
|
* Changed to make use of real-life units by Sven Neumann <sven@gimp.org>.
|
2003-11-06 15:27:05 +00:00
|
|
|
*
|
1999-08-24 18:36:38 +00:00
|
|
|
* The interface code is heavily commented in the hope that it will
|
|
|
|
* help other plug-in developers to adapt their plug-ins to make use
|
2003-11-06 15:27:05 +00:00
|
|
|
* of the gimp_size_entry functionality.
|
|
|
|
*
|
2000-02-22 21:25:18 +00:00
|
|
|
* Note: There is a convenience constructor called gimp_coordinetes_new ()
|
2003-11-06 15:27:05 +00:00
|
|
|
* which simplifies the task of setting up a standard X,Y sizeentry.
|
1999-08-24 18:36:38 +00:00
|
|
|
*
|
2000-05-22 13:53:43 +00:00
|
|
|
* For more info and bugs see libgimp/gimpsizeentry.h and libgimp/gimpwidgets.h
|
|
|
|
*
|
|
|
|
* May 2000 tim copperfield [timecop@japan.co.jp]
|
|
|
|
* http://www.ne.jp/asahi/linux/timecop
|
|
|
|
* Added dynamic preview. Due to weird implementation of signals from all
|
|
|
|
* controls, preview will not auto-update. But this plugin isn't really
|
|
|
|
* crying for real-time updating either.
|
|
|
|
*
|
1999-08-24 18:36:38 +00:00
|
|
|
*/
|
|
|
|
|
1999-11-20 02:16:17 +00:00
|
|
|
#include "config.h"
|
2000-01-06 22:26:10 +00:00
|
|
|
|
2000-09-30 20:13:06 +00:00
|
|
|
#include <string.h>
|
2000-01-06 22:26:10 +00:00
|
|
|
|
2000-04-30 21:03:44 +00:00
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <libgimp/gimpui.h>
|
2000-01-06 22:26:10 +00:00
|
|
|
|
1999-11-14 21:56:01 +00:00
|
|
|
#include "libgimp/stdplugins-intl.h"
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2005-08-13 22:52:41 +00:00
|
|
|
|
|
|
|
#define PLUG_IN_PROC "plug-in-grid"
|
|
|
|
#define PLUG_IN_BINARY "grid"
|
2011-04-08 20:31:34 +02:00
|
|
|
#define PLUG_IN_ROLE "gimp-grid"
|
2002-09-06 20:44:47 +00:00
|
|
|
#define SPIN_BUTTON_WIDTH 8
|
|
|
|
#define COLOR_BUTTON_WIDTH 55
|
|
|
|
|
1999-11-01 12:36:23 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
typedef struct _Grid Grid;
|
|
|
|
typedef struct _GridClass GridClass;
|
|
|
|
|
|
|
|
struct _Grid
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2023-06-21 15:36:28 +02:00
|
|
|
GimpPlugIn parent_instance;
|
|
|
|
|
|
|
|
GimpDrawable *drawable;
|
|
|
|
GimpProcedureConfig *config;
|
|
|
|
GtkWidget *hcolor_button;
|
|
|
|
GtkWidget *vcolor_button;
|
|
|
|
GtkWidget *icolor_button;
|
|
|
|
GtkWidget *color_chain;
|
1997-11-24 22:05:25 +00:00
|
|
|
};
|
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
struct _GridClass
|
|
|
|
{
|
|
|
|
GimpPlugInClass parent_class;
|
|
|
|
};
|
1997-11-24 22:05:25 +00:00
|
|
|
|
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
#define GRID_TYPE (grid_get_type ())
|
2023-06-21 15:36:28 +02:00
|
|
|
#define GRID(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRID_TYPE, Grid))
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
GType grid_get_type (void) G_GNUC_CONST;
|
1998-01-30 00:31:16 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
static GList * grid_query_procedures (GimpPlugIn *plug_in);
|
|
|
|
static GimpProcedure * grid_create_procedure (GimpPlugIn *plug_in,
|
|
|
|
const gchar *name);
|
2019-07-10 12:43:27 +02:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
static GimpValueArray * grid_run (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GimpImage *image,
|
2021-04-02 02:55:46 +02:00
|
|
|
GimpDrawable **drawables,
|
2023-06-21 15:36:28 +02:00
|
|
|
GimpProcedureConfig *config,
|
2019-08-30 15:26:06 +02:00
|
|
|
gpointer run_data);
|
1998-01-30 00:31:16 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
static guchar best_cmap_match (const guchar *cmap,
|
|
|
|
gint ncolors,
|
2024-02-15 03:39:52 +00:00
|
|
|
GeglColor *color);
|
2023-06-21 15:36:28 +02:00
|
|
|
static void render_grid (GimpImage *image,
|
2019-08-30 15:26:06 +02:00
|
|
|
GimpDrawable *drawable,
|
2023-06-21 15:36:28 +02:00
|
|
|
GimpProcedureConfig *config,
|
2019-08-30 15:26:06 +02:00
|
|
|
GimpPreview *preview);
|
|
|
|
static gint dialog (GimpImage *image,
|
2023-06-21 15:36:28 +02:00
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpProcedure *procedure,
|
|
|
|
GimpProcedureConfig *config);
|
1998-01-30 00:31:16 +00:00
|
|
|
|
1999-11-01 12:36:23 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
G_DEFINE_TYPE (Grid, grid, GIMP_TYPE_PLUG_IN)
|
2001-01-25 01:20:05 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
GIMP_MAIN (GRID_TYPE)
|
2022-05-26 00:59:36 +02:00
|
|
|
DEFINE_STD_SET_I18N
|
2004-10-29 23:54:17 +00:00
|
|
|
|
2001-01-25 01:20:05 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
static gint sx1, sy1, sx2, sy2;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
static GtkWidget *main_dialog = NULL;
|
2004-10-29 23:54:17 +00:00
|
|
|
|
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
static void
|
|
|
|
grid_class_init (GridClass *klass)
|
|
|
|
{
|
|
|
|
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
|
|
|
|
|
|
|
|
plug_in_class->query_procedures = grid_query_procedures;
|
|
|
|
plug_in_class->create_procedure = grid_create_procedure;
|
2022-05-26 00:59:36 +02:00
|
|
|
plug_in_class->set_i18n = STD_SET_I18N;
|
2019-08-30 15:26:06 +02:00
|
|
|
}
|
2003-12-10 22:50:26 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
static void
|
|
|
|
grid_init (Grid *grid)
|
|
|
|
{
|
|
|
|
}
|
2003-12-10 22:50:26 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
static GList *
|
|
|
|
grid_query_procedures (GimpPlugIn *plug_in)
|
|
|
|
{
|
|
|
|
return g_list_append (NULL, g_strdup (PLUG_IN_PROC));
|
|
|
|
}
|
2004-10-29 23:54:17 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
static GimpProcedure *
|
|
|
|
grid_create_procedure (GimpPlugIn *plug_in,
|
2024-02-15 03:39:52 +00:00
|
|
|
const gchar *name)
|
2019-08-30 15:26:06 +02:00
|
|
|
{
|
|
|
|
GimpProcedure *procedure = NULL;
|
2004-10-29 23:54:17 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
if (! strcmp (name, PLUG_IN_PROC))
|
|
|
|
{
|
2024-02-15 03:39:52 +00:00
|
|
|
GeglColor *default_hcolor;
|
|
|
|
GeglColor *default_vcolor;
|
|
|
|
GeglColor *default_icolor;
|
|
|
|
|
|
|
|
gegl_init (NULL, NULL);
|
|
|
|
|
|
|
|
default_hcolor = gegl_color_new ("black");
|
|
|
|
default_vcolor = gegl_color_new ("black");
|
|
|
|
default_icolor = gegl_color_new ("black");
|
2019-08-30 15:26:06 +02:00
|
|
|
|
2023-10-01 18:23:57 +02:00
|
|
|
procedure = gimp_image_procedure_new (plug_in, name,
|
|
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
|
|
grid_run, NULL, NULL);
|
2019-08-30 15:26:06 +02:00
|
|
|
|
|
|
|
gimp_procedure_set_image_types (procedure, "*");
|
2021-04-02 02:55:46 +02:00
|
|
|
gimp_procedure_set_sensitivity_mask (procedure,
|
|
|
|
GIMP_PROCEDURE_SENSITIVE_DRAWABLE);
|
2019-08-30 15:26:06 +02:00
|
|
|
|
2022-07-04 22:50:53 +02:00
|
|
|
gimp_procedure_set_menu_label (procedure, _("_Grid (legacy)..."));
|
2019-08-30 15:26:06 +02:00
|
|
|
gimp_procedure_add_menu_path (procedure,
|
|
|
|
"<Image>/Filters/Render/Pattern");
|
|
|
|
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
2022-07-04 22:50:53 +02:00
|
|
|
_("Draw a grid on the image"),
|
2019-08-30 15:26:06 +02:00
|
|
|
"Draws a grid using the specified "
|
|
|
|
"colors. The grid origin is the "
|
|
|
|
"upper left corner.",
|
|
|
|
name);
|
|
|
|
gimp_procedure_set_attribution (procedure,
|
|
|
|
"Tim Newsome",
|
|
|
|
"Tim Newsome, Sven Neumann, "
|
|
|
|
"Tom Rathborne, TC",
|
|
|
|
"1997 - 2000");
|
|
|
|
|
2024-06-12 16:53:12 +00:00
|
|
|
gimp_procedure_add_int_argument (procedure, "hwidth",
|
|
|
|
"H width",
|
|
|
|
"Horizontal width",
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 1,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_int_argument (procedure, "hspace",
|
|
|
|
"H space",
|
|
|
|
"Horizontal spacing",
|
|
|
|
1, GIMP_MAX_IMAGE_SIZE, 16,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_int_argument (procedure, "hoffset",
|
|
|
|
"H offset",
|
|
|
|
"Horizontal offset",
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 8,
|
|
|
|
G_PARAM_READWRITE);
|
2019-08-30 15:26:06 +02:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
/* TODO: for "hcolor", "icolor" and "vcolor", the original code would use
|
2024-02-15 03:39:52 +00:00
|
|
|
* the foreground color as default. Future work would be to get the
|
|
|
|
* foreground/background color from context.
|
2023-06-21 15:36:28 +02:00
|
|
|
*/
|
2024-06-12 16:53:12 +00:00
|
|
|
gimp_procedure_add_color_argument (procedure, "hcolor",
|
|
|
|
"H color",
|
|
|
|
"Horizontal color",
|
|
|
|
TRUE, default_hcolor,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_int_argument (procedure, "vwidth",
|
|
|
|
"V width",
|
|
|
|
"Vertical width",
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 1,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_int_argument (procedure, "vspace",
|
|
|
|
"V space",
|
|
|
|
"Vertical spacing",
|
|
|
|
1, GIMP_MAX_IMAGE_SIZE, 16,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_int_argument (procedure, "voffset",
|
|
|
|
"V offset",
|
|
|
|
"Vertical offset",
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 8,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_color_argument (procedure, "vcolor",
|
|
|
|
"V color",
|
|
|
|
"Vertical color",
|
|
|
|
TRUE, default_vcolor,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_int_argument (procedure, "iwidth",
|
|
|
|
"I width",
|
|
|
|
"Intersection width",
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 0,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_int_argument (procedure, "ispace",
|
|
|
|
"I space",
|
|
|
|
"Intersection spacing",
|
|
|
|
1, GIMP_MAX_IMAGE_SIZE, 2,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_int_argument (procedure, "ioffset",
|
|
|
|
"I offset",
|
|
|
|
"Intersection offset",
|
|
|
|
0, GIMP_MAX_IMAGE_SIZE, 6,
|
|
|
|
G_PARAM_READWRITE);
|
|
|
|
|
|
|
|
gimp_procedure_add_color_argument (procedure, "icolor",
|
|
|
|
"I color",
|
|
|
|
"Intersection color",
|
|
|
|
TRUE, default_icolor,
|
|
|
|
G_PARAM_READWRITE);
|
2024-02-15 03:39:52 +00:00
|
|
|
|
|
|
|
g_object_unref (default_hcolor);
|
|
|
|
g_object_unref (default_vcolor);
|
|
|
|
g_object_unref (default_icolor);
|
2019-08-30 15:26:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return procedure;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpValueArray *
|
|
|
|
grid_run (GimpProcedure *procedure,
|
|
|
|
GimpRunMode run_mode,
|
|
|
|
GimpImage *image,
|
2021-04-02 02:55:46 +02:00
|
|
|
GimpDrawable **drawables,
|
2023-06-21 15:36:28 +02:00
|
|
|
GimpProcedureConfig *config,
|
2019-08-30 15:26:06 +02:00
|
|
|
gpointer run_data)
|
|
|
|
{
|
2021-04-02 02:55:46 +02:00
|
|
|
GimpDrawable *drawable;
|
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
gegl_init (NULL, NULL);
|
|
|
|
|
2024-10-28 12:16:13 +01:00
|
|
|
if (gimp_core_object_array_get_length ((GObject **) drawables) != 1)
|
2021-04-02 02:55:46 +02:00
|
|
|
{
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
g_set_error (&error, GIMP_PLUG_IN_ERROR, 0,
|
|
|
|
_("Procedure '%s' only works with one drawable."),
|
|
|
|
PLUG_IN_PROC);
|
|
|
|
|
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_CALLING_ERROR,
|
|
|
|
error);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
drawable = drawables[0];
|
|
|
|
}
|
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
if (run_mode == GIMP_RUN_INTERACTIVE && ! dialog (image, drawable, procedure, config))
|
|
|
|
return gimp_procedure_new_return_values (procedure,
|
|
|
|
GIMP_PDB_CANCEL,
|
|
|
|
NULL);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
gimp_progress_init (_("Drawing grid"));
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
render_grid (image, drawable, config, NULL);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
if (run_mode != GIMP_RUN_NONINTERACTIVE)
|
|
|
|
gimp_displays_flush ();
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-08-30 15:26:06 +02:00
|
|
|
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
|
2000-02-22 21:25:18 +00:00
|
|
|
}
|
1998-01-30 00:31:16 +00:00
|
|
|
|
2000-02-22 21:25:18 +00:00
|
|
|
|
|
|
|
#define MAXDIFF 195076
|
|
|
|
|
|
|
|
static guchar
|
2003-07-02 11:07:41 +00:00
|
|
|
best_cmap_match (const guchar *cmap,
|
2003-12-10 22:50:26 +00:00
|
|
|
gint ncolors,
|
2024-02-15 03:39:52 +00:00
|
|
|
GeglColor *color)
|
2000-02-22 21:25:18 +00:00
|
|
|
{
|
|
|
|
guchar cmap_index = 0;
|
2024-02-15 03:39:52 +00:00
|
|
|
gint max = MAXDIFF;
|
2001-01-11 23:36:59 +00:00
|
|
|
gint i, diff, sum;
|
2024-02-15 03:39:52 +00:00
|
|
|
guchar rgb[3];
|
2001-01-11 23:36:59 +00:00
|
|
|
|
2024-02-15 03:39:52 +00:00
|
|
|
gegl_color_get_pixel (color, babl_format ("R'G'B' u8"), rgb);
|
2000-02-22 21:25:18 +00:00
|
|
|
|
|
|
|
for (i = 0; i < ncolors; i++)
|
|
|
|
{
|
2024-02-15 03:39:52 +00:00
|
|
|
diff = rgb[0] - *cmap++;
|
2000-02-22 21:25:18 +00:00
|
|
|
sum = SQR (diff);
|
2024-02-15 03:39:52 +00:00
|
|
|
diff = rgb[1] - *cmap++;
|
2000-02-22 21:25:18 +00:00
|
|
|
sum += SQR (diff);
|
2024-02-15 03:39:52 +00:00
|
|
|
diff = rgb[2] - *cmap++;
|
2000-02-22 21:25:18 +00:00
|
|
|
sum += SQR (diff);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2000-02-22 21:25:18 +00:00
|
|
|
if (sum < max)
|
2003-12-10 22:50:26 +00:00
|
|
|
{
|
|
|
|
cmap_index = i;
|
|
|
|
max = sum;
|
|
|
|
}
|
1998-01-30 00:31:16 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2000-02-22 21:25:18 +00:00
|
|
|
return cmap_index;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2004-11-14 02:50:33 +00:00
|
|
|
static inline void
|
2003-11-06 15:27:05 +00:00
|
|
|
pix_composite (guchar *p1,
|
2003-12-10 22:50:26 +00:00
|
|
|
guchar p2[4],
|
|
|
|
gint bytes,
|
|
|
|
gboolean blend,
|
|
|
|
gboolean alpha)
|
1999-11-01 12:36:23 +00:00
|
|
|
{
|
2000-02-22 21:25:18 +00:00
|
|
|
gint b;
|
2024-10-20 12:11:30 +00:00
|
|
|
gint alpha_index;
|
|
|
|
|
|
|
|
alpha_index = alpha ? (bytes - 1) : bytes;
|
2000-02-22 21:25:18 +00:00
|
|
|
|
|
|
|
if (blend)
|
|
|
|
{
|
2005-08-17 01:31:37 +00:00
|
|
|
if (alpha)
|
|
|
|
bytes--;
|
|
|
|
|
2000-02-22 21:25:18 +00:00
|
|
|
for (b = 0; b < bytes; b++)
|
2003-12-10 22:50:26 +00:00
|
|
|
{
|
2024-10-20 12:11:30 +00:00
|
|
|
*p1 = *p1 * (1.0 - p2[alpha_index] / 255.0) +
|
|
|
|
p2[b] * p2[alpha_index] / 255.0;
|
2003-12-10 22:50:26 +00:00
|
|
|
p1++;
|
|
|
|
}
|
2000-02-22 21:25:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* blend should only be TRUE for indexed (bytes == 1) */
|
|
|
|
*p1++ = *p2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (alpha && *p1 < 255)
|
|
|
|
{
|
2024-10-20 12:11:30 +00:00
|
|
|
b = *p1 + 255.0 * ((gdouble) p2[alpha_index] / (255.0 - *p1));
|
2005-08-17 01:31:37 +00:00
|
|
|
|
2000-02-22 21:25:18 +00:00
|
|
|
*p1 = b > 255 ? 255 : b;
|
|
|
|
}
|
1999-11-01 12:36:23 +00:00
|
|
|
}
|
|
|
|
|
1998-06-01 05:07:31 +00:00
|
|
|
static void
|
2023-06-21 15:36:28 +02:00
|
|
|
render_grid (GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
GimpPreview *preview)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2023-05-26 12:45:50 +02:00
|
|
|
GeglBuffer *src_buffer = NULL;
|
|
|
|
GeglBuffer *dest_buffer = NULL;
|
2019-07-10 12:43:27 +02:00
|
|
|
const Babl *format;
|
|
|
|
gint bytes;
|
|
|
|
gint x_offset;
|
|
|
|
gint y_offset;
|
2023-05-26 12:45:50 +02:00
|
|
|
guchar *dest = NULL;
|
|
|
|
guchar *buffer = NULL;
|
2019-07-10 12:43:27 +02:00
|
|
|
gint x, y;
|
|
|
|
gboolean alpha;
|
|
|
|
gboolean blend;
|
|
|
|
guchar hcolor[4];
|
|
|
|
guchar vcolor[4];
|
|
|
|
guchar icolor[4];
|
|
|
|
guchar *cmap;
|
|
|
|
gint ncolors;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
gint hwidth;
|
|
|
|
gint hspace;
|
|
|
|
gint hoffset;
|
2024-02-15 03:39:52 +00:00
|
|
|
GeglColor *hcolor_gegl;
|
2023-06-21 15:36:28 +02:00
|
|
|
gint vwidth;
|
|
|
|
gint vspace;
|
|
|
|
gint voffset;
|
2024-02-15 03:39:52 +00:00
|
|
|
GeglColor *vcolor_gegl;
|
2023-06-21 15:36:28 +02:00
|
|
|
gint iwidth;
|
|
|
|
gint ispace;
|
|
|
|
gint ioffset;
|
2024-02-15 03:39:52 +00:00
|
|
|
GeglColor *icolor_gegl;
|
2023-06-21 15:36:28 +02:00
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
"hwidth", &hwidth,
|
|
|
|
"hspace", &hspace,
|
|
|
|
"hoffset", &hoffset,
|
2024-02-15 03:39:52 +00:00
|
|
|
"hcolor", &hcolor_gegl,
|
2023-06-21 15:36:28 +02:00
|
|
|
"vwidth", &vwidth,
|
|
|
|
"vspace", &vspace,
|
|
|
|
"voffset", &voffset,
|
2024-02-15 03:39:52 +00:00
|
|
|
"vcolor", &vcolor_gegl,
|
2023-06-21 15:36:28 +02:00
|
|
|
"iwidth", &iwidth,
|
|
|
|
"ispace", &ispace,
|
|
|
|
"ioffset", &ioffset,
|
2024-02-15 03:39:52 +00:00
|
|
|
"icolor", &icolor_gegl,
|
2023-06-21 15:36:28 +02:00
|
|
|
NULL);
|
|
|
|
|
2024-02-15 03:39:52 +00:00
|
|
|
if (hcolor_gegl == NULL)
|
|
|
|
hcolor_gegl = gegl_color_new ("black");
|
|
|
|
if (vcolor_gegl == NULL)
|
|
|
|
vcolor_gegl = gegl_color_new ("black");
|
|
|
|
if (icolor_gegl == NULL)
|
|
|
|
icolor_gegl = gegl_color_new ("black");
|
2001-01-11 23:36:59 +00:00
|
|
|
|
2019-08-13 17:31:13 +02:00
|
|
|
alpha = gimp_drawable_has_alpha (drawable);
|
2019-07-10 12:43:27 +02:00
|
|
|
|
2021-04-06 00:47:07 +02:00
|
|
|
switch (gimp_image_get_base_type (image))
|
2000-02-22 21:25:18 +00:00
|
|
|
{
|
2004-08-07 00:04:16 +00:00
|
|
|
case GIMP_RGB:
|
2000-02-22 21:25:18 +00:00
|
|
|
blend = TRUE;
|
2019-07-10 12:43:27 +02:00
|
|
|
|
|
|
|
if (alpha)
|
|
|
|
format = babl_format ("R'G'B'A u8");
|
|
|
|
else
|
|
|
|
format = babl_format ("R'G'B' u8");
|
2024-02-15 03:39:52 +00:00
|
|
|
|
2024-10-20 12:11:30 +00:00
|
|
|
gegl_color_get_pixel (hcolor_gegl, babl_format ("R'G'B'A u8"), hcolor);
|
|
|
|
gegl_color_get_pixel (vcolor_gegl, babl_format ("R'G'B'A u8"), vcolor);
|
|
|
|
gegl_color_get_pixel (icolor_gegl, babl_format ("R'G'B'A u8"), icolor);
|
2004-08-07 00:04:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_GRAY:
|
|
|
|
blend = TRUE;
|
2019-07-10 12:43:27 +02:00
|
|
|
|
|
|
|
if (alpha)
|
|
|
|
format = babl_format ("Y'A u8");
|
|
|
|
else
|
|
|
|
format = babl_format ("Y' u8");
|
2024-02-15 03:39:52 +00:00
|
|
|
|
2024-10-20 12:11:30 +00:00
|
|
|
gegl_color_get_pixel (hcolor_gegl, babl_format ("Y'A u8"), hcolor);
|
|
|
|
gegl_color_get_pixel (vcolor_gegl, babl_format ("Y'A u8"), vcolor);
|
|
|
|
gegl_color_get_pixel (icolor_gegl, babl_format ("Y'A u8"), icolor);
|
2004-08-07 00:04:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_INDEXED:
|
2024-09-23 15:17:04 +02:00
|
|
|
cmap = gimp_palette_get_colormap (gimp_image_get_palette (image), babl_format ("R'G'B' u8"), &ncolors, NULL);
|
2004-09-03 16:37:53 +00:00
|
|
|
|
2024-02-15 03:39:52 +00:00
|
|
|
hcolor[0] = best_cmap_match (cmap, ncolors, hcolor_gegl);
|
|
|
|
vcolor[0] = best_cmap_match (cmap, ncolors, vcolor_gegl);
|
|
|
|
icolor[0] = best_cmap_match (cmap, ncolors, icolor_gegl);
|
2004-09-03 16:37:53 +00:00
|
|
|
|
2004-08-07 00:04:16 +00:00
|
|
|
g_free (cmap);
|
|
|
|
blend = FALSE;
|
2019-07-10 12:43:27 +02:00
|
|
|
|
2019-08-13 17:31:13 +02:00
|
|
|
format = gimp_drawable_get_format (drawable);
|
2004-08-07 00:04:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
blend = FALSE;
|
2000-05-22 13:53:43 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2024-02-15 03:39:52 +00:00
|
|
|
g_clear_object (&hcolor_gegl);
|
|
|
|
g_clear_object (&vcolor_gegl);
|
|
|
|
g_clear_object (&icolor_gegl);
|
|
|
|
|
2019-07-10 12:43:27 +02:00
|
|
|
bytes = babl_format_get_bytes_per_pixel (format);
|
2004-09-03 16:37:53 +00:00
|
|
|
|
|
|
|
if (preview)
|
2003-11-06 15:27:05 +00:00
|
|
|
{
|
2004-09-29 13:39:23 +00:00
|
|
|
gimp_preview_get_position (preview, &sx1, &sy1);
|
2004-09-03 16:37:53 +00:00
|
|
|
gimp_preview_get_size (preview, &sx2, &sy2);
|
|
|
|
|
|
|
|
buffer = g_new (guchar, bytes * sx2 * sy2);
|
2004-08-07 00:04:16 +00:00
|
|
|
|
2004-09-03 16:37:53 +00:00
|
|
|
sx2 += sx1;
|
|
|
|
sy2 += sy1;
|
2003-11-06 15:27:05 +00:00
|
|
|
}
|
|
|
|
else
|
2000-05-22 13:53:43 +00:00
|
|
|
{
|
2015-08-29 21:04:09 +10:00
|
|
|
gint w, h;
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2019-08-13 17:31:13 +02:00
|
|
|
if (! gimp_drawable_mask_intersect (drawable,
|
2015-08-29 21:04:09 +10:00
|
|
|
&sx1, &sy1, &w, &h))
|
2018-02-16 19:12:19 +01:00
|
|
|
return;
|
2015-08-29 21:04:09 +10:00
|
|
|
|
|
|
|
sx2 = sx1 + w;
|
|
|
|
sy2 = sy1 + h;
|
|
|
|
|
2019-08-13 17:31:13 +02:00
|
|
|
dest_buffer = gimp_drawable_get_shadow_buffer (drawable);
|
2000-02-22 21:25:18 +00:00
|
|
|
}
|
|
|
|
|
2019-08-13 17:31:13 +02:00
|
|
|
src_buffer = gimp_drawable_get_buffer (drawable);
|
2004-09-03 16:37:53 +00:00
|
|
|
|
|
|
|
dest = g_new (guchar, (sx2 - sx1) * bytes);
|
2005-06-23 17:13:57 +00:00
|
|
|
|
1999-11-01 12:36:23 +00:00
|
|
|
for (y = sy1; y < sy2; y++)
|
1998-01-30 00:31:16 +00:00
|
|
|
{
|
2019-07-10 12:43:27 +02:00
|
|
|
gegl_buffer_get (src_buffer, GEGL_RECTANGLE (sx1, y, sx2 - sx1, 1), 1.0,
|
|
|
|
format, dest,
|
|
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
1999-11-01 12:36:23 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
y_offset = y - hoffset;
|
2000-02-20 20:09:01 +00:00
|
|
|
while (y_offset < 0)
|
2023-06-21 15:36:28 +02:00
|
|
|
y_offset += hspace;
|
2000-02-20 19:34:51 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
if ((y_offset + (hwidth / 2)) % hspace < hwidth)
|
2003-12-10 22:50:26 +00:00
|
|
|
{
|
|
|
|
for (x = sx1; x < sx2; x++)
|
|
|
|
{
|
2005-06-23 17:13:57 +00:00
|
|
|
pix_composite (&dest[(x-sx1) * bytes],
|
|
|
|
hcolor, bytes, blend, alpha);
|
2003-12-10 22:50:26 +00:00
|
|
|
}
|
1999-11-01 12:36:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (x = sx1; x < sx2; x++)
|
|
|
|
{
|
2023-06-21 15:36:28 +02:00
|
|
|
x_offset = vspace + x - voffset;
|
2003-12-10 22:50:26 +00:00
|
|
|
while (x_offset < 0)
|
2023-06-21 15:36:28 +02:00
|
|
|
x_offset += vspace;
|
2000-02-20 19:34:51 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
if ((x_offset + (vwidth / 2)) % vspace < vwidth)
|
1999-11-01 12:36:23 +00:00
|
|
|
{
|
2005-06-23 17:13:57 +00:00
|
|
|
pix_composite (&dest[(x-sx1) * bytes],
|
|
|
|
vcolor, bytes, blend, alpha);
|
1999-11-01 12:36:23 +00:00
|
|
|
}
|
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
if ((x_offset + (iwidth / 2)) % vspace < iwidth
|
2003-12-10 22:50:26 +00:00
|
|
|
&&
|
2023-06-21 15:36:28 +02:00
|
|
|
((y_offset % hspace >= ispace
|
2003-12-10 22:50:26 +00:00
|
|
|
&&
|
2023-06-21 15:36:28 +02:00
|
|
|
y_offset % hspace < ioffset)
|
2003-12-10 22:50:26 +00:00
|
|
|
||
|
2023-06-21 15:36:28 +02:00
|
|
|
(hspace -
|
|
|
|
(y_offset % hspace) >= ispace
|
2003-12-10 22:50:26 +00:00
|
|
|
&&
|
2023-06-21 15:36:28 +02:00
|
|
|
hspace -
|
|
|
|
(y_offset % hspace) < ioffset)))
|
1999-11-01 12:36:23 +00:00
|
|
|
{
|
2005-06-23 17:13:57 +00:00
|
|
|
pix_composite (&dest[(x-sx1) * bytes],
|
|
|
|
icolor, bytes, blend, alpha);
|
1999-11-01 12:36:23 +00:00
|
|
|
}
|
|
|
|
}
|
2005-06-23 17:13:57 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
if ((y_offset + (iwidth / 2)) % hspace < iwidth)
|
2005-06-23 17:13:57 +00:00
|
|
|
{
|
|
|
|
for (x = sx1; x < sx2; x++)
|
|
|
|
{
|
2023-06-21 15:36:28 +02:00
|
|
|
x_offset = vspace + x - voffset;
|
2005-06-23 17:13:57 +00:00
|
|
|
while (x_offset < 0)
|
2023-06-21 15:36:28 +02:00
|
|
|
x_offset += vspace;
|
2005-06-23 17:13:57 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
if ((x_offset % vspace >= ispace
|
2005-06-23 17:13:57 +00:00
|
|
|
&&
|
2023-06-21 15:36:28 +02:00
|
|
|
x_offset % vspace < ioffset)
|
2005-06-23 17:13:57 +00:00
|
|
|
||
|
2023-06-21 15:36:28 +02:00
|
|
|
(vspace -
|
|
|
|
(x_offset % vspace) >= ispace
|
2005-06-23 17:13:57 +00:00
|
|
|
&&
|
2023-06-21 15:36:28 +02:00
|
|
|
vspace -
|
|
|
|
(x_offset % vspace) < ioffset))
|
2005-06-23 17:13:57 +00:00
|
|
|
{
|
|
|
|
pix_composite (&dest[(x-sx1) * bytes],
|
|
|
|
icolor, bytes, blend, alpha);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-03 16:37:53 +00:00
|
|
|
if (preview)
|
2003-12-10 22:50:26 +00:00
|
|
|
{
|
2004-09-03 16:37:53 +00:00
|
|
|
memcpy (buffer + (y - sy1) * (sx2 - sx1) * bytes,
|
|
|
|
dest,
|
|
|
|
(sx2 - sx1) * bytes);
|
2003-12-10 22:50:26 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
else
|
2003-12-10 22:50:26 +00:00
|
|
|
{
|
2019-07-10 12:43:27 +02:00
|
|
|
gegl_buffer_set (dest_buffer,
|
|
|
|
GEGL_RECTANGLE (sx1, y, sx2 - sx1, 1), 0,
|
|
|
|
format, dest,
|
|
|
|
GEGL_AUTO_ROWSTRIDE);
|
2005-08-17 01:31:37 +00:00
|
|
|
|
|
|
|
if (y % 16 == 0)
|
|
|
|
gimp_progress_update ((gdouble) y / (gdouble) (sy2 - sy1));
|
2003-12-10 22:50:26 +00:00
|
|
|
}
|
2003-11-06 15:27:05 +00:00
|
|
|
}
|
2004-09-03 16:37:53 +00:00
|
|
|
|
2000-02-11 02:22:01 +00:00
|
|
|
g_free (dest);
|
1998-01-30 00:31:16 +00:00
|
|
|
|
2019-07-10 12:43:27 +02:00
|
|
|
g_object_unref (src_buffer);
|
|
|
|
|
2004-09-03 16:37:53 +00:00
|
|
|
if (preview)
|
2000-05-22 13:53:43 +00:00
|
|
|
{
|
2004-09-29 15:33:02 +00:00
|
|
|
gimp_preview_draw_buffer (preview, buffer, bytes * (sx2 - sx1));
|
2004-08-07 00:04:16 +00:00
|
|
|
g_free (buffer);
|
2003-11-06 15:27:05 +00:00
|
|
|
}
|
|
|
|
else
|
2000-05-22 13:53:43 +00:00
|
|
|
{
|
2011-04-10 19:05:08 +02:00
|
|
|
gimp_progress_update (1.0);
|
2019-07-10 12:43:27 +02:00
|
|
|
|
|
|
|
g_object_unref (dest_buffer);
|
|
|
|
|
2019-08-13 17:31:13 +02:00
|
|
|
gimp_drawable_merge_shadow (drawable, TRUE);
|
|
|
|
gimp_drawable_update (drawable,
|
2003-06-02 12:27:13 +00:00
|
|
|
sx1, sy1, sx2 - sx1, sy2 - sy1);
|
2000-05-22 13:53:43 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
2000-02-22 21:25:18 +00:00
|
|
|
|
1997-11-24 22:05:25 +00:00
|
|
|
/***************************************************
|
|
|
|
* GUI stuff
|
|
|
|
*/
|
|
|
|
|
2003-06-02 12:27:13 +00:00
|
|
|
|
1998-06-01 05:07:31 +00:00
|
|
|
static void
|
2023-06-21 15:36:28 +02:00
|
|
|
update_values (Grid *grid)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
1999-08-24 18:36:38 +00:00
|
|
|
GtkWidget *entry;
|
2023-11-24 15:35:50 +01:00
|
|
|
GeglColor *color;
|
1999-08-24 18:36:38 +00:00
|
|
|
|
2003-06-02 12:27:13 +00:00
|
|
|
entry = g_object_get_data (G_OBJECT (main_dialog), "width");
|
2023-06-21 15:36:28 +02:00
|
|
|
g_object_set (grid->config,
|
|
|
|
"hwidth",
|
|
|
|
(gint) RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (entry), 0)),
|
|
|
|
"vwidth",
|
|
|
|
(gint) RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (entry), 1)),
|
|
|
|
"iwidth",
|
|
|
|
(gint) RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (entry), 2)),
|
|
|
|
NULL);
|
2001-12-29 13:26:29 +00:00
|
|
|
|
2003-06-02 12:27:13 +00:00
|
|
|
entry = g_object_get_data (G_OBJECT (main_dialog), "space");
|
2023-06-21 15:36:28 +02:00
|
|
|
g_object_set (grid->config,
|
|
|
|
"hspace",
|
|
|
|
(gint) RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (entry), 0)),
|
|
|
|
"vspace",
|
|
|
|
(gint) RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (entry), 1)),
|
|
|
|
"ispace",
|
|
|
|
(gint) RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (entry), 2)),
|
|
|
|
NULL);
|
2001-12-29 13:26:29 +00:00
|
|
|
|
2003-06-02 12:27:13 +00:00
|
|
|
entry = g_object_get_data (G_OBJECT (main_dialog), "offset");
|
2023-06-21 15:36:28 +02:00
|
|
|
g_object_set (grid->config,
|
|
|
|
"hoffset",
|
|
|
|
(gint) RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (entry), 0)),
|
|
|
|
"voffset",
|
|
|
|
(gint) RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (entry), 1)),
|
|
|
|
"ioffset",
|
|
|
|
(gint) RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (entry), 2)),
|
|
|
|
NULL);
|
|
|
|
|
2023-11-24 15:35:50 +01:00
|
|
|
color = gimp_color_button_get_color (GIMP_COLOR_BUTTON (grid->hcolor_button));
|
2024-02-15 03:39:52 +00:00
|
|
|
g_object_set (grid->config, "hcolor", color, NULL);
|
2023-11-24 15:35:50 +01:00
|
|
|
g_object_unref (color);
|
|
|
|
|
|
|
|
color = gimp_color_button_get_color (GIMP_COLOR_BUTTON (grid->vcolor_button));
|
2024-02-15 03:39:52 +00:00
|
|
|
g_object_set (grid->config, "vcolor", color, NULL);
|
2023-11-24 15:35:50 +01:00
|
|
|
g_object_unref (color);
|
|
|
|
|
|
|
|
color = gimp_color_button_get_color (GIMP_COLOR_BUTTON (grid->icolor_button));
|
2024-02-15 03:39:52 +00:00
|
|
|
g_object_set (grid->config, "icolor", color, NULL);
|
2023-11-24 15:35:50 +01:00
|
|
|
g_object_unref (color);
|
2003-06-02 12:27:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-06-21 15:36:28 +02:00
|
|
|
update_preview (GimpPreview *preview,
|
|
|
|
Grid *grid)
|
2003-06-02 12:27:13 +00:00
|
|
|
{
|
2023-06-21 15:36:28 +02:00
|
|
|
update_values (grid);
|
2003-06-02 12:27:13 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
render_grid (gimp_item_get_image (GIMP_ITEM (grid->drawable)),
|
|
|
|
grid->drawable, grid->config, preview);
|
2003-06-02 12:27:13 +00:00
|
|
|
}
|
|
|
|
|
1998-06-01 05:07:31 +00:00
|
|
|
static void
|
2003-11-06 15:27:05 +00:00
|
|
|
entry_callback (GtkWidget *widget,
|
2003-12-10 22:50:26 +00:00
|
|
|
gpointer data)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
1999-08-24 18:36:38 +00:00
|
|
|
static gdouble x = -1.0;
|
|
|
|
static gdouble y = -1.0;
|
|
|
|
gdouble new_x;
|
|
|
|
gdouble new_y;
|
|
|
|
|
|
|
|
new_x = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 0);
|
|
|
|
new_y = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (widget), 1);
|
|
|
|
|
|
|
|
if (gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (data)))
|
|
|
|
{
|
|
|
|
if (new_x != x)
|
2003-12-10 22:50:26 +00:00
|
|
|
{
|
|
|
|
y = new_y = x = new_x;
|
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (widget), 1, y);
|
|
|
|
}
|
1999-08-24 18:36:38 +00:00
|
|
|
if (new_y != y)
|
2003-12-10 22:50:26 +00:00
|
|
|
{
|
|
|
|
x = new_x = y = new_y;
|
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (widget), 0, x);
|
|
|
|
}
|
1999-08-24 18:36:38 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-12-23 12:39:55 +00:00
|
|
|
x = new_x;
|
|
|
|
y = new_y;
|
2003-06-02 12:27:13 +00:00
|
|
|
}
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|
|
|
|
|
1999-12-02 00:20:43 +00:00
|
|
|
static void
|
2001-01-10 22:49:45 +00:00
|
|
|
color_callback (GtkWidget *widget,
|
2003-12-10 22:50:26 +00:00
|
|
|
gpointer data)
|
1999-12-02 00:20:43 +00:00
|
|
|
{
|
2023-06-21 15:36:28 +02:00
|
|
|
Grid *grid = GRID (data);
|
|
|
|
GtkWidget *chain_button = grid->color_chain;
|
2023-11-24 15:35:50 +01:00
|
|
|
GeglColor *color;
|
|
|
|
|
|
|
|
color = gimp_color_button_get_color (GIMP_COLOR_BUTTON (widget));
|
2023-06-21 15:36:28 +02:00
|
|
|
|
|
|
|
if (gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chain_button)))
|
1999-12-02 00:20:43 +00:00
|
|
|
{
|
2023-06-21 15:36:28 +02:00
|
|
|
if (widget == grid->vcolor_button)
|
2025-05-06 04:04:37 +00:00
|
|
|
{
|
|
|
|
g_signal_handlers_block_by_func (grid->hcolor_button, color_callback,
|
|
|
|
grid);
|
|
|
|
gimp_color_button_set_color (GIMP_COLOR_BUTTON (grid->hcolor_button),
|
|
|
|
color);
|
|
|
|
g_signal_handlers_unblock_by_func (grid->hcolor_button,
|
|
|
|
color_callback, grid);
|
|
|
|
}
|
2023-06-21 15:36:28 +02:00
|
|
|
else if (widget == grid->hcolor_button)
|
2025-05-06 04:04:37 +00:00
|
|
|
{
|
|
|
|
g_signal_handlers_block_by_func (grid->vcolor_button, color_callback,
|
|
|
|
grid);
|
|
|
|
gimp_color_button_set_color (GIMP_COLOR_BUTTON (grid->vcolor_button),
|
|
|
|
color);
|
|
|
|
g_signal_handlers_unblock_by_func (grid->vcolor_button,
|
|
|
|
color_callback, grid);
|
|
|
|
}
|
1999-12-02 00:20:43 +00:00
|
|
|
}
|
2023-11-24 15:35:50 +01:00
|
|
|
|
|
|
|
if (widget == grid->hcolor_button)
|
2024-02-15 03:39:52 +00:00
|
|
|
g_object_set (grid->config, "hcolor", color, NULL);
|
2023-11-24 15:35:50 +01:00
|
|
|
else if (widget == grid->vcolor_button)
|
2024-02-15 03:39:52 +00:00
|
|
|
g_object_set (grid->config, "vcolor", color, NULL);
|
2023-11-24 15:35:50 +01:00
|
|
|
else if (widget == grid->icolor_button)
|
2024-02-15 03:39:52 +00:00
|
|
|
g_object_set (grid->config, "icolor", color, NULL);
|
2023-11-24 15:35:50 +01:00
|
|
|
|
|
|
|
g_object_unref (color);
|
2000-05-22 13:53:43 +00:00
|
|
|
}
|
|
|
|
|
2003-06-02 12:27:13 +00:00
|
|
|
|
1998-06-01 05:07:31 +00:00
|
|
|
static gint
|
2023-06-21 15:36:28 +02:00
|
|
|
dialog (GimpImage *image,
|
|
|
|
GimpDrawable *drawable,
|
|
|
|
GimpProcedure *procedure,
|
|
|
|
GimpProcedureConfig *config)
|
1997-11-24 22:05:25 +00:00
|
|
|
{
|
2023-06-21 15:36:28 +02:00
|
|
|
Grid *grid;
|
|
|
|
GimpColorConfig *color_config;
|
2017-12-31 13:57:41 +01:00
|
|
|
GtkWidget *dlg;
|
|
|
|
GtkWidget *main_vbox;
|
|
|
|
GtkWidget *vbox;
|
|
|
|
GtkSizeGroup *group;
|
|
|
|
GtkWidget *label;
|
|
|
|
GtkWidget *preview;
|
2019-07-10 12:43:27 +02:00
|
|
|
GtkWidget *width;
|
|
|
|
GtkWidget *space;
|
|
|
|
GtkWidget *offset;
|
|
|
|
GtkWidget *chain_button;
|
Issue #8900 and #9923: reimplementing GimpUnit as a proper class.
This fixes all our GObject Introspection issues with GimpUnit which was
both an enum and an int-derived type of user-defined units *completing*
the enum values. GIR clearly didn't like this!
Now GimpUnit is a proper class and units are unique objects, allowing to
compare them with an identity test (i.e. `unit == gimp_unit_pixel ()`
tells us if unit is the pixel unit or not), which makes it easy to use,
just like with int, yet adding also methods, making for nicer
introspected API.
As an aside, this also fixes #10738, by having all the built-in units
retrievable even if libgimpbase had not been properly initialized with
gimp_base_init().
I haven't checked in details how GIR works to introspect, but it looks
like it loads the library to inspect and runs functions, hence
triggering some CRITICALS because virtual methods (supposed to be
initialized with gimp_base_init() run by libgimp) are not set. This new
code won't trigger any critical because the vtable method are now not
necessary, at least for all built-in units.
Note that GimpUnit is still in libgimpbase. It could have been moved to
libgimp in order to avoid any virtual method table (since we need to
keep core and libgimp side's units in sync, PDB is required), but too
many libgimpwidgets widgets were already using GimpUnit. And technically
most of GimpUnit logic doesn't require PDB (only the creation/sync
part). This is one of the reasons why user-created GimpUnit list is
handled and stored differently from other types of objects.
Globally this simplifies the code a lot too and we don't need separate
implementations of various utils for core and libgimp, which means less
prone to errors.
2024-07-25 20:55:21 +02:00
|
|
|
GimpUnit *unit;
|
2019-07-10 12:43:27 +02:00
|
|
|
gint d_width;
|
|
|
|
gint d_height;
|
|
|
|
gdouble xres;
|
|
|
|
gdouble yres;
|
|
|
|
gboolean run;
|
1998-01-30 00:31:16 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
gint hwidth;
|
|
|
|
gint hspace;
|
|
|
|
gint hoffset;
|
2024-02-15 03:39:52 +00:00
|
|
|
GeglColor *hcolor;
|
2023-06-21 15:36:28 +02:00
|
|
|
gint vwidth;
|
|
|
|
gint vspace;
|
|
|
|
gint voffset;
|
2024-02-15 03:39:52 +00:00
|
|
|
GeglColor *vcolor;
|
2023-06-21 15:36:28 +02:00
|
|
|
gint iwidth;
|
|
|
|
gint ispace;
|
|
|
|
gint ioffset;
|
2024-02-15 03:39:52 +00:00
|
|
|
GeglColor *icolor;
|
2023-06-21 15:36:28 +02:00
|
|
|
|
2003-06-02 12:27:13 +00:00
|
|
|
g_return_val_if_fail (main_dialog == NULL, FALSE);
|
1998-01-30 00:31:16 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
g_object_get (config,
|
|
|
|
"hwidth", &hwidth,
|
|
|
|
"hspace", &hspace,
|
|
|
|
"hoffset", &hoffset,
|
|
|
|
"hcolor", &hcolor,
|
|
|
|
"vwidth", &vwidth,
|
|
|
|
"vspace", &vspace,
|
|
|
|
"voffset", &voffset,
|
|
|
|
"vcolor", &vcolor,
|
|
|
|
"iwidth", &iwidth,
|
|
|
|
"ispace", &ispace,
|
|
|
|
"ioffset", &ioffset,
|
|
|
|
"icolor", &icolor,
|
|
|
|
NULL);
|
|
|
|
|
2019-09-20 19:39:00 +02:00
|
|
|
gimp_ui_init (PLUG_IN_BINARY);
|
2000-01-05 15:47:06 +00:00
|
|
|
|
2021-04-06 14:28:40 +02:00
|
|
|
d_width = gimp_drawable_get_width (drawable);
|
|
|
|
d_height = gimp_drawable_get_height (drawable);
|
2019-07-10 12:43:27 +02:00
|
|
|
|
2011-04-08 20:31:34 +02:00
|
|
|
main_dialog = dlg = gimp_dialog_new (_("Grid"), PLUG_IN_ROLE,
|
2003-11-06 15:27:05 +00:00
|
|
|
NULL, 0,
|
2005-08-13 22:52:41 +00:00
|
|
|
gimp_standard_help_func, PLUG_IN_PROC,
|
1998-01-30 00:31:16 +00:00
|
|
|
|
2017-02-12 16:18:24 +01:00
|
|
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
|
|
_("_OK"), GTK_RESPONSE_OK,
|
2003-11-06 15:27:05 +00:00
|
|
|
|
|
|
|
NULL);
|
2000-01-06 22:26:10 +00:00
|
|
|
|
2018-05-10 17:04:37 +02:00
|
|
|
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dlg),
|
2005-08-13 22:52:41 +00:00
|
|
|
GTK_RESPONSE_OK,
|
|
|
|
GTK_RESPONSE_CANCEL,
|
|
|
|
-1);
|
2005-02-08 20:40:33 +00:00
|
|
|
|
2005-09-09 18:07:31 +00:00
|
|
|
gimp_window_set_transient (GTK_WINDOW (dlg));
|
2005-09-05 21:40:29 +00:00
|
|
|
|
1999-08-24 18:36:38 +00:00
|
|
|
/* Get the image resolution and unit */
|
2019-08-13 17:31:13 +02:00
|
|
|
gimp_image_get_resolution (image, &xres, &yres);
|
|
|
|
unit = gimp_image_get_unit (image);
|
1998-01-30 00:31:16 +00:00
|
|
|
|
2011-09-30 12:17:53 +02:00
|
|
|
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
2004-09-09 16:08:56 +00:00
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
|
2011-03-04 10:44:58 +01:00
|
|
|
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
|
|
|
|
main_vbox, TRUE, TRUE, 0);
|
2004-09-09 16:08:56 +00:00
|
|
|
gtk_widget_show (main_vbox);
|
2000-05-22 13:53:43 +00:00
|
|
|
|
2019-08-13 17:31:13 +02:00
|
|
|
preview = gimp_drawable_preview_new_from_drawable (drawable);
|
2004-09-09 16:08:56 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), preview, TRUE, TRUE, 0);
|
2004-08-07 00:04:16 +00:00
|
|
|
gtk_widget_show (preview);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
grid = GRID (gimp_procedure_get_plug_in (procedure));
|
|
|
|
grid->drawable = drawable;
|
|
|
|
grid->config = config;
|
2004-09-03 16:37:53 +00:00
|
|
|
g_signal_connect (preview, "invalidated",
|
|
|
|
G_CALLBACK (update_preview),
|
2023-06-21 15:36:28 +02:00
|
|
|
grid);
|
2004-09-03 16:37:53 +00:00
|
|
|
|
2011-09-30 12:17:53 +02:00
|
|
|
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
2004-09-09 16:08:56 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (vbox);
|
2003-11-06 15:27:05 +00:00
|
|
|
|
2000-05-22 13:53:43 +00:00
|
|
|
/* The width entries */
|
2003-11-06 15:27:05 +00:00
|
|
|
width = gimp_size_entry_new (3, /* number_of_fields */
|
2003-12-10 22:50:26 +00:00
|
|
|
unit, /* unit */
|
|
|
|
"%a", /* unit_format */
|
|
|
|
TRUE, /* menu_show_pixels */
|
|
|
|
TRUE, /* menu_show_percent */
|
|
|
|
FALSE, /* show_refval */
|
|
|
|
SPIN_BUTTON_WIDTH, /* spinbutton_usize */
|
|
|
|
GIMP_SIZE_ENTRY_UPDATE_SIZE); /* update_policy */
|
1999-08-24 18:36:38 +00:00
|
|
|
|
2004-09-09 16:08:56 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), width, FALSE, FALSE, 0);
|
2004-05-18 17:06:06 +00:00
|
|
|
gtk_widget_show (width);
|
|
|
|
|
2000-01-18 21:01:45 +00:00
|
|
|
/* set the unit back to pixels, since most times we will want pixels */
|
Issue #8900 and #9923: reimplementing GimpUnit as a proper class.
This fixes all our GObject Introspection issues with GimpUnit which was
both an enum and an int-derived type of user-defined units *completing*
the enum values. GIR clearly didn't like this!
Now GimpUnit is a proper class and units are unique objects, allowing to
compare them with an identity test (i.e. `unit == gimp_unit_pixel ()`
tells us if unit is the pixel unit or not), which makes it easy to use,
just like with int, yet adding also methods, making for nicer
introspected API.
As an aside, this also fixes #10738, by having all the built-in units
retrievable even if libgimpbase had not been properly initialized with
gimp_base_init().
I haven't checked in details how GIR works to introspect, but it looks
like it loads the library to inspect and runs functions, hence
triggering some CRITICALS because virtual methods (supposed to be
initialized with gimp_base_init() run by libgimp) are not set. This new
code won't trigger any critical because the vtable method are now not
necessary, at least for all built-in units.
Note that GimpUnit is still in libgimpbase. It could have been moved to
libgimp in order to avoid any virtual method table (since we need to
keep core and libgimp side's units in sync, PDB is required), but too
many libgimpwidgets widgets were already using GimpUnit. And technically
most of GimpUnit logic doesn't require PDB (only the creation/sync
part). This is one of the reasons why user-created GimpUnit list is
handled and stored differently from other types of objects.
Globally this simplifies the code a lot too and we don't need separate
implementations of various utils for core and libgimp, which means less
prone to errors.
2024-07-25 20:55:21 +02:00
|
|
|
gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (width), gimp_unit_pixel ());
|
2000-01-18 21:01:45 +00:00
|
|
|
|
1999-08-24 18:36:38 +00:00
|
|
|
/* set the resolution to the image resolution */
|
1999-11-01 12:36:23 +00:00
|
|
|
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (width), 0, xres, TRUE);
|
|
|
|
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (width), 1, yres, TRUE);
|
|
|
|
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (width), 2, xres, TRUE);
|
1999-08-24 18:36:38 +00:00
|
|
|
|
|
|
|
/* set the size (in pixels) that will be treated as 0% and 100% */
|
2019-07-10 12:43:27 +02:00
|
|
|
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (width), 0, 0.0, d_height);
|
|
|
|
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (width), 1, 0.0, d_width);
|
|
|
|
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (width), 2, 0.0, d_width);
|
1999-08-24 18:36:38 +00:00
|
|
|
|
|
|
|
/* set upper and lower limits (in pixels) */
|
2003-11-06 15:27:05 +00:00
|
|
|
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (width), 0, 0.0,
|
2019-07-10 12:43:27 +02:00
|
|
|
d_height);
|
2009-11-24 14:49:17 +01:00
|
|
|
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (width), 1, 0.0,
|
2019-07-10 12:43:27 +02:00
|
|
|
d_width);
|
2003-11-06 15:27:05 +00:00
|
|
|
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (width), 2, 0.0,
|
2019-07-10 12:43:27 +02:00
|
|
|
MAX (d_width, d_height));
|
2018-05-02 20:37:47 +02:00
|
|
|
gtk_grid_set_column_spacing (GTK_GRID (width), 6);
|
1999-12-02 00:20:43 +00:00
|
|
|
|
1999-08-24 18:36:38 +00:00
|
|
|
/* initialize the values */
|
2023-06-21 15:36:28 +02:00
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (width), 0, hwidth);
|
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (width), 1, vwidth);
|
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (width), 2, iwidth);
|
1999-08-24 18:36:38 +00:00
|
|
|
|
|
|
|
/* attach labels */
|
2009-11-24 14:58:28 +01:00
|
|
|
gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (width), _("Horizontal\nLines"),
|
2002-09-06 20:44:47 +00:00
|
|
|
0, 1, 0.0);
|
2009-11-24 14:58:28 +01:00
|
|
|
gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (width), _("Vertical\nLines"),
|
2002-09-06 20:44:47 +00:00
|
|
|
0, 2, 0.0);
|
|
|
|
gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (width), _("Intersection"),
|
|
|
|
0, 3, 0.0);
|
2004-05-18 17:06:06 +00:00
|
|
|
|
|
|
|
label = gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (width), _("Width:"),
|
|
|
|
1, 0, 0.0);
|
|
|
|
|
|
|
|
group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
|
|
|
gtk_size_group_add_widget (group, label);
|
|
|
|
g_object_unref (group);
|
1999-08-24 18:36:38 +00:00
|
|
|
|
|
|
|
/* put a chain_button under the size_entries */
|
1999-12-02 00:20:43 +00:00
|
|
|
chain_button = gimp_chain_button_new (GIMP_CHAIN_BOTTOM);
|
2023-06-21 15:36:28 +02:00
|
|
|
if (hwidth == vwidth)
|
1999-12-02 00:20:43 +00:00
|
|
|
gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chain_button), TRUE);
|
2018-05-02 20:37:47 +02:00
|
|
|
gtk_grid_attach (GTK_GRID (width), chain_button, 1, 2, 2, 1);
|
1999-12-02 00:20:43 +00:00
|
|
|
gtk_widget_show (chain_button);
|
2000-05-22 13:53:43 +00:00
|
|
|
|
2008-08-12 14:45:59 +00:00
|
|
|
/* connect to the 'value-changed' signal because we have to take care
|
2001-12-29 13:26:29 +00:00
|
|
|
* of keeping the entries in sync when the chainbutton is active
|
|
|
|
*/
|
2005-06-30 16:03:24 +00:00
|
|
|
g_signal_connect (width, "value-changed",
|
2001-12-29 13:26:29 +00:00
|
|
|
G_CALLBACK (entry_callback),
|
|
|
|
chain_button);
|
2005-06-30 16:03:24 +00:00
|
|
|
g_signal_connect_swapped (width, "value-changed",
|
2004-09-03 16:37:53 +00:00
|
|
|
G_CALLBACK (gimp_preview_invalidate),
|
|
|
|
preview);
|
1999-11-01 12:36:23 +00:00
|
|
|
|
1999-12-02 00:20:43 +00:00
|
|
|
/* The spacing entries */
|
2003-11-06 15:27:05 +00:00
|
|
|
space = gimp_size_entry_new (3, /* number_of_fields */
|
2003-12-10 22:50:26 +00:00
|
|
|
unit, /* unit */
|
|
|
|
"%a", /* unit_format */
|
|
|
|
TRUE, /* menu_show_pixels */
|
|
|
|
TRUE, /* menu_show_percent */
|
|
|
|
FALSE, /* show_refval */
|
|
|
|
SPIN_BUTTON_WIDTH, /* spinbutton_usize */
|
|
|
|
GIMP_SIZE_ENTRY_UPDATE_SIZE); /* update_policy */
|
2004-05-18 17:06:06 +00:00
|
|
|
|
2004-09-09 16:08:56 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), space, FALSE, FALSE, 0);
|
2004-05-18 17:06:06 +00:00
|
|
|
gtk_widget_show (space);
|
|
|
|
|
Issue #8900 and #9923: reimplementing GimpUnit as a proper class.
This fixes all our GObject Introspection issues with GimpUnit which was
both an enum and an int-derived type of user-defined units *completing*
the enum values. GIR clearly didn't like this!
Now GimpUnit is a proper class and units are unique objects, allowing to
compare them with an identity test (i.e. `unit == gimp_unit_pixel ()`
tells us if unit is the pixel unit or not), which makes it easy to use,
just like with int, yet adding also methods, making for nicer
introspected API.
As an aside, this also fixes #10738, by having all the built-in units
retrievable even if libgimpbase had not been properly initialized with
gimp_base_init().
I haven't checked in details how GIR works to introspect, but it looks
like it loads the library to inspect and runs functions, hence
triggering some CRITICALS because virtual methods (supposed to be
initialized with gimp_base_init() run by libgimp) are not set. This new
code won't trigger any critical because the vtable method are now not
necessary, at least for all built-in units.
Note that GimpUnit is still in libgimpbase. It could have been moved to
libgimp in order to avoid any virtual method table (since we need to
keep core and libgimp side's units in sync, PDB is required), but too
many libgimpwidgets widgets were already using GimpUnit. And technically
most of GimpUnit logic doesn't require PDB (only the creation/sync
part). This is one of the reasons why user-created GimpUnit list is
handled and stored differently from other types of objects.
Globally this simplifies the code a lot too and we don't need separate
implementations of various utils for core and libgimp, which means less
prone to errors.
2024-07-25 20:55:21 +02:00
|
|
|
gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (space), gimp_unit_pixel ());
|
2000-01-18 21:01:45 +00:00
|
|
|
|
1999-11-01 12:36:23 +00:00
|
|
|
/* set the resolution to the image resolution */
|
|
|
|
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (space), 0, xres, TRUE);
|
|
|
|
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (space), 1, yres, TRUE);
|
|
|
|
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (space), 2, xres, TRUE);
|
|
|
|
|
|
|
|
/* set the size (in pixels) that will be treated as 0% and 100% */
|
2019-07-10 12:43:27 +02:00
|
|
|
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (space), 0, 0.0, d_height);
|
|
|
|
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (space), 1, 0.0, d_width);
|
|
|
|
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (space), 2, 0.0, d_width);
|
1999-11-01 12:36:23 +00:00
|
|
|
|
|
|
|
/* set upper and lower limits (in pixels) */
|
2002-09-06 20:44:47 +00:00
|
|
|
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (space), 0, 1.0,
|
2019-07-10 12:43:27 +02:00
|
|
|
d_height);
|
2009-11-24 14:49:17 +01:00
|
|
|
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (space), 1, 1.0,
|
2019-07-10 12:43:27 +02:00
|
|
|
d_width);
|
2003-11-06 15:27:05 +00:00
|
|
|
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (space), 2, 0.0,
|
2019-07-10 12:43:27 +02:00
|
|
|
MAX (d_width, d_height));
|
2018-05-02 20:37:47 +02:00
|
|
|
gtk_grid_set_column_spacing (GTK_GRID (space), 6);
|
1999-12-02 00:20:43 +00:00
|
|
|
|
1999-11-01 12:36:23 +00:00
|
|
|
/* initialize the values */
|
2023-06-21 15:36:28 +02:00
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (space), 0, hspace);
|
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (space), 1, vspace);
|
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (space), 2, ispace);
|
2002-09-06 20:44:47 +00:00
|
|
|
|
1999-11-01 12:36:23 +00:00
|
|
|
/* attach labels */
|
2004-05-18 17:06:06 +00:00
|
|
|
label = gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (space), _("Spacing:"),
|
|
|
|
1, 0, 0.0);
|
|
|
|
gtk_size_group_add_widget (group, label);
|
1999-11-01 12:36:23 +00:00
|
|
|
|
1999-12-02 00:20:43 +00:00
|
|
|
/* put a chain_button under the spacing_entries */
|
|
|
|
chain_button = gimp_chain_button_new (GIMP_CHAIN_BOTTOM);
|
2023-06-21 15:36:28 +02:00
|
|
|
if (hspace == vspace)
|
1999-12-02 00:20:43 +00:00
|
|
|
gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chain_button), TRUE);
|
2018-05-02 20:37:47 +02:00
|
|
|
gtk_grid_attach (GTK_GRID (space), chain_button, 1, 2, 2, 1);
|
1999-12-02 00:20:43 +00:00
|
|
|
gtk_widget_show (chain_button);
|
2000-05-22 13:53:43 +00:00
|
|
|
|
2008-08-12 14:45:59 +00:00
|
|
|
/* connect to the 'value-changed' and "unit-changed" signals because
|
2001-12-29 13:26:29 +00:00
|
|
|
* we have to take care of keeping the entries in sync when the
|
|
|
|
* chainbutton is active
|
|
|
|
*/
|
2005-06-30 16:03:24 +00:00
|
|
|
g_signal_connect (space, "value-changed",
|
2001-12-29 13:26:29 +00:00
|
|
|
G_CALLBACK (entry_callback),
|
|
|
|
chain_button);
|
2008-08-12 14:45:59 +00:00
|
|
|
g_signal_connect (space, "unit-changed",
|
2001-12-29 13:26:29 +00:00
|
|
|
G_CALLBACK (entry_callback),
|
|
|
|
chain_button);
|
2005-06-30 16:03:24 +00:00
|
|
|
g_signal_connect_swapped (space, "value-changed",
|
2004-09-03 16:37:53 +00:00
|
|
|
G_CALLBACK (gimp_preview_invalidate),
|
|
|
|
preview);
|
1999-08-24 18:36:38 +00:00
|
|
|
|
1999-11-01 12:36:23 +00:00
|
|
|
/* The offset entries */
|
2003-11-06 15:27:05 +00:00
|
|
|
offset = gimp_size_entry_new (3, /* number_of_fields */
|
2003-12-10 22:50:26 +00:00
|
|
|
unit, /* unit */
|
|
|
|
"%a", /* unit_format */
|
|
|
|
TRUE, /* menu_show_pixels */
|
|
|
|
TRUE, /* menu_show_percent */
|
|
|
|
FALSE, /* show_refval */
|
|
|
|
SPIN_BUTTON_WIDTH, /* spinbutton_usize */
|
|
|
|
GIMP_SIZE_ENTRY_UPDATE_SIZE); /* update_policy */
|
2004-05-18 17:06:06 +00:00
|
|
|
|
2004-09-09 16:08:56 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), offset, FALSE, FALSE, 0);
|
2004-05-18 17:06:06 +00:00
|
|
|
gtk_widget_show (offset);
|
|
|
|
|
Issue #8900 and #9923: reimplementing GimpUnit as a proper class.
This fixes all our GObject Introspection issues with GimpUnit which was
both an enum and an int-derived type of user-defined units *completing*
the enum values. GIR clearly didn't like this!
Now GimpUnit is a proper class and units are unique objects, allowing to
compare them with an identity test (i.e. `unit == gimp_unit_pixel ()`
tells us if unit is the pixel unit or not), which makes it easy to use,
just like with int, yet adding also methods, making for nicer
introspected API.
As an aside, this also fixes #10738, by having all the built-in units
retrievable even if libgimpbase had not been properly initialized with
gimp_base_init().
I haven't checked in details how GIR works to introspect, but it looks
like it loads the library to inspect and runs functions, hence
triggering some CRITICALS because virtual methods (supposed to be
initialized with gimp_base_init() run by libgimp) are not set. This new
code won't trigger any critical because the vtable method are now not
necessary, at least for all built-in units.
Note that GimpUnit is still in libgimpbase. It could have been moved to
libgimp in order to avoid any virtual method table (since we need to
keep core and libgimp side's units in sync, PDB is required), but too
many libgimpwidgets widgets were already using GimpUnit. And technically
most of GimpUnit logic doesn't require PDB (only the creation/sync
part). This is one of the reasons why user-created GimpUnit list is
handled and stored differently from other types of objects.
Globally this simplifies the code a lot too and we don't need separate
implementations of various utils for core and libgimp, which means less
prone to errors.
2024-07-25 20:55:21 +02:00
|
|
|
gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (offset), gimp_unit_pixel ());
|
2000-01-18 21:01:45 +00:00
|
|
|
|
1999-11-01 12:36:23 +00:00
|
|
|
/* set the resolution to the image resolution */
|
1999-08-24 18:36:38 +00:00
|
|
|
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (offset), 0, xres, TRUE);
|
|
|
|
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (offset), 1, yres, TRUE);
|
1999-11-01 12:36:23 +00:00
|
|
|
gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (offset), 2, xres, TRUE);
|
|
|
|
|
|
|
|
/* set the size (in pixels) that will be treated as 0% and 100% */
|
2019-07-10 12:43:27 +02:00
|
|
|
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (offset), 0, 0.0, d_height);
|
|
|
|
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (offset), 1, 0.0, d_width);
|
|
|
|
gimp_size_entry_set_size (GIMP_SIZE_ENTRY (offset), 2, 0.0, d_width);
|
1999-11-01 12:36:23 +00:00
|
|
|
|
|
|
|
/* set upper and lower limits (in pixels) */
|
2003-11-06 15:27:05 +00:00
|
|
|
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (offset), 0, 0.0,
|
2019-07-10 12:43:27 +02:00
|
|
|
d_height);
|
2009-11-24 14:49:17 +01:00
|
|
|
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (offset), 1, 0.0,
|
2019-07-10 12:43:27 +02:00
|
|
|
d_width);
|
2003-11-06 15:27:05 +00:00
|
|
|
gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (offset), 2, 0.0,
|
2019-07-10 12:43:27 +02:00
|
|
|
MAX (d_width, d_height));
|
2018-05-02 20:37:47 +02:00
|
|
|
gtk_grid_set_column_spacing (GTK_GRID (offset), 6);
|
1999-12-02 00:20:43 +00:00
|
|
|
|
1999-11-01 12:36:23 +00:00
|
|
|
/* initialize the values */
|
2023-06-21 15:36:28 +02:00
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (offset), 0, hoffset);
|
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (offset), 1, voffset);
|
|
|
|
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (offset), 2, ioffset);
|
1999-11-01 12:36:23 +00:00
|
|
|
|
|
|
|
/* attach labels */
|
2004-05-18 17:06:06 +00:00
|
|
|
label = gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (offset), _("Offset:"),
|
|
|
|
1, 0, 0.0);
|
|
|
|
gtk_size_group_add_widget (group, label);
|
1999-11-01 12:36:23 +00:00
|
|
|
|
1999-12-02 00:20:43 +00:00
|
|
|
/* put a chain_button under the offset_entries */
|
|
|
|
chain_button = gimp_chain_button_new (GIMP_CHAIN_BOTTOM);
|
2023-06-21 15:36:28 +02:00
|
|
|
if (hoffset == voffset)
|
1999-12-02 00:20:43 +00:00
|
|
|
gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chain_button), TRUE);
|
2018-05-09 01:00:11 +02:00
|
|
|
gtk_grid_attach (GTK_GRID (offset), chain_button, 1, 2, 2, 1);
|
1999-12-02 00:20:43 +00:00
|
|
|
gtk_widget_show (chain_button);
|
|
|
|
|
2008-08-12 14:45:59 +00:00
|
|
|
/* connect to the 'value-changed' and "unit-changed" signals because
|
2001-12-29 13:26:29 +00:00
|
|
|
* we have to take care of keeping the entries in sync when the
|
|
|
|
* chainbutton is active
|
|
|
|
*/
|
2005-06-30 16:03:24 +00:00
|
|
|
g_signal_connect (offset, "value-changed",
|
2001-12-29 13:26:29 +00:00
|
|
|
G_CALLBACK (entry_callback),
|
|
|
|
chain_button);
|
2008-08-12 14:45:59 +00:00
|
|
|
g_signal_connect (offset, "unit-changed",
|
2001-12-29 13:26:29 +00:00
|
|
|
G_CALLBACK (entry_callback),
|
|
|
|
chain_button);
|
2005-06-30 16:03:24 +00:00
|
|
|
g_signal_connect_swapped (offset, "value-changed",
|
2004-09-03 16:37:53 +00:00
|
|
|
G_CALLBACK (gimp_preview_invalidate),
|
|
|
|
preview);
|
1999-12-02 00:20:43 +00:00
|
|
|
|
|
|
|
/* put a chain_button under the color_buttons */
|
2023-06-21 15:36:28 +02:00
|
|
|
grid->color_chain = gimp_chain_button_new (GIMP_CHAIN_BOTTOM);
|
2024-02-15 03:39:52 +00:00
|
|
|
if (gimp_color_is_perceptually_identical (hcolor, vcolor))
|
2023-06-21 15:36:28 +02:00
|
|
|
gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (grid->color_chain), TRUE);
|
|
|
|
gtk_grid_attach (GTK_GRID (offset), grid->color_chain, 1, 4, 2, 1);
|
|
|
|
gtk_widget_show (grid->color_chain);
|
1999-12-02 00:20:43 +00:00
|
|
|
|
2000-02-22 21:25:18 +00:00
|
|
|
/* attach color selectors */
|
2023-06-21 15:36:28 +02:00
|
|
|
grid->hcolor_button = gimp_color_button_new (_("Horizontal Color"),
|
|
|
|
COLOR_BUTTON_WIDTH, 16,
|
2024-02-15 03:39:52 +00:00
|
|
|
hcolor,
|
2023-06-21 15:36:28 +02:00
|
|
|
GIMP_COLOR_AREA_SMALL_CHECKS);
|
|
|
|
gimp_color_button_set_update (GIMP_COLOR_BUTTON (grid->hcolor_button), TRUE);
|
|
|
|
gtk_grid_attach (GTK_GRID (offset), grid->hcolor_button, 1, 3, 1, 1);
|
|
|
|
gtk_widget_show (grid->hcolor_button);
|
|
|
|
|
|
|
|
color_config = gimp_get_color_configuration ();
|
|
|
|
gimp_color_button_set_color_config (GIMP_COLOR_BUTTON (grid->hcolor_button),
|
|
|
|
color_config);
|
|
|
|
|
|
|
|
g_signal_connect (grid->hcolor_button, "color-changed",
|
2003-11-06 15:27:05 +00:00
|
|
|
G_CALLBACK (color_callback),
|
2023-06-21 15:36:28 +02:00
|
|
|
grid);
|
|
|
|
g_signal_connect_swapped (grid->hcolor_button, "color-changed",
|
2004-09-03 16:37:53 +00:00
|
|
|
G_CALLBACK (gimp_preview_invalidate),
|
|
|
|
preview);
|
2001-12-29 13:26:29 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
grid->vcolor_button = gimp_color_button_new (_("Vertical Color"),
|
|
|
|
COLOR_BUTTON_WIDTH, 16,
|
2024-02-15 03:39:52 +00:00
|
|
|
vcolor,
|
2023-06-21 15:36:28 +02:00
|
|
|
GIMP_COLOR_AREA_SMALL_CHECKS);
|
|
|
|
gimp_color_button_set_update (GIMP_COLOR_BUTTON (grid->vcolor_button), TRUE);
|
|
|
|
gtk_grid_attach (GTK_GRID (offset), grid->vcolor_button, 2, 3, 1, 1);
|
|
|
|
gtk_widget_show (grid->vcolor_button);
|
2001-12-29 13:26:29 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
gimp_color_button_set_color_config (GIMP_COLOR_BUTTON (grid->vcolor_button),
|
|
|
|
color_config);
|
2017-12-31 13:57:41 +01:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
g_signal_connect (grid->vcolor_button, "color-changed",
|
2003-11-06 15:27:05 +00:00
|
|
|
G_CALLBACK (color_callback),
|
2023-06-21 15:36:28 +02:00
|
|
|
grid);
|
|
|
|
g_signal_connect_swapped (grid->vcolor_button, "color-changed",
|
2004-09-03 16:37:53 +00:00
|
|
|
G_CALLBACK (gimp_preview_invalidate),
|
|
|
|
preview);
|
2001-12-29 13:26:29 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
grid->icolor_button = gimp_color_button_new (_("Intersection Color"),
|
|
|
|
COLOR_BUTTON_WIDTH, 16,
|
2024-02-15 03:39:52 +00:00
|
|
|
icolor,
|
2023-06-21 15:36:28 +02:00
|
|
|
GIMP_COLOR_AREA_SMALL_CHECKS);
|
|
|
|
gimp_color_button_set_update (GIMP_COLOR_BUTTON (grid->icolor_button), TRUE);
|
|
|
|
gtk_grid_attach (GTK_GRID (offset), grid->icolor_button, 3, 3, 1, 1);
|
|
|
|
gtk_widget_show (grid->icolor_button);
|
2001-12-29 13:26:29 +00:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
gimp_color_button_set_color_config (GIMP_COLOR_BUTTON (grid->icolor_button),
|
|
|
|
color_config);
|
|
|
|
g_object_unref (color_config);
|
2024-02-15 03:39:52 +00:00
|
|
|
g_object_unref (hcolor);
|
|
|
|
g_object_unref (vcolor);
|
|
|
|
g_object_unref (icolor);
|
2017-12-31 13:57:41 +01:00
|
|
|
|
2023-06-21 15:36:28 +02:00
|
|
|
g_signal_connect (grid->icolor_button, "color-changed",
|
2023-11-24 15:35:50 +01:00
|
|
|
G_CALLBACK (color_callback),
|
|
|
|
grid);
|
2023-06-21 15:36:28 +02:00
|
|
|
g_signal_connect_swapped (grid->icolor_button, "color-changed",
|
2004-09-03 16:37:53 +00:00
|
|
|
G_CALLBACK (gimp_preview_invalidate),
|
|
|
|
preview);
|
2001-12-29 13:26:29 +00:00
|
|
|
|
1998-01-30 00:31:16 +00:00
|
|
|
gtk_widget_show (dlg);
|
1997-11-24 22:05:25 +00:00
|
|
|
|
2004-09-03 16:37:53 +00:00
|
|
|
g_object_set_data (G_OBJECT (dlg), "width", width);
|
|
|
|
g_object_set_data (G_OBJECT (dlg), "space", space);
|
|
|
|
g_object_set_data (G_OBJECT (dlg), "offset", offset);
|
2004-08-07 00:04:16 +00:00
|
|
|
|
2003-11-11 18:11:56 +00:00
|
|
|
run = (gimp_dialog_run (GIMP_DIALOG (dlg)) == GTK_RESPONSE_OK);
|
1998-01-30 00:31:16 +00:00
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
if (run)
|
2023-06-21 15:36:28 +02:00
|
|
|
update_values (grid);
|
1998-01-30 00:31:16 +00:00
|
|
|
|
2003-11-06 15:27:05 +00:00
|
|
|
gtk_widget_destroy (dlg);
|
|
|
|
|
|
|
|
return run;
|
1997-11-24 22:05:25 +00:00
|
|
|
}
|