~ubuntu-branches/ubuntu/karmic/gimp/karmic-security

« back to all changes in this revision

Viewing changes to plug-ins/common/papertile.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2008-10-06 13:30:41 UTC
  • mfrom: (1.1.15 upstream)
  • Revision ID: james.westby@ubuntu.com-20081006133041-axco233xt49jobn7
Tags: 2.6.0-1ubuntu1
* Sync on debian and new version (lp: #276839)
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch:
  - updated some strings for ubuntu
* debian/rules:
  - updated translation templates

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*============================================================================*
2
 
 
3
 
  Paper Tile 1.0  -- A GIMP PLUG-IN
4
 
 
5
 
  Copyright (C) 1997-1999 Hirotsuna Mizuno <s1041150@u-aizu.ac.jp>
6
 
 
7
 
  This program  is  free software;  you can redistribute it  and/or  modify it
8
 
  under the terms of the GNU Public License as published  by the Free Software
9
 
  Foundation;  either version 2 of the License,  or (at your option) any later
10
 
  version.
11
 
 
12
 
  This program is distributed in the hope that it will be useful,  but WITHOUT
13
 
  ANY WARRANTY;  without  even  the  implied  warranty  of MERCHANTABILITY  or
14
 
  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU General Public License  for
15
 
  more details.
16
 
 
17
 
  You should have received a copy of the GNU General Public License along with
18
 
  this program; if not, write to the Free Software Foundation, Inc.,
19
 
  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
 
 
21
 
 *===========================================================================*/
22
 
 
23
 
#include "config.h"
24
 
 
25
 
#include <stdlib.h>
26
 
 
27
 
#include <libgimp/gimp.h>
28
 
#include <libgimp/gimpui.h>
29
 
 
30
 
#include "libgimp/stdplugins-intl.h"
31
 
 
32
 
 
33
 
/*===========================================================================*/
34
 
/* DEFINES                                                                   */
35
 
/*===========================================================================*/
36
 
 
37
 
#define PLUG_IN_PROC   "plug-in-papertile"
38
 
#define PLUG_IN_BINARY "papertile"
39
 
 
40
 
/*===========================================================================*/
41
 
/* TYPES                                                                     */
42
 
/*===========================================================================*/
43
 
 
44
 
typedef enum
45
 
{
46
 
  BACKGROUND_TYPE_TRANSPARENT,
47
 
  BACKGROUND_TYPE_INVERTED,
48
 
  BACKGROUND_TYPE_IMAGE,
49
 
  BACKGROUND_TYPE_FOREGROUND,
50
 
  BACKGROUND_TYPE_BACKGROUND,
51
 
  BACKGROUND_TYPE_COLOR
52
 
} BackgroundType;
53
 
 
54
 
typedef enum
55
 
{
56
 
  FRACTIONAL_TYPE_BACKGROUND,           /* AS BACKGROUND */
57
 
  FRACTIONAL_TYPE_IGNORE,               /* NOT OPERATED  */
58
 
  FRACTIONAL_TYPE_FORCE                 /* FORCE DIVISION */
59
 
} FractionalType;
60
 
 
61
 
typedef struct _PluginParams PluginParams;
62
 
struct _PluginParams
63
 
{
64
 
  gint32          tile_width;
65
 
  gint32          tile_height;
66
 
  gint32          division_x;
67
 
  gint32          division_y;
68
 
  gdouble         move_max_rate;
69
 
  FractionalType  fractional_type;
70
 
  gboolean        centering;
71
 
  gboolean        wrap_around;
72
 
  BackgroundType  background_type;
73
 
  GimpRGB         background_color;
74
 
};
75
 
 
76
 
/*===========================================================================*/
77
 
/* VARIABLES                                                                 */
78
 
/*===========================================================================*/
79
 
 
80
 
static struct
81
 
{
82
 
  PluginParams  params;
83
 
 
84
 
  gint32        image;
85
 
  GimpDrawable *drawable;
86
 
  gboolean      drawable_has_alpha;
87
 
 
88
 
  struct
89
 
  {
90
 
    gint        x0;
91
 
    gint        y0;
92
 
    gint        x1;
93
 
    gint        y1;
94
 
    gint        width;
95
 
    gint        height;
96
 
  } selection;
97
 
 
98
 
  GimpRunMode  run_mode;
99
 
  gboolean         run;
100
 
} p =
101
 
{
102
 
  {
103
 
    1,                          /* tile_width            */
104
 
    1,                          /* tile_height           */
105
 
    16,                         /* division_x            */
106
 
    16,                         /* division_y            */
107
 
    25.0,                       /* move_max_rate         */
108
 
    FRACTIONAL_TYPE_BACKGROUND, /* fractional_type       */
109
 
    TRUE,                       /* centering             */
110
 
    FALSE,                      /* wrap_around           */
111
 
    BACKGROUND_TYPE_INVERTED,   /* background_type       */
112
 
    { 0.0, 0.0, 1.0, 1.0 }      /* background_color      */
113
 
  },
114
 
 
115
 
  0,                            /* image                 */
116
 
  NULL,                         /* drawable              */
117
 
  FALSE,                        /* drawable_has_alpha    */
118
 
 
119
 
  { 0, 0, 0, 0, 0, 0 },         /* selection             */
120
 
 
121
 
  GIMP_RUN_INTERACTIVE,         /* run_mode              */
122
 
  FALSE                         /* run                   */
123
 
};
124
 
 
125
 
/*---------------------------------------------------------------------------*/
126
 
 
127
 
static void
128
 
params_save_to_gimp (void)
129
 
{
130
 
  gimp_set_data (PLUG_IN_PROC, &p.params, sizeof p.params);
131
 
}
132
 
 
133
 
static void
134
 
params_load_from_gimp (void)
135
 
{
136
 
  gimp_get_data (PLUG_IN_PROC, &p.params);
137
 
 
138
 
  if (0 < p.params.division_x)
139
 
    {
140
 
      p.params.tile_width  = p.drawable->width / p.params.division_x;
141
 
      if (0 < p.params.tile_width)
142
 
        {
143
 
          p.params.division_y = p.drawable->height / p.params.tile_height;
144
 
        }
145
 
    }
146
 
 
147
 
  if (p.params.tile_width <= 0 ||
148
 
      p.params.tile_height <= 0 ||
149
 
      p.params.division_x <= 0 ||
150
 
      p.params.division_y <= 0)
151
 
    {
152
 
      p.params.tile_width = p.drawable->width;
153
 
      p.params.tile_height = p.drawable->height;
154
 
      p.params.division_x = p.drawable->width / p.params.tile_width;
155
 
      p.params.division_y = p.drawable->height / p.params.tile_height;
156
 
    }
157
 
 
158
 
  if (!p.drawable_has_alpha)
159
 
    {
160
 
      if (p.params.background_type == BACKGROUND_TYPE_TRANSPARENT)
161
 
        {
162
 
          p.params.background_type = BACKGROUND_TYPE_INVERTED;
163
 
        }
164
 
 
165
 
      gimp_rgb_set_alpha (&p.params.background_color, 1.0);
166
 
    }
167
 
}
168
 
 
169
 
/*===========================================================================*/
170
 
/* GUI                                                                       */
171
 
/*===========================================================================*/
172
 
 
173
 
static struct
174
 
{
175
 
  GtkObject *tile_width_adj;
176
 
  GtkObject *tile_height_adj;
177
 
  GtkObject *division_x_adj;
178
 
  GtkObject *division_y_adj;
179
 
} w;
180
 
 
181
 
static void
182
 
tile_width_adj_changed (GtkAdjustment *adj)
183
 
{
184
 
  if (p.params.tile_width != (gint)adj->value)
185
 
    {
186
 
      p.params.tile_width  = adj->value;
187
 
      p.params.division_x = p.drawable->width  / p.params.tile_width;
188
 
      gtk_adjustment_set_value (GTK_ADJUSTMENT (w.division_x_adj),
189
 
                                p.params.division_x);
190
 
    }
191
 
}
192
 
 
193
 
static void
194
 
tile_height_adj_changed (GtkAdjustment *adj)
195
 
{
196
 
  if (p.params.tile_height != (gint)adj->value)
197
 
    {
198
 
      p.params.tile_height  = adj->value;
199
 
      p.params.division_y = p.drawable->height / p.params.tile_height;
200
 
      gtk_adjustment_set_value (GTK_ADJUSTMENT (w.division_y_adj),
201
 
                                p.params.division_y);
202
 
    }
203
 
}
204
 
 
205
 
static void
206
 
division_x_adj_changed (GtkAdjustment *adj)
207
 
{
208
 
  if (p.params.division_x != (gint) adj->value)
209
 
    {
210
 
      p.params.division_x = adj->value;
211
 
      p.params.tile_width  = p.drawable->width  / p.params.division_x;
212
 
      gtk_adjustment_set_value (GTK_ADJUSTMENT (w.tile_width_adj),
213
 
                                p.params.tile_width);
214
 
    }
215
 
}
216
 
 
217
 
static void
218
 
division_y_adj_changed (GtkAdjustment *adj)
219
 
{
220
 
  if (p.params.division_y != (gint)adj->value)
221
 
    {
222
 
      p.params.division_y = adj->value;
223
 
      p.params.tile_height  = p.drawable->height / p.params.division_y;
224
 
      gtk_adjustment_set_value (GTK_ADJUSTMENT (w.tile_height_adj),
225
 
                                p.params.tile_height);
226
 
    }
227
 
}
228
 
 
229
 
static void
230
 
open_dialog (void)
231
 
{
232
 
  GtkWidget *dialog;
233
 
  GtkWidget *main_hbox;
234
 
  GtkWidget *button;
235
 
  GtkObject *adjustment;
236
 
  GtkWidget *vbox;
237
 
  GtkWidget *table;
238
 
  GtkWidget *frame;
239
 
  GtkWidget *color_button;
240
 
 
241
 
  gimp_ui_init (PLUG_IN_BINARY, TRUE);
242
 
 
243
 
  dialog = gimp_dialog_new (_("Paper Tile"), PLUG_IN_BINARY,
244
 
                            NULL, 0,
245
 
                            gimp_standard_help_func, PLUG_IN_PROC,
246
 
 
247
 
                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
248
 
                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
249
 
 
250
 
                            NULL);
251
 
 
252
 
  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
253
 
                                           GTK_RESPONSE_OK,
254
 
                                           GTK_RESPONSE_CANCEL,
255
 
                                           -1);
256
 
 
257
 
  gimp_window_set_transient (GTK_WINDOW (dialog));
258
 
 
259
 
  main_hbox = gtk_hbox_new (FALSE, 12);
260
 
  gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
261
 
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_hbox);
262
 
  gtk_widget_show (main_hbox);
263
 
 
264
 
  /* Left */
265
 
  vbox = gtk_vbox_new (FALSE, 12);
266
 
  gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0);
267
 
  gtk_widget_show (vbox);
268
 
 
269
 
  frame = gimp_frame_new (_("Division"));
270
 
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
271
 
  gtk_widget_show (frame);
272
 
 
273
 
  table = gtk_table_new (4, 2, FALSE);
274
 
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
275
 
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
276
 
  gtk_container_add (GTK_CONTAINER (frame), table);
277
 
  gtk_widget_show (table);
278
 
 
279
 
  button = gimp_spin_button_new (&w.division_x_adj, p.params.division_x,
280
 
                                 1.0, p.drawable->width, 1.0, 5.0, 0, 1, 0);
281
 
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
282
 
                             _("_X:"), 0.0, 0.5,
283
 
                             button, 1, TRUE);
284
 
  g_signal_connect (w.division_x_adj, "value-changed",
285
 
                    G_CALLBACK (division_x_adj_changed),
286
 
                    NULL);
287
 
 
288
 
  button = gimp_spin_button_new (&w.division_y_adj, p.params.division_y,
289
 
                                 1.0, p.drawable->width, 1.0, 5.0, 0, 1, 0);
290
 
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
291
 
                             _("_Y:"), 0.0, 0.5,
