Advertisement
Guest User

C Solid Noise

a guest
Nov 2nd, 2010
1,471
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 19.99 KB | None | 0 0
  1. /* Solid Noise plug-in -- creates solid noise textures
  2.  * Copyright (C) 1997, 1998 Marcelo de Gomensoro Malheiros
  3.  *
  4.  * GIMP - The GNU Image Manipulation Program
  5.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20.  */
  21.  
  22. /* Solid Noise plug-in version 1.04, May 2004
  23.  *
  24.  * This plug-in generates solid noise textures based on the
  25.  * `Noise' and `Turbulence' functions described in the paper
  26.  *
  27.  *    Perlin, K, and Hoffert, E. M., "Hypertexture",
  28.  *    Computer Graphics 23, 3 (August 1989)
  29.  *
  30.  * The algorithm implemented here also makes possible the
  31.  * creation of seamless tiles.
  32.  *
  33.  * You can contact me at <malheiro@dca.fee.unicamp.br>.
  34.  * Comments and improvements for this code are welcome.
  35.  *
  36.  * The overall plug-in structure is based on the Whirl plug-in,
  37.  * which is Copyright (C) 1997 Federico Mena Quintero
  38.  */
  39.  
  40. /* Version 1.04:
  41.  *
  42.  *  Dynamic preview added (Yeti <yeti@physics.muni.cz>).
  43.  *
  44.  * Version 1.03:
  45.  *
  46.  *  Added patch from Kevin Turner <kevint@poboxes.com> to use the
  47.  *  current time as the random seed. Thank you!
  48.  *  Incorporated some portability changes from the GIMP distribution.
  49.  *
  50.  * Version 1.02:
  51.  *
  52.  *  Fixed a stupid bug with the alpha channel.
  53.  *  Fixed a rounding bug for small tilable textures.
  54.  *  Now the dialog is more compact; using the settings from gtkrc.
  55.  *
  56.  * Version 1.01:
  57.  *
  58.  *  Quick fix for wrong pdb declaration. Also changed default seed to 1.
  59.  *  Thanks to Adrian Likins and Federico Mena for the patch!
  60.  *
  61.  * Version 1.0:
  62.  *
  63.  *  Initial release.
  64.  */
  65.  
  66. #include "config.h"
  67.  
  68. #include <libgimp/gimp.h>
  69. #include <libgimp/gimpui.h>
  70.  
  71. #include "libgimp/stdplugins-intl.h"
  72.  
  73.  
  74. /*---- Defines ----*/
  75.  
  76. #define PLUG_IN_PROC   "plug-in-solid-noise"
  77. #define PLUG_IN_BINARY "noise-solid"
  78.  
  79. #define TABLE_SIZE      64
  80. #define WEIGHT(T)      ((2.0*fabs(T)-3.0)*(T)*(T)+1.0)
  81.  
  82. #define SCALE_WIDTH    128
  83. #define MIN_SIZE         0.1
  84. #define MAX_SIZE        16.0
  85.  
  86. /*---- Typedefs ----*/
  87.  
  88. typedef struct
  89. {
  90.   gboolean tilable;
  91.   gboolean turbulent;
  92.   guint    seed;
  93.   gint     detail;
  94.   gdouble  xsize;
  95.   gdouble  ysize;
  96.   gboolean random_seed;
  97. } SolidNoiseValues;
  98.  
  99.  
  100. /*---- Prototypes ----*/
  101.  
  102. static void        query (void);
  103. static void        run   (const gchar      *name,
  104.                           gint              nparams,
  105.                           const GimpParam  *param,
  106.                           gint             *nreturn_vals,
  107.                           GimpParam       **return_vals);
  108.  
  109. static void        solid_noise               (GimpDrawable *drawable,
  110.                                               GimpPreview  *preview);
  111. static void        solid_noise_init          (void);
  112. static gdouble     plain_noise               (gdouble       x,
  113.                                               gdouble       y,
  114.                                               guint         s);
  115. static gdouble     noise                     (gdouble       x,
  116.                                               gdouble       y);
  117.  
  118. static gboolean    solid_noise_dialog        (GimpDrawable *drawable);
  119. static void        solid_noise_draw_one_tile (GimpPixelRgn *rgn,
  120.                                               gdouble       width,
  121.                                               gdouble       height,
  122.                                               gint          xoffset,
  123.                                               gint          yoffset,
  124.                                               gint          chns,
  125.                                               gboolean      has_alpha);
  126.  
  127.  
  128. /*---- Variables ----*/
  129.  
  130. const GimpPlugInInfo PLUG_IN_INFO =
  131. {
  132.   NULL,  /* init_proc  */
  133.   NULL,  /* quit_proc  */
  134.   query, /* query_proc */
  135.   run,   /* run_proc   */
  136. };
  137.  
  138. static SolidNoiseValues snvals =
  139. {
  140.   FALSE, /* tilable       */
  141.   FALSE, /* turbulent     */
  142.   0,     /* seed          */
  143.   1,     /* detail        */
  144.   4.0,   /* xsize         */
  145.   4.0,   /* ysize         */
  146.   FALSE  /* random seed   */
  147. };
  148.  
  149. static gint         xclip, yclip;
  150. static gdouble      offset, factor;
  151. static gdouble      xsize, ysize;
  152. static gint         perm_tab[TABLE_SIZE];
  153. static GimpVector2  grad_tab[TABLE_SIZE];
  154.  
  155. /*---- Functions ----*/
  156.  
  157. MAIN ()
  158.  
  159. static void
  160. query (void)
  161. {
  162.   static const GimpParamDef args[] =
  163.   {
  164.     { GIMP_PDB_INT32,    "run-mode",  "Interactive, non-interactive" },
  165.     { GIMP_PDB_IMAGE,    "image",     "Input image" },
  166.     { GIMP_PDB_DRAWABLE, "drawable",  "Input drawable" },
  167.     { GIMP_PDB_INT32,    "tilable",   "Create a tilable output (n=0/y=1)" },
  168.     { GIMP_PDB_INT32,    "turbulent", "Make a turbulent noise (n=0/y=1)" },
  169.     { GIMP_PDB_INT32,    "seed",      "Random seed" },
  170.     { GIMP_PDB_INT32,    "detail",    "Detail level (0 - 15)" },
  171.     { GIMP_PDB_FLOAT,    "xsize",     "Horizontal texture size" },
  172.     { GIMP_PDB_FLOAT,    "ysize",     "Vertical texture size" }
  173.   };
  174.  
  175.   gimp_install_procedure (PLUG_IN_PROC,
  176.                           N_("Create a random cloud-like texture"),
  177.                           "Generates 2D textures using Perlin's classic "
  178.                           "solid noise function.",
  179.                           "Marcelo de Gomensoro Malheiros",
  180.                           "Marcelo de Gomensoro Malheiros",
  181.                           "May 2004, v1.04",
  182.                           N_("_Solid Noise..."),
  183.                           "RGB*, GRAY*",
  184.                           GIMP_PLUGIN,
  185.                           G_N_ELEMENTS (args), 0,
  186.                           args, NULL);
  187.  
  188.   gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Render/Clouds");
  189. }
  190.  
  191.  
  192. static void
  193. run (const gchar      *name,
  194.      gint              nparams,
  195.      const GimpParam  *param,
  196.      gint             *nreturn_vals,
  197.      GimpParam       **return_vals)
  198. {
  199.   static GimpParam values[1];
  200.  
  201.   GimpDrawable      *drawable;
  202.   GimpRunMode        run_mode;
  203.   GimpPDBStatusType  status;
  204.  
  205.   status = GIMP_PDB_SUCCESS;
  206.   run_mode = param[0].data.d_int32;
  207.  
  208.   INIT_I18N ();
  209.  
  210.   *nreturn_vals = 1;
  211.   *return_vals  = values;
  212.  
  213.   values[0].type          = GIMP_PDB_STATUS;
  214.   values[0].data.d_status = status;
  215.  
  216.   drawable = gimp_drawable_get (param[2].data.d_drawable);
  217.  
  218.   switch (run_mode)
  219.     {
  220.     case GIMP_RUN_INTERACTIVE:
  221.       gimp_get_data (PLUG_IN_PROC, &snvals);
  222.  
  223.       if (!solid_noise_dialog (drawable))
  224.         return;
  225.       break;
  226.  
  227.     case GIMP_RUN_NONINTERACTIVE:
  228.       if (nparams != 9)
  229.         {
  230.           status = GIMP_PDB_CALLING_ERROR;
  231.         }
  232.       else
  233.         {
  234.           snvals.tilable   = param[3].data.d_int32;
  235.           snvals.turbulent = param[4].data.d_int32;
  236.           snvals.seed      = param[5].data.d_int32;
  237.           snvals.detail    = param[6].data.d_int32;
  238.           snvals.xsize     = param[7].data.d_float;
  239.           snvals.ysize     = param[8].data.d_float;
  240.  
  241.           if (snvals.random_seed)
  242.             snvals.seed = g_random_int ();
  243.         }
  244.       break;
  245.  
  246.     case GIMP_RUN_WITH_LAST_VALS:
  247.       /*  Possibly retrieve data  */
  248.       gimp_get_data (PLUG_IN_PROC, &snvals);
  249.  
  250.       if (snvals.random_seed)
  251.         snvals.seed = g_random_int ();
  252.       break;
  253.  
  254.     default:
  255.       break;
  256.     }
  257.  
  258.   if ((status == GIMP_PDB_SUCCESS) &&
  259.       (gimp_drawable_is_rgb (drawable->drawable_id) ||
  260.        gimp_drawable_is_gray (drawable->drawable_id)))
  261.     {
  262.       solid_noise (drawable, NULL);
  263.  
  264.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  265.         gimp_displays_flush ();
  266.  
  267.       if (run_mode == GIMP_RUN_INTERACTIVE ||
  268.           run_mode == GIMP_RUN_WITH_LAST_VALS)
  269.         {
  270.           gimp_set_data (PLUG_IN_PROC, &snvals, sizeof (SolidNoiseValues));
  271.         }
  272.     }
  273.   else
  274.     {
  275.       status = GIMP_PDB_EXECUTION_ERROR;
  276.     }
  277.  
  278.   values[0].data.d_status = status;
  279.  
  280.   gimp_drawable_detach (drawable);
  281. }
  282.  
  283.  
  284. static void
  285. solid_noise (GimpDrawable *drawable,
  286.              GimpPreview  *preview)
  287. {
  288.   GimpPixelRgn  dest_rgn;
  289.   gint          bytes;
  290.   gint          x, y;
  291.   gint          width, height;
  292.   gint          progress, max_progress;
  293.   gpointer      pr;
  294.   gboolean      has_alpha;
  295.   gint          rowstride;
  296.   gint          i;
  297.  
  298.   /*  Get selection area  */
  299.   if (preview)
  300.     {
  301.       x = 0;
  302.       y = 0;
  303.       gimp_preview_get_size (preview, &width, &height);
  304.     }
  305.   else
  306.     {
  307.       if (! gimp_drawable_mask_intersect (drawable->drawable_id,
  308.                                           &x, &y, &width, &height))
  309.         return;
  310.     }
  311.  
  312.   /*  Initialization  */
  313.   solid_noise_init ();
  314.   if (!preview)
  315.     gimp_progress_init (_("Solid Noise"));
  316.  
  317.   progress = 0;
  318.   max_progress = width * height;
  319.  
  320.   bytes     = gimp_drawable_bpp (drawable->drawable_id);
  321.   rowstride = width * bytes;
  322.   has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
  323.  
  324.   if (preview)
  325.     {
  326.       dest_rgn.x = dest_rgn.y = 0;
  327.       dest_rgn.w = width;
  328.       dest_rgn.h = height;
  329.  
  330.       dest_rgn.bpp       = bytes;
  331.       dest_rgn.rowstride = rowstride;
  332.       dest_rgn.data      = g_new (guchar, rowstride * height);
  333.     }
  334.   else
  335.     {
  336.       gimp_pixel_rgn_init (&dest_rgn, drawable,
  337.                            x, y, width, height, TRUE, TRUE);
  338.     }
  339.  
  340.   if (has_alpha)
  341.     bytes--;
  342.  
  343.   if (preview)
  344.     {
  345.       solid_noise_draw_one_tile (&dest_rgn, width, height,
  346.                                  x, y, bytes, has_alpha);
  347.     }
  348.   else
  349.     {
  350.       for (pr = gimp_pixel_rgns_register (1, &dest_rgn), i = 0;
  351.            pr != NULL;
  352.            pr = gimp_pixel_rgns_process (pr), i++)
  353.         {
  354.           solid_noise_draw_one_tile (&dest_rgn, width, height,
  355.                                      x, y, bytes, has_alpha);
  356.  
  357.           progress += dest_rgn.w * dest_rgn.h;
  358.  
  359.           if (i % 16 == 0)
  360.             gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
  361.         }
  362.  
  363.       gimp_progress_update (1.0);
  364.     }
  365.  
  366.   /*  Update the drawable  */
  367.   if (preview)
  368.     {
  369.       gimp_preview_draw_buffer (preview, dest_rgn.data, rowstride);
  370.       g_free (dest_rgn.data);
  371.     }
  372.   else
  373.     {
  374.       gimp_drawable_flush (drawable);
  375.       gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  376.       gimp_drawable_update (drawable->drawable_id, x, y, width, height);
  377.     }
  378. }
  379.  
  380. static void
  381. solid_noise_draw_one_tile (GimpPixelRgn *dest_rgn,
  382.                            gdouble       width,
  383.                            gdouble       height,
  384.                            gint          xoffset,
  385.                            gint          yoffset,
  386.                            gint          chns,
  387.                            gboolean      has_alpha)
  388. {
  389.   guchar  *dest, *dest_row;
  390.   gint     row, col, i;
  391.   guchar   val;
  392.  
  393.   dest_row = dest_rgn->data;
  394.  
  395.   for (row = dest_rgn->y; row < (dest_rgn->y + dest_rgn->h); row++)
  396.     {
  397.       dest = dest_row;
  398.  
  399.       for (col = dest_rgn->x; col < (dest_rgn->x + dest_rgn->w); col++)
  400.         {
  401.           val = (guchar) floor (255.0 * noise ((col - xoffset) / width,
  402.                                                (row - yoffset) / height));
  403.  
  404.           for (i = 0; i < chns; i++)
  405.             *dest++ = val;
  406.  
  407.           if (has_alpha)
  408.             *dest++ = 255;
  409.         }
  410.  
  411.       dest_row += dest_rgn->rowstride;
  412.     }
  413. }
  414.  
  415. static void
  416. solid_noise_init (void)
  417. {
  418.   gint     i, j, k, t;
  419.   gdouble  m;
  420.   GRand   *gr;
  421.  
  422.   gr = g_rand_new ();
  423.  
  424.   g_rand_set_seed (gr, snvals.seed);
  425.  
  426.   /*  Force sane parameters  */
  427.   snvals.detail = CLAMP (snvals.detail, 0, 15);
  428.   snvals.xsize  = CLAMP (snvals.xsize, MIN_SIZE, MAX_SIZE);
  429.   snvals.ysize  = CLAMP (snvals.ysize, MIN_SIZE, MAX_SIZE);
  430.  
  431.   /*  Set scaling factors  */
  432.   if (snvals.tilable)
  433.     {
  434.       xsize = ceil (snvals.xsize);
  435.       ysize = ceil (snvals.ysize);
  436.       xclip = (gint) xsize;
  437.       yclip = (gint) ysize;
  438.     }
  439.   else
  440.     {
  441.       xsize = snvals.xsize;
  442.       ysize = snvals.ysize;
  443.     }
  444.  
  445.   /*  Set totally empiric normalization values  */
  446.   if (snvals.turbulent)
  447.     {
  448.       offset = 0.0;
  449.       factor = 1.0;
  450.     }
  451.   else
  452.     {
  453.       offset = 0.94;
  454.       factor = 0.526;
  455.     }
  456.  
  457.   /*  Initialize the permutation table  */
  458.   for (i = 0; i < TABLE_SIZE; i++)
  459.     perm_tab[i] = i;
  460.  
  461.   for (i = 0; i < (TABLE_SIZE >> 1); i++)
  462.     {
  463.       j = g_rand_int_range (gr, 0, TABLE_SIZE);
  464.       k = g_rand_int_range (gr, 0, TABLE_SIZE);
  465.       t = perm_tab[j];
  466.       perm_tab[j] = perm_tab[k];
  467.       perm_tab[k] = t;
  468.     }
  469.  
  470.   /*  Initialize the gradient table  */
  471.   for (i = 0; i < TABLE_SIZE; i++)
  472.     {
  473.       do
  474.         {
  475.           grad_tab[i].x = g_rand_double_range (gr, -1, 1);
  476.           grad_tab[i].y = g_rand_double_range (gr, -1, 1);
  477.           m = grad_tab[i].x * grad_tab[i].x + grad_tab[i].y * grad_tab[i].y;
  478.         }
  479.       while (m == 0.0 || m > 1.0);
  480.  
  481.       m = 1.0 / sqrt(m);
  482.       grad_tab[i].x *= m;
  483.       grad_tab[i].y *= m;
  484.     }
  485.  
  486.   g_rand_free (gr);
  487. }
  488.  
  489.  
  490. static gdouble
  491. plain_noise (gdouble x,
  492.              gdouble y,
  493.              guint   s)
  494. {
  495.   GimpVector2 v;
  496.   gint        a, b, i, j, n;
  497.   gdouble     sum;
  498.  
  499.   sum = 0.0;
  500.   x *= s;
  501.   y *= s;
  502.   a = (int) floor (x);
  503.   b = (int) floor (y);
  504.  
  505.   for (i = 0; i < 2; i++)
  506.     for (j = 0; j < 2; j++)
  507.       {
  508.         if (snvals.tilable)
  509.           n = perm_tab[(((a + i) % (xclip * s)) + perm_tab[((b + j) % (yclip * s)) % TABLE_SIZE]) % TABLE_SIZE];
  510.         else
  511.           n = perm_tab[(a + i + perm_tab[(b + j) % TABLE_SIZE]) % TABLE_SIZE];
  512.         v.x = x - a - i;
  513.         v.y = y - b - j;
  514.         sum += WEIGHT(v.x) * WEIGHT(v.y) * (grad_tab[n].x * v.x + grad_tab[n].y * v.y);
  515.       }
  516.  
  517.   return sum / s;
  518. }
  519.  
  520.  
  521. static gdouble
  522. noise (gdouble x,
  523.        gdouble y)
  524. {
  525.   gint i;
  526.   guint s;
  527.   gdouble sum;
  528.  
  529.   s = 1;
  530.   sum = 0.0;
  531.   x *= xsize;
  532.   y *= ysize;
  533.  
  534.   for (i = 0; i <= snvals.detail; i++)
  535.     {
  536.       if (snvals.turbulent)
  537.         sum += fabs (plain_noise (x, y, s));
  538.       else
  539.         sum += plain_noise (x, y, s);
  540.       s <<= 1;
  541.     }
  542.  
  543.   return (sum+offset)*factor;
  544. }
  545.  
  546. static gboolean
  547. solid_noise_dialog (GimpDrawable *drawable)
  548. {
  549.   GtkWidget *dialog;
  550.   GtkWidget *main_vbox;
  551.   GtkWidget *preview;
  552.   GtkWidget *toggle;
  553.   GtkWidget *table;
  554.   GtkWidget *label;
  555.   GtkWidget *seed_hbox;
  556.   GtkWidget *spinbutton;
  557.   GtkObject *adj;
  558.   gboolean   run;
  559.  
  560.   gimp_ui_init (PLUG_IN_BINARY, FALSE);
  561.  
  562.   /*  Dialog initialization  */
  563.   dialog = gimp_dialog_new (_("Solid Noise"), PLUG_IN_BINARY,
  564.                             NULL, 0,
  565.                             gimp_standard_help_func, PLUG_IN_PROC,
  566.  
  567.                             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  568.                             GTK_STOCK_OK,     GTK_RESPONSE_OK,
  569.  
  570.                             NULL);
  571.  
  572.   gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
  573.                                            GTK_RESPONSE_OK,
  574.                                            GTK_RESPONSE_CANCEL,
  575.                                            -1);
  576.  
  577.   gimp_window_set_transient (GTK_WINDOW (dialog));
  578.  
  579.   main_vbox = gtk_vbox_new (FALSE, 12);
  580.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
  581.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
  582.   gtk_widget_show (main_vbox);
  583.  
  584.   preview = gimp_aspect_preview_new (drawable, NULL);
  585.   gtk_box_pack_start (GTK_BOX (main_vbox), preview, TRUE, TRUE, 0);
  586.   gtk_widget_show (preview);
  587.  
  588.   g_signal_connect_swapped (preview, "invalidated",
  589.                             G_CALLBACK (solid_noise),
  590.                             drawable);
  591.  
  592.   /*  Table  */
  593.   table = gtk_table_new (4, 3, FALSE);
  594.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  595.   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  596.   gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
  597.   gtk_widget_show (table);
  598.  
  599.   /*  Random Seed  */
  600.   seed_hbox = gimp_random_seed_new (&snvals.seed, &snvals.random_seed);
  601.   label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  602.                                      _("_Random seed:"), 1.0, 0.5,
  603.                                      seed_hbox, 1, TRUE);
  604.   gtk_label_set_mnemonic_widget (GTK_LABEL (label),
  605.                                  GIMP_RANDOM_SEED_SPINBUTTON (seed_hbox));
  606.   g_signal_connect_swapped (GIMP_RANDOM_SEED_SPINBUTTON_ADJ (seed_hbox),
  607.                            "value-changed",
  608.                             G_CALLBACK (gimp_preview_invalidate),
  609.                             preview);
  610.  
  611.   /*  Detail  */
  612.   spinbutton = gimp_spin_button_new (&adj, snvals.detail,
  613.                                      1, 15, 1, 3, 0, 1, 0);
  614.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  615.                              _("_Detail:"), 0.0, 0.5,
  616.                              spinbutton, 1, TRUE);
  617.   g_signal_connect (adj, "value-changed",
  618.                     G_CALLBACK (gimp_int_adjustment_update),
  619.                     &snvals.detail);
  620.   g_signal_connect_swapped (adj, "value-changed",
  621.                             G_CALLBACK (gimp_preview_invalidate),
  622.                             preview);
  623.  
  624.   /*  Turbulent  */
  625.   toggle = gtk_check_button_new_with_mnemonic ( _("T_urbulent"));
  626.   gtk_table_attach (GTK_TABLE (table), toggle, 2, 3, 0, 1,
  627.                     GTK_SHRINK | GTK_FILL, GTK_FILL, 1, 0);
  628.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), snvals.turbulent);
  629.   gtk_widget_show (toggle);
  630.  
  631.   g_signal_connect (toggle, "toggled",
  632.                     G_CALLBACK (gimp_toggle_button_update),
  633.                     &snvals.turbulent);
  634.   g_signal_connect_swapped (toggle, "toggled",
  635.                             G_CALLBACK (gimp_preview_invalidate),
  636.                             preview);
  637.  
  638.   /*  Tilable  */
  639.   toggle = gtk_check_button_new_with_mnemonic ( _("T_ilable"));
  640.   gtk_table_attach (GTK_TABLE (table), toggle, 2, 3, 1, 2,
  641.                     GTK_SHRINK | GTK_FILL, GTK_FILL, 1, 0);
  642.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), snvals.tilable);
  643.   gtk_widget_show (toggle);
  644.  
  645.   g_signal_connect (toggle, "toggled",
  646.                     G_CALLBACK (gimp_toggle_button_update),
  647.                     &snvals.tilable);
  648.   g_signal_connect_swapped (toggle, "toggled",
  649.                             G_CALLBACK (gimp_preview_invalidate),
  650.                             preview);
  651.  
  652.   /*  X Size  */
  653.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
  654.                               _("_X size:"), SCALE_WIDTH, 0,
  655.                               snvals.xsize, MIN_SIZE, MAX_SIZE, 0.1, 1.0, 1,
  656.                               TRUE, 0, 0,
  657.                               NULL, NULL);
  658.   g_signal_connect (adj, "value-changed",
  659.                     G_CALLBACK (gimp_double_adjustment_update),
  660.                     &snvals.xsize);
  661.   g_signal_connect_swapped (adj, "value-changed",
  662.                             G_CALLBACK (gimp_preview_invalidate),
  663.                             preview);
  664.  
  665.   /*  Y Size  */
  666.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 3,
  667.                               _("_Y size:"), SCALE_WIDTH, 0,
  668.                               snvals.ysize, MIN_SIZE, MAX_SIZE, 0.1, 1.0, 1,
  669.                               TRUE, 0, 0,
  670.                               NULL, NULL);
  671.   g_signal_connect (adj, "value-changed",
  672.                     G_CALLBACK (gimp_double_adjustment_update),
  673.                     &snvals.ysize);
  674.   g_signal_connect_swapped (adj, "value-changed",
  675.                             G_CALLBACK (gimp_preview_invalidate),
  676.                             preview);
  677.  
  678.   gtk_widget_show (dialog);
  679.  
  680.   run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
  681.  
  682.   gtk_widget_destroy (dialog);
  683.  
  684.   return run;
  685. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement