home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / brush_edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  11.8 KB  |  368 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * brush_edit module Copyright 1998 Jay Cox <jaycox@earthlink.net>
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19.  */
  20.  
  21. #include "config.h"
  22.  
  23. #include <string.h>
  24.  
  25. #include <gtk/gtk.h>
  26.  
  27. #include "apptypes.h"
  28.  
  29. #include "appenv.h"
  30. #include "gimpbrushgenerated.h"
  31. #include "brush_edit.h"
  32. #include "gimpui.h"
  33.  
  34. #include "libgimp/gimpmath.h"
  35.  
  36. #include "libgimp/gimpintl.h"
  37.  
  38.  
  39. static void brush_edit_close_callback (GtkWidget                *widget,
  40.                        gpointer                  data);
  41. static gint brush_edit_preview_resize (GtkWidget                *widget,
  42.                        GdkEvent                 *event, 
  43.                        BrushEditGeneratedWindow *begw);
  44.  
  45.  
  46. static void
  47. update_brush_callback (GtkAdjustment            *adjustment,
  48.                BrushEditGeneratedWindow *begw)
  49. {
  50.   if (begw->brush &&
  51.       ((begw->radius_data->value  
  52.     != gimp_brush_generated_get_radius (begw->brush))
  53.        || (begw->hardness_data->value
  54.        != gimp_brush_generated_get_hardness (begw->brush))
  55.        || (begw->aspect_ratio_data->value
  56.        != gimp_brush_generated_get_aspect_ratio (begw->brush))
  57.        || (begw->angle_data->value
  58.        != gimp_brush_generated_get_angle (begw->brush))))
  59.     {
  60.       gimp_brush_generated_freeze (begw->brush);
  61.       gimp_brush_generated_set_radius       (begw->brush,
  62.                          begw->radius_data->value);
  63.       gimp_brush_generated_set_hardness     (begw->brush,
  64.                          begw->hardness_data->value);
  65.       gimp_brush_generated_set_aspect_ratio (begw->brush,
  66.                          begw->aspect_ratio_data->value);
  67.       gimp_brush_generated_set_angle        (begw->brush,
  68.                          begw->angle_data->value);
  69.       gimp_brush_generated_thaw (begw->brush);
  70.     }
  71. }
  72.  
  73. static void
  74. brush_edit_clear_preview (BrushEditGeneratedWindow *begw)
  75. {
  76.   guchar *buf;
  77.   gint    i;
  78.  
  79.   buf = g_new (guchar, begw->preview->requisition.width);
  80.  
  81.   /*  Set the buffer to white  */
  82.   memset (buf, 255, begw->preview->requisition.width);
  83.  
  84.   /*  Set the image buffer to white  */
  85.   for (i = 0; i < begw->preview->requisition.height; i++)
  86.     gtk_preview_draw_row (GTK_PREVIEW (begw->preview), buf, 0, i,
  87.               begw->preview->requisition.width);
  88.  
  89.   g_free (buf);
  90. }
  91.  
  92. static gint 
  93. brush_edit_brush_dirty_callback (GimpBrush                *brush,
  94.                  BrushEditGeneratedWindow *begw)
  95. {
  96.   gint x, y, width, yend, ystart, xo;
  97.   gint scale;
  98.   gchar *src, *buf;
  99.  
  100.   brush_edit_clear_preview (begw);
  101.   if (brush == NULL || brush->mask == NULL)
  102.     return TRUE;
  103.   scale = MAX (ceil (brush->mask->width/
  104.              (float) begw->preview->requisition.width),
  105.            ceil (brush->mask->height/
  106.              (float) begw->preview->requisition.height));
  107.  
  108.   ystart = 0;
  109.   xo = begw->preview->requisition.width/2 - brush->mask->width/(2*scale);
  110.   ystart = begw->preview->requisition.height/2 - brush->mask->height/(2*scale);
  111.   yend = ystart + brush->mask->height/(scale);
  112.   width = CLAMP (brush->mask->width/scale, 0, begw->preview->requisition.width);
  113.  
  114.   buf = g_new (gchar, width);
  115.   src = (gchar *) temp_buf_data (brush->mask);
  116.  
  117.   for (y = ystart; y < yend; y++)
  118.     {
  119.       /*  Invert the mask for display.
  120.        */
  121.       for (x = 0; x < width; x++)
  122.     buf[x] = 255 - src[x*scale];
  123.       gtk_preview_draw_row (GTK_PREVIEW (begw->preview), (guchar *)buf, xo, y,
  124.                 width);
  125.       src += brush->mask->width*scale;
  126.     }
  127.   g_free (buf);
  128.   if (begw->scale != scale)
  129.     {
  130.       gchar str[255];
  131.       begw->scale = scale;
  132.       g_snprintf (str, sizeof (str), "%d:1", scale);
  133.       gtk_label_set_text (GTK_LABEL (begw->scale_label), str);
  134.       gtk_widget_draw (begw->scale_label, NULL);
  135.     }
  136.   gtk_widget_draw (begw->preview, NULL);
  137.   return TRUE;
  138. }
  139.  
  140. static void
  141. brush_renamed_callback (GtkWidget                *widget,
  142.             BrushEditGeneratedWindow *begw)
  143. {
  144.   gtk_entry_set_text (GTK_ENTRY (begw->name),
  145.               gimp_brush_get_name (GIMP_BRUSH (begw->brush)));
  146. }
  147.  
  148. void
  149. brush_edit_generated_set_brush (BrushEditGeneratedWindow *begw,
  150.                 GimpBrush                *gbrush)
  151. {
  152.   GimpBrushGenerated *brush = NULL;
  153.  
  154.   g_return_if_fail (begw != NULL);
  155.  
  156.   if (begw->brush == (GimpBrushGenerated *) gbrush)
  157.     return;
  158.  
  159.   if (begw->brush)
  160.     {
  161.       gtk_signal_disconnect_by_data (GTK_OBJECT (begw->brush), begw);
  162.       gtk_object_unref (GTK_OBJECT (begw->brush));
  163.       begw->brush = NULL;
  164.     }
  165.  
  166.   if (!gbrush || !GIMP_IS_BRUSH_GENERATED (gbrush))
  167.     {
  168.       begw->brush = NULL;
  169.       if (GTK_WIDGET_VISIBLE (begw->shell))
  170.     gtk_widget_hide (begw->shell);
  171.       return;
  172.     }
  173.  
  174.   brush = GIMP_BRUSH_GENERATED (gbrush);
  175.  
  176.   gtk_signal_connect (GTK_OBJECT (brush), "dirty",
  177.               GTK_SIGNAL_FUNC (brush_edit_brush_dirty_callback),
  178.               begw);
  179.   gtk_signal_connect (GTK_OBJECT (brush), "rename",
  180.               GTK_SIGNAL_FUNC (brush_renamed_callback),
  181.               begw);
  182.  
  183.   begw->brush = NULL;
  184.   gtk_adjustment_set_value (GTK_ADJUSTMENT (begw->radius_data),
  185.                 gimp_brush_generated_get_radius (brush));
  186.   gtk_adjustment_set_value (GTK_ADJUSTMENT (begw->hardness_data),
  187.                 gimp_brush_generated_get_hardness (brush));
  188.   gtk_adjustment_set_value (GTK_ADJUSTMENT (begw->angle_data),
  189.                 gimp_brush_generated_get_angle (brush));
  190.   gtk_adjustment_set_value (GTK_ADJUSTMENT (begw->aspect_ratio_data),
  191.                 gimp_brush_generated_get_aspect_ratio (brush));
  192.   gtk_entry_set_text (GTK_ENTRY (begw->name), gimp_brush_get_name (gbrush));
  193.   begw->brush = brush;
  194.  
  195.   gtk_object_ref (GTK_OBJECT (begw->brush));
  196.   brush_edit_brush_dirty_callback (GIMP_BRUSH (brush), begw);
  197. }
  198.  
  199. void
  200. name_changed_func (GtkWidget                *widget,
  201.            BrushEditGeneratedWindow *begw)
  202. {
  203.   gchar *entry_text;
  204.  
  205.   entry_text = gtk_entry_get_text (GTK_ENTRY (widget));
  206.   gimp_brush_set_name (GIMP_BRUSH (begw->brush), entry_text);
  207. }
  208.  
  209. void
  210. focus_out_func (GtkWidget                *wid1,
  211.         GtkWidget                *wid2,
  212.         BrushEditGeneratedWindow *begw)
  213. {
  214.   name_changed_func (wid1, begw);
  215. }
  216.  
  217. BrushEditGeneratedWindow *
  218. brush_edit_generated_new (void)
  219. {
  220.   BrushEditGeneratedWindow *begw;
  221.   GtkWidget *vbox;
  222.   GtkWidget *slider;
  223.   GtkWidget *table;
  224.  
  225.   begw = g_new0 (BrushEditGeneratedWindow, 1);
  226.  
  227.   begw->shell = gimp_dialog_new (_("Brush Editor"), "generated_brush_editor",
  228.                  gimp_standard_help_func,
  229.                  "dialogs/brush_editor.html",
  230.                  GTK_WIN_POS_NONE,
  231.                  FALSE, TRUE, FALSE,
  232.  
  233.                  _("Close"), brush_edit_close_callback,
  234.                  begw, NULL, NULL, TRUE, TRUE,
  235.  
  236.                  NULL);
  237.  
  238.   vbox = gtk_vbox_new (FALSE, 1);
  239.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  240.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (begw->shell)->vbox), vbox);
  241.  
  242.   /* Brush's name */
  243.   begw->name = gtk_entry_new ();
  244.   gtk_box_pack_start (GTK_BOX (vbox), begw->name, FALSE, FALSE, 0);
  245.  
  246.   gtk_signal_connect (GTK_OBJECT (begw->name), "activate",
  247.               GTK_SIGNAL_FUNC (name_changed_func),
  248.               begw);
  249.   gtk_signal_connect (GTK_OBJECT (begw->name), "focus_out_event",
  250.               GTK_SIGNAL_FUNC (focus_out_func),
  251.               begw);
  252.  
  253.   gtk_widget_show (begw->name);
  254.  
  255.   /* brush's preview widget w/frame  */
  256.   begw->frame = gtk_frame_new (NULL);
  257.   gtk_frame_set_shadow_type (GTK_FRAME (begw->frame), GTK_SHADOW_IN);
  258.   gtk_box_pack_start (GTK_BOX (vbox), begw->frame, TRUE, TRUE, 0);
  259.  
  260.   begw->preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
  261.   gtk_preview_size (GTK_PREVIEW (begw->preview), 125, 100);
  262.   gtk_signal_connect_after (GTK_OBJECT (begw->frame), "size_allocate",
  263.                 GTK_SIGNAL_FUNC (brush_edit_preview_resize),
  264.                 begw);
  265.   gtk_container_add (GTK_CONTAINER (begw->frame), begw->preview);
  266.  
  267.   gtk_widget_show (begw->preview);
  268.   gtk_widget_show (begw->frame);
  269.  
  270.   /* table for sliders/labels */
  271.   begw->scale_label = gtk_label_new ("-1:1");
  272.   gtk_box_pack_start (GTK_BOX (vbox), begw->scale_label, FALSE, FALSE, 0);
  273.   gtk_widget_show (begw->scale_label);
  274.  
  275.   begw->scale = -1;
  276.  
  277.   /* table for sliders/labels */
  278.   table = gtk_table_new (4, 2, FALSE);
  279.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  280.  
  281.   /*  brush radius scale  */
  282.   begw->radius_data =
  283.     GTK_ADJUSTMENT (gtk_adjustment_new (10.0, 0.0, 100.0, 0.1, 1.0, 0.0));
  284.   slider = gtk_hscale_new (begw->radius_data);
  285.   gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
  286.   gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
  287.   gtk_signal_connect (GTK_OBJECT (begw->radius_data), "value_changed",
  288.               GTK_SIGNAL_FUNC (update_brush_callback),
  289.               begw);
  290.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  291.                  _("Radius:"), 1.0, 1.0,
  292.                  slider, 1, FALSE);
  293.  
  294.   /*  brush hardness scale  */
  295.   begw->hardness_data =
  296.     GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1.0, 0.01, 0.01, 0.0));
  297.   slider = gtk_hscale_new (begw->hardness_data);
  298.   gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
  299.   gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
  300.   gtk_signal_connect (GTK_OBJECT (begw->hardness_data), "value_changed",
  301.               GTK_SIGNAL_FUNC (update_brush_callback),
  302.               begw);
  303.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  304.                  _("Hardness:"), 1.0, 1.0,
  305.                  slider, 1, FALSE);
  306.  
  307.   /*  brush aspect ratio scale  */
  308.   begw->aspect_ratio_data =
  309.     GTK_ADJUSTMENT (gtk_adjustment_new (1.0, 1.0, 20.0, 0.1, 1.0, 0.0));
  310.   slider = gtk_hscale_new (begw->aspect_ratio_data);
  311.   gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
  312.   gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
  313.   gtk_signal_connect (GTK_OBJECT (begw->aspect_ratio_data), "value_changed",
  314.               GTK_SIGNAL_FUNC (update_brush_callback),
  315.               begw);
  316.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
  317.                  _("Aspect Ratio:"), 1.0, 1.0,
  318.                  slider, 1, FALSE);
  319.  
  320.   /*  brush angle scale  */
  321.   begw->angle_data =
  322.     GTK_ADJUSTMENT (gtk_adjustment_new (00.0, 0.0, 180.0, 0.1, 1.0, 0.0));
  323.   slider = gtk_hscale_new (begw->angle_data);
  324.   gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
  325.   gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
  326.   gtk_signal_connect (GTK_OBJECT (begw->angle_data), "value_changed",
  327.               GTK_SIGNAL_FUNC (update_brush_callback),
  328.               begw);
  329.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
  330.                  _("Angle:"), 1.0, 1.0,
  331.                  slider, 1, FALSE);
  332.  
  333.   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
  334.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
  335.   gtk_widget_show (table);
  336.  
  337.   gtk_widget_show (vbox);
  338.   gtk_widget_show (begw->shell);
  339.  
  340.   return begw;
  341. }
  342.  
  343. static gint 
  344. brush_edit_preview_resize (GtkWidget                *widget,
  345.                GdkEvent                 *event,
  346.                BrushEditGeneratedWindow *begw)
  347. {
  348.   gtk_preview_size (GTK_PREVIEW (begw->preview),
  349.             widget->allocation.width - 4,
  350.             widget->allocation.height - 4);
  351.  
  352.   /*  update the display  */
  353.   if (begw->brush)
  354.     brush_edit_brush_dirty_callback (GIMP_BRUSH (begw->brush), begw);
  355.  
  356.   return FALSE;
  357. }
  358.  
  359. static void
  360. brush_edit_close_callback (GtkWidget *widget,
  361.                gpointer   data)
  362. {
  363.   BrushEditGeneratedWindow *begw = (BrushEditGeneratedWindow *) data;
  364.  
  365.   if (GTK_WIDGET_VISIBLE (begw->shell))
  366.     gtk_widget_hide (begw->shell);
  367. }
  368.