292
 
                             button, 1, TRUE);
293
 
  g_signal_connect (w.division_y_adj, "value-changed",
294
 
                    G_CALLBACK (division_y_adj_changed),
295
 
                    NULL);
296
 
 
297
 
  button = gimp_spin_button_new (&w.tile_width_adj, p.params.tile_width,
298
 
                                 1.0, MAX (p.drawable->width,
299
 
                                           p.drawable->height),
300
 
                                 1.0, 5.0, 0, 1, 0);
301
 
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
302
 
                             _("_Width:"), 0.0, 0.5,
303
 
                             button, 1, TRUE);
304
 
  g_signal_connect (w.tile_width_adj, "value-changed",
305
 
                    G_CALLBACK (tile_width_adj_changed),
306
 
                    NULL);
307
 
 
308
 
  button = gimp_spin_button_new (&w.tile_height_adj, p.params.tile_height,
309
 
                                 1.0, MAX (p.drawable->width,
310
 
                                 p.drawable->height),
311
 
                                 1.0, 5.0, 0, 1, 0);
312
 
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
313
 
                             _("_Height:"), 0.0, 0.5,
314
 
                             button, 1, TRUE);
315
 
  g_signal_connect (w.tile_height_adj, "value-changed",
316
 
                    G_CALLBACK (tile_height_adj_changed),
317
 
                    NULL);
318
 
 
319
 
  frame = gimp_int_radio_group_new (TRUE, _("Fractional Pixels"),
320
 
                                    G_CALLBACK (gimp_radio_button_update),
321
 
                                    &p.params.fractional_type,
322
 
                                    p.params.fractional_type,
323
 
 
324
 
                                    _("_Background"),
325
 
                                    FRACTIONAL_TYPE_BACKGROUND, NULL,
326
 
                                    _("_Ignore"),
327
 
                                    FRACTIONAL_TYPE_IGNORE, NULL,
328
 
                                    _("_Force"),
329
 
                                    FRACTIONAL_TYPE_FORCE, NULL,
330
 
 
331
 
                                    NULL);
332
 
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
333
 
  gtk_widget_show (frame);
334
 
 
335
 
  button = gtk_check_button_new_with_mnemonic(_("C_entering"));
336
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
337
 
                                p.params.centering);
338
 
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
339
 
  gtk_widget_show (button);
340
 
 
341
 
  g_signal_connect (button, "toggled",
342
 
                    G_CALLBACK (gimp_toggle_button_update),
343
 
                    &p.params.centering);
344
 
 
345
 
  /* Right */
346
 
  vbox = gtk_vbox_new (FALSE, 12);
347
 
  gtk_box_pack_start (GTK_BOX (main_hbox), vbox, TRUE, TRUE, 0);
348
 
  gtk_widget_show (vbox);
349
 
 
350
 
  frame = gimp_frame_new (_("Movement"));
351
 
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
352
 
  gtk_widget_show (frame);
353
 
 
354
 
  table = gtk_table_new (2, 2, FALSE);
355
 
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
356
 
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
357
 
  gtk_container_add (GTK_CONTAINER (frame), table);
