summaryrefslogtreecommitdiffstats
path: root/plug-ins/selection-to-path/selection-to-path-dialog.c
diff options
context:
space:
mode:
Diffstat (limited to 'plug-ins/selection-to-path/selection-to-path-dialog.c')
-rw-r--r--plug-ins/selection-to-path/selection-to-path-dialog.c403
1 files changed, 403 insertions, 0 deletions
diff --git a/plug-ins/selection-to-path/selection-to-path-dialog.c b/plug-ins/selection-to-path/selection-to-path-dialog.c
new file mode 100644
index 0000000..f6f3f18
--- /dev/null
+++ b/plug-ins/selection-to-path/selection-to-path-dialog.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This is a plug-in for GIMP.
+ *
+ * Plugin to convert a selection to a path.
+ *
+ * Copyright (C) 1999 Andy Thomas alt@gimp.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+/* Change log:-
+ * 0.1 First version.
+ */
+
+#include "config.h"
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "types.h"
+
+#include "selection-to-path.h"
+
+#include "libgimp/stdplugins-intl.h"
+
+#define SCALE_WIDTH 100
+#define SCALE_DIGITS 8
+
+
+static GSList * adjust_widgets = NULL;
+
+
+/* Reset to recommended defaults */
+void
+reset_adv_dialog (void)
+{
+ GSList *list;
+ GtkObject *widget;
+ gdouble *value;
+
+ for (list = adjust_widgets; list; list = g_slist_next (list))
+ {
+ widget = GTK_OBJECT (list->data);
+ value = (gdouble *) g_object_get_data (G_OBJECT (widget),
+ "default_value");
+
+ if (GTK_IS_ADJUSTMENT (widget))
+ {
+ gtk_adjustment_set_value (GTK_ADJUSTMENT (widget),
+ *value);
+ }
+ else if (GTK_IS_TOGGLE_BUTTON (widget))
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
+ (gboolean)(*value));
+ }
+ else
+ g_warning ("Internal widget list error");
+ }
+}
+
+static gpointer
+def_val (gdouble default_value)
+{
+ gdouble *value = g_new0 (gdouble, 1);
+ *value = default_value;
+ return (value);
+}
+
+GtkWidget *
+dialog_create_selection_area (SELVALS *sels)
+{
+ GtkWidget *scrolled_win;
+ GtkWidget *viewport;
+ GtkWidget *table;
+ GtkWidget *check;
+ GtkObject *adj;
+ gint row;
+
+ scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_set_size_request (scrolled_win, -1, 400);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
+ GTK_SHADOW_NONE);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_ALWAYS);
+
+ viewport = gtk_viewport_new (NULL, NULL);
+ gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE);
+ gtk_container_add (GTK_CONTAINER (scrolled_win), viewport);
+ gtk_widget_show (viewport);
+
+ table = gtk_table_new (20, 3, FALSE);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+ gtk_container_add (GTK_CONTAINER (viewport), table);
+ gtk_widget_show (table);
+
+ row = 0;
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Align Threshold:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->align_threshold,
+ 0.2, 2.0, 0.1, 0.1, 2,
+ TRUE, 0, 0,
+ _("If two endpoints are closer than this, "
+ "they are made to be equal."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->align_threshold);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (0.5));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Corner Always Threshold:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->corner_always_threshold,
+ 30, 180, 1, 1, 2,
+ TRUE, 0, 0,
+ _("If the angle defined by a point and its predecessors "
+ "and successors is smaller than this, it's a corner, "
+ "even if it's within 'corner_surround' pixels of a "
+ "point with a smaller angle."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->corner_always_threshold);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (60.0));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Corner Surround:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->corner_surround,
+ 3, 8, 1, 1, 0,
+ TRUE, 0, 0,
+ _("Number of points to consider when determining if a "
+ "point is a corner or not."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->corner_surround);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (4.0));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Corner Threshold:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->corner_threshold,
+ 0, 180, 1, 1, 2,
+ TRUE, 0, 0,
+ _("If a point, its predecessors, and its successors "
+ "define an angle smaller than this, it's a corner."),
+ NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->corner_threshold);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (100.0));
+
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Error Threshold:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->error_threshold,
+ 0.2, 10, 0.1, 0.1, 2,
+ TRUE, 0, 0,
+ _("Amount of error at which a fitted spline is "
+ "unacceptable. If any pixel is further away "
+ "than this from the fitted curve, we try again."),
+ NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->error_threshold);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (0.40));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Filter Alternative Surround:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->filter_alternative_surround,
+ 1, 10, 1, 1, 0,
+ TRUE, 0, 0,
+ _("A second number of adjacent points to consider "
+ "when filtering."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->filter_alternative_surround);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (1.0));
+
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Filter Epsilon:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->filter_epsilon,
+ 5, 40, 1, 1, 2,
+ TRUE, 0, 0,
+ _("If the angles between the vectors produced by "
+ "filter_surround and filter_alternative_surround "
+ "points differ by more than this, use the one from "
+ "filter_alternative_surround."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->filter_epsilon);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (10.0));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Filter Iteration Count:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->filter_iteration_count,
+ 4, 70, 1, 1, 0,
+ TRUE, 0, 0,
+ _("Number of times to smooth original data points. "
+ "Increasing this number dramatically --- to 50 or "
+ "so --- can produce vastly better results. But if "
+ "any points that 'should' be corners aren't found, "
+ "the curve goes to hell around that point."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->filter_iteration_count);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (4.0));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Filter Percent:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->filter_percent,
+ 0, 1, 0.05, 0.01, 2,
+ TRUE, 0, 0,
+ _("To produce the new point, use the old point plus "
+ "this times the neighbors."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->filter_percent);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (0.33));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Filter Secondary Surround:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->filter_secondary_surround,
+ 3, 10, 1, 1, 0,
+ TRUE, 0, 0,
+ _("Number of adjacent points to consider if "
+ "'filter_surround' points defines a straight line."),
+ NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->filter_secondary_surround);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (3.0));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Filter Surround:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->filter_surround,
+ 2, 10, 1, 1, 0,
+ TRUE, 0, 0,
+ _("Number of adjacent points to consider when filtering."),
+ NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->filter_surround);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (2.0));
+
+ check = gtk_check_button_new_with_label (_("Keep Knees"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), sels->keep_knees);
+ gtk_table_attach (GTK_TABLE (table), check, 1, 3, row, row + 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+ gimp_help_set_help_data (GTK_WIDGET (check),
+ _("Says whether or not to remove 'knee' "
+ "points after finding the outline."), NULL);
+ g_signal_connect (check, "toggled",
+ G_CALLBACK (gimp_toggle_button_update),
+ &sels->keep_knees);
+ gtk_widget_show (check);
+ adjust_widgets = g_slist_append (adjust_widgets, check);
+ g_object_set_data (G_OBJECT (check), "default_value", def_val ((gdouble)FALSE));
+ row++;
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Line Reversion Threshold:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->line_reversion_threshold,
+ 0.01, 0.2, 0.01, 0.01, 3,
+ TRUE, 0, 0,
+ _("If a spline is closer to a straight line than this, "
+ "it remains a straight line, even if it would otherwise "
+ "be changed back to a curve. This is weighted by the "
+ "square of the curve length, to make shorter curves "
+ "more likely to be reverted."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->line_reversion_threshold);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (0.01));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Line Threshold:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->line_threshold,
+ 0.2, 4, 0.1, 0.01, 2,
+ TRUE, 0, 0,
+ _("How many pixels (on the average) a spline can "
+ "diverge from the line determined by its endpoints "
+ "before it is changed to a straight line."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->line_threshold);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (0.5));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Reparametrize Improvement:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->reparameterize_improvement,
+ 0, 1, 0.05, 0.01, 2,
+ TRUE, 0, 0,
+ _("If reparameterization doesn't improve the fit by this "
+ "much percent, stop doing it. ""Amount of error at which "
+ "it is pointless to reparameterize."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->reparameterize_improvement);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (0.01));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Reparametrize Threshold:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->reparameterize_threshold,
+ 1, 50, 0.5, 0.5, 2,
+ TRUE, 0, 0,
+ _("Amount of error at which it is pointless to reparameterize. "
+ "This happens, for example, when we are trying to fit the "
+ "outline of the outside of an 'O' with a single spline. "
+ "The initial fit is not good enough for the Newton-Raphson "
+ "iteration to improve it. It may be that it would be better "
+ "to detect the cases where we didn't find any corners."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->reparameterize_threshold);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (1.0));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Subdivide Search:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->subdivide_search,
+ 0.05, 1, 0.05, 0.01, 2,
+ TRUE, 0, 0,
+ _("Percentage of the curve away from the worst point "
+ "to look for a better place to subdivide."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->subdivide_search);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (0.1));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Subdivide Surround:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->subdivide_surround,
+ 2, 10, 1, 1, 0,
+ TRUE, 0, 0,
+ _("Number of points to consider when deciding whether "
+ "a given point is a better place to subdivide."),
+ NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->subdivide_surround);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (4.0));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Subdivide Threshold:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->subdivide_threshold,
+ 0.01, 1, 0.01, 0.01, 2,
+ TRUE, 0, 0,
+ _("How many pixels a point can diverge from a straight "
+ "line and still be considered a better place to "
+ "subdivide."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->subdivide_threshold);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (0.03));
+
+ adj = gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
+ _("Tangent Surround:"), SCALE_WIDTH, SCALE_DIGITS,
+ sels->tangent_surround,
+ 2, 10, 1, 1, 0,
+ TRUE, 0, 0,
+ _("Number of points to look at on either side of a "
+ "point when computing the approximation to the "
+ "tangent at that point."), NULL);
+ g_signal_connect (adj, "value-changed",
+ G_CALLBACK (gimp_double_adjustment_update),
+ &sels->tangent_surround);
+ adjust_widgets = g_slist_append (adjust_widgets, adj);
+ g_object_set_data (G_OBJECT (adj), "default_value", def_val (3.0));
+
+ return scrolled_win;
+}