/* * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * This is a plug-in for GIMP. * * Generates images containing vector type drawings. * * Copyright (C) 1997 Andy Thomas alt@picnic.demon.co.uk * * 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 . * */ #include "config.h" #include #include #include #include #include "libgimp/stdplugins-intl.h" #include "gfig.h" #include "gfig-dobject.h" #include "gfig-style.h" static void gfig_read_parameter_string (gchar **text, gint nitems, const gchar *name, gchar **style_entry); static void gfig_read_parameter_int (gchar **text, gint nitems, const gchar *name, gint *style_entry); static void gfig_read_parameter_double (gchar **text, gint nitems, const gchar *name, gdouble *style_entry); static void gfig_read_parameter_gimp_rgb (gchar **text, gint nitems, const gchar *name, GimpRGB *style_entry); static void gfig_read_parameter_string (gchar **text, gint nitems, const gchar *name, gchar **style_entry) { gint n = 0; gchar *ptr; gchar *tmpstr; *style_entry = NULL; while (n < nitems) { ptr = strchr (text[n], ':'); if (ptr) { tmpstr = g_strndup (text[n], ptr - text[n]); ptr++; if (!strcmp (tmpstr, name)) { *style_entry = g_strdup (g_strchug (ptr)); g_free (tmpstr); return; } g_free (tmpstr); } ++n; } g_message ("Parameter '%s' not found", name); } static void gfig_read_parameter_int (gchar **text, gint nitems, const gchar *name, gint *style_entry) { gint n = 0; gchar *ptr; gchar *tmpstr; *style_entry = 0; while (n < nitems) { ptr = strchr (text[n], ':'); if (ptr) { tmpstr = g_strndup (text[n], ptr - text[n]); ptr++; if (!strcmp (tmpstr, name)) { *style_entry = atoi (g_strchug (ptr)); g_free (tmpstr); return; } g_free (tmpstr); } ++n; } } static void gfig_read_parameter_double (gchar **text, gint nitems, const gchar *name, gdouble *style_entry) { gint n = 0; gchar *ptr; gchar *endptr; gchar *tmpstr; *style_entry = 0.; while (n < nitems) { ptr = strchr (text[n], ':'); if (ptr) { tmpstr = g_strndup (text[n], ptr - text[n]); ptr++; if (!strcmp (tmpstr, name)) { *style_entry = g_ascii_strtod (g_strchug (ptr), &endptr); g_free (tmpstr); return; } g_free (tmpstr); } ++n; } } static void gfig_read_parameter_gimp_rgb (gchar **text, gint nitems, const gchar *name, GimpRGB *style_entry) { gint n = 0; gchar *ptr; gchar *tmpstr; gchar *endptr; gchar fmt_str[32]; gchar colorstr_r[G_ASCII_DTOSTR_BUF_SIZE]; gchar colorstr_g[G_ASCII_DTOSTR_BUF_SIZE]; gchar colorstr_b[G_ASCII_DTOSTR_BUF_SIZE]; gchar colorstr_a[G_ASCII_DTOSTR_BUF_SIZE]; style_entry->r = style_entry->g = style_entry->b = style_entry->a = 0.; snprintf (fmt_str, sizeof (fmt_str), "%%%" G_GSIZE_FORMAT "s" " %%%" G_GSIZE_FORMAT "s" " %%%" G_GSIZE_FORMAT "s" " %%%" G_GSIZE_FORMAT "s", sizeof (colorstr_r) - 1, sizeof (colorstr_g) - 1, sizeof (colorstr_b) - 1, sizeof (colorstr_a) - 1); while (n < nitems) { ptr = strchr (text[n], ':'); if (ptr) { tmpstr = g_strndup (text[n], ptr - text[n]); ptr++; if (!strcmp (tmpstr, name)) { sscanf (ptr, fmt_str, colorstr_r, colorstr_g, colorstr_b, colorstr_a); style_entry->r = g_ascii_strtod (colorstr_r, &endptr); style_entry->g = g_ascii_strtod (colorstr_g, &endptr); style_entry->b = g_ascii_strtod (colorstr_b, &endptr); style_entry->a = g_ascii_strtod (colorstr_a, &endptr); g_free (tmpstr); return; } g_free (tmpstr); } ++n; } } #define MAX_STYLE_TEXT_ENTRIES 100 gboolean gfig_load_style (Style *style, FILE *fp) { gulong offset; gchar load_buf2[MAX_LOAD_LINE]; gchar *style_text[MAX_STYLE_TEXT_ENTRIES]; gint nitems = 0; gint value; gint k; gchar name[100]; offset = ftell (fp); get_line (load_buf2, MAX_LOAD_LINE, fp, 0); /* nuke final > and preserve spaces in name */ if (1 != sscanf (load_buf2, "") || feof (fp)) break; style_text[nitems] = g_strdup (load_buf2); nitems++; if (nitems >= MAX_STYLE_TEXT_ENTRIES) break; } if (feof (fp) || (nitems >= MAX_STYLE_TEXT_ENTRIES)) { g_message ("Error reading style data"); return TRUE; } gfig_read_parameter_string (style_text, nitems, "BrushName", &style->brush_name); if (style->brush_name == NULL) g_message ("Error loading style: got NULL for brush name."); gfig_read_parameter_string (style_text, nitems, "Pattern", &style->pattern); gfig_read_parameter_string (style_text, nitems, "Gradient", &style->gradient); gfig_read_parameter_gimp_rgb (style_text, nitems, "Foreground", &style->foreground); gfig_read_parameter_gimp_rgb (style_text, nitems, "Background", &style->background); gfig_read_parameter_int (style_text, nitems, "FillType", &value); style->fill_type = value; gfig_read_parameter_int (style_text, nitems, "PaintType", &value); style->paint_type = value; gfig_read_parameter_double (style_text, nitems, "FillOpacity", &style->fill_opacity); for (k = 0; k < nitems; k++) { g_free (style_text[k]); } if (gfig_context->debug_styles) g_printerr ("done\n"); return FALSE; } gboolean gfig_skip_style (Style *style, FILE *fp) { gulong offset; gchar load_buf2[MAX_LOAD_LINE]; offset = ftell (fp); get_line (load_buf2, MAX_LOAD_LINE, fp, 0); if (strncmp (load_buf2, "\n"); } void gfig_style_save_as_attributes (Style *style, GString *string) { gchar buffer[G_ASCII_DTOSTR_BUF_SIZE]; gchar buffer_r[G_ASCII_DTOSTR_BUF_SIZE]; gchar buffer_g[G_ASCII_DTOSTR_BUF_SIZE]; gchar buffer_b[G_ASCII_DTOSTR_BUF_SIZE]; gchar buffer_a[G_ASCII_DTOSTR_BUF_SIZE]; gint blen = G_ASCII_DTOSTR_BUF_SIZE; if (gfig_context->debug_styles) g_printerr ("Saving style %s as attributes\n", style->name); g_string_append_printf (string, "BrushName=\"%s\" ", style->brush_name); g_string_append_printf (string, "Foreground=\"%s %s %s %s\" ", g_ascii_dtostr (buffer_r, blen, style->foreground.r), g_ascii_dtostr (buffer_g, blen, style->foreground.g), g_ascii_dtostr (buffer_b, blen, style->foreground.b), g_ascii_dtostr (buffer_a, blen, style->foreground.a)); g_string_append_printf (string, "Background=\"%s %s %s %s\" ", g_ascii_dtostr (buffer_r, blen, style->background.r), g_ascii_dtostr (buffer_g, blen, style->background.g), g_ascii_dtostr (buffer_b, blen, style->background.b), g_ascii_dtostr (buffer_a, blen, style->background.a)); g_string_append_printf (string, "FillType=%d ", style->fill_type); g_string_append_printf (string, "PaintType=%d ", style->paint_type); g_string_append_printf (string, "FillOpacity=%s ", g_ascii_dtostr (buffer, blen, style->fill_opacity)); } void gfig_save_styles (GString *string) { if (gfig_context->debug_styles) g_printerr ("Saving global styles.\n"); gfig_save_style (&gfig_context->default_style, string); } /* * set_foreground_callback() is the callback for the Foreground color select * widget. It reads the color from the widget, and applies this color to the * current style. It then produces a repaint (which will be suppressed if * gfig_context->enable_repaint is FALSE). */ void set_foreground_callback (GimpColorButton *button, gpointer data) { GimpRGB color2; Style *current_style; if (gfig_context->debug_styles) g_printerr ("Setting foreground color from color selector\n"); current_style = gfig_context_get_current_style (); gimp_color_button_get_color (button, &color2); gimp_rgba_set (¤t_style->foreground, color2.r, color2.g, color2.b, color2.a); gfig_paint_callback (); } void set_background_callback (GimpColorButton *button, gpointer data) { GimpRGB color2; Style *current_style; if (gfig_context->debug_styles) g_printerr ("Setting background color from color selector\n"); current_style = gfig_context_get_current_style (); gimp_color_button_get_color (button, &color2); gimp_rgba_set (¤t_style->background, color2.r, color2.g, color2.b, color2.a); gfig_paint_callback (); } void set_paint_type_callback (GtkToggleButton *toggle, gpointer data) { gboolean paint_type; Style *current_style; current_style = gfig_context_get_current_style (); paint_type = gtk_toggle_button_get_active (toggle); current_style->paint_type = paint_type; gfig_paint_callback (); gtk_widget_set_sensitive (GTK_WIDGET (data), paint_type); } /* * gfig_brush_changed_callback() is the callback for the brush * selector widget. It reads the brush name from the widget, and * applies this to the current style, as well as the gfig_context->bdesc * values. It then produces a repaint (which will be suppressed if * gfig_context->enable_repaint is FALSE). */ void gfig_brush_changed_callback (GimpBrushSelectButton *button, const gchar *brush_name, gdouble opacity, gint spacing, GimpLayerMode paint_mode, gint width, gint height, const guchar *mask_data, gboolean dialog_closing, gpointer user_data) { Style *current_style; current_style = gfig_context_get_current_style (); current_style->brush_name = g_strdup (brush_name); /* this will soon be unneeded. How soon? */ gfig_context->bdesc.name = g_strdup (brush_name); gfig_context->bdesc.width = width; gfig_context->bdesc.height = height; gimp_context_set_brush (brush_name); gimp_context_set_brush_default_size (); gfig_paint_callback (); } void gfig_pattern_changed_callback (GimpPatternSelectButton *button, const gchar *pattern_name, gint width, gint height, gint bpp, const guchar *mask_data, gboolean dialog_closing, gpointer user_data) { Style *current_style; current_style = gfig_context_get_current_style (); current_style->pattern = g_strdup (pattern_name); gfig_paint_callback (); } void gfig_gradient_changed_callback (GimpGradientSelectButton *button, const gchar *gradient_name, gint width, const gdouble *grad_data, gboolean dialog_closing, gpointer user_data) { Style *current_style; current_style = gfig_context_get_current_style (); current_style->gradient = g_strdup (gradient_name); gfig_paint_callback (); } void gfig_rgba_copy (GimpRGB *color1, GimpRGB *color2) { color1->r = color2->r; color1->g = color2->g; color1->b = color2->b; color1->a = color2->a; } void gfig_style_copy (Style *style1, Style *style0, const gchar *name) { if (name) style1->name = g_strdup (name); else g_message ("Error: name is NULL in gfig_style_copy."); if (gfig_context->debug_styles) g_printerr ("Copying style %s as style %s\n", style0->name, name); gfig_rgba_copy (&style1->foreground, &style0->foreground); gfig_rgba_copy (&style1->background, &style0->background); if (!style0->brush_name) g_message ("Error copying style %s: brush name is NULL.", style0->name); style1->brush_name = g_strdup (style0->brush_name); style1->gradient = g_strdup (style0->gradient); style1->pattern = g_strdup (style0->pattern); style1->fill_type = style0->fill_type; style1->fill_opacity = style0->fill_opacity; style1->paint_type = style0->paint_type; } /* * gfig_style_apply() applies the settings from the specified style to * the GIMP core. It does not change any widgets, and does not cause * a repaint. */ void gfig_style_apply (Style *style) { if (gfig_context->debug_styles) g_printerr ("Applying style '%s' -- ", style->name); gimp_context_set_foreground (&style->foreground); gimp_context_set_background (&style->background); if (! gimp_context_set_brush (style->brush_name)) g_message ("Style apply: Failed to set brush to '%s' in style '%s'", style->brush_name, style->name); gimp_context_set_brush_default_size (); gimp_context_set_pattern (style->pattern); gimp_context_set_gradient (style->gradient); if (gfig_context->debug_styles) g_printerr ("done.\n"); } /* * gfig_read_gimp_style() reads the style settings from the Gimp core, * and applies them to the specified style, giving that style the * specified name. This is mainly useful as a way of initializing * a style. The function does not cause a repaint. */ void gfig_read_gimp_style (Style *style, const gchar *name) { gint dummy; if (!name) g_message ("Error: name is NULL in gfig_read_gimp_style."); if (gfig_context->debug_styles) g_printerr ("Reading Gimp settings as style %s\n", name); style->name = g_strdup (name); gimp_context_get_foreground (&style->foreground); gimp_context_get_background (&style->background); style->brush_name = gimp_context_get_brush (); gimp_brush_get_info (style->brush_name, &style->brush_width, &style->brush_height, &dummy, &dummy); gimp_brush_get_spacing (style->brush_name, &style->brush_spacing); style->gradient = gimp_context_get_gradient (); style->pattern = gimp_context_get_pattern (); style->fill_opacity = 100.; gfig_context->bdesc.name = style->brush_name; gfig_context->bdesc.width = style->brush_width; gfig_context->bdesc.height = style->brush_height; } /* * gfig_style_set_content_from_style() sets all of the style control widgets * to values from the specified style. This in turn sets the Gimp core's * values to the same things. Repainting is suppressed while this happens, * so calling this function will not produce a repaint. * */ void gfig_style_set_context_from_style (Style *style) { gboolean enable_repaint; if (gfig_context->debug_styles) g_printerr ("Setting context from style '%s' -- ", style->name); enable_repaint = gfig_context->enable_repaint; gfig_context->enable_repaint = FALSE; gimp_color_button_set_color (GIMP_COLOR_BUTTON (gfig_context->fg_color_button), &style->foreground); gimp_color_button_set_color (GIMP_COLOR_BUTTON (gfig_context->bg_color_button), &style->background); if (! gimp_context_set_brush (style->brush_name)) g_message ("Style from context: Failed to set brush to '%s'", style->brush_name); gimp_context_set_brush_default_size (); gimp_brush_select_button_set_brush (GIMP_BRUSH_SELECT_BUTTON (gfig_context->brush_select), style->brush_name, -1.0, -1, -1); /* FIXME */ gimp_pattern_select_button_set_pattern (GIMP_PATTERN_SELECT_BUTTON (gfig_context->pattern_select), style->pattern); gimp_gradient_select_button_set_gradient (GIMP_GRADIENT_SELECT_BUTTON (gfig_context->gradient_select), style->gradient); gfig_context->bdesc.name = style->brush_name; if (gfig_context->debug_styles) g_printerr ("done.\n"); gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (gfig_context->fillstyle_combo), (gint) style->fill_type); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gfig_context->paint_type_toggle), style->paint_type); gfig_context->enable_repaint = enable_repaint; } /* * gfig_style_set_style_from_context() sets the values in the specified * style to those that appear in the style control widgets f */ void gfig_style_set_style_from_context (Style *style) { Style *current_style; GimpRGB color; gint value; style->name = "object"; current_style = gfig_context_get_current_style (); gimp_color_button_get_color (GIMP_COLOR_BUTTON (gfig_context->fg_color_button), &color); if (gfig_context->debug_styles) g_printerr ("Setting foreground color to %lg %lg %lg\n", color.r, color.g, color.b); gfig_rgba_copy (&style->foreground, &color); gimp_color_button_get_color (GIMP_COLOR_BUTTON (gfig_context->bg_color_button), &color); gfig_rgba_copy (&style->background, &color); style->brush_name = current_style->brush_name; if (!style->pattern || strcmp (style->pattern, current_style->pattern)) { style->pattern = g_strdup (current_style->pattern); /* why strduping? */ } style->gradient = current_style->gradient; if (gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (gfig_context->fillstyle_combo), &value)) style->fill_type = value; /* FIXME when there is an opacity control widget to read */ style->fill_opacity = 100.; style->paint_type = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gfig_context->paint_type_toggle)); } void mygimp_brush_info (gint *width, gint *height) { gchar *name = gimp_context_get_brush (); gint dummy; if (name && gimp_brush_get_info (name, width, height, &dummy, &dummy)) { *width = MAX (*width, 32); *height = MAX (*height, 32); } else { g_message ("Failed to get brush info"); *width = *height = 48; } g_free (name); } Style * gfig_context_get_current_style (void) { if (gfig_context->selected_obj) return &gfig_context->selected_obj->style; else return &gfig_context->default_style; }