358
 
  gtk_widget_show (table);
359
 
 
360
 
  button = gimp_spin_button_new (&adjustment, p.params.move_max_rate,
361
 
                                 0.0, 100.0, 1.0, 10.0, 0, 1, 0);
362
 
  gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
363
 
                             _("_Max (%):"), 0.0, 0.5,
364
 
                             button, 1, TRUE);
365
 
  g_signal_connect (adjustment, "value-changed",
366
 
                    G_CALLBACK (gimp_double_adjustment_update),
367
 
                    &p.params.move_max_rate);
368
 
 
369
 
  button = gtk_check_button_new_with_mnemonic (_("_Wrap around"));
370
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
371
 
                                p.params.wrap_around);
372
 
  gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 2, 1, 2);
373
 
  gtk_widget_show (button);
374
 
 
375
 
  g_signal_connect (button, "toggled",
376
 
                    G_CALLBACK (gimp_toggle_button_update),
377
 
                    &p.params.wrap_around);
378
 
 
379
 
  frame = gimp_int_radio_group_new (TRUE, _("Background Type"),
380
 
                                    G_CALLBACK (gimp_radio_button_update),
381
 
                                    &p.params.background_type,
382
 
                                    p.params.background_type,
383
 
 
384
 
                                    _("_Transparent"),
385
 
                                    BACKGROUND_TYPE_TRANSPARENT, NULL,
386
 
                                    _("I_nverted image"),
387
 
                                    BACKGROUND_TYPE_INVERTED, NULL,
388
 
                                    _("Im_age"),
389
 
                                    BACKGROUND_TYPE_IMAGE, NULL,
390
 
                                    _("Fo_reground color"),
391
 
                                    BACKGROUND_TYPE_FOREGROUND, NULL,
392
 
                                    _("Bac_kground color"),
393
 
                                    BACKGROUND_TYPE_BACKGROUND, NULL,
394
 
                                    _("S_elect here:"),
395
 
                                    BACKGROUND_TYPE_COLOR, &button,
396
 
 
397
 
                                    NULL);
398
 
  gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
399
 
  gtk_widget_show (frame);
400
 
 
401
 
  color_button = gimp_color_button_new (_("Background Color"), 100, 16,
402
 
                                        &p.params.background_color,
403
 
                                        p.drawable_has_alpha ?
404
 
                                        GIMP_COLOR_AREA_SMALL_CHECKS :
405
 
                                        GIMP_COLOR_AREA_FLAT);
406
 
  gtk_box_pack_start (GTK_BOX (GTK_BIN (frame)->child),
407
 
                      color_button, TRUE, TRUE, 0);
408
 
  gtk_widget_show (color_button);
409
 
 
410
 
  gtk_widget_set_sensitive (color_button,
411
 
                            p.params.background_type == BACKGROUND_TYPE_COLOR);
412
 
  g_object_set_data (G_OBJECT (button), "set_sensitive", color_button);
413
 
 
414
 
  g_signal_connect (color_button, "color-changed",
415
 
                    G_CALLBACK (gimp_color_button_get_color),
416
 
                    &p.params.background_color);
417
 
 
418
 
  gtk_widget_show (dialog);
419
 
 
420
 
  p.run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
421
 
 
422
 
  gtk_widget_destroy (dialog);
423
 
}
424
 
 
425
 
/*===========================================================================*/
426
 
/* PLUGIN CORE                                                               */
427
 
/*===========================================================================*/
428
 
typedef struct _Tile
429
 
{
430
 
  guint x;
431
 
  guint y;
432
 
  gint  z;
433
 
  guint width;
434
 
  guint height;
435
 
  gint  move_x;
436
 
  gint  move_y;
437
 
} Tile;
438
 
 
439
 
static gint
440
 
tile_compare (const void *x,
441
 
              const void *y)
442
 
{
443
 
  return ((Tile *) x)->z - ((Tile *) y)->z;
444
 
}
445
 
 
446
 
static inline gdouble
447
 
drand (void)
448
 
{
449
 
  return g_random_double_range (-1, 1);
450
 
}
451
 
 
452
 
static inline void
453
 
random_move (gint *x,
454
 
             gint *y,
455
 
             gint  max)
456
 
{
457
 
  gdouble angle  = drand () * G_PI;
458
 
  gdouble radius = drand () * (gdouble) max;
459
 
  *x = (gint) (radius * cos (angle));
460
 
  *y = (gint) (radius * sin (angle));
461
 
}
462
 
 
463
 
static void
464
 
overlap_RGB (guchar       *base,
465
 
             const guchar *top)
466
 
{
467
 
  base[0] = top[0];
468
 
  base[1] = top[1];
469
 
  base[2] = top[2];
470
 
}
471
 
 
472
 
static void
473
 
overlap_RGBA (guchar       *base,
474
 
              const guchar *top)
475
 
