From 9ac0e40758e1cdebb146984c2f531f30b3d5089b Mon Sep 17 00:00:00 2001 From: Adrian Likins Date: Tue, 9 Dec 1997 05:57:33 +0000 Subject: [PATCH] added glasstile, colorify, papertile, and illusion plugins updated despeckle, and math map --- ChangeLog | 7 + plug-ins/Makefile.am | 4 + plug-ins/colorify/Makefile.am | 42 ++ plug-ins/colorify/colorify.c | 473 ++++++++++++++++++++ plug-ins/common/colorify.c | 473 ++++++++++++++++++++ plug-ins/common/despeckle.c | 45 +- plug-ins/common/glasstile.c | 427 ++++++++++++++++++ plug-ins/common/illusion.c | 368 +++++++++++++++ plug-ins/common/papertile.c | 469 +++++++++++++++++++ plug-ins/despeckle/despeckle.c | 45 +- plug-ins/gfig/gfig-examples/spirals & stars | 55 +++ plug-ins/glasstile/Makefile.am | 42 ++ plug-ins/glasstile/glasstile.c | 427 ++++++++++++++++++ plug-ins/illusion/Makefile.am | 42 ++ plug-ins/illusion/illusion.c | 368 +++++++++++++++ plug-ins/mathmap/builtins.c | 169 +++++-- plug-ins/mathmap/builtins.h | 41 +- plug-ins/mathmap/exprtree.c | 137 +++++- plug-ins/mathmap/exprtree.h | 72 ++- plug-ins/mathmap/mathmap.c | 58 ++- plug-ins/mathmap/parser.y | 21 +- plug-ins/mathmap/postfix.c | 309 +++++++++++-- plug-ins/mathmap/postfix.h | 5 +- plug-ins/mathmap/scanner.fl | 22 +- plug-ins/papertile/Makefile.am | 42 ++ plug-ins/papertile/papertile.c | 469 +++++++++++++++++++ 26 files changed, 4462 insertions(+), 170 deletions(-) create mode 100644 plug-ins/colorify/Makefile.am create mode 100644 plug-ins/colorify/colorify.c create mode 100644 plug-ins/common/colorify.c create mode 100644 plug-ins/common/glasstile.c create mode 100644 plug-ins/common/illusion.c create mode 100644 plug-ins/common/papertile.c create mode 100644 plug-ins/gfig/gfig-examples/spirals & stars create mode 100644 plug-ins/glasstile/Makefile.am create mode 100644 plug-ins/glasstile/glasstile.c create mode 100644 plug-ins/illusion/Makefile.am create mode 100644 plug-ins/illusion/illusion.c create mode 100644 plug-ins/papertile/Makefile.am create mode 100644 plug-ins/papertile/papertile.c diff --git a/ChangeLog b/ChangeLog index 966b6876a0..e25fab3269 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Tue Dec 9 00:52:15 EST 1997 Adrian Likins + + * added illusion, papertile, colorify, and glasstile + plugins + + * updated despeckle, and math map + Mon Dec 8 21:59:03 PST 1997 Manish Singh * updated CML_explorer diff --git a/plug-ins/Makefile.am b/plug-ins/Makefile.am index 29d3b83d7c..d73fe5a2b3 100644 --- a/plug-ins/Makefile.am +++ b/plug-ins/Makefile.am @@ -42,6 +42,7 @@ SUBDIRS = \ c_astretch \ CEL \ checkerboard \ + colorify \ compose \ convmatrix \ coordmap \ @@ -68,6 +69,7 @@ SUBDIRS = \ gfli \ gicon \ gif \ + glasstile \ gqbist \ gradmap \ grid \ @@ -77,6 +79,7 @@ SUBDIRS = \ hot \ hrz \ ifscompose \ + illusion \ iwarp \ laplace \ lic \ @@ -91,6 +94,7 @@ SUBDIRS = \ normalize \ nova \ oilify \ + papertile \ pat \ pcx \ pix \ diff --git a/plug-ins/colorify/Makefile.am b/plug-ins/colorify/Makefile.am new file mode 100644 index 0000000000..f5a6d4cdab --- /dev/null +++ b/plug-ins/colorify/Makefile.am @@ -0,0 +1,42 @@ +## Process this file with automake to produce Makefile.in + +pluginlibdir = $(gimpplugindir)/plug-ins + +pluginlib_PROGRAMS = colorify + +colorify_SOURCES = \ + colorify.c + +INCLUDES = \ + $(X_CFLAGS) \ + -I$(top_srcdir) \ + -I$(includedir) + +LDADD = \ + $(top_builddir)/libgimp/libgimpui.la \ + $(top_builddir)/libgimp/libgimp.la \ + $(X_LIBS) \ + \ + -lc + +DEPS = \ + $(top_builddir)/libgimp/libgimpui.la \ + $(top_builddir)/libgimp/libgimp.la + +colorify_DEPENDENCIES = $(DEPS) + +.PHONY: files + +files: + @files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \ + echo $$p; \ + done + @for subdir in $(SUBDIRS); do \ + files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \ + for file in $$files; do \ + echo $$subdir/$$file; \ + done; \ + done + + + diff --git a/plug-ins/colorify/colorify.c b/plug-ins/colorify/colorify.c new file mode 100644 index 0000000000..bb7624dcbf --- /dev/null +++ b/plug-ins/colorify/colorify.c @@ -0,0 +1,473 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * Colorify. Changes the pixel's luminosity to a specified color + * Copyright (C) 1997 Francisco Bustamante + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Changes: + + 1.1 + -Corrected small bug when calling color selection dialog + -Added LUTs to speed things a little bit up + + 1.0 + -First release */ + +#include +#include +#include +#include "gtk/gtk.h" +#include "libgimp/gimp.h" + +#define PLUG_IN_NAME "Colorify" +#define PLUG_IN_VERSION "1.1" + +static void query (void); +static void run (char *name, + int nparams, + GParam *param, + int *nreturn_vals, + GParam **return_vals); + +typedef struct { + guchar color[3]; +} ColorifyVals; + +typedef struct { + gint run; +} ColorifyInterface; + +typedef struct { + guchar red; + guchar green; + guchar blue; + GtkWidget *preview; + gint button_num; +} ButtonInformation; + +static ColorifyInterface cint = +{ + FALSE +}; + +static ColorifyVals cvals = +{ + {255, 255, 255} +}; + +static ButtonInformation button_info[] = +{ + {255, 0, 0, NULL, 0}, + {255, 255, 0, NULL, 0}, + {0, 255, 0, NULL, 0}, + {0, 255, 255, NULL, 0}, + {0, 0, 255, NULL, 0}, + {255, 0, 255, NULL, 0}, + {255, 255, 255, NULL, 0}, +}; + +GPlugInInfo PLUG_IN_INFO = +{ + NULL, + NULL, + query, + run, +}; + +gint lum_red_lookup[256], lum_green_lookup[256], lum_blue_lookup[256]; +gint final_red_lookup[256], final_green_lookup[256], final_blue_lookup[256]; + +MAIN () + +static int colorify_dialog (guchar red, guchar green, guchar blue); +static void colorify (GDrawable *drawable); +static void set_preview_color (GtkWidget *preview, guchar red, guchar green, guchar blue); + +static void +query () +{ + static GParamDef args[] = + { + { PARAM_INT32, "run_mode", "Interactive, non-interactive" }, + { PARAM_IMAGE, "image", "Input image" }, + { PARAM_DRAWABLE, "drawable", "Input drawable" }, + { PARAM_COLOR, "color", "Color to apply"}, + }; + + static GParamDef *return_vals = NULL; + static int nargs = sizeof(args) / sizeof(args[0]), + nreturn_vals = 0; + + gimp_install_procedure ("Colorify", + "Similar to the \"Color\" mode for layers.", + "Makes an average of the RGB channels and uses it to set the color", + "Francisco Bustamante", "Francisco Bustamante", + "0.0.1", "/Filters/Image/Colorify", "RGB", + PROC_PLUG_IN, + nargs, nreturn_vals, + args, return_vals); +} + +gint sel_x1, sel_x2, sel_y1, sel_y2, sel_width, sel_height; +GtkWidget *preview; +GtkWidget *c_dialog; + + +static void +run (char *name, + int nparams, + GParam *param, + int *nreturn_vals, + GParam **return_vals) +{ + GRunModeType run_mode; + GStatusType status; + static GParam values[1]; + GDrawable *drawable; + + status = STATUS_SUCCESS; + run_mode = param[0].data.d_int32; + + values[0].type = PARAM_STATUS; + values[0].data.d_status = status; + + *nreturn_vals = 1; + *return_vals = values; + + drawable = gimp_drawable_get (param[2].data.d_drawable); + + gimp_drawable_mask_bounds (drawable->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2); + + sel_width = sel_x2 - sel_x1; + sel_height = sel_y2 - sel_y1; + + switch (run_mode) { + case RUN_INTERACTIVE : + gimp_get_data(PLUG_IN_NAME, &cvals); + if (!colorify_dialog (cvals.color[0], cvals.color[1], cvals.color[2])) + return; + break; + + case RUN_NONINTERACTIVE : + if (nparams != 4) + status = STATUS_CALLING_ERROR; + if (status == STATUS_SUCCESS) { + cvals.color[0] = param[3].data.d_color.red; + cvals.color[1] = param[3].data.d_color.green; + cvals.color[2] = param[3].data.d_color.blue; + } + break; + + case RUN_WITH_LAST_VALS : + /* Possibly retrieve data */ + gimp_get_data (PLUG_IN_NAME, &cvals); + break; + + default : + break; + } + + if (status == STATUS_SUCCESS) { + gimp_progress_init("Colorifying..."); + + colorify (drawable); + + if (run_mode == RUN_INTERACTIVE) + gimp_set_data (PLUG_IN_NAME, &cvals, sizeof (ColorifyVals)); + + if (run_mode != RUN_NONINTERACTIVE) { + gimp_displays_flush (); + } + } + + values[0].data.d_status = status; +} + +static void colorify_row (guchar *row, + gint width); +static void close_callback (GtkWidget *widget, + gpointer data); +static void colorify_ok_callback (GtkWidget *widget, + gpointer data); +static void custom_color_callback (GtkWidget *widget, + gpointer data); +static void predefined_color_callback (GtkWidget *widget, + gpointer data); +static void color_changed (GtkWidget *widget, + gpointer data); + +static void +colorify (GDrawable *drawable) +{ + GPixelRgn source_region, dest_region; + guchar *row; + gint y = 0; + gint progress = 0; + gint i = 0; + + for (i = 0; i < 256; i ++) { + lum_red_lookup[i] = i * 0.30; + lum_green_lookup[i] = i * 0.59; + lum_blue_lookup[i] = i * 0.11; + final_red_lookup[i] = i * cvals.color[0] / 255; + final_green_lookup[i] = i * cvals.color[1] / 255; + final_blue_lookup[i] = i * cvals.color[2] / 255; + } + + row = g_malloc (sel_width * 3 * sizeof(guchar)); + + gimp_pixel_rgn_init (&source_region, drawable, sel_x1, sel_y1, sel_width, sel_height, FALSE, FALSE); + gimp_pixel_rgn_init (&dest_region, drawable, sel_x1, sel_y1, sel_width, sel_height, TRUE, TRUE); + + for (y = sel_y1; y < sel_y2; y++) { + gimp_pixel_rgn_get_row (&source_region, row, sel_x1, y, sel_width); + + colorify_row (row, sel_width); + + gimp_pixel_rgn_set_row (&dest_region, row, sel_x1, y, sel_width); + gimp_progress_update ((double) ++progress / sel_height); + + } + + g_free (row); + + gimp_drawable_flush (drawable); + gimp_drawable_merge_shadow (drawable->id, TRUE); + gimp_drawable_update (drawable->id, sel_x1, sel_y1, sel_width, sel_height); +} + +static void +colorify_row (guchar *row, + gint width) +{ + gint cur_x; + gint lum; /* luminosity */ + guchar *current = row; + + for (cur_x = 0; cur_x < width; cur_x++) { + lum = lum_red_lookup[current[0]] + lum_green_lookup[current[1]] + lum_blue_lookup[current[2]]; + + current[0] = final_red_lookup[lum]; + current[1] = final_green_lookup[lum]; + current[2] = final_blue_lookup[lum]; + + current += 3; + } +} + +static int +colorify_dialog (guchar red, + guchar green, + guchar blue) +{ + GtkWidget *dialog; + GtkWidget *label; + GtkWidget *button; + GtkWidget *frame; + GtkWidget *table; + gchar **argv; + gint argc; + gint i; + GSList *group = NULL; + + argc = 1; + argv = g_new (gchar *, 1); + argv[0] = g_strdup ("colorify"); + + gtk_init (&argc, &argv); + gtk_rc_parse (gimp_gtkrc()); + + dialog = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (dialog), "Colorify"); + gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE); + gtk_signal_connect (GTK_OBJECT (dialog), "destroy", + (GtkSignalFunc) close_callback, + NULL); + + button = gtk_button_new_with_label ("Ok"); + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + gtk_signal_connect (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) colorify_ok_callback, + dialog); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, TRUE, TRUE, 0); + gtk_widget_grab_default (button); + gtk_widget_show (button); + + button = gtk_button_new_with_label ("Cancel"); + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + gtk_signal_connect_object (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) gtk_widget_destroy, + GTK_OBJECT (dialog)); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, TRUE, TRUE, 0); + gtk_widget_show (button); + + frame = gtk_frame_new ("Color"); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); + gtk_container_border_width (GTK_CONTAINER (frame), 10); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, TRUE, TRUE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (2, 7, TRUE); + gtk_container_border_width (GTK_CONTAINER (table), 10); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + gtk_widget_show (table); + + label = gtk_label_new ("Custom Color: "); + gtk_table_attach (GTK_TABLE (table), label, 4, 6, 0, 1, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (label); + + button = gtk_radio_button_new (group); + gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); + gtk_widget_set_usize (button, 35, 35); + gtk_signal_connect (GTK_OBJECT (button), "button_press_event", + (GtkSignalFunc) custom_color_callback, + NULL); + gtk_table_attach (GTK_TABLE (table), button, 6, 7, 0, 1, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (button); + + preview = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_preview_size (GTK_PREVIEW (preview), 30, 30); + set_preview_color (preview, cvals.color[0], cvals.color[1], cvals.color[2]); + gtk_container_add (GTK_CONTAINER (button), preview); + gtk_widget_show (preview); + + for(i = 0; i < 7; i++) { + group = gtk_radio_button_group (GTK_RADIO_BUTTON (button)); + button = gtk_radio_button_new (group); + gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); + button_info[i].preview = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_preview_size (GTK_PREVIEW (button_info[i].preview), + 30, 30); + gtk_container_add (GTK_CONTAINER (button), button_info[i].preview); + set_preview_color (button_info[i].preview, + button_info[i].red, + button_info[i].green, + button_info[i].blue); + button_info[i].button_num = i; + gtk_signal_connect (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) predefined_color_callback, + &button_info[i].button_num); + gtk_widget_show (button_info[i].preview); + + gtk_table_attach (GTK_TABLE (table), button, i, i + 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (button); + } + + gtk_widget_show (dialog); + + gtk_main(); + return cint.run; +} + +static void +close_callback (GtkWidget *widget, + gpointer data) +{ + gtk_main_quit(); +} + +static void +colorify_ok_callback (GtkWidget *widget, + gpointer data) +{ + gtk_widget_destroy (GTK_WIDGET (data)); + cint.run = TRUE; +} + +static void +set_preview_color (GtkWidget *preview, + guchar red, + guchar green, + guchar blue) +{ + gint i; + guchar buf[3 * 30]; + + for (i = 0; i < 30; i ++) { + buf [3 * i] = red; + buf [3 * i + 1] = green; + buf [3 * i + 2] = blue; + } + + for (i = 0; i < 30; i ++) + gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 30); + + gtk_widget_draw (preview, NULL); +} + +static void +custom_color_callback (GtkWidget *widget, + gpointer data) +{ + GtkColorSelectionDialog *csd; + gdouble colour[3]; + + c_dialog = gtk_color_selection_dialog_new ("Colorify Custom Color"); + csd = GTK_COLOR_SELECTION_DIALOG (c_dialog); + gtk_color_selection_set_update_policy (GTK_COLOR_SELECTION(csd->colorsel), + GTK_UPDATE_DISCONTINUOUS); + + gtk_widget_destroy (csd->help_button); + gtk_widget_destroy (csd->cancel_button); + + gtk_signal_connect (GTK_OBJECT (csd->ok_button), "clicked", + (GtkSignalFunc) color_changed, + NULL); + + colour[0] = cvals.color[0] / 255.0; + colour[1] = cvals.color[1] / 255.0; + colour[2] = cvals.color[2] / 255.0; + + gtk_color_selection_set_color (GTK_COLOR_SELECTION (csd->colorsel), + colour); + gtk_window_position (GTK_WINDOW(c_dialog), GTK_WIN_POS_MOUSE); + gtk_widget_show (c_dialog); +} + +static void +predefined_color_callback (GtkWidget *widget, + gpointer data) +{ + gint *num; + + num = (gint *) data; + + cvals.color[0] = button_info[*num].red; + cvals.color[1] = button_info[*num].green; + cvals.color[2] = button_info[*num].blue; +} + +static void +color_changed (GtkWidget *widget, + gpointer data) +{ + gdouble colour[3]; + + gtk_color_selection_get_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (c_dialog)->colorsel), + colour); + + cvals.color[0] = (guchar) (colour[0] * 255.0); + cvals.color[1] = (guchar) (colour[1] * 255.0); + cvals.color[2] = (guchar) (colour[2] * 255.0); + + set_preview_color (preview, cvals.color[0], cvals.color[1], cvals.color[2]); + gtk_widget_destroy (c_dialog); +} + diff --git a/plug-ins/common/colorify.c b/plug-ins/common/colorify.c new file mode 100644 index 0000000000..bb7624dcbf --- /dev/null +++ b/plug-ins/common/colorify.c @@ -0,0 +1,473 @@ +/* The GIMP -- an image manipulation program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * Colorify. Changes the pixel's luminosity to a specified color + * Copyright (C) 1997 Francisco Bustamante + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Changes: + + 1.1 + -Corrected small bug when calling color selection dialog + -Added LUTs to speed things a little bit up + + 1.0 + -First release */ + +#include +#include +#include +#include "gtk/gtk.h" +#include "libgimp/gimp.h" + +#define PLUG_IN_NAME "Colorify" +#define PLUG_IN_VERSION "1.1" + +static void query (void); +static void run (char *name, + int nparams, + GParam *param, + int *nreturn_vals, + GParam **return_vals); + +typedef struct { + guchar color[3]; +} ColorifyVals; + +typedef struct { + gint run; +} ColorifyInterface; + +typedef struct { + guchar red; + guchar green; + guchar blue; + GtkWidget *preview; + gint button_num; +} ButtonInformation; + +static ColorifyInterface cint = +{ + FALSE +}; + +static ColorifyVals cvals = +{ + {255, 255, 255} +}; + +static ButtonInformation button_info[] = +{ + {255, 0, 0, NULL, 0}, + {255, 255, 0, NULL, 0}, + {0, 255, 0, NULL, 0}, + {0, 255, 255, NULL, 0}, + {0, 0, 255, NULL, 0}, + {255, 0, 255, NULL, 0}, + {255, 255, 255, NULL, 0}, +}; + +GPlugInInfo PLUG_IN_INFO = +{ + NULL, + NULL, + query, + run, +}; + +gint lum_red_lookup[256], lum_green_lookup[256], lum_blue_lookup[256]; +gint final_red_lookup[256], final_green_lookup[256], final_blue_lookup[256]; + +MAIN () + +static int colorify_dialog (guchar red, guchar green, guchar blue); +static void colorify (GDrawable *drawable); +static void set_preview_color (GtkWidget *preview, guchar red, guchar green, guchar blue); + +static void +query () +{ + static GParamDef args[] = + { + { PARAM_INT32, "run_mode", "Interactive, non-interactive" }, + { PARAM_IMAGE, "image", "Input image" }, + { PARAM_DRAWABLE, "drawable", "Input drawable" }, + { PARAM_COLOR, "color", "Color to apply"}, + }; + + static GParamDef *return_vals = NULL; + static int nargs = sizeof(args) / sizeof(args[0]), + nreturn_vals = 0; + + gimp_install_procedure ("Colorify", + "Similar to the \"Color\" mode for layers.", + "Makes an average of the RGB channels and uses it to set the color", + "Francisco Bustamante", "Francisco Bustamante", + "0.0.1", "/Filters/Image/Colorify", "RGB", + PROC_PLUG_IN, + nargs, nreturn_vals, + args, return_vals); +} + +gint sel_x1, sel_x2, sel_y1, sel_y2, sel_width, sel_height; +GtkWidget *preview; +GtkWidget *c_dialog; + + +static void +run (char *name, + int nparams, + GParam *param, + int *nreturn_vals, + GParam **return_vals) +{ + GRunModeType run_mode; + GStatusType status; + static GParam values[1]; + GDrawable *drawable; + + status = STATUS_SUCCESS; + run_mode = param[0].data.d_int32; + + values[0].type = PARAM_STATUS; + values[0].data.d_status = status; + + *nreturn_vals = 1; + *return_vals = values; + + drawable = gimp_drawable_get (param[2].data.d_drawable); + + gimp_drawable_mask_bounds (drawable->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2); + + sel_width = sel_x2 - sel_x1; + sel_height = sel_y2 - sel_y1; + + switch (run_mode) { + case RUN_INTERACTIVE : + gimp_get_data(PLUG_IN_NAME, &cvals); + if (!colorify_dialog (cvals.color[0], cvals.color[1], cvals.color[2])) + return; + break; + + case RUN_NONINTERACTIVE : + if (nparams != 4) + status = STATUS_CALLING_ERROR; + if (status == STATUS_SUCCESS) { + cvals.color[0] = param[3].data.d_color.red; + cvals.color[1] = param[3].data.d_color.green; + cvals.color[2] = param[3].data.d_color.blue; + } + break; + + case RUN_WITH_LAST_VALS : + /* Possibly retrieve data */ + gimp_get_data (PLUG_IN_NAME, &cvals); + break; + + default : + break; + } + + if (status == STATUS_SUCCESS) { + gimp_progress_init("Colorifying..."); + + colorify (drawable); + + if (run_mode == RUN_INTERACTIVE) + gimp_set_data (PLUG_IN_NAME, &cvals, sizeof (ColorifyVals)); + + if (run_mode != RUN_NONINTERACTIVE) { + gimp_displays_flush (); + } + } + + values[0].data.d_status = status; +} + +static void colorify_row (guchar *row, + gint width); +static void close_callback (GtkWidget *widget, + gpointer data); +static void colorify_ok_callback (GtkWidget *widget, + gpointer data); +static void custom_color_callback (GtkWidget *widget, + gpointer data); +static void predefined_color_callback (GtkWidget *widget, + gpointer data); +static void color_changed (GtkWidget *widget, + gpointer data); + +static void +colorify (GDrawable *drawable) +{ + GPixelRgn source_region, dest_region; + guchar *row; + gint y = 0; + gint progress = 0; + gint i = 0; + + for (i = 0; i < 256; i ++) { + lum_red_lookup[i] = i * 0.30; + lum_green_lookup[i] = i * 0.59; + lum_blue_lookup[i] = i * 0.11; + final_red_lookup[i] = i * cvals.color[0] / 255; + final_green_lookup[i] = i * cvals.color[1] / 255; + final_blue_lookup[i] = i * cvals.color[2] / 255; + } + + row = g_malloc (sel_width * 3 * sizeof(guchar)); + + gimp_pixel_rgn_init (&source_region, drawable, sel_x1, sel_y1, sel_width, sel_height, FALSE, FALSE); + gimp_pixel_rgn_init (&dest_region, drawable, sel_x1, sel_y1, sel_width, sel_height, TRUE, TRUE); + + for (y = sel_y1; y < sel_y2; y++) { + gimp_pixel_rgn_get_row (&source_region, row, sel_x1, y, sel_width); + + colorify_row (row, sel_width); + + gimp_pixel_rgn_set_row (&dest_region, row, sel_x1, y, sel_width); + gimp_progress_update ((double) ++progress / sel_height); + + } + + g_free (row); + + gimp_drawable_flush (drawable); + gimp_drawable_merge_shadow (drawable->id, TRUE); + gimp_drawable_update (drawable->id, sel_x1, sel_y1, sel_width, sel_height); +} + +static void +colorify_row (guchar *row, + gint width) +{ + gint cur_x; + gint lum; /* luminosity */ + guchar *current = row; + + for (cur_x = 0; cur_x < width; cur_x++) { + lum = lum_red_lookup[current[0]] + lum_green_lookup[current[1]] + lum_blue_lookup[current[2]]; + + current[0] = final_red_lookup[lum]; + current[1] = final_green_lookup[lum]; + current[2] = final_blue_lookup[lum]; + + current += 3; + } +} + +static int +colorify_dialog (guchar red, + guchar green, + guchar blue) +{ + GtkWidget *dialog; + GtkWidget *label; + GtkWidget *button; + GtkWidget *frame; + GtkWidget *table; + gchar **argv; + gint argc; + gint i; + GSList *group = NULL; + + argc = 1; + argv = g_new (gchar *, 1); + argv[0] = g_strdup ("colorify"); + + gtk_init (&argc, &argv); + gtk_rc_parse (gimp_gtkrc()); + + dialog = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (dialog), "Colorify"); + gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE); + gtk_signal_connect (GTK_OBJECT (dialog), "destroy", + (GtkSignalFunc) close_callback, + NULL); + + button = gtk_button_new_with_label ("Ok"); + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + gtk_signal_connect (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) colorify_ok_callback, + dialog); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, TRUE, TRUE, 0); + gtk_widget_grab_default (button); + gtk_widget_show (button); + + button = gtk_button_new_with_label ("Cancel"); + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + gtk_signal_connect_object (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) gtk_widget_destroy, + GTK_OBJECT (dialog)); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, TRUE, TRUE, 0); + gtk_widget_show (button); + + frame = gtk_frame_new ("Color"); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); + gtk_container_border_width (GTK_CONTAINER (frame), 10); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, TRUE, TRUE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (2, 7, TRUE); + gtk_container_border_width (GTK_CONTAINER (table), 10); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_table_set_row_spacings (GTK_TABLE (table), 5); + gtk_table_set_col_spacings (GTK_TABLE (table), 5); + gtk_widget_show (table); + + label = gtk_label_new ("Custom Color: "); + gtk_table_attach (GTK_TABLE (table), label, 4, 6, 0, 1, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (label); + + button = gtk_radio_button_new (group); + gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); + gtk_widget_set_usize (button, 35, 35); + gtk_signal_connect (GTK_OBJECT (button), "button_press_event", + (GtkSignalFunc) custom_color_callback, + NULL); + gtk_table_attach (GTK_TABLE (table), button, 6, 7, 0, 1, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (button); + + preview = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_preview_size (GTK_PREVIEW (preview), 30, 30); + set_preview_color (preview, cvals.color[0], cvals.color[1], cvals.color[2]); + gtk_container_add (GTK_CONTAINER (button), preview); + gtk_widget_show (preview); + + for(i = 0; i < 7; i++) { + group = gtk_radio_button_group (GTK_RADIO_BUTTON (button)); + button = gtk_radio_button_new (group); + gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); + button_info[i].preview = gtk_preview_new (GTK_PREVIEW_COLOR); + gtk_preview_size (GTK_PREVIEW (button_info[i].preview), + 30, 30); + gtk_container_add (GTK_CONTAINER (button), button_info[i].preview); + set_preview_color (button_info[i].preview, + button_info[i].red, + button_info[i].green, + button_info[i].blue); + button_info[i].button_num = i; + gtk_signal_connect (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) predefined_color_callback, + &button_info[i].button_num); + gtk_widget_show (button_info[i].preview); + + gtk_table_attach (GTK_TABLE (table), button, i, i + 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (button); + } + + gtk_widget_show (dialog); + + gtk_main(); + return cint.run; +} + +static void +close_callback (GtkWidget *widget, + gpointer data) +{ + gtk_main_quit(); +} + +static void +colorify_ok_callback (GtkWidget *widget, + gpointer data) +{ + gtk_widget_destroy (GTK_WIDGET (data)); + cint.run = TRUE; +} + +static void +set_preview_color (GtkWidget *preview, + guchar red, + guchar green, + guchar blue) +{ + gint i; + guchar buf[3 * 30]; + + for (i = 0; i < 30; i ++) { + buf [3 * i] = red; + buf [3 * i + 1] = green; + buf [3 * i + 2] = blue; + } + + for (i = 0; i < 30; i ++) + gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 30); + + gtk_widget_draw (preview, NULL); +} + +static void +custom_color_callback (GtkWidget *widget, + gpointer data) +{ + GtkColorSelectionDialog *csd; + gdouble colour[3]; + + c_dialog = gtk_color_selection_dialog_new ("Colorify Custom Color"); + csd = GTK_COLOR_SELECTION_DIALOG (c_dialog); + gtk_color_selection_set_update_policy (GTK_COLOR_SELECTION(csd->colorsel), + GTK_UPDATE_DISCONTINUOUS); + + gtk_widget_destroy (csd->help_button); + gtk_widget_destroy (csd->cancel_button); + + gtk_signal_connect (GTK_OBJECT (csd->ok_button), "clicked", + (GtkSignalFunc) color_changed, + NULL); + + colour[0] = cvals.color[0] / 255.0; + colour[1] = cvals.color[1] / 255.0; + colour[2] = cvals.color[2] / 255.0; + + gtk_color_selection_set_color (GTK_COLOR_SELECTION (csd->colorsel), + colour); + gtk_window_position (GTK_WINDOW(c_dialog), GTK_WIN_POS_MOUSE); + gtk_widget_show (c_dialog); +} + +static void +predefined_color_callback (GtkWidget *widget, + gpointer data) +{ + gint *num; + + num = (gint *) data; + + cvals.color[0] = button_info[*num].red; + cvals.color[1] = button_info[*num].green; + cvals.color[2] = button_info[*num].blue; +} + +static void +color_changed (GtkWidget *widget, + gpointer data) +{ + gdouble colour[3]; + + gtk_color_selection_get_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (c_dialog)->colorsel), + colour); + + cvals.color[0] = (guchar) (colour[0] * 255.0); + cvals.color[1] = (guchar) (colour[1] * 255.0); + cvals.color[2] = (guchar) (colour[2] * 255.0); + + set_preview_color (preview, cvals.color[0], cvals.color[1], cvals.color[2]); + gtk_widget_destroy (c_dialog); +} + diff --git a/plug-ins/common/despeckle.c b/plug-ins/common/despeckle.c index df703895a7..4434f62102 100644 --- a/plug-ins/common/despeckle.c +++ b/plug-ins/common/despeckle.c @@ -44,17 +44,19 @@ * Revision History: * * $Log$ - * Revision 1.1.1.1 1997/11/24 22:04:12 sopwith - * Let's try this import one last time. + * Revision 1.2 1997/12/09 05:57:27 adrian + * added glasstile, colorify, papertile, and illusion plugins * - * Revision 1.1 1997/11/14 20:08:37 nobody - * *** empty log message *** + * updated despeckle, and math map * - * Revision 1.2 1997/09/27 10:30:27 nobody - * Boatload of changes from 0.99.11 to 0.99.12. For details, see the ChangeLog :-) + * Revision 1.14 1997/11/14 17:17:59 mike + * Updated to dynamically allocate return params in the run() function. * - * (Now that we are all using cvs (right?), this boatload of changes kind - * of commit shouldn't happen...) + * Revision 1.13 1997/11/12 15:53:34 mike + * Added header file for Digital UNIX... + * + * Revision 1.12 1997/10/17 13:56:54 mike + * Updated author/contact information. * * Revision 1.11 1997/06/12 16:58:11 mike * Optimized final despeckle - now grab gimp_tile_height() rows at a time @@ -101,18 +103,27 @@ #include #include +#include #include #include #include #include +/* + * Macros... + */ + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) + + /* * Constants... */ #define PLUG_IN_NAME "plug_in_despeckle" -#define PLUG_IN_VERSION "1.1" +#define PLUG_IN_VERSION "1.1.3 - 14 November 1997" #define PREVIEW_SIZE 128 #define SCALE_WIDTH 64 #define ENTRY_WIDTH 64 @@ -219,8 +230,10 @@ query(void) gimp_install_procedure(PLUG_IN_NAME, "Despeckle filter, typically used to \'despeckle\' a photographic image.", "This plug-in selectively performs a median or adaptive box filter on an image.", - "Michael Sweet", "Michael Sweet", - PLUG_IN_VERSION, "/Filters/Image/Despeckle...", "RGB*, GRAY*", + "Michael Sweet ", + "Michael Sweet ", + PLUG_IN_VERSION, + "/Filters/Image/Despeckle...", "RGB*, GRAY*", PROC_PLUG_IN, nargs, nreturn_vals, args, return_vals); } @@ -238,7 +251,7 @@ run(char *name, /* I - Name of filter program. */ { GRunModeType run_mode; /* Current run mode */ GStatusType status; /* Return status */ - static GParam values[1]; /* Return values */ + GParam *values; /* Return values */ /* @@ -248,6 +261,8 @@ run(char *name, /* I - Name of filter program. */ status = STATUS_SUCCESS; run_mode = param[0].data.d_int32; + values = g_new(GParam, 1); + values[0].type = PARAM_STATUS; values[0].data.d_status = status; @@ -783,7 +798,8 @@ despeckle_dialog(void) static void preview_init(void) { - int size, /* Size of filter box */ + int row, /* Current row in preview_srcs */ + size, /* Size of filter box */ width; /* Byte width of the image */ @@ -1003,7 +1019,8 @@ preview_update(void) static void preview_exit(void) { - int size; /* Size of row buffer */ + int row, /* Looping var */ + size; /* Size of row buffer */ size = MAX_RADIUS * 2 + 1; diff --git a/plug-ins/common/glasstile.c b/plug-ins/common/glasstile.c new file mode 100644 index 0000000000..44092f0dba --- /dev/null +++ b/plug-ins/common/glasstile.c @@ -0,0 +1,427 @@ +/* + * This is the Glass Tile plug-in for the GIMP 0.99 + * Version 1.01 + * + * Copyright (C) 1997 Karl-Johan Andersson (t96kja@student.tdb.uu.se) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * This filter divide the image into square "glass"-blocks in which + * the image is refracted. + * + * The alpha-channel is left unchanged. + * + * Please send any comments or suggestions to + * Karl-Johan Andersson (t96kja@student.tdb.uu.se) + * + */ + + +#include +#include "libgimp/gimp.h" +#include "gtk/gtk.h" + +/* --- Typedefs --- */ +typedef struct { + gint xblock; + gint yblock; +} GlassValues; +typedef struct { + gint run; +} GlassInterface; + +/* --- Declare local functions --- */ +static void query (void); +static void run (char *name, + int nparams, + GParam *param, + int *nreturn_vals, + GParam **return_vals); +static gint glass_dialog (void); +static void glass_close_callback (GtkWidget *widget, gpointer data); +static void glass_ok_callback (GtkWidget *widget, gpointer data); +static void glass_scale_update (GtkAdjustment *adjustment, gpointer data); +static void glasstile (GDrawable *drawable); + +/* --- Variables --- */ +GPlugInInfo PLUG_IN_INFO = +{ + NULL, /* init_proc */ + NULL, /* quit_proc */ + query, /* query_proc */ + run, /* run_proc */ +}; +static GlassValues gtvals = +{ + 20, /* tile width */ + 20 /* tile height */ +}; +static GlassInterface gt_int = +{ + FALSE /* run */ +}; + +/* --- Functions --- */ + +MAIN () + +static void query () +{ + static GParamDef args[] = + { + { PARAM_INT32, "run_mode", "Interactive, non-interactive" }, + { PARAM_IMAGE, "image", "Input image (unused)" }, + { PARAM_DRAWABLE, "drawable", "Input drawable" }, + { PARAM_INT32, "tilex", "Tile width (10 - 50)" }, + { PARAM_INT32, "tiley", "Tile height (10 - 50)" }, + }; + static GParamDef *return_vals = NULL; + static int nargs = sizeof (args) / sizeof (args[0]); + static int nreturn_vals = 0; + + gimp_install_procedure ("plug_in_glasstile", + "Divide the image into square glassblocks", + "More here later", + "Karl-Johan Andersson", /* Author */ + "Karl-Johan Andersson", /* Copyright */ + "1997", + "/Filters/Distorts/Glass Tile", + "RGB*, GRAY*", + PROC_PLUG_IN, + nargs, nreturn_vals, + args, return_vals); +} + +static void run (gchar *name, + gint nparams, + GParam *param, + gint *nreturn_vals, + GParam **return_vals) +{ + static GParam values[1]; + GDrawable *drawable; + GRunModeType run_mode; + GStatusType status = STATUS_SUCCESS; + + run_mode = param[0].data.d_int32; + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = PARAM_STATUS; + values[0].data.d_status = status; + + /* Get the specified drawable */ + drawable = gimp_drawable_get (param[2].data.d_drawable); + + switch (run_mode) + { + case RUN_INTERACTIVE: + /* Possibly retrieve data */ + gimp_get_data ("plug_in_glasstile", >vals); + + /* First acquire information with a dialog */ + if (! glass_dialog ()) + { + gimp_drawable_detach (drawable); + return; + } + break; + + case RUN_NONINTERACTIVE: + /* Make sure all the arguments are there! */ + if (nparams != 5) + status = STATUS_CALLING_ERROR; + if (status == STATUS_SUCCESS) + { + gtvals.xblock = (gint) param[3].data.d_int32; + gtvals.yblock = (gint) param[4].data.d_int32; + } + if (gtvals.xblock < 10 || gtvals.xblock > 50) + status = STATUS_CALLING_ERROR; + if (gtvals.yblock < 10 || gtvals.yblock > 50) + status = STATUS_CALLING_ERROR; + break; + + case RUN_WITH_LAST_VALS: + /* Possibly retrieve data */ + gimp_get_data ("plug_in_glasstile", >vals); + break; + + default: + break; + } + + if (status == STATUS_SUCCESS) + { + /* Make sure that the drawable is gray or RGB color */ + if (gimp_drawable_color (drawable->id) || gimp_drawable_gray (drawable->id)) + { + gimp_progress_init ("Glass Tile..."); + gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1)); + + glasstile (drawable); + + if (run_mode != RUN_NONINTERACTIVE) + gimp_displays_flush (); + /* Store data */ + if (run_mode == RUN_INTERACTIVE) + gimp_set_data ("plug_in_glasstile", >vals, sizeof (GlassValues)); + } + else + { + /* gimp_message ("glasstile: cannot operate on indexed color images"); */ + status = STATUS_EXECUTION_ERROR; + } + } + + values[0].data.d_status = status; + + gimp_drawable_detach (drawable); +} + +static gint glass_dialog () +{ + GtkWidget *dlg; + GtkWidget *label; + GtkWidget *button; + GtkWidget *scale; + GtkWidget *frame; + GtkWidget *table; + GtkObject *adjustment; + gchar **argv; + gint argc; + + argc = 1; + argv = g_new (gchar *, 1); + argv[0] = g_strdup ("glasstile"); + + gtk_init (&argc, &argv); + gtk_rc_parse (gimp_gtkrc ()); + + dlg = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (dlg), "Glass Tile"); + gtk_window_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE); + gtk_signal_connect (GTK_OBJECT (dlg), "destroy", + (GtkSignalFunc) glass_close_callback, + NULL); + + /* Action area */ + button = gtk_button_new_with_label ("OK"); + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + gtk_signal_connect (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) glass_ok_callback, + dlg); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0); + gtk_widget_grab_default (button); + gtk_widget_show (button); + + button = gtk_button_new_with_label ("Cancel"); + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + gtk_signal_connect_object (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) gtk_widget_destroy, + GTK_OBJECT (dlg)); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0); + gtk_widget_show (button); + + /* Parameter settings */ + frame = gtk_frame_new ("Parameter Settings"); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); + gtk_container_border_width (GTK_CONTAINER (frame), 10); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0); + table = gtk_table_new (2, 2, FALSE); /* table height, width */ + gtk_container_border_width (GTK_CONTAINER (table), 10); + gtk_container_add (GTK_CONTAINER (frame), table); + + /* Horizontal scale - Width */ + label = gtk_label_new ("Tile Width"); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL, 0, 5, 0); + /* xStart, xEnd, yStart, yEnd */ + + adjustment = gtk_adjustment_new (gtvals.xblock, 10, 50, 1, 1, 0); + gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed", + (GtkSignalFunc) glass_scale_update, + &(gtvals.xblock)); + scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment)); + gtk_widget_set_usize (scale, 150, 30); + gtk_table_attach (GTK_TABLE (table), scale, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); + gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); + gtk_scale_set_digits (GTK_SCALE (scale), 0); + gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE); + gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); + gtk_widget_show (label); + gtk_widget_show (scale); + + /* Horizontal scale - Height */ + label = gtk_label_new ("Tile Height"); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, 0, 5, 0); + + adjustment = gtk_adjustment_new (gtvals.yblock, 10, 50, 1, 1, 0); + gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed", + (GtkSignalFunc) glass_scale_update, + &(gtvals.yblock)); + scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment)); + gtk_widget_set_usize (scale, 150, 30); + gtk_table_attach (GTK_TABLE (table), scale, 1, 2, 1, 2, GTK_FILL, 0, 0, 0); + gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); + gtk_scale_set_digits (GTK_SCALE (scale), 0); + gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE); + gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); + gtk_widget_show (label); + gtk_widget_show (scale); + + gtk_widget_show (frame); + gtk_widget_show (table); + gtk_widget_show (dlg); + + gtk_main (); + gdk_flush (); + + return gt_int.run; +} + +/* - Interface functions - */ +static void glass_close_callback (GtkWidget *widget, gpointer data) +{ + gtk_main_quit (); +} + +static void glass_ok_callback (GtkWidget *widget, gpointer data) +{ + gt_int.run = TRUE; + gtk_widget_destroy (GTK_WIDGET (data)); +} + +static void glass_scale_update (GtkAdjustment *adjustment, gpointer data) +{ + gint *dptr = (gint*) data; + *dptr = (gint) adjustment->value; +} + +/* - Filter function - */ +static void glasstile (GDrawable *drawable) +{ + GPixelRgn srcPR, destPR; + gint width, height; + gint bytes; + guchar *dest, *d, *ad; + guchar *cur_row; + gint row, col, i, iwidth; + gint x1, y1, x2, y2; + + gint rutbredd, xpixel1, xpixel2; + gint ruthojd , ypixel2; + gint xhalv, xoffs, xmitt, xplus; + gint yhalv, yoffs, ymitt, yplus, cbytes; + + /* Get the input area. This is the bounding box of the selection in + * the image (or the entire image if there is no selection). Only + * operating on the input area is simply an optimization. It doesn't + * need to be done for correct operation. (It simply makes it go + * faster, since fewer pixels need to be operated on). + */ + gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2); + + /* Get the size of the input image. (This will/must be the same + * as the size of the output image. + */ + width = drawable->width; + height = drawable->height; + bytes = drawable->bpp; + + /* allocate row buffers */ + cur_row = (guchar *) malloc ((x2 - x1) * bytes); + dest = (guchar *) malloc ((x2 - x1) * bytes); + ad = (guchar *) malloc ((x2 - x1) * bytes); + + /* initialize the pixel regions */ + gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE); + gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE); + + rutbredd = gtvals.xblock; + ruthojd = gtvals.yblock; + + xhalv = rutbredd / 2; + yhalv = ruthojd / 2; + cbytes = bytes; + if (cbytes%2 == 0) cbytes--; + iwidth = width - x1; + xplus = rutbredd % 2; + yplus = ruthojd % 2; + + ymitt = y1; + yoffs = 0; + /* Loop through the rows */ + for (row = y1; row < y2; row++) + { + d = dest; + ypixel2 = ymitt + yoffs * 2; + if (ypixel2 < height) + gimp_pixel_rgn_get_row (&srcPR, cur_row, x1, ypixel2, iwidth); + else + gimp_pixel_rgn_get_row (&srcPR, cur_row, x1, y2-1, iwidth); + if (cbytes != bytes) /* Alpha check */ + gimp_pixel_rgn_get_row (&srcPR, ad, x1, row, (x2-x1)); + + yoffs++; + if (yoffs == yhalv) { + ymitt += ruthojd; + yoffs =- yhalv; + yoffs -= yplus; + } + xmitt = 0; + xoffs = 0; + for (col = 0; col < (x2 - x1); col++) /* one pixel */ + { + xpixel1 = (xmitt + xoffs) * bytes; + xpixel2 = (xmitt + xoffs * 2) * bytes; + if (xpixel2 < ((x2 - x1) * bytes)) { + for (i = 0; i < cbytes; i++) + d[xpixel1 + i] = cur_row[xpixel2 + i]; + } + else { + for (i = 0; i < cbytes; i++) + d[xpixel1 + i]=cur_row[xpixel1 + i]; + } + if (cbytes != bytes) /* Alpha channel unchanged */ + d[xpixel1 + cbytes] = ad[xpixel1 + cbytes]; + xoffs++; + if (xoffs == xhalv) { + xmitt += rutbredd; + xoffs =- xhalv; + xoffs -= xplus; + } + } + /* Store the dest */ + gimp_pixel_rgn_set_row (&destPR, dest, x1, row, iwidth); + + if ((row % 5) == 0) + gimp_progress_update ((double) row / (double) (y2 - y1)); + } + + /* Update region */ + gimp_drawable_flush (drawable); + gimp_drawable_merge_shadow (drawable->id, TRUE); + gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1)); + + free (cur_row); + free (dest); + free (ad); +} diff --git a/plug-ins/common/illusion.c b/plug-ins/common/illusion.c new file mode 100644 index 0000000000..277c15ead8 --- /dev/null +++ b/plug-ins/common/illusion.c @@ -0,0 +1,368 @@ +/******************************************************************************* + + illusion.c -- This is a plug-in for the GIMP 1.0 + + Copyright (C) 1997 Hirotsuna Mizuno + s1041150@u-aizu.ac.jp + + 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 2 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, write to the Free Software Foundation, Inc., + 675 Mass Ave, Cambridge, MA 02139, USA. + +*******************************************************************************/ + +#include +#include +#include +#include "libgimp/gimp.h" + +#define PLUG_IN_NAME "plug_in_illusion" +#define PLUG_IN_VERSION "v0.7 (Dec. 25 1997)" + +#define DIALOG_CAPTION "Illusion" + +#ifndef PI +#define PI 3.141592653589793238462643383279 +#endif +#ifndef PI_2 +#define PI_2 (PI*2) +#endif + +/******************************************************************************/ + +static void query( void ); +static void run( char *, int, GParam *, int *, GParam ** ); +static void filter( GDrawable *drawable ); +static int dialog( void ); + +/******************************************************************************/ + +typedef struct { + gint32 division; +} parameter_t; + +/******************************************************************************/ + +GPlugInInfo PLUG_IN_INFO = { + NULL, /* init_proc */ + NULL, /* quit_proc */ + query, /* query_proc */ + run, /* run_proc */ +}; + +static parameter_t parameters = { + 8 +}; + +static gint image_width; +static gint image_height; +static gint image_bpp; +static gint image_has_alpha; +static gint select_x1; +static gint select_y1; +static gint select_x2; +static gint select_y2; +static gint select_width; +static gint select_height; +static gdouble center_x; +static gdouble center_y; + +/******************************************************************************/ + +MAIN(); + +/******************************************************************************/ + +static void query( void ) +{ + static int nargs = 4; + static GParamDef args[] = { + { PARAM_INT32, "run_mode", "interactive / non-interactive" }, + { PARAM_IMAGE, "image", "input image" }, + { PARAM_DRAWABLE, "drawable", "input drawable" }, + { PARAM_INT32, "division", "the number of divisions" } + }; + static int nreturn_vals = 0; + static GParamDef *return_vals = NULL; + + gimp_install_procedure( + PLUG_IN_NAME, + "produce illusion", + "produce illusion", + "Hirotsuna Mizuno ", + "Hirotsuna Mizuno", + PLUG_IN_VERSION, + "/Filters/Effects/Illusion", + "RGB*, GRAY*", + PROC_PLUG_IN, + nargs, + nreturn_vals, + args, + return_vals + ); +} + +/******************************************************************************/ + +static void run( char *name, + int paramc, + GParam *params, + int *returnc, + GParam **returns ) +{ + GDrawable *drawable; + GRunModeType run_mode; + static GParam returnv[1]; + GStatusType status = STATUS_SUCCESS; + + run_mode = params[0].data.d_int32; + drawable = gimp_drawable_get( params[2].data.d_drawable ); + *returnc = 1; + *returns = returnv; + + /* get the drawable info */ + image_width = gimp_drawable_width( drawable->id ); + image_height = gimp_drawable_height( drawable->id ); + image_bpp = gimp_drawable_bpp( drawable->id ); + image_has_alpha = gimp_drawable_has_alpha( drawable->id ); + gimp_drawable_mask_bounds( drawable->id, + &select_x1, &select_y1, &select_x2, &select_y2 ); + select_width = select_x2 - select_x1; + select_height = select_y2 - select_y1; + center_x = select_x1 + (gdouble)select_width / 2; + center_y = select_y1 + (gdouble)select_height / 2; + + /* switch the run mode */ + switch( run_mode ){ + + case RUN_INTERACTIVE: + gimp_get_data( PLUG_IN_NAME, ¶meters ); + if( ! dialog() ) return; + gimp_set_data( PLUG_IN_NAME, ¶meters, sizeof( parameter_t ) ); + break; + + case RUN_NONINTERACTIVE: + if( paramc != 4 ){ + status = STATUS_CALLING_ERROR; + } else { + parameters.division = params[3].data.d_int32; + } + break; + + case RUN_WITH_LAST_VALS: + gimp_get_data( PLUG_IN_NAME, ¶meters ); + break; + + } + + if( status == STATUS_SUCCESS ){ + + if( gimp_drawable_color( drawable->id ) || + gimp_drawable_gray( drawable->id ) ){ + + gimp_tile_cache_ntiles( 2 * ( drawable->width / gimp_tile_width() + 1 ) ); + filter( drawable ); + if( run_mode != RUN_NONINTERACTIVE ) gimp_displays_flush (); + + } else { + + status = STATUS_EXECUTION_ERROR; + + } + + } + + returnv[0].type = PARAM_STATUS; + returnv[0].data.d_status = status; + + gimp_drawable_detach( drawable ); +} + +/******************************************************************************/ + +static void filter( GDrawable *drawable ) +{ + GPixelRgn srcPR, destPR; + guchar **pixels; + guchar **destpixels; + gint x, y, b; + gint xx, yy; + gdouble scale, radius, cx, cy, angle, offset; + + gimp_pixel_rgn_init( &srcPR, drawable, + 0, 0, image_width, image_height, FALSE, FALSE ); + gimp_pixel_rgn_init( &destPR, drawable, + 0, 0, image_width, image_height, TRUE, TRUE ); + + pixels = (guchar **)malloc( image_height * sizeof(guchar *) ); + destpixels = (guchar **)malloc( image_height * sizeof(guchar *) ); + for( y = 0; y < image_height; y++ ){ + pixels[y] = (guchar *)malloc( image_width * image_bpp ); + destpixels[y] = (guchar *)malloc( image_width * image_bpp ); + gimp_pixel_rgn_get_row( &srcPR, pixels[y], 0, y, image_width ); + } + + /* + for( y = select_y1; y < select_y2; y++ ){ + for( x = select_x1; x < select_x2; x++ ){ + for( b = 0; b < image_bpp; b++ ){ + destpixels[y][x*image_bpp+b] = 0; + } + } + } + */ + + gimp_progress_init( PLUG_IN_NAME ); + + scale = sqrt(select_width*select_width+select_height*select_height) / 2; + offset = (gint)(scale / 2); + + for( y = select_y1; y < select_y2; y++ ){ + cy = ((gdouble)y - center_y) / scale; + for( x = select_x1; x < select_x2; x++ ){ + cx = ((gdouble)x - center_x) / scale; + angle = floor( atan2(cy,cx) * parameters.division / PI_2 ) + * PI_2 / parameters.division + ( PI / parameters.division ); + radius = sqrt((gdouble)(cx*cx+cy*cy)); + xx = x - offset * cos( angle ); + yy = y - offset * sin( angle ); + if( xx < 0 ) xx = 0; + else if( image_width <= xx ) xx = image_width - 1; + if( yy < 0 ) yy = 0; + else if( image_height <= yy ) yy = image_height - 1; + for( b = 0; b < image_bpp; b++ ) + destpixels[y][x*image_bpp+b] = + (1-radius)*pixels[y][x*image_bpp+b] + + radius*pixels[yy][xx*image_bpp+b]; + } + gimp_pixel_rgn_set_row (&destPR, destpixels[y], 0, y, image_width ); + gimp_progress_update ( (double)( y - select_y1 ) / (double)select_height ); + } + + gimp_drawable_flush( drawable ); + gimp_drawable_merge_shadow( drawable->id, TRUE ); + gimp_drawable_update( drawable->id, + select_x1, select_y1, select_width, select_height ); + + for( y = select_y1; y < select_y2; y++ ) free( pixels[y-select_y1] ); + free( pixels ); + for( y = select_y1; y < select_y2; y++ ) free( destpixels[y-select_y1] ); + free( destpixels ); +} + +/******************************************************************************/ + +static int dialog_status; + +static GtkWidget *entry_division; + +static void dialog_destroy_handler( GtkWidget *widget, gpointer *data ) +{ + gtk_main_quit(); +} + +static void dialog_ok_handler( GtkWidget *widget, gpointer *data ) +{ + dialog_status = TRUE; + + parameters.division = + (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_division ) ) ); + + gtk_widget_destroy( GTK_WIDGET( data ) ); +} + +static void dialog_cancel_handler( GtkWidget *widget, gpointer *data ) +{ + dialog_status = FALSE; + gtk_widget_destroy( GTK_WIDGET( data ) ); +} + +/******************************************************************************/ + +static int dialog( void ) +{ + GtkWidget *window; + + dialog_status = FALSE; + + { + gint argc = 1; + gchar **argv = g_new( gchar *, 1 ); + argv[0] = g_strdup( DIALOG_CAPTION ); + gtk_init( &argc, &argv ); + } + + /* dialog window */ + window = gtk_dialog_new(); + gtk_signal_connect( GTK_OBJECT( window ), "destroy", + GTK_SIGNAL_FUNC( dialog_destroy_handler ), NULL ); + gtk_container_border_width( GTK_CONTAINER( window ), 0 ); + gtk_container_border_width( GTK_CONTAINER( GTK_DIALOG( window )->vbox ), 5 ); + + { + /* buttons */ + GtkWidget *button; + + /* ok button */ + button = gtk_button_new_with_label( "OK" ); + gtk_signal_connect_object( GTK_OBJECT( button ), "clicked", + GTK_SIGNAL_FUNC( dialog_ok_handler ), + GTK_OBJECT( window ) ); + GTK_WIDGET_SET_FLAGS( button, GTK_CAN_DEFAULT ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->action_area ), + button, TRUE, TRUE, 0 ); + gtk_widget_grab_default( button ); + gtk_widget_show( button ); + + /* cancel button */ + button = gtk_button_new_with_label( "Cancel" ); + gtk_signal_connect_object( GTK_OBJECT( button ), "clicked", + GTK_SIGNAL_FUNC( dialog_cancel_handler ), + GTK_OBJECT( window )) ; + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->action_area ), + button, TRUE, TRUE, 0 ); + gtk_widget_show( button ); + } + + { + /* text boxes */ + GtkWidget *table; + GtkWidget *label; + char buffer[32]; + + /* table */ + table = gtk_table_new( 1, 2, FALSE ); + gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); + gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->vbox ), + table, TRUE, TRUE, 0 ); + gtk_widget_show( table ); + + /* tile width */ + label = gtk_label_new( "division: " ); + entry_division = gtk_entry_new(); + sprintf( buffer, "%d", parameters.division ); + gtk_entry_set_text( GTK_ENTRY( entry_division ), buffer ); + gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 0, 1 ); + gtk_table_attach_defaults( GTK_TABLE( table ), entry_division, 1, 2, 0, 1 ); + gtk_widget_show( label ); + gtk_widget_show( entry_division ); + } + + gtk_widget_show( window ); + gtk_main(); + + return dialog_status; +} + +/******************************************************************************/ diff --git a/plug-ins/common/papertile.c b/plug-ins/common/papertile.c new file mode 100644 index 0000000000..bf44e1f652 --- /dev/null +++ b/plug-ins/common/papertile.c @@ -0,0 +1,469 @@ +/******************************************************************************* + + papertile.c -- This is a plug-in for the GIMP 1.0 + + Copyright (C) 1997 Hirotsuna Mizuno + s1041150@u-aizu.ac.jp + + 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 2 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, write to the Free Software Foundation, Inc., + 675 Mass Ave, Cambridge, MA 02139, USA. + +*******************************************************************************/ + +#include +#include +#include + +#define PLUG_IN_NAME "plug_in_paper_tile" +#define PLUG_IN_VERSION "v0.7 (Dec. 25 1997)" +#define DIALOG_CAPTION "Paper Tile" + +/******************************************************************************/ + +static void query( void ); +static void run( char *, int, GParam *, int *, GParam ** ); +static void filter( GDrawable *drawable ); +static int dialog( void ); + +/******************************************************************************/ + +#define BG_TYPE_TRANSPARENT 0 +#define BG_TYPE_BLACK 1 +#define BG_TYPE_WHITE 2 + +typedef struct { + gint32 tile_width; + gint32 tile_height; + gint32 slide_length; + gint32 bg_type; +} parameter_t; + +/******************************************************************************/ + +GPlugInInfo PLUG_IN_INFO = { + NULL, /* init_proc */ + NULL, /* quit_proc */ + query, /* query_proc */ + run, /* run_proc */ +}; + +static parameter_t parameters = { + 50, + 50, + 10, + BG_TYPE_TRANSPARENT +}; + +static gint image_width; +static gint image_height; +static gint image_bpp; +static gint image_has_alpha; +static gint select_x1; +static gint select_y1; +static gint select_x2; +static gint select_y2; +static gint select_width; +static gint select_height; + +/******************************************************************************/ + +MAIN(); + +/******************************************************************************/ + +static void query( void ) +{ + static int nargs = 7; + static GParamDef args[] = { + { PARAM_INT32, "run_mode", "interactive / non-interactive" }, + { PARAM_IMAGE, "image", "input image" }, + { PARAM_DRAWABLE, "drawable", "input drawable" }, + { PARAM_INT32, "width", "tile width" }, + { PARAM_INT32, "height", "tile height" }, + { PARAM_INT32, "slide_length", "slide length" }, + { PARAM_INT32, "bg_type", "background color " + "(0=transparent, 1=black, 2=white )" } + }; + static int nreturn_vals = 0; + static GParamDef *return_vals = NULL; + + gimp_install_procedure( + PLUG_IN_NAME, + "cut and slide image", + "cut and slide image", + "Hirotsuna Mizuno ", + "Hirotsuna Mizuno", + PLUG_IN_VERSION, + "/Filters/Effects/Paper Tile", + "RGB*, GRAY*", + PROC_PLUG_IN, + nargs, + nreturn_vals, + args, + return_vals + ); +} + +/******************************************************************************/ + +static void run( char *name, + int paramc, + GParam *params, + int *returnc, + GParam **returns ) +{ + GDrawable *drawable; + GRunModeType run_mode; + static GParam returnv[1]; + GStatusType status = STATUS_SUCCESS; + + run_mode = params[0].data.d_int32; + drawable = gimp_drawable_get( params[2].data.d_drawable ); + *returnc = 1; + *returns = returnv; + + /* get the drawable info */ + image_width = gimp_drawable_width( drawable->id ); + image_height = gimp_drawable_height( drawable->id ); + image_bpp = gimp_drawable_bpp( drawable->id ); + image_has_alpha = gimp_drawable_has_alpha( drawable->id ); + gimp_drawable_mask_bounds( drawable->id, + &select_x1, &select_y1, &select_x2, &select_y2 ); + select_width = select_x2 - select_x1; + select_height = select_y2 - select_y1; + + /* switch the run mode */ + switch( run_mode ){ + + case RUN_INTERACTIVE: + gimp_get_data( PLUG_IN_NAME, ¶meters ); + if( ! dialog() ) return; + gimp_set_data( PLUG_IN_NAME, ¶meters, sizeof( parameter_t ) ); + break; + + case RUN_NONINTERACTIVE: + if( paramc != 7 ){ + status = STATUS_CALLING_ERROR; + } else { + parameters.tile_width = params[3].data.d_int32; + parameters.tile_height = params[4].data.d_int32; + parameters.slide_length = params[5].data.d_int32; + parameters.bg_type = params[6].data.d_int32; + } + break; + + case RUN_WITH_LAST_VALS: + gimp_get_data( PLUG_IN_NAME, ¶meters ); + break; + + } + + if( status == STATUS_SUCCESS ){ + if( gimp_drawable_color( drawable->id ) || + gimp_drawable_gray( drawable->id ) ){ + + gimp_tile_cache_ntiles( 2 * ( drawable->width / gimp_tile_width() + 1 ) ); + filter( drawable ); + if( run_mode != RUN_NONINTERACTIVE ) gimp_displays_flush (); + + } else { + + status = STATUS_EXECUTION_ERROR; + + } + } + + returnv[0].type = PARAM_STATUS; + returnv[0].data.d_status = status; + + gimp_drawable_detach( drawable ); +} + +/******************************************************************************/ + +static void filter( GDrawable *drawable ) +{ + GPixelRgn srcPR, destPR; + guchar **pixels; + guchar **destpixels; + gint x, y, b; + gint vx, vy, xx, yy; + + gimp_pixel_rgn_init( &srcPR, drawable, + 0, 0, image_width, image_height, FALSE, FALSE ); + gimp_pixel_rgn_init( &destPR, drawable, + 0, 0, image_width, image_height, TRUE, TRUE ); + + pixels = (guchar **)malloc( image_height * sizeof(guchar *) ); + destpixels = (guchar **)malloc( image_height * sizeof(guchar *) ); + for( y = 0; y < image_height; y++ ){ + pixels[y] = (guchar *)malloc( image_width * image_bpp ); + destpixels[y] = (guchar *)malloc( image_width * image_bpp ); + gimp_pixel_rgn_get_row( &srcPR, pixels[y], 0, y, image_width ); + } + + for( y = select_y1; y < select_y2; y++ ){ + for( x = select_x1; x < select_x2; x++ ){ + switch( parameters.bg_type ){ + + case BG_TYPE_TRANSPARENT: + for( b = 0; b < image_bpp; b++ ){ + destpixels[y][x*image_bpp+b] = 0; + } + break; + + case BG_TYPE_BLACK: + for( b = 0; b < image_bpp; b++ ){ + if( b == image_bpp - 1 && image_has_alpha ){ + destpixels[y][x*image_bpp+b] = 255; + } else { + destpixels[y][x*image_bpp+b] = 0; + } + } + break; + + case BG_TYPE_WHITE: + for( b = 0; b < image_bpp; b++ ){ + destpixels[y][x*image_bpp+b] = 255; + } + break; + + } + } + } + + gimp_progress_init( PLUG_IN_NAME ); + + for( y = select_y1; y < select_y2; y+=parameters.tile_height ) + for( x = select_x1; x < select_x2; x+=parameters.tile_width ){ + vx = rand()%parameters.slide_length - parameters.slide_length/2; + vy = rand()%parameters.slide_length - parameters.slide_length/2; + for( xx = 0; xx < parameters.tile_width; xx++ ) + if( 0 <= x+xx+vx && x+xx+vx < image_width && x+xx < image_width ) + for( yy = 0; yy < parameters.tile_height; yy++ ) + if( 0 <= y+yy+vy && y+yy+vy < image_height && y+yy < image_height ) + for( b = 0; b < image_bpp; b++ ) + destpixels[y+yy+vy][(x+xx+vx)*image_bpp+b] + = pixels[y+yy][(x+xx)*image_bpp+b]; + } + + for( y = select_y1; y < select_y2; y++ ){ + gimp_pixel_rgn_set_row (&destPR, destpixels[y], 0, y, image_width ); + gimp_progress_update ( (double)( y - select_y1 ) / select_height ); + } + + gimp_drawable_flush( drawable ); + gimp_drawable_merge_shadow( drawable->id, TRUE ); + gimp_drawable_update( drawable->id, + select_x1, select_y1, select_width, select_height ); + + for( y = select_y1; y < select_y2; y++ ) free( pixels[y-select_y1] ); + free( pixels ); + for( y = select_y1; y < select_y2; y++ ) free( destpixels[y-select_y1] ); + free( destpixels ); +} + +/******************************************************************************/ + +static int dialog_status; + +static GtkWidget *entry_width; +static GtkWidget *entry_height; +static GtkWidget *entry_slide; +static GtkWidget *button_transparent; +static GtkWidget *button_black; +static GtkWidget *button_white; + +static void dialog_destroy_handler( GtkWidget *widget, + gpointer *data ) +{ + gtk_main_quit(); +} + +static void dialog_ok_handler( GtkWidget *widget, + gpointer *data ) +{ + dialog_status = TRUE; + + if( GTK_TOGGLE_BUTTON( button_white )->active ) parameters.bg_type = BG_TYPE_WHITE; + if( GTK_TOGGLE_BUTTON( button_black )->active ) parameters.bg_type = BG_TYPE_BLACK; + if( image_has_alpha ){ + if( GTK_TOGGLE_BUTTON( button_transparent )->active ){ + parameters.bg_type = BG_TYPE_TRANSPARENT; + } + } + + parameters.tile_width = + (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_width ) ) ); + parameters.tile_height = + (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_height ) ) ); + parameters.slide_length = + (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_slide ) ) ); + + gtk_widget_destroy( GTK_WIDGET( data ) ); +} + +static void dialog_cancel_handler( GtkWidget *widget, + gpointer *data ) +{ + dialog_status = FALSE; + gtk_widget_destroy( GTK_WIDGET( data ) ); +} + +/******************************************************************************/ + +static int dialog( void ) +{ + GtkWidget *window; + dialog_status = FALSE; + { + gint argc = 1; + gchar **argv = g_new( gchar *, 1 ); + argv[0] = g_strdup( DIALOG_CAPTION ); + gtk_init( &argc, &argv ); + } + + /* dialog window */ + window = gtk_dialog_new(); + gtk_signal_connect( GTK_OBJECT( window ), "destroy", + GTK_SIGNAL_FUNC( dialog_destroy_handler ), NULL ); + gtk_container_border_width( GTK_CONTAINER( window ), 0 ); + gtk_container_border_width( GTK_CONTAINER( GTK_DIALOG( window )->vbox ), 5 ); + + { + /* buttons */ + GtkWidget *button; + + /* ok button */ + button = gtk_button_new_with_label( "OK" ); + gtk_signal_connect_object( GTK_OBJECT( button ), "clicked", + GTK_SIGNAL_FUNC( dialog_ok_handler ), + GTK_OBJECT( window ) ); + GTK_WIDGET_SET_FLAGS( button, GTK_CAN_DEFAULT ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->action_area ), + button, TRUE, TRUE, 0 ); + gtk_widget_grab_default( button ); + gtk_widget_show( button ); + + /* cancel button */ + button = gtk_button_new_with_label( "Cancel" ); + gtk_signal_connect_object( GTK_OBJECT( button ), "clicked", + GTK_SIGNAL_FUNC( dialog_cancel_handler ), + GTK_OBJECT( window )); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->action_area ), + button, TRUE, TRUE, 0 ); + gtk_widget_show( button ); + } + + { + /* text boxes */ + GtkWidget *table; + GtkWidget *label; + char buffer[32]; + + /* table */ + table = gtk_table_new( 3, 2, FALSE ); + gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); + gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->vbox ), + table, TRUE, TRUE, 0 ); + gtk_widget_show( table ); + + /* tile width */ + label = gtk_label_new( "width: " ); + entry_width = gtk_entry_new(); + sprintf( buffer, "%d", parameters.tile_width ); + gtk_entry_set_text( GTK_ENTRY( entry_width ), buffer ); + gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 0, 1 ); + gtk_table_attach_defaults( GTK_TABLE( table ), entry_width, 1, 2, 0, 1 ); + gtk_widget_show( label ); + gtk_widget_show( entry_width ); + + /* tile height */ + label = gtk_label_new( "height: " ); + entry_height = gtk_entry_new(); + sprintf( buffer, "%d", parameters.tile_height ); + gtk_entry_set_text( GTK_ENTRY( entry_height ), buffer ); + gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 1, 2 ); + gtk_table_attach_defaults( GTK_TABLE( table ), entry_height, 1, 2, 1, 2 ); + gtk_widget_show( label ); + gtk_widget_show( entry_height ); + + /* slide length */ + label = gtk_label_new( "slide: " ); + entry_slide = gtk_entry_new(); + sprintf( buffer, "%d", parameters.slide_length ); + gtk_entry_set_text( GTK_ENTRY( entry_slide ), buffer ); + gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 2, 3 ); + gtk_table_attach_defaults( GTK_TABLE( table ), entry_slide, 1, 2, 2, 3 ); + gtk_widget_show( label ); + gtk_widget_show( entry_slide ); + } + + { + /* radio buttons */ + GtkWidget *frame; + GtkWidget *vbox; + GSList *group; + + frame = gtk_frame_new( "Background" ); + gtk_container_border_width( GTK_CONTAINER( frame ), 0 ); + gtk_frame_set_shadow_type( GTK_FRAME( frame ), GTK_SHADOW_ETCHED_IN ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->vbox ), + frame, TRUE, TRUE, 0 ); + gtk_widget_show( frame ); + + vbox = gtk_vbox_new( FALSE, 0 ); + gtk_container_border_width( GTK_CONTAINER( vbox ), 0 ); + gtk_container_add( GTK_CONTAINER( frame ), vbox ); + gtk_widget_show( vbox ); + + group = NULL; + + if( image_has_alpha ){ + /* transparent */ + button_transparent = + gtk_radio_button_new_with_label( NULL, "Transparent" ); + gtk_box_pack_start( GTK_BOX( vbox ), + button_transparent, TRUE, TRUE, 0 ); + if( parameters.bg_type == BG_TYPE_TRANSPARENT ) + gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( button_transparent ), + TRUE ); + gtk_widget_show( button_transparent ); + group = gtk_radio_button_group( GTK_RADIO_BUTTON( button_transparent ) ); + } + + /* black */ + button_black = gtk_radio_button_new_with_label( group, "Black" ); + gtk_box_pack_start( GTK_BOX( vbox ), button_black, TRUE, TRUE, 0 ); + if( parameters.bg_type == BG_TYPE_BLACK ) + gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( button_black ), TRUE ); + gtk_widget_show( button_black ); + group = gtk_radio_button_group( GTK_RADIO_BUTTON( button_black ) ); + + /* white */ + button_white = gtk_radio_button_new_with_label( group, "White" ); + gtk_box_pack_start( GTK_BOX( vbox ), button_white, TRUE, TRUE, 0 ); + if( parameters.bg_type == BG_TYPE_WHITE ) + gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( button_white ), TRUE ); + gtk_widget_show( button_white ); + } + + gtk_widget_show( window ); + gtk_main(); + + return dialog_status; +} + +/******************************************************************************/ diff --git a/plug-ins/despeckle/despeckle.c b/plug-ins/despeckle/despeckle.c index df703895a7..4434f62102 100644 --- a/plug-ins/despeckle/despeckle.c +++ b/plug-ins/despeckle/despeckle.c @@ -44,17 +44,19 @@ * Revision History: * * $Log$ - * Revision 1.1.1.1 1997/11/24 22:04:12 sopwith - * Let's try this import one last time. + * Revision 1.2 1997/12/09 05:57:27 adrian + * added glasstile, colorify, papertile, and illusion plugins * - * Revision 1.1 1997/11/14 20:08:37 nobody - * *** empty log message *** + * updated despeckle, and math map * - * Revision 1.2 1997/09/27 10:30:27 nobody - * Boatload of changes from 0.99.11 to 0.99.12. For details, see the ChangeLog :-) + * Revision 1.14 1997/11/14 17:17:59 mike + * Updated to dynamically allocate return params in the run() function. * - * (Now that we are all using cvs (right?), this boatload of changes kind - * of commit shouldn't happen...) + * Revision 1.13 1997/11/12 15:53:34 mike + * Added header file for Digital UNIX... + * + * Revision 1.12 1997/10/17 13:56:54 mike + * Updated author/contact information. * * Revision 1.11 1997/06/12 16:58:11 mike * Optimized final despeckle - now grab gimp_tile_height() rows at a time @@ -101,18 +103,27 @@ #include #include +#include #include #include #include #include +/* + * Macros... + */ + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) + + /* * Constants... */ #define PLUG_IN_NAME "plug_in_despeckle" -#define PLUG_IN_VERSION "1.1" +#define PLUG_IN_VERSION "1.1.3 - 14 November 1997" #define PREVIEW_SIZE 128 #define SCALE_WIDTH 64 #define ENTRY_WIDTH 64 @@ -219,8 +230,10 @@ query(void) gimp_install_procedure(PLUG_IN_NAME, "Despeckle filter, typically used to \'despeckle\' a photographic image.", "This plug-in selectively performs a median or adaptive box filter on an image.", - "Michael Sweet", "Michael Sweet", - PLUG_IN_VERSION, "/Filters/Image/Despeckle...", "RGB*, GRAY*", + "Michael Sweet ", + "Michael Sweet ", + PLUG_IN_VERSION, + "/Filters/Image/Despeckle...", "RGB*, GRAY*", PROC_PLUG_IN, nargs, nreturn_vals, args, return_vals); } @@ -238,7 +251,7 @@ run(char *name, /* I - Name of filter program. */ { GRunModeType run_mode; /* Current run mode */ GStatusType status; /* Return status */ - static GParam values[1]; /* Return values */ + GParam *values; /* Return values */ /* @@ -248,6 +261,8 @@ run(char *name, /* I - Name of filter program. */ status = STATUS_SUCCESS; run_mode = param[0].data.d_int32; + values = g_new(GParam, 1); + values[0].type = PARAM_STATUS; values[0].data.d_status = status; @@ -783,7 +798,8 @@ despeckle_dialog(void) static void preview_init(void) { - int size, /* Size of filter box */ + int row, /* Current row in preview_srcs */ + size, /* Size of filter box */ width; /* Byte width of the image */ @@ -1003,7 +1019,8 @@ preview_update(void) static void preview_exit(void) { - int size; /* Size of row buffer */ + int row, /* Looping var */ + size; /* Size of row buffer */ size = MAX_RADIUS * 2 + 1; diff --git a/plug-ins/gfig/gfig-examples/spirals & stars b/plug-ins/gfig/gfig-examples/spirals & stars new file mode 100644 index 0000000000..fae6052eb0 --- /dev/null +++ b/plug-ins/gfig/gfig-examples/spirals & stars @@ -0,0 +1,55 @@ +GFIG Version 0.1 +Name: First\040gfig +Version: 0.000000 +ObjCount: 6 + +GridSpacing: 30 +GridType: RECT_GRID +DrawGrid: FALSE +Snap2Grid: FALSE +LockOnGrid: FALSE +ShowControl: TRUE + + +71 81 +96 103 + +4 + + + +152 79 +179 91 + +-4 + + + +116 94 +105 147 +73 161 + +4 + + + +206 106 +228 123 +214 112 + +3 + + + +26 115 +10 133 +20 121 + +3 + + + +38 169 +92 218 +182 182 + diff --git a/plug-ins/glasstile/Makefile.am b/plug-ins/glasstile/Makefile.am new file mode 100644 index 0000000000..c7e2882e83 --- /dev/null +++ b/plug-ins/glasstile/Makefile.am @@ -0,0 +1,42 @@ +## Process this file with automake to produce Makefile.in + +pluginlibdir = $(gimpplugindir)/plug-ins + +pluginlib_PROGRAMS = glasstile + +glasstile_SOURCES = \ + glasstile.c + +INCLUDES = \ + $(X_CFLAGS) \ + -I$(top_srcdir) \ + -I$(includedir) + +LDADD = \ + $(top_builddir)/libgimp/libgimpui.la \ + $(top_builddir)/libgimp/libgimp.la \ + $(X_LIBS) \ + \ + -lc + +DEPS = \ + $(top_builddir)/libgimp/libgimpui.la \ + $(top_builddir)/libgimp/libgimp.la + +glasstile_DEPENDENCIES = $(DEPS) + +.PHONY: files + +files: + @files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \ + echo $$p; \ + done + @for subdir in $(SUBDIRS); do \ + files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \ + for file in $$files; do \ + echo $$subdir/$$file; \ + done; \ + done + + + diff --git a/plug-ins/glasstile/glasstile.c b/plug-ins/glasstile/glasstile.c new file mode 100644 index 0000000000..44092f0dba --- /dev/null +++ b/plug-ins/glasstile/glasstile.c @@ -0,0 +1,427 @@ +/* + * This is the Glass Tile plug-in for the GIMP 0.99 + * Version 1.01 + * + * Copyright (C) 1997 Karl-Johan Andersson (t96kja@student.tdb.uu.se) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * This filter divide the image into square "glass"-blocks in which + * the image is refracted. + * + * The alpha-channel is left unchanged. + * + * Please send any comments or suggestions to + * Karl-Johan Andersson (t96kja@student.tdb.uu.se) + * + */ + + +#include +#include "libgimp/gimp.h" +#include "gtk/gtk.h" + +/* --- Typedefs --- */ +typedef struct { + gint xblock; + gint yblock; +} GlassValues; +typedef struct { + gint run; +} GlassInterface; + +/* --- Declare local functions --- */ +static void query (void); +static void run (char *name, + int nparams, + GParam *param, + int *nreturn_vals, + GParam **return_vals); +static gint glass_dialog (void); +static void glass_close_callback (GtkWidget *widget, gpointer data); +static void glass_ok_callback (GtkWidget *widget, gpointer data); +static void glass_scale_update (GtkAdjustment *adjustment, gpointer data); +static void glasstile (GDrawable *drawable); + +/* --- Variables --- */ +GPlugInInfo PLUG_IN_INFO = +{ + NULL, /* init_proc */ + NULL, /* quit_proc */ + query, /* query_proc */ + run, /* run_proc */ +}; +static GlassValues gtvals = +{ + 20, /* tile width */ + 20 /* tile height */ +}; +static GlassInterface gt_int = +{ + FALSE /* run */ +}; + +/* --- Functions --- */ + +MAIN () + +static void query () +{ + static GParamDef args[] = + { + { PARAM_INT32, "run_mode", "Interactive, non-interactive" }, + { PARAM_IMAGE, "image", "Input image (unused)" }, + { PARAM_DRAWABLE, "drawable", "Input drawable" }, + { PARAM_INT32, "tilex", "Tile width (10 - 50)" }, + { PARAM_INT32, "tiley", "Tile height (10 - 50)" }, + }; + static GParamDef *return_vals = NULL; + static int nargs = sizeof (args) / sizeof (args[0]); + static int nreturn_vals = 0; + + gimp_install_procedure ("plug_in_glasstile", + "Divide the image into square glassblocks", + "More here later", + "Karl-Johan Andersson", /* Author */ + "Karl-Johan Andersson", /* Copyright */ + "1997", + "/Filters/Distorts/Glass Tile", + "RGB*, GRAY*", + PROC_PLUG_IN, + nargs, nreturn_vals, + args, return_vals); +} + +static void run (gchar *name, + gint nparams, + GParam *param, + gint *nreturn_vals, + GParam **return_vals) +{ + static GParam values[1]; + GDrawable *drawable; + GRunModeType run_mode; + GStatusType status = STATUS_SUCCESS; + + run_mode = param[0].data.d_int32; + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = PARAM_STATUS; + values[0].data.d_status = status; + + /* Get the specified drawable */ + drawable = gimp_drawable_get (param[2].data.d_drawable); + + switch (run_mode) + { + case RUN_INTERACTIVE: + /* Possibly retrieve data */ + gimp_get_data ("plug_in_glasstile", >vals); + + /* First acquire information with a dialog */ + if (! glass_dialog ()) + { + gimp_drawable_detach (drawable); + return; + } + break; + + case RUN_NONINTERACTIVE: + /* Make sure all the arguments are there! */ + if (nparams != 5) + status = STATUS_CALLING_ERROR; + if (status == STATUS_SUCCESS) + { + gtvals.xblock = (gint) param[3].data.d_int32; + gtvals.yblock = (gint) param[4].data.d_int32; + } + if (gtvals.xblock < 10 || gtvals.xblock > 50) + status = STATUS_CALLING_ERROR; + if (gtvals.yblock < 10 || gtvals.yblock > 50) + status = STATUS_CALLING_ERROR; + break; + + case RUN_WITH_LAST_VALS: + /* Possibly retrieve data */ + gimp_get_data ("plug_in_glasstile", >vals); + break; + + default: + break; + } + + if (status == STATUS_SUCCESS) + { + /* Make sure that the drawable is gray or RGB color */ + if (gimp_drawable_color (drawable->id) || gimp_drawable_gray (drawable->id)) + { + gimp_progress_init ("Glass Tile..."); + gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1)); + + glasstile (drawable); + + if (run_mode != RUN_NONINTERACTIVE) + gimp_displays_flush (); + /* Store data */ + if (run_mode == RUN_INTERACTIVE) + gimp_set_data ("plug_in_glasstile", >vals, sizeof (GlassValues)); + } + else + { + /* gimp_message ("glasstile: cannot operate on indexed color images"); */ + status = STATUS_EXECUTION_ERROR; + } + } + + values[0].data.d_status = status; + + gimp_drawable_detach (drawable); +} + +static gint glass_dialog () +{ + GtkWidget *dlg; + GtkWidget *label; + GtkWidget *button; + GtkWidget *scale; + GtkWidget *frame; + GtkWidget *table; + GtkObject *adjustment; + gchar **argv; + gint argc; + + argc = 1; + argv = g_new (gchar *, 1); + argv[0] = g_strdup ("glasstile"); + + gtk_init (&argc, &argv); + gtk_rc_parse (gimp_gtkrc ()); + + dlg = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (dlg), "Glass Tile"); + gtk_window_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE); + gtk_signal_connect (GTK_OBJECT (dlg), "destroy", + (GtkSignalFunc) glass_close_callback, + NULL); + + /* Action area */ + button = gtk_button_new_with_label ("OK"); + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + gtk_signal_connect (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) glass_ok_callback, + dlg); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0); + gtk_widget_grab_default (button); + gtk_widget_show (button); + + button = gtk_button_new_with_label ("Cancel"); + GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); + gtk_signal_connect_object (GTK_OBJECT (button), "clicked", + (GtkSignalFunc) gtk_widget_destroy, + GTK_OBJECT (dlg)); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0); + gtk_widget_show (button); + + /* Parameter settings */ + frame = gtk_frame_new ("Parameter Settings"); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); + gtk_container_border_width (GTK_CONTAINER (frame), 10); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0); + table = gtk_table_new (2, 2, FALSE); /* table height, width */ + gtk_container_border_width (GTK_CONTAINER (table), 10); + gtk_container_add (GTK_CONTAINER (frame), table); + + /* Horizontal scale - Width */ + label = gtk_label_new ("Tile Width"); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL, 0, 5, 0); + /* xStart, xEnd, yStart, yEnd */ + + adjustment = gtk_adjustment_new (gtvals.xblock, 10, 50, 1, 1, 0); + gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed", + (GtkSignalFunc) glass_scale_update, + &(gtvals.xblock)); + scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment)); + gtk_widget_set_usize (scale, 150, 30); + gtk_table_attach (GTK_TABLE (table), scale, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); + gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); + gtk_scale_set_digits (GTK_SCALE (scale), 0); + gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE); + gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); + gtk_widget_show (label); + gtk_widget_show (scale); + + /* Horizontal scale - Height */ + label = gtk_label_new ("Tile Height"); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, 0, 5, 0); + + adjustment = gtk_adjustment_new (gtvals.yblock, 10, 50, 1, 1, 0); + gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed", + (GtkSignalFunc) glass_scale_update, + &(gtvals.yblock)); + scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment)); + gtk_widget_set_usize (scale, 150, 30); + gtk_table_attach (GTK_TABLE (table), scale, 1, 2, 1, 2, GTK_FILL, 0, 0, 0); + gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); + gtk_scale_set_digits (GTK_SCALE (scale), 0); + gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE); + gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP); + gtk_widget_show (label); + gtk_widget_show (scale); + + gtk_widget_show (frame); + gtk_widget_show (table); + gtk_widget_show (dlg); + + gtk_main (); + gdk_flush (); + + return gt_int.run; +} + +/* - Interface functions - */ +static void glass_close_callback (GtkWidget *widget, gpointer data) +{ + gtk_main_quit (); +} + +static void glass_ok_callback (GtkWidget *widget, gpointer data) +{ + gt_int.run = TRUE; + gtk_widget_destroy (GTK_WIDGET (data)); +} + +static void glass_scale_update (GtkAdjustment *adjustment, gpointer data) +{ + gint *dptr = (gint*) data; + *dptr = (gint) adjustment->value; +} + +/* - Filter function - */ +static void glasstile (GDrawable *drawable) +{ + GPixelRgn srcPR, destPR; + gint width, height; + gint bytes; + guchar *dest, *d, *ad; + guchar *cur_row; + gint row, col, i, iwidth; + gint x1, y1, x2, y2; + + gint rutbredd, xpixel1, xpixel2; + gint ruthojd , ypixel2; + gint xhalv, xoffs, xmitt, xplus; + gint yhalv, yoffs, ymitt, yplus, cbytes; + + /* Get the input area. This is the bounding box of the selection in + * the image (or the entire image if there is no selection). Only + * operating on the input area is simply an optimization. It doesn't + * need to be done for correct operation. (It simply makes it go + * faster, since fewer pixels need to be operated on). + */ + gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2); + + /* Get the size of the input image. (This will/must be the same + * as the size of the output image. + */ + width = drawable->width; + height = drawable->height; + bytes = drawable->bpp; + + /* allocate row buffers */ + cur_row = (guchar *) malloc ((x2 - x1) * bytes); + dest = (guchar *) malloc ((x2 - x1) * bytes); + ad = (guchar *) malloc ((x2 - x1) * bytes); + + /* initialize the pixel regions */ + gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE); + gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE); + + rutbredd = gtvals.xblock; + ruthojd = gtvals.yblock; + + xhalv = rutbredd / 2; + yhalv = ruthojd / 2; + cbytes = bytes; + if (cbytes%2 == 0) cbytes--; + iwidth = width - x1; + xplus = rutbredd % 2; + yplus = ruthojd % 2; + + ymitt = y1; + yoffs = 0; + /* Loop through the rows */ + for (row = y1; row < y2; row++) + { + d = dest; + ypixel2 = ymitt + yoffs * 2; + if (ypixel2 < height) + gimp_pixel_rgn_get_row (&srcPR, cur_row, x1, ypixel2, iwidth); + else + gimp_pixel_rgn_get_row (&srcPR, cur_row, x1, y2-1, iwidth); + if (cbytes != bytes) /* Alpha check */ + gimp_pixel_rgn_get_row (&srcPR, ad, x1, row, (x2-x1)); + + yoffs++; + if (yoffs == yhalv) { + ymitt += ruthojd; + yoffs =- yhalv; + yoffs -= yplus; + } + xmitt = 0; + xoffs = 0; + for (col = 0; col < (x2 - x1); col++) /* one pixel */ + { + xpixel1 = (xmitt + xoffs) * bytes; + xpixel2 = (xmitt + xoffs * 2) * bytes; + if (xpixel2 < ((x2 - x1) * bytes)) { + for (i = 0; i < cbytes; i++) + d[xpixel1 + i] = cur_row[xpixel2 + i]; + } + else { + for (i = 0; i < cbytes; i++) + d[xpixel1 + i]=cur_row[xpixel1 + i]; + } + if (cbytes != bytes) /* Alpha channel unchanged */ + d[xpixel1 + cbytes] = ad[xpixel1 + cbytes]; + xoffs++; + if (xoffs == xhalv) { + xmitt += rutbredd; + xoffs =- xhalv; + xoffs -= xplus; + } + } + /* Store the dest */ + gimp_pixel_rgn_set_row (&destPR, dest, x1, row, iwidth); + + if ((row % 5) == 0) + gimp_progress_update ((double) row / (double) (y2 - y1)); + } + + /* Update region */ + gimp_drawable_flush (drawable); + gimp_drawable_merge_shadow (drawable->id, TRUE); + gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1)); + + free (cur_row); + free (dest); + free (ad); +} diff --git a/plug-ins/illusion/Makefile.am b/plug-ins/illusion/Makefile.am new file mode 100644 index 0000000000..9613ec74c9 --- /dev/null +++ b/plug-ins/illusion/Makefile.am @@ -0,0 +1,42 @@ +## Process this file with automake to produce Makefile.in + +pluginlibdir = $(gimpplugindir)/plug-ins + +pluginlib_PROGRAMS = illusion + +illusion_SOURCES = \ + illusion.c + +INCLUDES = \ + $(X_CFLAGS) \ + -I$(top_srcdir) \ + -I$(includedir) + +LDADD = \ + $(top_builddir)/libgimp/libgimpui.la \ + $(top_builddir)/libgimp/libgimp.la \ + $(X_LIBS) \ + \ + -lc + +DEPS = \ + $(top_builddir)/libgimp/libgimpui.la \ + $(top_builddir)/libgimp/libgimp.la + +illusion_DEPENDENCIES = $(DEPS) + +.PHONY: files + +files: + @files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \ + echo $$p; \ + done + @for subdir in $(SUBDIRS); do \ + files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \ + for file in $$files; do \ + echo $$subdir/$$file; \ + done; \ + done + + + diff --git a/plug-ins/illusion/illusion.c b/plug-ins/illusion/illusion.c new file mode 100644 index 0000000000..277c15ead8 --- /dev/null +++ b/plug-ins/illusion/illusion.c @@ -0,0 +1,368 @@ +/******************************************************************************* + + illusion.c -- This is a plug-in for the GIMP 1.0 + + Copyright (C) 1997 Hirotsuna Mizuno + s1041150@u-aizu.ac.jp + + 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 2 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, write to the Free Software Foundation, Inc., + 675 Mass Ave, Cambridge, MA 02139, USA. + +*******************************************************************************/ + +#include +#include +#include +#include "libgimp/gimp.h" + +#define PLUG_IN_NAME "plug_in_illusion" +#define PLUG_IN_VERSION "v0.7 (Dec. 25 1997)" + +#define DIALOG_CAPTION "Illusion" + +#ifndef PI +#define PI 3.141592653589793238462643383279 +#endif +#ifndef PI_2 +#define PI_2 (PI*2) +#endif + +/******************************************************************************/ + +static void query( void ); +static void run( char *, int, GParam *, int *, GParam ** ); +static void filter( GDrawable *drawable ); +static int dialog( void ); + +/******************************************************************************/ + +typedef struct { + gint32 division; +} parameter_t; + +/******************************************************************************/ + +GPlugInInfo PLUG_IN_INFO = { + NULL, /* init_proc */ + NULL, /* quit_proc */ + query, /* query_proc */ + run, /* run_proc */ +}; + +static parameter_t parameters = { + 8 +}; + +static gint image_width; +static gint image_height; +static gint image_bpp; +static gint image_has_alpha; +static gint select_x1; +static gint select_y1; +static gint select_x2; +static gint select_y2; +static gint select_width; +static gint select_height; +static gdouble center_x; +static gdouble center_y; + +/******************************************************************************/ + +MAIN(); + +/******************************************************************************/ + +static void query( void ) +{ + static int nargs = 4; + static GParamDef args[] = { + { PARAM_INT32, "run_mode", "interactive / non-interactive" }, + { PARAM_IMAGE, "image", "input image" }, + { PARAM_DRAWABLE, "drawable", "input drawable" }, + { PARAM_INT32, "division", "the number of divisions" } + }; + static int nreturn_vals = 0; + static GParamDef *return_vals = NULL; + + gimp_install_procedure( + PLUG_IN_NAME, + "produce illusion", + "produce illusion", + "Hirotsuna Mizuno ", + "Hirotsuna Mizuno", + PLUG_IN_VERSION, + "/Filters/Effects/Illusion", + "RGB*, GRAY*", + PROC_PLUG_IN, + nargs, + nreturn_vals, + args, + return_vals + ); +} + +/******************************************************************************/ + +static void run( char *name, + int paramc, + GParam *params, + int *returnc, + GParam **returns ) +{ + GDrawable *drawable; + GRunModeType run_mode; + static GParam returnv[1]; + GStatusType status = STATUS_SUCCESS; + + run_mode = params[0].data.d_int32; + drawable = gimp_drawable_get( params[2].data.d_drawable ); + *returnc = 1; + *returns = returnv; + + /* get the drawable info */ + image_width = gimp_drawable_width( drawable->id ); + image_height = gimp_drawable_height( drawable->id ); + image_bpp = gimp_drawable_bpp( drawable->id ); + image_has_alpha = gimp_drawable_has_alpha( drawable->id ); + gimp_drawable_mask_bounds( drawable->id, + &select_x1, &select_y1, &select_x2, &select_y2 ); + select_width = select_x2 - select_x1; + select_height = select_y2 - select_y1; + center_x = select_x1 + (gdouble)select_width / 2; + center_y = select_y1 + (gdouble)select_height / 2; + + /* switch the run mode */ + switch( run_mode ){ + + case RUN_INTERACTIVE: + gimp_get_data( PLUG_IN_NAME, ¶meters ); + if( ! dialog() ) return; + gimp_set_data( PLUG_IN_NAME, ¶meters, sizeof( parameter_t ) ); + break; + + case RUN_NONINTERACTIVE: + if( paramc != 4 ){ + status = STATUS_CALLING_ERROR; + } else { + parameters.division = params[3].data.d_int32; + } + break; + + case RUN_WITH_LAST_VALS: + gimp_get_data( PLUG_IN_NAME, ¶meters ); + break; + + } + + if( status == STATUS_SUCCESS ){ + + if( gimp_drawable_color( drawable->id ) || + gimp_drawable_gray( drawable->id ) ){ + + gimp_tile_cache_ntiles( 2 * ( drawable->width / gimp_tile_width() + 1 ) ); + filter( drawable ); + if( run_mode != RUN_NONINTERACTIVE ) gimp_displays_flush (); + + } else { + + status = STATUS_EXECUTION_ERROR; + + } + + } + + returnv[0].type = PARAM_STATUS; + returnv[0].data.d_status = status; + + gimp_drawable_detach( drawable ); +} + +/******************************************************************************/ + +static void filter( GDrawable *drawable ) +{ + GPixelRgn srcPR, destPR; + guchar **pixels; + guchar **destpixels; + gint x, y, b; + gint xx, yy; + gdouble scale, radius, cx, cy, angle, offset; + + gimp_pixel_rgn_init( &srcPR, drawable, + 0, 0, image_width, image_height, FALSE, FALSE ); + gimp_pixel_rgn_init( &destPR, drawable, + 0, 0, image_width, image_height, TRUE, TRUE ); + + pixels = (guchar **)malloc( image_height * sizeof(guchar *) ); + destpixels = (guchar **)malloc( image_height * sizeof(guchar *) ); + for( y = 0; y < image_height; y++ ){ + pixels[y] = (guchar *)malloc( image_width * image_bpp ); + destpixels[y] = (guchar *)malloc( image_width * image_bpp ); + gimp_pixel_rgn_get_row( &srcPR, pixels[y], 0, y, image_width ); + } + + /* + for( y = select_y1; y < select_y2; y++ ){ + for( x = select_x1; x < select_x2; x++ ){ + for( b = 0; b < image_bpp; b++ ){ + destpixels[y][x*image_bpp+b] = 0; + } + } + } + */ + + gimp_progress_init( PLUG_IN_NAME ); + + scale = sqrt(select_width*select_width+select_height*select_height) / 2; + offset = (gint)(scale / 2); + + for( y = select_y1; y < select_y2; y++ ){ + cy = ((gdouble)y - center_y) / scale; + for( x = select_x1; x < select_x2; x++ ){ + cx = ((gdouble)x - center_x) / scale; + angle = floor( atan2(cy,cx) * parameters.division / PI_2 ) + * PI_2 / parameters.division + ( PI / parameters.division ); + radius = sqrt((gdouble)(cx*cx+cy*cy)); + xx = x - offset * cos( angle ); + yy = y - offset * sin( angle ); + if( xx < 0 ) xx = 0; + else if( image_width <= xx ) xx = image_width - 1; + if( yy < 0 ) yy = 0; + else if( image_height <= yy ) yy = image_height - 1; + for( b = 0; b < image_bpp; b++ ) + destpixels[y][x*image_bpp+b] = + (1-radius)*pixels[y][x*image_bpp+b] + + radius*pixels[yy][xx*image_bpp+b]; + } + gimp_pixel_rgn_set_row (&destPR, destpixels[y], 0, y, image_width ); + gimp_progress_update ( (double)( y - select_y1 ) / (double)select_height ); + } + + gimp_drawable_flush( drawable ); + gimp_drawable_merge_shadow( drawable->id, TRUE ); + gimp_drawable_update( drawable->id, + select_x1, select_y1, select_width, select_height ); + + for( y = select_y1; y < select_y2; y++ ) free( pixels[y-select_y1] ); + free( pixels ); + for( y = select_y1; y < select_y2; y++ ) free( destpixels[y-select_y1] ); + free( destpixels ); +} + +/******************************************************************************/ + +static int dialog_status; + +static GtkWidget *entry_division; + +static void dialog_destroy_handler( GtkWidget *widget, gpointer *data ) +{ + gtk_main_quit(); +} + +static void dialog_ok_handler( GtkWidget *widget, gpointer *data ) +{ + dialog_status = TRUE; + + parameters.division = + (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_division ) ) ); + + gtk_widget_destroy( GTK_WIDGET( data ) ); +} + +static void dialog_cancel_handler( GtkWidget *widget, gpointer *data ) +{ + dialog_status = FALSE; + gtk_widget_destroy( GTK_WIDGET( data ) ); +} + +/******************************************************************************/ + +static int dialog( void ) +{ + GtkWidget *window; + + dialog_status = FALSE; + + { + gint argc = 1; + gchar **argv = g_new( gchar *, 1 ); + argv[0] = g_strdup( DIALOG_CAPTION ); + gtk_init( &argc, &argv ); + } + + /* dialog window */ + window = gtk_dialog_new(); + gtk_signal_connect( GTK_OBJECT( window ), "destroy", + GTK_SIGNAL_FUNC( dialog_destroy_handler ), NULL ); + gtk_container_border_width( GTK_CONTAINER( window ), 0 ); + gtk_container_border_width( GTK_CONTAINER( GTK_DIALOG( window )->vbox ), 5 ); + + { + /* buttons */ + GtkWidget *button; + + /* ok button */ + button = gtk_button_new_with_label( "OK" ); + gtk_signal_connect_object( GTK_OBJECT( button ), "clicked", + GTK_SIGNAL_FUNC( dialog_ok_handler ), + GTK_OBJECT( window ) ); + GTK_WIDGET_SET_FLAGS( button, GTK_CAN_DEFAULT ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->action_area ), + button, TRUE, TRUE, 0 ); + gtk_widget_grab_default( button ); + gtk_widget_show( button ); + + /* cancel button */ + button = gtk_button_new_with_label( "Cancel" ); + gtk_signal_connect_object( GTK_OBJECT( button ), "clicked", + GTK_SIGNAL_FUNC( dialog_cancel_handler ), + GTK_OBJECT( window )) ; + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->action_area ), + button, TRUE, TRUE, 0 ); + gtk_widget_show( button ); + } + + { + /* text boxes */ + GtkWidget *table; + GtkWidget *label; + char buffer[32]; + + /* table */ + table = gtk_table_new( 1, 2, FALSE ); + gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); + gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->vbox ), + table, TRUE, TRUE, 0 ); + gtk_widget_show( table ); + + /* tile width */ + label = gtk_label_new( "division: " ); + entry_division = gtk_entry_new(); + sprintf( buffer, "%d", parameters.division ); + gtk_entry_set_text( GTK_ENTRY( entry_division ), buffer ); + gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 0, 1 ); + gtk_table_attach_defaults( GTK_TABLE( table ), entry_division, 1, 2, 0, 1 ); + gtk_widget_show( label ); + gtk_widget_show( entry_division ); + } + + gtk_widget_show( window ); + gtk_main(); + + return dialog_status; +} + +/******************************************************************************/ diff --git a/plug-ins/mathmap/builtins.c b/plug-ins/mathmap/builtins.c index 80fa766952..87162f5c4a 100644 --- a/plug-ins/mathmap/builtins.c +++ b/plug-ins/mathmap/builtins.c @@ -18,67 +18,91 @@ extern int stackp; double color_to_double (int red, int green, int blue) { - return (red << 16) | (green << 8) | blue; + double val; + + *(int*)&val = (red << 16) | (green << 8) | blue; + + return val; } void double_to_color (double val, int *red, int *green, int *blue) { - int color = val; + int color = *(int*)&val; *red = color >> 16; *green = (color >> 8) & 0xff; *blue = color & 0xff; } -void -builtin_if (double arg) +int +red_component (double val) { - if (stack[stackp - 3] != 0.0) - stack[stackp - 3] = stack[stackp - 2]; - else - stack[stackp - 3] = stack[stackp - 1]; - stackp -= 2; + int color = *(int*)&val; + + return color >> 16; +} + +int +green_component (double val) +{ + int color = *(int*)&val; + + return (color >> 8) & 0xff; +} + +int +blue_component (double val) +{ + int color = *(int*)&val; + + return color & 0xff; } void -builtin_sin (double arg) +builtin_sin (void *arg) { stack[stackp - 1] = sin(stack[stackp - 1] * M_PI / 180.0); } void -builtin_cos (double arg) +builtin_cos (void *arg) { stack[stackp - 1] = cos(stack[stackp - 1] * M_PI / 180.0); } void -builtin_tan (double arg) +builtin_tan (void *arg) { stack[stackp - 1] = tan(stack[stackp - 1] * M_PI / 180.0); } void -builtin_asin (double arg) +builtin_asin (void *arg) { stack[stackp - 1] = asin(stack[stackp - 1]) * 180.0 / M_PI; } void -builtin_acos (double arg) +builtin_acos (void *arg) { stack[stackp - 1] = acos(stack[stackp - 1]) * 180.0 / M_PI; } void -builtin_atan (double arg) +builtin_atan (void *arg) { stack[stackp - 1] = atan(stack[stackp - 1]) * 180.0 / M_PI; } void -builtin_sign (double arg) +builtin_abs (void *arg) +{ + stack[stackp - 1] = fabs(stack[stackp - 1]); +} + +void +builtin_sign (void *arg) { if (stack[stackp - 1] < 0) stack[stackp - 1] = -1.0; @@ -89,7 +113,7 @@ builtin_sign (double arg) } void -builtin_min (double arg) +builtin_min (void *arg) { if (stack[stackp - 2] >= stack[stackp - 1]) stack[stackp - 2] = stack[stackp - 1]; @@ -97,7 +121,7 @@ builtin_min (double arg) } void -builtin_max (double arg) +builtin_max (void *arg) { if (stack[stackp - 2] <= stack[stackp - 1]) stack[stackp - 2] = stack[stackp - 1]; @@ -105,7 +129,37 @@ builtin_max (double arg) } void -builtin_inintv (double arg) +builtin_or (void *arg) +{ + if (stack[stackp - 2] || stack[stackp - 1]) + stack[stackp - 2] = 1.0; + else + stack[stackp - 2] = 0.0; + --stackp; +} + +void +builtin_and (void *arg) +{ + if (stack[stackp - 2] && stack[stackp - 1]) + stack[stackp - 2] = 1.0; + else + stack[stackp - 2] = 0.0; + --stackp; +} + +void +builtin_less (void *arg) +{ + if (stack[stackp - 2] < stack[stackp - 1]) + stack[stackp - 2] = 1.0; + else + stack[stackp - 2] = 0.0; + --stackp; +} + +void +builtin_inintv (void *arg) { if (stack[stackp - 3] >= stack[stackp - 2] && stack[stackp - 3] <= stack[stackp - 1]) stack[stackp - 3] = 1.0; @@ -115,7 +169,7 @@ builtin_inintv (double arg) } void -builtin_rand (double arg) +builtin_rand (void *arg) { stack[stackp - 2] = (random() / (double)0x7fffffff) * (stack[stackp - 1] - stack[stackp - 2]) + stack[stackp - 2]; @@ -132,20 +186,20 @@ extern int originX, wholeImageHeight; void -builtin_origValXY (double arg) +builtin_origValXY (void *arg) { - int x = stack[stackp - 2], - y = stack[stackp - 1]; - unsigned char pixel[4]; + int x = stack[stackp - 2], + y = stack[stackp - 1]; + unsigned char pixel[4]; - mathmap_get_pixel(x + originX + middleX, y + originY + middleY, pixel); + mathmap_get_pixel(x + originX + middleX, y + originY + middleY, pixel); - stack[stackp - 2] = color_to_double(pixel[0], pixel[1], pixel[2]); - --stackp; + stack[stackp - 2] = color_to_double(pixel[0], pixel[1], pixel[2]); + --stackp; } void -builtin_origValXYIntersample (double arg) +builtin_origValXYIntersample (void *arg) { double x = stack[stackp - 2] + middleX + originX, y = stack[stackp - 1] + middleY + originY; @@ -203,7 +257,7 @@ builtin_origValXYIntersample (double arg) } void -builtin_origValRA (double arg) +builtin_origValRA (void *arg) { int x = cos(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleX, y = sin(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleY; @@ -216,7 +270,7 @@ builtin_origValRA (double arg) } void -builtin_origValRAIntersample (double arg) +builtin_origValRAIntersample (void *arg) { double x = cos(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleX + originX, y = sin(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleY + originY; @@ -276,7 +330,7 @@ builtin_origValRAIntersample (double arg) #else void -builtin_origValXY (double arg) +builtin_origValXY (void *arg) { int x = stack[stackp - 2] + middleX, y = stack[stackp - 1] + middleY; @@ -296,7 +350,7 @@ builtin_origValXY (double arg) } void -builtin_origValXYIntersample (double arg) +builtin_origValXYIntersample (void *arg) { double x = stack[stackp - 2] + middleX, y = stack[stackp - 1] + middleY; @@ -350,7 +404,7 @@ builtin_origValXYIntersample (double arg) } void -builtin_origValRA (double arg) +builtin_origValRA (void *arg) { int x = cos(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleX, y = sin(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleY; @@ -370,7 +424,7 @@ builtin_origValRA (double arg) } void -builtin_origValRAIntersample (double arg) +builtin_origValRAIntersample (void *arg) { double x = cos(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleX, y = sin(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleY; @@ -426,7 +480,52 @@ builtin_origValRAIntersample (double arg) #endif /* _GIMP */ void -builtin_grayColor (double arg) +builtin_red (void *arg) +{ + stack[stackp - 1] = red_component(stack[stackp - 1]) / 255.0; +} + +void +builtin_green (void *arg) +{ + stack[stackp - 1] = green_component(stack[stackp - 1]) / 255.0; +} + +void +builtin_blue (void *arg) +{ + stack[stackp - 1] = blue_component(stack[stackp - 1]) / 255.0; +} + +void +builtin_rgbColor (void *arg) +{ + int redComponent = stack[stackp - 3] * 255, + greenComponent = stack[stackp - 2] * 255, + blueComponent = stack[stackp - 1] * 255; + + stackp -= 2; + + if (redComponent < 0) + redComponent = 0; + else if (redComponent > 255) + redComponent = 255; + + if (greenComponent < 0) + greenComponent = 0; + else if (greenComponent > 255) + greenComponent = 255; + + if (blueComponent < 0) + blueComponent = 0; + else if (blueComponent > 255) + blueComponent = 255; + + stack[stackp - 1] = color_to_double(redComponent, greenComponent, blueComponent); +} + +void +builtin_grayColor (void *arg) { int grayLevel = stack[stackp - 1] * 255; diff --git a/plug-ins/mathmap/builtins.h b/plug-ins/mathmap/builtins.h index 997641772c..4fc84c9628 100644 --- a/plug-ins/mathmap/builtins.h +++ b/plug-ins/mathmap/builtins.h @@ -2,20 +2,27 @@ double color_to_double (int red, int green, int blue); void double_to_color (double val, int *red, int *green, int *blue); -void builtin_if (double arg); -void builtin_sin (double arg); -void builtin_cos (double arg); -void builtin_tan (double arg); -void builtin_asin (double arg); -void builtin_acos (double arg); -void builtin_atan (double arg); -void builtin_sign (double arg); -void builtin_min (double arg); -void builtin_max (double arg); -void builtin_inintv (double arg); -void builtin_rand (double arg); -void builtin_origValXY (double arg); -void builtin_origValXYIntersample (double arg); -void builtin_origValRA (double arg); -void builtin_origValRAIntersample (double arg); -void builtin_grayColor (double arg); +void builtin_sin (void *arg); +void builtin_cos (void *arg); +void builtin_tan (void *arg); +void builtin_asin (void *arg); +void builtin_acos (void *arg); +void builtin_atan (void *arg); +void builtin_abs (void *arg); +void builtin_sign (void *arg); +void builtin_min (void *arg); +void builtin_max (void *arg); +void builtin_or (void *arg); +void builtin_and (void *arg); +void builtin_less (void *arg); +void builtin_inintv (void *arg); +void builtin_rand (void *arg); +void builtin_origValXY (void *arg); +void builtin_origValXYIntersample (void *arg); +void builtin_origValRA (void *arg); +void builtin_origValRAIntersample (void *arg); +void builtin_red (void *arg); +void builtin_green (void *arg); +void builtin_blue (void *arg); +void builtin_rgbColor (void *arg); +void builtin_grayColor (void *arg); diff --git a/plug-ins/mathmap/exprtree.c b/plug-ins/mathmap/exprtree.c index d715932019..bee71ed7e2 100644 --- a/plug-ins/mathmap/exprtree.c +++ b/plug-ins/mathmap/exprtree.c @@ -57,8 +57,8 @@ make_var (char *name) tree->type = EXPR_VAR_BIG_Y; else { - tree->type = EXPR_NUMBER; - tree->val.number = 0.0; + tree->type = EXPR_VARIABLE; + tree->val.var = register_variable(name); } tree->next = 0; @@ -85,12 +85,7 @@ make_function (char *name, exprtree *args) { exprtree *tree = (exprtree*)malloc(sizeof(exprtree)); - if (strcmp(name, "if") == 0) - { - tree->val.func.routine = builtin_if; - tree->val.func.numArgs = 3; - } - else if (strcmp(name, "sin") == 0) + if (strcmp(name, "sin") == 0) { tree->val.func.routine = builtin_sin; tree->val.func.numArgs = 1; @@ -120,6 +115,11 @@ make_function (char *name, exprtree *args) tree->val.func.routine = builtin_atan; tree->val.func.numArgs = 1; } + else if (strcmp(name, "abs") == 0) + { + tree->val.func.routine = builtin_abs; + tree->val.func.numArgs = 1; + } else if (strcmp(name, "sign") == 0) { tree->val.func.routine = builtin_sign; @@ -135,6 +135,21 @@ make_function (char *name, exprtree *args) tree->val.func.routine = builtin_max; tree->val.func.numArgs = 2; } + else if (strcmp(name, "or") == 0) + { + tree->val.func.routine = builtin_or; + tree->val.func.numArgs = 2; + } + else if (strcmp(name, "and") == 0) + { + tree->val.func.routine = builtin_and; + tree->val.func.numArgs = 2; + } + else if (strcmp(name, "less") == 0) + { + tree->val.func.routine = builtin_less; + tree->val.func.numArgs = 2; + } else if (strcmp(name, "inintv") == 0) { tree->val.func.routine = builtin_inintv; @@ -161,6 +176,26 @@ make_function (char *name, exprtree *args) tree->val.func.routine = builtin_origValRA; tree->val.func.numArgs = 2; } + else if (strcmp(name, "red") == 0) + { + tree->val.func.routine = builtin_red; + tree->val.func.numArgs = 1; + } + else if (strcmp(name, "green") == 0) + { + tree->val.func.routine = builtin_green; + tree->val.func.numArgs = 1; + } + else if (strcmp(name, "blue") == 0) + { + tree->val.func.routine = builtin_blue; + tree->val.func.numArgs = 1; + } + else if (strcmp(name, "rgbColor") == 0) + { + tree->val.func.routine = builtin_rgbColor; + tree->val.func.numArgs = 3; + } else if (strcmp(name, "grayColor") == 0) { tree->val.func.routine = builtin_grayColor; @@ -184,6 +219,92 @@ make_function (char *name, exprtree *args) return tree; } +exprtree* +make_sequence (exprtree *left, exprtree *right) +{ + exprtree *tree = (exprtree*)malloc(sizeof(exprtree)); + + tree->type = EXPR_SEQUENCE; + tree->val.operator.left = left; + tree->val.operator.right = right; + + tree->next = 0; + + return tree; +} + +exprtree* +make_assignment (char *name, exprtree *value) +{ + exprtree *tree = (exprtree*)malloc(sizeof(exprtree)); + variable *var = register_variable(name); + + tree->type = EXPR_ASSIGNMENT; + tree->val.assignment.var = var; + tree->val.assignment.value = value; + + tree->next = 0; + + return tree; +} + +exprtree* +make_if_then (exprtree *condition, exprtree *consequence) +{ + exprtree *tree = (exprtree*)malloc(sizeof(exprtree)); + + tree->type = EXPR_IF_THEN; + tree->val.ifExpr.condition = condition; + tree->val.ifExpr.consequence = consequence; + + tree->next = 0; + + return tree; +} + +exprtree* +make_if_then_else (exprtree *condition, exprtree *consequence, exprtree *alternative) +{ + exprtree *tree = (exprtree*)malloc(sizeof(exprtree)); + + tree->type = EXPR_IF_THEN_ELSE; + tree->val.ifExpr.condition = condition; + tree->val.ifExpr.consequence = consequence; + tree->val.ifExpr.alternative = alternative; + + tree->next = 0; + + return tree; +} + +exprtree* +make_while (exprtree *invariant, exprtree *body) +{ + exprtree *tree = (exprtree*)malloc(sizeof(exprtree)); + + tree->type = EXPR_WHILE; + tree->val.whileExpr.invariant = invariant; + tree->val.whileExpr.body = body; + + tree->next = 0; + + return tree; +} + +exprtree* +make_do_while (exprtree *body, exprtree *invariant) +{ + exprtree *tree = (exprtree*)malloc(sizeof(exprtree)); + + tree->type = EXPR_DO_WHILE; + tree->val.whileExpr.invariant = invariant; + tree->val.whileExpr.body = body; + + tree->next = 0; + + return tree; +} + exprtree* arglist_append (exprtree *list1, exprtree *list2) { diff --git a/plug-ins/mathmap/exprtree.h b/plug-ins/mathmap/exprtree.h index acdf5c7dd8..55a077b554 100644 --- a/plug-ins/mathmap/exprtree.h +++ b/plug-ins/mathmap/exprtree.h @@ -1,10 +1,12 @@ #ifndef __EXPRTREE_H__ #define __EXPRTREE_H__ +#include "vars.h" + #ifdef USE_TREE typedef double (*function) (double*); #else -typedef void (*function) (double); +typedef void (*function) (void*); #endif typedef char ident[64]; @@ -16,6 +18,7 @@ typedef struct _exprtree union { double number; + variable *var; struct { int numArgs; @@ -27,33 +30,66 @@ typedef struct _exprtree struct _exprtree *left; struct _exprtree *right; } operator; + struct + { + variable *var; + struct _exprtree *value; + } assignment; + struct + { + struct _exprtree *condition; + struct _exprtree *consequence; + struct _exprtree *alternative; + int label1; + int label2; + } ifExpr; + struct + { + struct _exprtree *invariant; + struct _exprtree *body; + int label1; + int label2; + } whileExpr; } val; struct _exprtree *next; } exprtree; -#define EXPR_NUMBER 1 -#define EXPR_ADD 2 -#define EXPR_SUB 3 -#define EXPR_MUL 4 -#define EXPR_DIV 5 -#define EXPR_MOD 6 -#define EXPR_NEG 7 -#define EXPR_FUNC 8 -#define EXPR_VAR_X 9 -#define EXPR_VAR_Y 10 -#define EXPR_VAR_R 11 -#define EXPR_VAR_A 12 -#define EXPR_VAR_W 13 -#define EXPR_VAR_H 14 -#define EXPR_VAR_BIG_R 15 -#define EXPR_VAR_BIG_X 16 -#define EXPR_VAR_BIG_Y 17 +#define EXPR_NUMBER 1 +#define EXPR_ADD 2 +#define EXPR_SUB 3 +#define EXPR_MUL 4 +#define EXPR_DIV 5 +#define EXPR_MOD 6 +#define EXPR_NEG 7 +#define EXPR_FUNC 8 +#define EXPR_VAR_X 9 +#define EXPR_VAR_Y 10 +#define EXPR_VAR_R 11 +#define EXPR_VAR_A 12 +#define EXPR_VAR_W 13 +#define EXPR_VAR_H 14 +#define EXPR_VAR_BIG_R 15 +#define EXPR_VAR_BIG_X 16 +#define EXPR_VAR_BIG_Y 17 +#define EXPR_SEQUENCE 18 +#define EXPR_ASSIGNMENT 19 +#define EXPR_VARIABLE 20 +#define EXPR_IF_THEN 21 +#define EXPR_IF_THEN_ELSE 22 +#define EXPR_WHILE 23 +#define EXPR_DO_WHILE 24 exprtree* make_number (double num); exprtree* make_var (char *name); exprtree* make_operator (int type, exprtree *left, exprtree *right); exprtree* make_function (char *name, exprtree *args); +exprtree* make_sequence (exprtree *left, exprtree *right); +exprtree* make_assignment (char *name, exprtree *value); +exprtree* make_if_then (exprtree *condition, exprtree *conclusion); +exprtree* make_if_then_else (exprtree *condition, exprtree *conclusion, exprtree *alternative); +exprtree* make_while (exprtree *invariant, exprtree *body); +exprtree* make_do_while (exprtree *body, exprtree *invariant); exprtree* arglist_append (exprtree *list1, exprtree *list2); diff --git a/plug-ins/mathmap/mathmap.c b/plug-ins/mathmap/mathmap.c index 08e210e843..90b8512d29 100644 --- a/plug-ins/mathmap/mathmap.c +++ b/plug-ins/mathmap/mathmap.c @@ -10,6 +10,8 @@ * Copyright (C) 1997 Federico Mena Quintero * federico@nuclecu.unam.mx * + * Version 0.2 + * * 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 2 of the License, or @@ -29,6 +31,7 @@ #include #include #include +#include #include #include @@ -36,6 +39,7 @@ #include "exprtree.h" #include "builtins.h" #include "postfix.h" +#include "scanner.h" /***** Macros *****/ @@ -168,17 +172,37 @@ char *examples[][2] = { { "pond", "origValRA(r+sin(r*30)*3,a)" }, { "enhanced pond", "origValRA(r+(sin(500000/(r+100))*7),a)" }, { "twirl 90", "origValRA(r,a+(r/R-1)*45)" }, - { "sphere", "origValRA(r*(1-inintv(r/(X*2),-0.5,0.5))+X/90*asin(inintv(r/(X*2),-0.5,0.5)*r/X),a)" }, + { "sphere", "p=r/(X*2);origValRA(r*(1-inintv(p,-0.5,0.5))+X/90*asin(inintv(p,-0.5,0.5)*r/X),a)" }, { "jitter", "origValRA(r,a+a%8-4)" }, { "radial mosaic", "origValRA(r-r%5,a-a%5)" }, { "circular slice", "origValRA(r,a+(r%5)-2)" }, { "fisheye", "origValRA(r*r/R,a)" }, { "center shake", "origValXY(x+max(0,cos(x*2))*5*max(0,cos(y*2))*cos(y*10),y+max(0,cos(x*2))*5*max(0,cos(y*2))*cos(x*10))" }, { "scatter", "origValXY(x+rand(-3,3),y+rand(-3,3))" }, + { "darts", "p=origValXY(x,y);p=if inintv((a-9)%36,0,18) then p else rgbColor(1-red(p),1-green(p),1-blue(p)) end;if inintv(r%80,68,80) then p else rgbColor(1-red(p),1-green(p),1-blue(p)) end" }, { "?", "origValRA(r,a+sin(a*10)*20)" }, { "?", "origValRA(r+r%20,a)" }, { "sine wave", "grayColor(sin(r*10)*0.5+0.5)" }, - { "grid", "grayColor(if((x%20)*(y%20),1,0))" }, + { "grid", "grayColor(if (x%20)*(y%20) then 1 else 0 end)" }, + { "moire1", "rgbColor(abs(sin(15*r)+sin(15*a))*0.5,abs(sin(17*r)+sin(17*a))*0.5,abs(sin(19*r)+sin(19*a))*0.5)" }, + { "moire2", "grayColor(sin(x*y)*0.5+0.5)" }, + { "mandelbrot", + "tx=1.5*x/X-0.5; " + "ty=1.5*y/X-0; " + "iter=0; " + "xr=0; " + "xi=0; " + "xrsq=0; " + "xisq=0; " + "while and(less(xrsq+xisq,4),less(iter,31)) " + "do " + "xrsq=xr*xr; " + "xisq=xi*xi; " + "xi=2*xr*xi+ty; " + "xr=xrsq-xisq+tx; " + "iter=iter+1 " + "end; " + "grayColor(iter/32)" }, { 0, 0 } }; @@ -428,12 +452,15 @@ mathmap(void) theExprtree = 0; - yy_scan_string(mmvals.expression); + scanFromString(mmvals.expression); yyparse(); + endScanningFromString(); + if (theExprtree == 0) return; make_postfix(theExprtree); + /* output_postfix(); */ /* Initialize pixel region */ @@ -562,6 +589,11 @@ mathmap(void) iy = (int) cy; currentX = col - sel_x1 - middleX; currentY = row - sel_y1 - middleY; + if (!intersamplingEnabled) + { + currentX += 0.5; + currentY += 0.5; + } calc_ra(); result = eval_postfix(); double_to_color(result, &red, &green, &blue); @@ -623,6 +655,7 @@ mathmap_get_pixel(int x, int y, guchar *pixel) gimp_tile_unref(the_tile, FALSE); the_tile = gimp_drawable_get_tile(drawable, FALSE, newrow, newcol); + assert(the_tile != 0); gimp_tile_ref(the_tile); col = newcol; @@ -730,8 +763,6 @@ mathmap_dialog(void) gtk_widget_set_default_visual(gtk_preview_get_visual()); gtk_widget_set_default_colormap(gtk_preview_get_cmap()); - fprintf(stderr, "here we are5!\n"); - build_preview_source_image(); dialog = gtk_dialog_new(); @@ -895,7 +926,6 @@ dialog_update_preview(void) { double left, right, bottom, top; double dx, dy; - double px, py; double cx, cy; int ix, iy; int x, y; @@ -916,18 +946,16 @@ dialog_update_preview(void) scale_x = (double) (preview_width - 1) / (right - left); scale_y = (double) (preview_height - 1) / (bottom - top); - py = top; - p_ul = wint.wimage; p_lr = wint.wimage + 3 * (preview_width * preview_height - 1); - theExprtree = 0; - - yy_scan_string(mmvals.expression); + scanFromString(mmvals.expression); yyparse(); + endScanningFromString(); + if (theExprtree == 0) return; - + make_postfix(theExprtree); imageWidth = sel_width; @@ -950,10 +978,8 @@ dialog_update_preview(void) imageR = sqrt(imageX * imageX + imageY * imageY); - for (y = 0; y <= preview_height; y++) + for (y = 0; y < preview_height; y++) { - px = left; - for (x = 0; x < preview_width; x++) { double result; @@ -981,7 +1007,7 @@ dialog_update_preview(void) gtk_preview_draw_row(GTK_PREVIEW(wint.preview), p, 0, y, preview_width); p += preview_width * 3; - } /* for */ + } gtk_widget_draw(wint.preview, NULL); gdk_flush(); diff --git a/plug-ins/mathmap/parser.y b/plug-ins/mathmap/parser.y index 84839e99d2..0bcb4e45f5 100644 --- a/plug-ins/mathmap/parser.y +++ b/plug-ins/mathmap/parser.y @@ -12,14 +12,18 @@ extern exprtree *theExprtree; } %token T_IDENT T_NUMBER +%token T_IF T_THEN T_ELSE T_END +%token T_WHILE T_DO +%right ';' +%right '=' %left '+' '-' %left '*' '/' '%' %left NEG %% -start : expr { theExprtree = $1; } +start : expr { theExprtree = $1; } ; expr : T_NUMBER { $$ = $1; } @@ -36,7 +40,20 @@ expr : T_NUMBER { $$ = $1; } $1, $3); } | '-' expr %prec NEG { $$ = make_operator(EXPR_NEG, $2, 0); } | '(' expr ')' { $$ = $2; }; - | T_IDENT '(' arglist ')' { $$ = make_function($1, $3); } + | T_IDENT '(' arglist ')' + { $$ = make_function($1, $3); } + | T_IDENT '=' expr { $$ = make_assignment($1, $3); } + | expr ';' expr { $$ = make_sequence($1, $3); } + | T_IF expr T_THEN expr T_END + { $$ = make_if_then($2, $4); } + | T_IF expr T_THEN expr T_ELSE expr T_END + { $$ = make_if_then_else($2, + $4, + $6); } + | T_WHILE expr T_DO expr T_END + { $$ = make_while($2, $4); } + | T_DO expr T_WHILE expr T_END + { $$ = make_do_while($2, $4); } ; arglist : { $$ = 0; } diff --git a/plug-ins/mathmap/postfix.c b/plug-ins/mathmap/postfix.c index 23f5acdd7b..019c7d80cb 100644 --- a/plug-ins/mathmap/postfix.c +++ b/plug-ins/mathmap/postfix.c @@ -1,5 +1,9 @@ #include #include +#include + +#include "builtins.h" +#include "vars.h" #include "postfix.h" @@ -24,144 +28,184 @@ int exprp, exprlen; void -stack_push (double arg) +stack_push (double *arg) { - stack[stackp++] = arg; + stack[stackp++] = *arg; } void -stack_add (double arg) +stack_pop (void *arg) +{ + --stackp; +} + +void +stack_jmp (int *arg) +{ + exprp = *arg - 1; +} + +void +stack_jez (int *arg) +{ + if (stack[--stackp] == 0.0) + exprp = *arg - 1; +} + +void +stack_jnez (int *arg) +{ + if (stack[--stackp] != 0.0) + exprp = *arg - 1; +} + +void +stack_add (void *arg) { stack[stackp - 2] = stack[stackp - 2] + stack[stackp - 1]; --stackp; } void -stack_add_i (double arg) +stack_add_i (double *arg) { - stack[stackp - 1] += arg; + stack[stackp - 1] += *arg; } void -stack_sub (double arg) +stack_sub (void *arg) { stack[stackp - 2] = stack[stackp - 2] - stack[stackp - 1]; --stackp; } void -stack_sub_i (double arg) +stack_sub_i (double *arg) { - stack[stackp - 1] -= arg; + stack[stackp - 1] -= *arg; } void -stack_neg (double arg) +stack_neg (void *arg) { stack[stackp - 1] = -stack[stackp - 1]; } void -stack_mul (double arg) +stack_mul (void *arg) { stack[stackp - 2] = stack[stackp - 2] * stack[stackp - 1]; --stackp; } void -stack_mul_i (double arg) +stack_mul_i (double *arg) { - stack[stackp - 1] *= arg; + stack[stackp - 1] *= *arg; } void -stack_div (double arg) +stack_div (void *arg) { stack[stackp - 2] = stack[stackp - 2] / stack[stackp - 1]; --stackp; } void -stack_div_i (double arg) +stack_div_i (double *arg) { - stack[stackp - 1] /= arg; + stack[stackp - 1] /= *arg; } void -stack_mod (double arg) +stack_mod (void *arg) { stack[stackp - 2] = fmod(stack[stackp - 2], stack[stackp - 1]); --stackp; } void -stack_mod_i (double arg) +stack_mod_i (double *arg) { - stack[stackp - 1] = fmod(stack[stackp - 1], arg); + stack[stackp - 1] = fmod(stack[stackp - 1], *arg); } void -stack_var_x (double arg) +stack_var_x (void *arg) { stack[stackp++] = currentX; } void -stack_var_y (double arg) +stack_var_y (void *arg) { stack[stackp++] = currentY; } void -stack_var_r (double arg) +stack_var_r (void *arg) { stack[stackp++] = currentR; } void -stack_var_a (double arg) +stack_var_a (void *arg) { stack[stackp++] = currentA; } void -stack_var_w (double arg) +stack_var_w (void *arg) { stack[stackp++] = imageWidth; } void -stack_var_h (double arg) +stack_var_h (void *arg) { stack[stackp++] = imageHeight; } void -stack_var_big_r (double arg) +stack_var_big_r (void *arg) { stack[stackp++] = imageR; } void -stack_var_big_x (double arg) +stack_var_big_x (void *arg) { stack[stackp++] = imageX; } void -stack_var_big_y (double arg) +stack_var_big_y (void *arg) { stack[stackp++] = imageY; } +void +stack_variable (variable *var) +{ + stack[stackp++] = var->value; +} + +void +stack_assign (variable *var) +{ + var->value = stack[stackp - 1]; +} + void make_postfix_recursive (exprtree *tree) { + static double theZeroValue = 0.0; + switch (tree->type) { case EXPR_NUMBER : - expression[exprp].func = stack_push; - expression[exprp].arg = tree->val.number; + expression[exprp].func = (stackfunc)stack_push; + expression[exprp].arg = &tree->val.number; ++exprp; break; @@ -169,8 +213,8 @@ make_postfix_recursive (exprtree *tree) make_postfix_recursive(tree->val.operator.left); if (tree->val.operator.right->type == EXPR_NUMBER) { - expression[exprp].func = stack_add_i; - expression[exprp].arg = tree->val.operator.right->val.number; + expression[exprp].func = (stackfunc)stack_add_i; + expression[exprp].arg = &tree->val.operator.right->val.number; } else { @@ -184,8 +228,8 @@ make_postfix_recursive (exprtree *tree) make_postfix_recursive(tree->val.operator.left); if (tree->val.operator.right->type == EXPR_NUMBER) { - expression[exprp].func = stack_sub_i; - expression[exprp].arg = tree->val.operator.right->val.number; + expression[exprp].func = (stackfunc)stack_sub_i; + expression[exprp].arg = &tree->val.operator.right->val.number; } else { @@ -196,16 +240,17 @@ make_postfix_recursive (exprtree *tree) break; case EXPR_NEG : + /* if (tree->val.operator.left->type == EXPR_NUMBER) { - expression[exprp].func = stack_push; + expression[exprp].func = (stackfunc)stack_push; expression[exprp].arg = -tree->val.operator.left->val.number; } else - { + { */ make_postfix_recursive(tree->val.operator.left); expression[exprp].func = stack_neg; - } + /* } */ ++exprp; break; @@ -213,8 +258,8 @@ make_postfix_recursive (exprtree *tree) make_postfix_recursive(tree->val.operator.left); if (tree->val.operator.right->type == EXPR_NUMBER) { - expression[exprp].func = stack_mul_i; - expression[exprp].arg = tree->val.operator.right->val.number; + expression[exprp].func = (stackfunc)stack_mul_i; + expression[exprp].arg = &tree->val.operator.right->val.number; } else { @@ -228,8 +273,8 @@ make_postfix_recursive (exprtree *tree) make_postfix_recursive(tree->val.operator.left); if (tree->val.operator.right->type == EXPR_NUMBER) { - expression[exprp].func = stack_div_i; - expression[exprp].arg = tree->val.operator.right->val.number; + expression[exprp].func = (stackfunc)stack_div_i; + expression[exprp].arg = &tree->val.operator.right->val.number; } else { @@ -243,8 +288,8 @@ make_postfix_recursive (exprtree *tree) make_postfix_recursive(tree->val.operator.left); if (tree->val.operator.right->type == EXPR_NUMBER) { - expression[exprp].func = stack_mod_i; - expression[exprp].arg = tree->val.operator.right->val.number; + expression[exprp].func = (stackfunc)stack_mod_i; + expression[exprp].arg = &tree->val.operator.right->val.number; } else { @@ -304,6 +349,85 @@ make_postfix_recursive (exprtree *tree) break; } + case EXPR_VARIABLE : + expression[exprp].func = (stackfunc)stack_variable; + expression[exprp].arg = tree->val.var; + ++exprp; + break; + + case EXPR_ASSIGNMENT : + make_postfix_recursive(tree->val.assignment.value); + expression[exprp].func = (stackfunc)stack_assign; + expression[exprp].arg = tree->val.assignment.var; + ++exprp; + break; + + case EXPR_SEQUENCE : + make_postfix_recursive(tree->val.operator.left); + expression[exprp++].func = stack_pop; + make_postfix_recursive(tree->val.operator.right); + break; + + case EXPR_IF_THEN : + make_postfix_recursive(tree->val.ifExpr.condition); + expression[exprp].func = (stackfunc)stack_jez; + expression[exprp].arg = &tree->val.ifExpr.label1; + ++exprp; + make_postfix_recursive(tree->val.ifExpr.consequence); + expression[exprp].func = (stackfunc)stack_jmp; + expression[exprp].arg = &tree->val.ifExpr.label2; + ++exprp; + tree->val.ifExpr.label1 = exprp; + expression[exprp].func = (stackfunc)stack_push; + expression[exprp].arg = &theZeroValue; + ++exprp; + tree->val.ifExpr.label2 = exprp; + break; + + case EXPR_IF_THEN_ELSE : + make_postfix_recursive(tree->val.ifExpr.condition); + expression[exprp].func = (stackfunc)stack_jez; + expression[exprp].arg = &tree->val.ifExpr.label1; + ++exprp; + make_postfix_recursive(tree->val.ifExpr.consequence); + expression[exprp].func = (stackfunc)stack_jmp; + expression[exprp].arg = &tree->val.ifExpr.label2; + ++exprp; + tree->val.ifExpr.label1 = exprp; + make_postfix_recursive(tree->val.ifExpr.alternative); + tree->val.ifExpr.label2 = exprp; + break; + + case EXPR_WHILE : + tree->val.whileExpr.label1 = exprp; + make_postfix_recursive(tree->val.whileExpr.invariant); + expression[exprp].func = (stackfunc)stack_jez; + expression[exprp].arg = &tree->val.whileExpr.label2; + ++exprp; + make_postfix_recursive(tree->val.whileExpr.body); + expression[exprp++].func = stack_pop; + expression[exprp].func = (stackfunc)stack_jmp; + expression[exprp].arg = &tree->val.whileExpr.label1; + ++exprp; + tree->val.whileExpr.label2 = exprp; + expression[exprp].func = (stackfunc)stack_push; + expression[exprp].arg = &theZeroValue; + ++exprp; + break; + + case EXPR_DO_WHILE : + tree->val.whileExpr.label1 = exprp; + make_postfix_recursive(tree->val.whileExpr.body); + expression[exprp++].func = stack_pop; + make_postfix_recursive(tree->val.whileExpr.invariant); + expression[exprp].func = (stackfunc)stack_jnez; + expression[exprp].arg = &tree->val.whileExpr.label1; + ++exprp; + expression[exprp].func = (stackfunc)stack_push; + expression[exprp].arg = &theZeroValue; + ++exprp; + break; + default : fprintf(stderr, "illegal expr\n"); } @@ -317,6 +441,107 @@ make_postfix (exprtree *tree) exprlen = exprp; } +void +output_postfix (void) +{ + int i; + + printf("-------------------------\n"); + + for (i = 0; i < exprlen; ++i) + { + printf("%d ", i); + if (expression[i].func == (stackfunc)stack_push) + printf("push %f\n", *(double*)expression[i].arg); + else if (expression[i].func == stack_pop) + printf("pop\n"); + else if (expression[i].func == (stackfunc)stack_jmp) + printf("jmp %d\n", *(int*)expression[i].arg); + else if (expression[i].func == (stackfunc)stack_jez) + printf("jez %d\n", *(int*)expression[i].arg); + else if (expression[i].func == (stackfunc)stack_jnez) + printf("jnez %d\n", *(int*)expression[i].arg); + else if (expression[i].func == stack_add) + printf("add\n"); + else if (expression[i].func == (stackfunc)stack_add_i) + printf("addi %f\n", *(double*)expression[i].arg); + else if (expression[i].func == stack_sub) + printf("sub\n"); + else if (expression[i].func == (stackfunc)stack_sub_i) + printf("subi %f\n", *(double*)expression[i].arg); + else if (expression[i].func == stack_neg) + printf("neg\n"); + else if (expression[i].func == stack_mul) + printf("mul\n"); + else if (expression[i].func == (stackfunc)stack_mul_i) + printf("muli %f\n", *(double*)expression[i].arg); + else if (expression[i].func == stack_div) + printf("div\n"); + else if (expression[i].func == (stackfunc)stack_div_i) + printf("divi %f\n", *(double*)expression[i].arg); + else if (expression[i].func == stack_mod) + printf("mod\n"); + else if (expression[i].func == (stackfunc)stack_mod_i) + printf("modi %f\n", *(double*)expression[i].arg); + else if (expression[i].func == stack_var_x) + printf("push x\n"); + else if (expression[i].func == stack_var_y) + printf("push y\n"); + else if (expression[i].func == stack_var_r) + printf("push r\n"); + else if (expression[i].func == stack_var_a) + printf("push a\n"); + else if (expression[i].func == stack_var_w) + printf("push w\n"); + else if (expression[i].func == stack_var_h) + printf("push h\n"); + else if (expression[i].func == stack_var_big_r) + printf("push R\n"); + else if (expression[i].func == stack_var_big_x) + printf("push X\n"); + else if (expression[i].func == stack_var_big_y) + printf("push Y\n"); + else if (expression[i].func == (stackfunc)stack_variable) + printf("push %s\n", ((variable*)expression[i].arg)->name); + else if (expression[i].func == (stackfunc)stack_assign) + printf("sto %s\n", ((variable*)expression[i].arg)->name); + else if (expression[i].func == builtin_sin) + printf("sin\n"); + else if (expression[i].func == builtin_cos) + printf("cos\n"); + else if (expression[i].func == builtin_tan) + printf("tan\n"); + else if (expression[i].func == builtin_asin) + printf("asin\n"); + else if (expression[i].func == builtin_acos) + printf("acos\n"); + else if (expression[i].func == builtin_atan) + printf("atan\n"); + else if (expression[i].func == builtin_sign) + printf("sign\n"); + else if (expression[i].func == builtin_min) + printf("min\n"); + else if (expression[i].func == builtin_max) + printf("max\n"); + else if (expression[i].func == builtin_inintv) + printf("inintv\n"); + else if (expression[i].func == builtin_rand) + printf("rand\n"); + else if (expression[i].func == builtin_origValXY) + printf("origValXY\n"); + else if (expression[i].func == builtin_origValXYIntersample) + printf("origValXY\n"); + else if (expression[i].func == builtin_origValRA) + printf("origValRA\n"); + else if (expression[i].func == builtin_origValRAIntersample) + printf("origValRA\n"); + else if (expression[i].func == builtin_grayColor) + printf("grayColor\n"); + else + printf("unknown opcode\n"); + } +} + double eval_postfix (void) { diff --git a/plug-ins/mathmap/postfix.h b/plug-ins/mathmap/postfix.h index 4694b834ff..644538b9d0 100644 --- a/plug-ins/mathmap/postfix.h +++ b/plug-ins/mathmap/postfix.h @@ -1,12 +1,13 @@ #include "exprtree.h" -typedef void (*stackfunc) (double); +typedef void (*stackfunc) (void*); typedef struct _postfix { stackfunc func; - double arg; + void *arg; } postfix; void make_postfix (exprtree *tree); +void output_postfix (void); double eval_postfix (void); diff --git a/plug-ins/mathmap/scanner.fl b/plug-ins/mathmap/scanner.fl index 062e77073c..015ef261f4 100644 --- a/plug-ins/mathmap/scanner.fl +++ b/plug-ins/mathmap/scanner.fl @@ -9,14 +9,32 @@ %% +if return T_IF; +then return T_THEN; +else return T_ELSE; +end return T_END; +while return T_WHILE; +do return T_DO; [a-zA-Z_][a-zA-Z0-9_]* { strncpy(yylval.ident, yytext, 63); yylval.ident[63] = 0; return T_IDENT; } [0-9]+ { yylval.exprtree = make_number(atof(yytext)); return T_NUMBER; } [0-9]*\.[0-9]+ { yylval.exprtree = make_number(atof(yytext)); return T_NUMBER; } -[-,()+*/%] return yytext[0]; -;.* ; +[-,()+*/%=;] return yytext[0]; +#.* ; [ \t\n] ; %% + +void +scanFromString (char *string) +{ + yy_scan_string(string); +} + +void +endScanningFromString (void) +{ + yy_delete_buffer(YY_CURRENT_BUFFER); +} diff --git a/plug-ins/papertile/Makefile.am b/plug-ins/papertile/Makefile.am new file mode 100644 index 0000000000..94f02bd8ec --- /dev/null +++ b/plug-ins/papertile/Makefile.am @@ -0,0 +1,42 @@ +## Process this file with automake to produce Makefile.in + +pluginlibdir = $(gimpplugindir)/plug-ins + +pluginlib_PROGRAMS = papertile + +papertile_SOURCES = \ + papertile.c + +INCLUDES = \ + $(X_CFLAGS) \ + -I$(top_srcdir) \ + -I$(includedir) + +LDADD = \ + $(top_builddir)/libgimp/libgimpui.la \ + $(top_builddir)/libgimp/libgimp.la \ + $(X_LIBS) \ + \ + -lc + +DEPS = \ + $(top_builddir)/libgimp/libgimpui.la \ + $(top_builddir)/libgimp/libgimp.la + +papertile_DEPENDENCIES = $(DEPS) + +.PHONY: files + +files: + @files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \ + echo $$p; \ + done + @for subdir in $(SUBDIRS); do \ + files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \ + for file in $$files; do \ + echo $$subdir/$$file; \ + done; \ + done + + + diff --git a/plug-ins/papertile/papertile.c b/plug-ins/papertile/papertile.c new file mode 100644 index 0000000000..bf44e1f652 --- /dev/null +++ b/plug-ins/papertile/papertile.c @@ -0,0 +1,469 @@ +/******************************************************************************* + + papertile.c -- This is a plug-in for the GIMP 1.0 + + Copyright (C) 1997 Hirotsuna Mizuno + s1041150@u-aizu.ac.jp + + 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 2 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, write to the Free Software Foundation, Inc., + 675 Mass Ave, Cambridge, MA 02139, USA. + +*******************************************************************************/ + +#include +#include +#include + +#define PLUG_IN_NAME "plug_in_paper_tile" +#define PLUG_IN_VERSION "v0.7 (Dec. 25 1997)" +#define DIALOG_CAPTION "Paper Tile" + +/******************************************************************************/ + +static void query( void ); +static void run( char *, int, GParam *, int *, GParam ** ); +static void filter( GDrawable *drawable ); +static int dialog( void ); + +/******************************************************************************/ + +#define BG_TYPE_TRANSPARENT 0 +#define BG_TYPE_BLACK 1 +#define BG_TYPE_WHITE 2 + +typedef struct { + gint32 tile_width; + gint32 tile_height; + gint32 slide_length; + gint32 bg_type; +} parameter_t; + +/******************************************************************************/ + +GPlugInInfo PLUG_IN_INFO = { + NULL, /* init_proc */ + NULL, /* quit_proc */ + query, /* query_proc */ + run, /* run_proc */ +}; + +static parameter_t parameters = { + 50, + 50, + 10, + BG_TYPE_TRANSPARENT +}; + +static gint image_width; +static gint image_height; +static gint image_bpp; +static gint image_has_alpha; +static gint select_x1; +static gint select_y1; +static gint select_x2; +static gint select_y2; +static gint select_width; +static gint select_height; + +/******************************************************************************/ + +MAIN(); + +/******************************************************************************/ + +static void query( void ) +{ + static int nargs = 7; + static GParamDef args[] = { + { PARAM_INT32, "run_mode", "interactive / non-interactive" }, + { PARAM_IMAGE, "image", "input image" }, + { PARAM_DRAWABLE, "drawable", "input drawable" }, + { PARAM_INT32, "width", "tile width" }, + { PARAM_INT32, "height", "tile height" }, + { PARAM_INT32, "slide_length", "slide length" }, + { PARAM_INT32, "bg_type", "background color " + "(0=transparent, 1=black, 2=white )" } + }; + static int nreturn_vals = 0; + static GParamDef *return_vals = NULL; + + gimp_install_procedure( + PLUG_IN_NAME, + "cut and slide image", + "cut and slide image", + "Hirotsuna Mizuno ", + "Hirotsuna Mizuno", + PLUG_IN_VERSION, + "/Filters/Effects/Paper Tile", + "RGB*, GRAY*", + PROC_PLUG_IN, + nargs, + nreturn_vals, + args, + return_vals + ); +} + +/******************************************************************************/ + +static void run( char *name, + int paramc, + GParam *params, + int *returnc, + GParam **returns ) +{ + GDrawable *drawable; + GRunModeType run_mode; + static GParam returnv[1]; + GStatusType status = STATUS_SUCCESS; + + run_mode = params[0].data.d_int32; + drawable = gimp_drawable_get( params[2].data.d_drawable ); + *returnc = 1; + *returns = returnv; + + /* get the drawable info */ + image_width = gimp_drawable_width( drawable->id ); + image_height = gimp_drawable_height( drawable->id ); + image_bpp = gimp_drawable_bpp( drawable->id ); + image_has_alpha = gimp_drawable_has_alpha( drawable->id ); + gimp_drawable_mask_bounds( drawable->id, + &select_x1, &select_y1, &select_x2, &select_y2 ); + select_width = select_x2 - select_x1; + select_height = select_y2 - select_y1; + + /* switch the run mode */ + switch( run_mode ){ + + case RUN_INTERACTIVE: + gimp_get_data( PLUG_IN_NAME, ¶meters ); + if( ! dialog() ) return; + gimp_set_data( PLUG_IN_NAME, ¶meters, sizeof( parameter_t ) ); + break; + + case RUN_NONINTERACTIVE: + if( paramc != 7 ){ + status = STATUS_CALLING_ERROR; + } else { + parameters.tile_width = params[3].data.d_int32; + parameters.tile_height = params[4].data.d_int32; + parameters.slide_length = params[5].data.d_int32; + parameters.bg_type = params[6].data.d_int32; + } + break; + + case RUN_WITH_LAST_VALS: + gimp_get_data( PLUG_IN_NAME, ¶meters ); + break; + + } + + if( status == STATUS_SUCCESS ){ + if( gimp_drawable_color( drawable->id ) || + gimp_drawable_gray( drawable->id ) ){ + + gimp_tile_cache_ntiles( 2 * ( drawable->width / gimp_tile_width() + 1 ) ); + filter( drawable ); + if( run_mode != RUN_NONINTERACTIVE ) gimp_displays_flush (); + + } else { + + status = STATUS_EXECUTION_ERROR; + + } + } + + returnv[0].type = PARAM_STATUS; + returnv[0].data.d_status = status; + + gimp_drawable_detach( drawable ); +} + +/******************************************************************************/ + +static void filter( GDrawable *drawable ) +{ + GPixelRgn srcPR, destPR; + guchar **pixels; + guchar **destpixels; + gint x, y, b; + gint vx, vy, xx, yy; + + gimp_pixel_rgn_init( &srcPR, drawable, + 0, 0, image_width, image_height, FALSE, FALSE ); + gimp_pixel_rgn_init( &destPR, drawable, + 0, 0, image_width, image_height, TRUE, TRUE ); + + pixels = (guchar **)malloc( image_height * sizeof(guchar *) ); + destpixels = (guchar **)malloc( image_height * sizeof(guchar *) ); + for( y = 0; y < image_height; y++ ){ + pixels[y] = (guchar *)malloc( image_width * image_bpp ); + destpixels[y] = (guchar *)malloc( image_width * image_bpp ); + gimp_pixel_rgn_get_row( &srcPR, pixels[y], 0, y, image_width ); + } + + for( y = select_y1; y < select_y2; y++ ){ + for( x = select_x1; x < select_x2; x++ ){ + switch( parameters.bg_type ){ + + case BG_TYPE_TRANSPARENT: + for( b = 0; b < image_bpp; b++ ){ + destpixels[y][x*image_bpp+b] = 0; + } + break; + + case BG_TYPE_BLACK: + for( b = 0; b < image_bpp; b++ ){ + if( b == image_bpp - 1 && image_has_alpha ){ + destpixels[y][x*image_bpp+b] = 255; + } else { + destpixels[y][x*image_bpp+b] = 0; + } + } + break; + + case BG_TYPE_WHITE: + for( b = 0; b < image_bpp; b++ ){ + destpixels[y][x*image_bpp+b] = 255; + } + break; + + } + } + } + + gimp_progress_init( PLUG_IN_NAME ); + + for( y = select_y1; y < select_y2; y+=parameters.tile_height ) + for( x = select_x1; x < select_x2; x+=parameters.tile_width ){ + vx = rand()%parameters.slide_length - parameters.slide_length/2; + vy = rand()%parameters.slide_length - parameters.slide_length/2; + for( xx = 0; xx < parameters.tile_width; xx++ ) + if( 0 <= x+xx+vx && x+xx+vx < image_width && x+xx < image_width ) + for( yy = 0; yy < parameters.tile_height; yy++ ) + if( 0 <= y+yy+vy && y+yy+vy < image_height && y+yy < image_height ) + for( b = 0; b < image_bpp; b++ ) + destpixels[y+yy+vy][(x+xx+vx)*image_bpp+b] + = pixels[y+yy][(x+xx)*image_bpp+b]; + } + + for( y = select_y1; y < select_y2; y++ ){ + gimp_pixel_rgn_set_row (&destPR, destpixels[y], 0, y, image_width ); + gimp_progress_update ( (double)( y - select_y1 ) / select_height ); + } + + gimp_drawable_flush( drawable ); + gimp_drawable_merge_shadow( drawable->id, TRUE ); + gimp_drawable_update( drawable->id, + select_x1, select_y1, select_width, select_height ); + + for( y = select_y1; y < select_y2; y++ ) free( pixels[y-select_y1] ); + free( pixels ); + for( y = select_y1; y < select_y2; y++ ) free( destpixels[y-select_y1] ); + free( destpixels ); +} + +/******************************************************************************/ + +static int dialog_status; + +static GtkWidget *entry_width; +static GtkWidget *entry_height; +static GtkWidget *entry_slide; +static GtkWidget *button_transparent; +static GtkWidget *button_black; +static GtkWidget *button_white; + +static void dialog_destroy_handler( GtkWidget *widget, + gpointer *data ) +{ + gtk_main_quit(); +} + +static void dialog_ok_handler( GtkWidget *widget, + gpointer *data ) +{ + dialog_status = TRUE; + + if( GTK_TOGGLE_BUTTON( button_white )->active ) parameters.bg_type = BG_TYPE_WHITE; + if( GTK_TOGGLE_BUTTON( button_black )->active ) parameters.bg_type = BG_TYPE_BLACK; + if( image_has_alpha ){ + if( GTK_TOGGLE_BUTTON( button_transparent )->active ){ + parameters.bg_type = BG_TYPE_TRANSPARENT; + } + } + + parameters.tile_width = + (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_width ) ) ); + parameters.tile_height = + (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_height ) ) ); + parameters.slide_length = + (gint32)atof(gtk_entry_get_text( GTK_ENTRY( entry_slide ) ) ); + + gtk_widget_destroy( GTK_WIDGET( data ) ); +} + +static void dialog_cancel_handler( GtkWidget *widget, + gpointer *data ) +{ + dialog_status = FALSE; + gtk_widget_destroy( GTK_WIDGET( data ) ); +} + +/******************************************************************************/ + +static int dialog( void ) +{ + GtkWidget *window; + dialog_status = FALSE; + { + gint argc = 1; + gchar **argv = g_new( gchar *, 1 ); + argv[0] = g_strdup( DIALOG_CAPTION ); + gtk_init( &argc, &argv ); + } + + /* dialog window */ + window = gtk_dialog_new(); + gtk_signal_connect( GTK_OBJECT( window ), "destroy", + GTK_SIGNAL_FUNC( dialog_destroy_handler ), NULL ); + gtk_container_border_width( GTK_CONTAINER( window ), 0 ); + gtk_container_border_width( GTK_CONTAINER( GTK_DIALOG( window )->vbox ), 5 ); + + { + /* buttons */ + GtkWidget *button; + + /* ok button */ + button = gtk_button_new_with_label( "OK" ); + gtk_signal_connect_object( GTK_OBJECT( button ), "clicked", + GTK_SIGNAL_FUNC( dialog_ok_handler ), + GTK_OBJECT( window ) ); + GTK_WIDGET_SET_FLAGS( button, GTK_CAN_DEFAULT ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->action_area ), + button, TRUE, TRUE, 0 ); + gtk_widget_grab_default( button ); + gtk_widget_show( button ); + + /* cancel button */ + button = gtk_button_new_with_label( "Cancel" ); + gtk_signal_connect_object( GTK_OBJECT( button ), "clicked", + GTK_SIGNAL_FUNC( dialog_cancel_handler ), + GTK_OBJECT( window )); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->action_area ), + button, TRUE, TRUE, 0 ); + gtk_widget_show( button ); + } + + { + /* text boxes */ + GtkWidget *table; + GtkWidget *label; + char buffer[32]; + + /* table */ + table = gtk_table_new( 3, 2, FALSE ); + gtk_table_set_row_spacings( GTK_TABLE( table ), 5 ); + gtk_table_set_col_spacings( GTK_TABLE( table ), 5 ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->vbox ), + table, TRUE, TRUE, 0 ); + gtk_widget_show( table ); + + /* tile width */ + label = gtk_label_new( "width: " ); + entry_width = gtk_entry_new(); + sprintf( buffer, "%d", parameters.tile_width ); + gtk_entry_set_text( GTK_ENTRY( entry_width ), buffer ); + gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 0, 1 ); + gtk_table_attach_defaults( GTK_TABLE( table ), entry_width, 1, 2, 0, 1 ); + gtk_widget_show( label ); + gtk_widget_show( entry_width ); + + /* tile height */ + label = gtk_label_new( "height: " ); + entry_height = gtk_entry_new(); + sprintf( buffer, "%d", parameters.tile_height ); + gtk_entry_set_text( GTK_ENTRY( entry_height ), buffer ); + gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 1, 2 ); + gtk_table_attach_defaults( GTK_TABLE( table ), entry_height, 1, 2, 1, 2 ); + gtk_widget_show( label ); + gtk_widget_show( entry_height ); + + /* slide length */ + label = gtk_label_new( "slide: " ); + entry_slide = gtk_entry_new(); + sprintf( buffer, "%d", parameters.slide_length ); + gtk_entry_set_text( GTK_ENTRY( entry_slide ), buffer ); + gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, 2, 3 ); + gtk_table_attach_defaults( GTK_TABLE( table ), entry_slide, 1, 2, 2, 3 ); + gtk_widget_show( label ); + gtk_widget_show( entry_slide ); + } + + { + /* radio buttons */ + GtkWidget *frame; + GtkWidget *vbox; + GSList *group; + + frame = gtk_frame_new( "Background" ); + gtk_container_border_width( GTK_CONTAINER( frame ), 0 ); + gtk_frame_set_shadow_type( GTK_FRAME( frame ), GTK_SHADOW_ETCHED_IN ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( window )->vbox ), + frame, TRUE, TRUE, 0 ); + gtk_widget_show( frame ); + + vbox = gtk_vbox_new( FALSE, 0 ); + gtk_container_border_width( GTK_CONTAINER( vbox ), 0 ); + gtk_container_add( GTK_CONTAINER( frame ), vbox ); + gtk_widget_show( vbox ); + + group = NULL; + + if( image_has_alpha ){ + /* transparent */ + button_transparent = + gtk_radio_button_new_with_label( NULL, "Transparent" ); + gtk_box_pack_start( GTK_BOX( vbox ), + button_transparent, TRUE, TRUE, 0 ); + if( parameters.bg_type == BG_TYPE_TRANSPARENT ) + gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( button_transparent ), + TRUE ); + gtk_widget_show( button_transparent ); + group = gtk_radio_button_group( GTK_RADIO_BUTTON( button_transparent ) ); + } + + /* black */ + button_black = gtk_radio_button_new_with_label( group, "Black" ); + gtk_box_pack_start( GTK_BOX( vbox ), button_black, TRUE, TRUE, 0 ); + if( parameters.bg_type == BG_TYPE_BLACK ) + gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( button_black ), TRUE ); + gtk_widget_show( button_black ); + group = gtk_radio_button_group( GTK_RADIO_BUTTON( button_black ) ); + + /* white */ + button_white = gtk_radio_button_new_with_label( group, "White" ); + gtk_box_pack_start( GTK_BOX( vbox ), button_white, TRUE, TRUE, 0 ); + if( parameters.bg_type == BG_TYPE_WHITE ) + gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( button_white ), TRUE ); + gtk_widget_show( button_white ); + } + + gtk_widget_show( window ); + gtk_main(); + + return dialog_status; +} + +/******************************************************************************/