~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to plug-ins/common/noise-solid.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2008-10-06 13:30:41 UTC
  • mto: This revision was merged to the branch mainline in revision 35.
  • Revision ID: james.westby@ubuntu.com-20081006133041-3panbkcanaymfsmp
Tags: upstream-2.6.0
ImportĀ upstreamĀ versionĀ 2.6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}