{
476
 
  gdouble R1 = (gdouble) base[0] / 255.0;
477
 
  gdouble G1 = (gdouble) base[1] / 255.0;
478
 
  gdouble B1 = (gdouble) base[2] / 255.0;
479
 
  gdouble A1 = (gdouble) base[3] / 255.0;
480
 
  gdouble R2 = (gdouble)  top[0] / 255.0;
481
 
  gdouble G2 = (gdouble)  top[1] / 255.0;
482
 
  gdouble B2 = (gdouble)  top[2] / 255.0;
483
 
  gdouble A2 = (gdouble)  top[3] / 255.0;
484
 
  gdouble A3 = A2 + A1 * (1.0 - A2);
485
 
 
486
 
  if (0.0 < A3)
487
 
    {
488
 
      gdouble R3 = (R1 * A1 * (1.0 - A2) + R2 * A2) / A3;
489
 
      gdouble G3 = (G1 * A1 * (1.0 - A2) + G2 * A2) / A3;
490
 
      gdouble B3 = (B1 * A1 * (1.0 - A2) + B2 * A2) / A3;
491
 
 
492
 
      R3 = CLAMP (R3, 0.0, 1.0);
493
 
      G3 = CLAMP (G3, 0.0, 1.0);
494
 
      B3 = CLAMP (B3, 0.0, 1.0);
495
 
 
496
 
      base[0] = (guchar) (R3 * 255.0);
497
 
      base[1] = (guchar) (G3 * 255.0);
498
 
      base[2] = (guchar) (B3 * 255.0);
499
 
      base[3] = (guchar) (A3 * 255.0);
500
 
    }
501
 
  else
502
 
    {
503
 
      base[0] = 0;
504
 
      base[1] = 0;
505
 
      base[2] = 0;
506
 
      base[3] = 0;
507
 
    }
508
 
}
509
 
 
510
 
static inline void
511
 
filter (void)
512
 
{
513
 
  static void (* overlap)(guchar *, const guchar *);
514
 
  GimpPixelRgn  src;
515
 
  GimpPixelRgn  dst;
516
 
  GimpRGB       color;
517
 
  guchar     pixel[4];
518
 
  gint       division_x;
519
 
  gint       division_y;
520
 
  gint       offset_x;
521
 
  gint       offset_y;
522
 
  Tile      *tiles;
523
 
  gint       numof_tiles;
524
 
  Tile      *t;
525
 
  gint       i;
526
 
  gint       x;
527
 
  gint       y;
528
 
  gint       move_max_pixels;
529
 
  gint       clear_x0;
530
 
  gint       clear_y0;
531
 
  gint       clear_x1;
532
 
  gint       clear_y1;
533
 
  gint       clear_width;
534
 
  gint       clear_height;
535
 
  guchar    *pixels;
536
 
  guchar    *buffer;
537
 
  gint       dindex;
538
 
  gint       sindex;
539
 
  gint       px, py;
540
 
  GRand     *gr;
541
 
 
542
 
  gr = g_rand_new ();
543
 
 
544
 
  /* INITIALIZE */
545
 
  gimp_pixel_rgn_init (&src, p.drawable, 0, 0,
546
 
                       p.drawable->width, p.drawable->height, FALSE, FALSE);
547
 
  gimp_pixel_rgn_init (&dst, p.drawable, 0, 0,
548
 
                       p.drawable->width, p.drawable->height, TRUE, TRUE);
549
 
  pixels = g_new (guchar,
550
 
                  p.drawable->bpp * p.drawable->width * p.drawable->height);
551
 
  buffer = g_new (guchar,
552
 
                  p.drawable->bpp * p.params.tile_width * p.params.tile_height);
553
 
 
554
 
  overlap = p.drawable_has_alpha ? overlap_RGBA : overlap_RGB;
555
 
 
556
 
  gimp_progress_init (_("Paper Tile"));
557
 
 
558
 
  gimp_drawable_mask_bounds (p.drawable->drawable_id,
559
 
                             &p.selection.x0, &p.selection.y0,
560
 
                             &p.selection.x1, &p.selection.y1);
561
 
  p.selection.width  = p.selection.x1 - p.selection.x0;
562
 
  p.selection.height = p.selection.y1 - p.selection.y0;
563
 
 
564
 
  gimp_tile_cache_ntiles (2 * (p.selection.width / gimp_tile_width () + 1));
565
 
 
566
 
  /* TILES */
567
 
  division_x = p.params.division_x;
568
 
  division_y = p.params.division_y;
569
 
  if (p.params.fractional_type == FRACTIONAL_TYPE_FORCE)
570
 
    {
571
 
      if (0 < p.drawable->width  % p.params.tile_width) division_x++;
572
 
      if (0 < p.drawable->height % p.params.tile_height) division_y++;
573
 
      if (p.params.centering)
574
 
        {
575
 
          if (1 < p.drawable->width % p.params.tile_width)
576
 
            {
577
 
              division_x++;
578
 
              offset_x =
579
 
                (p.drawable->width % p.params.tile_width) / 2 -
580
 
                p.params.tile_width;
581
 
            }
582
 
          else
583
 
            {
584
 
              offset_x = 0;
585
 
            }
586
 
 
587
 
          if (1 < p.drawable->height % p.params.tile_height)
588
 
            {
589
 
              division_y++;
590
 
              offset_y =
591
 
                (p.drawable->height % p.params.tile_height) / 2 -
592
 
                p.params.tile_height;
593
 
            }
594
 
          else
595
 
            {
596
 
              offset_y = 0;
597
 
            }
598
 
        }
599
 
      else
600
 
        {
601
 
          offset_x = 0;
602
 
          offset_y = 0;
603
 
        }
604
 
    }
605
 
  else
606
 
    {
607
 
      if (p.params.centering)
608
 
        {
609
 
          offset_x = (p.drawable->width  % p.params.tile_width) / 2;
610
 
          offset_y = (p.drawable->height % p.params.tile_height) / 2;
611
 
        }
612
 
      else
613
 
        {
614
 
          offset_x = 0;
615
 
          offset_y = 0;
616
 
        }
617
 
    }
618
 
 
619
 
  move_max_pixels = p.params.move_max_rate * p.params.tile_width / 100.0;
620
 
  numof_tiles = division_x * division_y;
621
 
  t = tiles = g_new(Tile, numof_tiles);
622
 
 
623
 
  for (y = 0; y < division_y; y++)
624
 
    {
625
 
      gint srcy = offset_y + p.params.tile_height * y;
626
 
 
627
 
      for (x = 0; x < division_x; x++, t++)
628
 
        {
629
 
          gint srcx = offset_x + p.params.tile_width * x;
630
 
 
631
 
          if (srcx < 0)
632
 
            {
633
 
              t->x     = 0;
634
 
              t->width = srcx + p.params.tile_width;
635
 
            }
636
 
          else if (srcx + p.params.tile_width < p.drawable->width)
637
 
            {
638
 
              t->x     = srcx;
639
 
              t->width = p.params.tile_width;
640
 
            }
641
 
          else
642
 
            {
643
 
              t->x     = srcx;
644
 
              t->width = p.drawable->width - srcx;
645
 
            }
646
 
 
647
 
          if (srcy < 0)
648
 
            {
649
 
              t->y      = 0;
650
 
              t->height = srcy + p.params.tile_height;
651
 
            }
652
 
          else if (srcy + p.params.tile_height < p.drawable->height)
653
 
            {
654
 
              t->y      = srcy;
655
 
              t->height = p.params.tile_height;
656
 
            }
657
 
          else
658
 
            {
659
 
              t->y      = srcy;
660
 
              t->height = p.drawable->height - srcy;
661
 
            }
662
 
 
663
 
          t->z = g_rand_int (gr);
664
 
          random_move (&t->move_x, &t->move_y, move_max_pixels);
665
 
        }
666
 
    }
667
 
 
668
 
  qsort (tiles, numof_tiles, sizeof *tiles, tile_compare);
669
 
 
670
 
  gimp_pixel_rgn_get_rect (&src, pixels, 0, 0, p.drawable->width,
671
 
                           p.drawable->height);
672
 
 
673
 
  if (p.params.fractional_type == FRACTIONAL_TYPE_IGNORE)
674
 
    {
675
 
      clear_x0     = offset_x;
676
 
      clear_y0     = offset_y;
677
 
      clear_width  = p.params.tile_width * division_x;
678
 
      clear_height = p.params.tile_height * division_y;
679
 
    }
680
 
  else
681
 
    {
682
 
      clear_x0     = 0;
683
 
      clear_y0     = 0;
684
 
      clear_width  = p.drawable->width;
685
 
      clear_height = p.drawable->height;
686
 
    }
687
 
 
688
 
  clear_x1 = clear_x0 + clear_width;
689
 
  clear_y1 = clear_y0 + clear_height;
690
 
 
691
 
  switch (p.params.background_type)
692
 
    {
693
 
    case BACKGROUND_TYPE_TRANSPARENT:
694
 
      for (y = clear_y0; y < clear_y1; y++)
695
 
        {
696
 
          for (x = clear_x0; x < clear_x1; x++)
697
 
            {
698
 
              dindex = p.drawable->bpp * (p.drawable->width * y + x);
699
 
              for (i = 0; i < p.drawable->bpp; i++)
700
 
                {
701
 
                  pixels[dindex+i] = 0;
702
 
                }
703
 
            }
704
 
        }
705
 
      break;
706
 
 
707
 
    case BACKGROUND_TYPE_INVERTED:
708
 
      for (y = clear_y0; y < clear_y1; y++)
709
 
        {
710
 
          for (x = clear_x0; x < clear_x1; x++)
711
 
            {
712
 
              dindex = p.drawable->bpp * (p.drawable->width * y + x);
713
 
              pixels[dindex+0] = 255 - pixels[dindex+0];
714
 
              pixels[dindex+1] = 255 - pixels[dindex+1];
715
 
              pixels[dindex+2] = 255 - pixels[dindex+2];
716
 
            }
717
 
        }
718
 
      break;
719
 
 
720
 
    case BACKGROUND_TYPE_IMAGE:
721
 
      break;
722
 
 
723
 
    case BACKGROUND_TYPE_FOREGROUND:
724
 
      gimp_context_get_foreground (&color);
725
 
      gimp_rgb_get_uchar (&color, &pixel[0], &pixel[1], &pixel[2]);
726
 
      pixel[3] = 255;
727
 
      for (y = clear_y0; y < clear_y1; y++)
728
 
        {
729
 
          for (x = clear_x0; x < clear_x1; x++)
730
 
            {
731
 
              dindex = p.drawable->bpp * (p.drawable->width * y + x);
732
 
              for (i = 0; i < p.drawable->bpp; i++)
733
 
                {
734
 
                  pixels[dindex+i] = pixel[i];
735
 
                }
736
 
            }
737
 
        }
738
 
      break;
739
 
 
740
 
    case BACKGROUND_TYPE_BACKGROUND:
741
 
      gimp_context_get_background (&color);
742
 
      gimp_rgb_get_uchar (&color, &pixel[0], &pixel[1], &pixel[2]);
743
 
      pixel[3] = 255;
744
 
      for (y = clear_y0; y < clear_y1; y++)
745
 
        {
746
 
          for (x = clear_x0; x < clear_x1; x++)
747
 
            {
748
 
              dindex = p.drawable->bpp * (p.drawable->width * y + x);
749
 
              for(i = 0; i < p.drawable->bpp; i++)
750
 
                {
751
 
                  pixels[dindex+i] = pixel[i];
752
 
                }
753
 
            }
754
 
        }
755
 
      break;
756
 
 
757
 
    case BACKGROUND_TYPE_COLOR:
758
 
      gimp_rgba_get_uchar (&p.params.background_color,
759
 
                           pixel, pixel + 1, pixel + 2, pixel + 3);
760
 
      for (y = clear_y0; y < clear_y1; y++)
761
 
        {
762
 
          for (x = clear_x0; x < clear_x1; x++)
763
 
            {
764
 
              dindex = p.drawable->bpp * (p.drawable->width * y + x);
765
 
              for(i = 0; i < p.drawable->bpp; i++)
766
 
                {
767
 
                  pixels[dindex+i] = pixel[i];
768
 
                }
769
 
            }
770
 
        }
771
 
      break;
772
 
    }
773
 
 
774
 
  /* DRAW */
775
 
  for (t = tiles, i = 0; i < numof_tiles; i++, t++)
776
 
    {
777
 
      gint x0 = t->x + t->move_x;
778
 
      gint y0 = t->y + t->move_y;
779
 
 
780
 
      gimp_pixel_rgn_get_rect (&src, buffer, t->x, t->y, t->width, t->height);
781
 
 
782
 
      for (y = 0; y < t->height; y++)
783
 
        {
784
 
          py = y0 + y;
785
 
          for (x = 0; x < t->width; x++)
786
 
            {
787
 
              px = x0 + x;
788
 
              sindex = p.drawable->bpp * (t->width * y + x);
789
 
              if (0 <= px && px < p.drawable->width &&
790
 
                  0 <= py && py < p.drawable->height)
791
 
                {
792
 
                  dindex = p.drawable->bpp * (p.drawable->width * py + px);
793
 
                  overlap(&pixels[dindex], &buffer[sindex]);
794
 
                }
795
 
              else if (p.params.wrap_around)
796
 
                {
797
 
                  px = (px + p.drawable->width)  % p.drawable->width;
798
 
                  py = (py + p.drawable->height) % p.drawable->height;
799
 
                  dindex = p.drawable->bpp * (p.drawable->width * py + px);
800
 
                  overlap(&pixels[dindex], &buffer[sindex]);
801
 
                }
802
 
            }
803
 
        }
804
 
 
805
 
      gimp_progress_update ((gdouble) i / (gdouble) numof_tiles);
806
 
    }
807
 
 
808
 
  gimp_pixel_rgn_set_rect (&dst, pixels, 0, 0, p.drawable->width,
809
 
                           p.drawable->height);
810
 
 
811
 
  gimp_drawable_flush (p.drawable);
812
 
  gimp_drawable_merge_shadow (p.drawable->drawable_id, TRUE);
813
 
  gimp_drawable_update (p.drawable->drawable_id,
814
 
                        p.selection.x0, p.selection.y0,
815
 
                        p.selection.width, p.selection.height);
816
 
 
817
 
  g_rand_free (gr);
818
 
  g_free (buffer);
819
 
  g_free (pixels);
820
 
  g_free (tiles);
821
 
}
822
 
 
823
 
/*============================================================================*/
824
 
/* PLUGIN INTERFACES                                                          */
825
 
/*============================================================================*/
826
 
 
827
 
static void
828
 
plugin_query (void)
829
 
{
830
 
  static const GimpParamDef args[] =
831
 
  {
832
 
    { GIMP_PDB_INT32,    "run-mode",         "run mode"                       },
833
 
    { GIMP_PDB_IMAGE,    "image",            "input image"                    },
834
 
    { GIMP_PDB_DRAWABLE, "drawable",         "input drawable"                 },
835
 
    { GIMP_PDB_INT32,    "tile-size",        "tile size (pixels)"             },
836
 
    { GIMP_PDB_FLOAT,    "move-max",         "max move rate (%)"              },
837
 
    { GIMP_PDB_INT32,    "fractional-type",  "0:Background 1:Ignore 2:Force"  },
838
 
    { GIMP_PDB_INT32,    "wrap-around",      "wrap around (bool)"             },
839
 
    { GIMP_PDB_INT32,    "centering",        "centering (bool)"               },
840
 
    { GIMP_PDB_INT32,    "background-type",  "0:Transparent 1:Inverted 2:Image? 3:FG 4:BG 5:Color"                  },
841
 
    { GIMP_PDB_INT32,    "background-color", "background color (for bg-type 5)" },
842
 
    { GIMP_PDB_INT32,    "background-alpha", "opacity (for bg-type 5)"        }
843
 
  };
844
 
 
845
 
  gimp_install_procedure (PLUG_IN_PROC,
846
 
                          N_("Cut image into paper tiles, and slide them"),
847
 
                          "This plug-in cuts an image into paper tiles and "
848
 
                          "slides each paper tile.",
849
 
                          "Hirotsuna Mizuno <s1041150@u-aizu.ac.jp>",
850
 
                          "Copyright (c)1997-1999 Hirotsuna Mizuno",
851
 
                          _("September 31, 1999"),
852
 
                          N_("_Paper Tile..."),
853
 
                          "RGB*",
854
 
                          GIMP_PLUGIN,
855
 
                          G_N_ELEMENTS (args), 0,
856
 
                          args, NULL);
857
 
 
858
 
  gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Map");
859
 
}
860
 
 
861
 
static void
862
 
plugin_run (const gchar      *name,
863
 
            gint              numof_params,
864
 
            const GimpParam  *params,
865
 
            gint             *numof_return_vals,
866
 
            GimpParam       **return_vals)
867
 
{
868
 
  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
869
 
 
870
 
  INIT_I18N ();
871
 
 
872
 
  p.run                = FALSE;
873
 
  p.run_mode           = params[0].data.d_int32;
874
 
  p.image              = params[1].data.d_image;
875
 
  p.drawable           = gimp_drawable_get(params[2].data.d_drawable);
876
 
  p.drawable_has_alpha = gimp_drawable_has_alpha(p.drawable->drawable_id);
877
 
 
878
 
  if (gimp_drawable_is_rgb (p.drawable->drawable_id))
879
 
    {
880
 
      switch (p.run_mode)
881
 
        {
882
 
        case GIMP_RUN_INTERACTIVE:
883
 
          params_load_from_gimp ();
884
 
          open_dialog ();
885
 
          break;
886
 
 
887
 
        case GIMP_RUN_NONINTERACTIVE:
888
 
          if (numof_params == 11)
889
 
            {
890
 
              p.params.tile_width       = params[3].data.d_int32;
891
 
              p.params.tile_height      = params[3].data.d_int32;
892
 
              p.params.division_x       = p.drawable->width  / p.params.tile_width;
893
 
              p.params.division_y       = p.drawable->height / p.params.tile_height;
894
 
              p.params.move_max_rate    = params[4].data.d_float;
895
 
              p.params.fractional_type  = (FractionalType)params[5].data.d_int32;
896
 
              p.params.wrap_around      = params[6].data.d_int32;
897
 
              p.params.centering        = params[7].data.d_int32;
898
 
              p.params.background_type  = (BackgroundType)params[8].data.d_int32;
899
 
              p.params.background_color = params[9].data.d_color;
900
 
 
901
 
              /*  FIXME:  this used to be the alpha value
902
 
                                          params[10].data.d_int32
903
 
               */
904
 
              p.run = TRUE;
905
 
            }
906
 
          else
907
 
            {
908
 
              status = GIMP_PDB_CALLING_ERROR;
909
 
            }
910
 
          break;
911
 
 
912
 
        case GIMP_RUN_WITH_LAST_VALS:
913
 
          params_load_from_gimp ();
914
 
          p.run = TRUE;
915
 
          break;
916
 
        }
917
 
    }
918
 
  else
919
 
    {
920
 
      status = GIMP_PDB_EXECUTION_ERROR;
921
 
    }
922
 
 
923
 
  if (status == GIMP_PDB_SUCCESS && p.run)
924
 
    {
925
 
      params_save_to_gimp ();
926
 
 
927
 
      filter ();
928
 
 
929
 
      if (p.run_mode != GIMP_RUN_NONINTERACTIVE)
930
 
        gimp_displays_flush ();
931
 
    }
932
 
 
933
 
  gimp_drawable_detach (p.drawable);
934
 
 
935
 
  {
936
 
    static GimpParam return_value[1];
937
 
    return_value[0].type          = GIMP_PDB_STATUS;
938
 
    return_value[0].data.d_status = status;
939
 
    *numof_return_vals            = 1;
940
 
    *return_vals                  = return_value;
941
 
  }
942
 
}
943
 
 
944
 
const GimpPlugInInfo PLUG_IN_INFO =
945
 
{
946
 
  NULL,
947
 
  NULL,
948
 
  plugin_query,
949
 
  plugin_run
950
 
};
951
 
 
952
 
MAIN ()