~ubuntu-branches/ubuntu/maverick/gimp/maverick-updates

« back to all changes in this revision

Viewing changes to plug-ins/maze/maze.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-12-09 19:44:52 UTC
  • Revision ID: james.westby@ubuntu.com-20051209194452-yggpemjlofpjqyf4
Tags: upstream-2.2.9
ImportĀ upstreamĀ versionĀ 2.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: maze.c,v 1.37 2004/11/18 08:59:56 neo Exp $
 
2
 * This is a plug-in for the GIMP.
 
3
 * It draws mazes...
 
4
 *
 
5
 * Implemented as a GIMP 0.99 Plugin by
 
6
 * Kevin Turner <acapnotic@users.sourceforge.net>
 
7
 * http://gimp-plug-ins.sourceforge.net/maze/
 
8
 *
 
9
 * Code generously borrowed from assorted GIMP plugins
 
10
 * and used as a template to get me started on this one.  :)
 
11
 *
 
12
 * TO DO:
 
13
 *   maze_face.c: Rework the divboxes to be more like spinbuttons.
 
14
 *
 
15
 *   Maybe add an option to kill the outer border.
 
16
 *
 
17
 *   Fix that stray line down there between maze wall and dead space border...
 
18
 *
 
19
 *   handy.c: Make get_colors() work with indexed.  * HELP! *
 
20
 *
 
21
 */
 
22
 
 
23
/*
 
24
 * This program is free software; you can redistribute it and/or modify
 
25
 * it under the terms of the GNU General Public License as published by
 
26
 * the Free Software Foundation; either version 2 of the License, or
 
27
 * (at your option) any later version.
 
28
 *
 
29
 * This program is distributed in the hope that it will be useful,
 
30
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
31
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
32
 * GNU General Public License for more details.
 
33
 *
 
34
 * You should have received a copy of the GNU General Public License
 
35
 * along with this program; if not, write to the Free Software
 
36
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
37
 *
 
38
 */
 
39
 
 
40
#include "config.h"
 
41
 
 
42
#include <stdio.h>
 
43
#include <stdlib.h>
 
44
 
 
45
#include "libgimp/gimp.h"
 
46
#include "libgimp/gimpui.h"
 
47
 
 
48
#include "maze.h"
 
49
 
 
50
#include "libgimp/stdplugins-intl.h"
 
51
 
 
52
 
 
53
static void      query     (void);
 
54
static void      run       (const gchar      *name,
 
55
                            gint              nparams,
 
56
                            const GimpParam  *param,
 
57
                            gint             *nreturn_vals,
 
58
                            GimpParam       **return_vals);
 
59
 
 
60
static void      maze      (GimpDrawable     *drawable);
 
61
 
 
62
static void      mask_maze (gint32  selection_ID,
 
63
                            guchar *maz,
 
64
                            guint   mw,
 
65
                            guint   mh,
 
66
                            gint    x1,
 
67
                            gint    x2,
 
68
                            gint    y1,
 
69
                            gint    y2,
 
70
                            gint    deadx,
 
71
                            gint    deady);
 
72
 
 
73
/* In maze_face.c */
 
74
extern gint      maze_dialog      (void);
 
75
 
 
76
/* In algorithms.c */
 
77
extern void      mazegen          (gint    pos,
 
78
                                   guchar *maz,
 
79
                                   gint    x,
 
80
                                   gint    y,
 
81
                                   gint    rnd);
 
82
extern void      mazegen_tileable (gint    pos,
 
83
                                   guchar *maz,
 
84
                                   gint    x,
 
85
                                   gint    y,
 
86
                                   gint    rnd);
 
87
extern void      prim             (guint   pos,
 
88
                                   guchar *maz,
 
89
                                   guint   x,
 
90
                                   guint   y);
 
91
extern void      prim_tileable    (guchar *maz,
 
92
                                   guint   x,
 
93
                                   guint   y);
 
94
 
 
95
/* In handy.c */
 
96
extern void      get_colors (GimpDrawable *drawable,
 
97
                             guint8       *fg,
 
98
                             guint8       *bg);
 
99
 
 
100
extern void      drawbox    (GimpPixelRgn *dest_rgn,
 
101
                             guint         x,
 
102
                             guint         y,
 
103
                             guint         w,
 
104
                             guint         h,
 
105
                             guint8        clr[4]);
 
106
 
 
107
 
 
108
GimpPlugInInfo PLUG_IN_INFO =
 
109
{
 
110
  NULL,    /* init_proc */
 
111
  NULL,    /* quit_proc */
 
112
  query,   /* query_proc */
 
113
  run,     /* run_proc */
 
114
};
 
115
 
 
116
MazeValues mvals =
 
117
{
 
118
  5,           /* Passage width */
 
119
  5,           /* Passage height */
 
120
  0,           /* seed */
 
121
  FALSE,       /* Tileable? */
 
122
  57,          /* multiple * These two had "Experiment with this?" comments */
 
123
  1,           /* offset   * in the maz.c source, so, lets expiriment.  :) */
 
124
  DEPTH_FIRST, /* Algorithm */
 
125
  TRUE,        /* random_seed */
 
126
};
 
127
 
 
128
GRand *gr;
 
129
 
 
130
guint sel_w, sel_h;
 
131
 
 
132
 
 
133
MAIN ()
 
134
 
 
135
 
 
136
static void
 
137
query (void)
 
138
{
 
139
  static GimpParamDef args[] =
 
140
  {
 
141
    { GIMP_PDB_INT32,    "run_mode",    "Interactive, non-interactive" },
 
142
    { GIMP_PDB_IMAGE,    "image_ID",    "(unused)" },
 
143
    { GIMP_PDB_DRAWABLE, "drawable_ID", "ID of drawable" },
 
144
    /* If we did have parameters, these be them: */
 
145
    { GIMP_PDB_INT16,    "width",       "Width of the passages" },
 
146
    { GIMP_PDB_INT16,    "height",      "Height of the passages"},
 
147
    { GIMP_PDB_INT8,     "tileable",    "Tileable maze?"},
 
148
    { GIMP_PDB_INT8,     "algorithm",   "Generation algorithm"
 
149
                                        "(0=DEPTH FIRST, 1=PRIM'S ALGORITHM)" },
 
150
    { GIMP_PDB_INT32,    "seed",        "Random Seed"},
 
151
    { GIMP_PDB_INT16,    "multiple",    "Multiple (use 57)" },
 
152
    { GIMP_PDB_INT16,    "offset",      "Offset (use 1)" }
 
153
  };
 
154
 
 
155
  gimp_install_procedure ("plug_in_maze",
 
156
                          "Draws a maze.",
 
157
                          "Generates a maze using either the depth-first "
 
158
                          "search method or Prim's algorithm.  Can make "
 
159
                          "tileable mazes too.",
 
160
                          "Kevin Turner <kevint@poboxes.com>",
 
161
                          "Kevin Turner",
 
162
                          "1997, 1998",
 
163
                          N_("_Maze..."),
 
164
                          "RGB*, GRAY*, INDEXED*",
 
165
                          GIMP_PLUGIN,
 
166
                          G_N_ELEMENTS (args), 0,
 
167
                          args, NULL);
 
168
 
 
169
  gimp_plugin_menu_register ("plug_in_maze",
 
170
                             "<Image>/Filters/Render/Pattern");
 
171
}
 
172
 
 
173
static void
 
174
run (const gchar      *name,
 
175
     gint              nparams,
 
176
     const GimpParam  *param,
 
177
     gint             *nreturn_vals,
 
178
     GimpParam       **return_vals)
 
179
{
 
180
  static GimpParam   values[1];
 
181
  GimpDrawable      *drawable;
 
182
  GimpRunMode        run_mode;
 
183
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
 
184
  gint               x1, y1, x2, y2;
 
185
 
 
186
#ifdef MAZE_DEBUG
 
187
  g_print("maze PID: %d\n",getpid());
 
188
#endif
 
189
  run_mode = param[0].data.d_int32;
 
190
 
 
191
  *nreturn_vals = 1;
 
192
  *return_vals = values;
 
193
 
 
194
  INIT_I18N ();
 
195
 
 
196
  gr = g_rand_new ();
 
197
 
 
198
  values[0].type = GIMP_PDB_STATUS;
 
199
  values[0].data.d_status = status;
 
200
 
 
201
  drawable = gimp_drawable_get (param[2].data.d_drawable);
 
202
 
 
203
  switch (run_mode)
 
204
    {
 
205
    case GIMP_RUN_INTERACTIVE:
 
206
      /* Possibly retrieve data */
 
207
      gimp_get_data ("plug_in_maze", &mvals);
 
208
 
 
209
      /* The interface needs to know the dimensions of the image... */
 
210
      gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
 
211
      sel_w = x2 - x1;
 
212
      sel_h = y2 - y1;
 
213
 
 
214
      /* Acquire info with a dialog */
 
215
      if (! maze_dialog ())
 
216
        {
 
217
          gimp_drawable_detach (drawable);
 
218
          return;
 
219
        }
 
220
      break;
 
221
 
 
222
    case GIMP_RUN_NONINTERACTIVE:
 
223
      if (nparams != 10)
 
224
        status = GIMP_PDB_CALLING_ERROR;
 
225
 
 
226
      if (status == GIMP_PDB_SUCCESS)
 
227
        {
 
228
          mvals.width     = (gint16)  param[3].data.d_int16;
 
229
          mvals.height    = (gint16)  param[4].data.d_int16;
 
230
          mvals.tile      = (gint8)   param[5].data.d_int8;
 
231
          mvals.algorithm = (gint8)   param[6].data.d_int8;
 
232
          mvals.seed      = (guint32) param[7].data.d_int32;
 
233
          mvals.multiple  = (gint16)  param[8].data.d_int16;
 
234
          mvals.offset    = (gint16)  param[9].data.d_int16;
 
235
 
 
236
          if (mvals.random_seed)
 
237
            mvals.seed = g_random_int ();
 
238
        }
 
239
      break;
 
240
 
 
241
    case GIMP_RUN_WITH_LAST_VALS:
 
242
      /* Possibly retrieve data */
 
243
      gimp_get_data ("plug_in_maze", &mvals);
 
244
 
 
245
      if (mvals.random_seed)
 
246
        mvals.seed = g_random_int ();
 
247
      break;
 
248
 
 
249
    default:
 
250
      break;
 
251
  }
 
252
 
 
253
  /* color, gray, or indexed... hmm, miss anything?  ;)  */
 
254
  if (gimp_drawable_is_rgb (drawable->drawable_id) ||
 
255
      gimp_drawable_is_gray (drawable->drawable_id) ||
 
256
      gimp_drawable_is_indexed (drawable->drawable_id))
 
257
    {
 
258
      maze (drawable);
 
259
 
 
260
      if (run_mode != GIMP_RUN_NONINTERACTIVE)
 
261
        gimp_displays_flush ();
 
262
 
 
263
      if (run_mode == GIMP_RUN_INTERACTIVE ||
 
264
          (run_mode == GIMP_RUN_WITH_LAST_VALS))
 
265
        gimp_set_data ("plug_in_maze", &mvals, sizeof (MazeValues));
 
266
    }
 
267
  else
 
268
    {
 
269
      status = GIMP_PDB_EXECUTION_ERROR;
 
270
    }
 
271
 
 
272
  values[0].data.d_status = status;
 
273
 
 
274
  g_rand_free (gr);
 
275
  gimp_drawable_detach (drawable);
 
276
}
 
277
 
 
278
#ifdef MAZE_DEBUG
 
279
void
 
280
maze_dump (guchar *maz, gint mw, gint mh)
 
281
{
 
282
  short xx, yy;
 
283
  int   foo = 0;
 
284
 
 
285
  for (yy = 0; yy < mh; yy++)
 
286
    {
 
287
      for (xx = 0; xx < mw; xx++)
 
288
        g_print ("%3d ", maz[foo++]);
 
289
      g_print ("\n");
 
290
    }
 
291
}
 
292
 
 
293
void
 
294
maze_dumpX (guchar *maz, gint mw, gint mh)
 
295
{
 
296
  short xx, yy;
 
297
  int   foo = 0;
 
298
 
 
299
  for (yy = 0; yy < mh; yy++)
 
300
    {
 
301
      for (xx = 0; xx < mw; xx++)
 
302
        g_print ("%c", maz[foo++] ? 'X' : '.');
 
303
      g_print ("\n");
 
304
    }
 
305
}
 
306
#endif
 
307
 
 
308
static void
 
309
maze (GimpDrawable * drawable)
 
310
{
 
311
  GimpPixelRgn dest_rgn;
 
312
  guint        mw, mh;
 
313
  gint         deadx, deady;
 
314
  guint        progress, max_progress;
 
315
  gint         x1, y1, x2, y2, x, y;
 
316
  gint         dx, dy, xx, yy;
 
317
  gint         maz_x, maz_xx, maz_row, maz_yy;
 
318
  guint8       fg[4], bg[4];
 
319
  gpointer     pr;
 
320
  gboolean     active_selection;
 
321
 
 
322
  guchar      *maz;
 
323
  guint        pos;
 
324
 
 
325
  /* Gets the input area... */
 
326
  active_selection = gimp_drawable_mask_bounds (drawable->drawable_id,
 
327
                                                &x1, &y1, &x2, &y2);
 
328
 
 
329
  /***************** Maze Stuff Happens Here ***************/
 
330
 
 
331
  mw = (x2-x1) / mvals.width;
 
332
  mh = (y2-y1) / mvals.height;
 
333
 
 
334
  if (!mvals.tile)
 
335
    {
 
336
      mw -= !(mw & 1); /* mazegen doesn't work with even-sized mazes. */
 
337
      mh -= !(mh & 1); /* Note I don't warn the user about this... */
 
338
    }
 
339
  else
 
340
    {
 
341
      /* On the other hand, tileable mazes must be even. */
 
342
      mw -= (mw & 1);
 
343
      mh -= (mh & 1);
 
344
    };
 
345
 
 
346
  /* It will really suck if your tileable maze ends up with this dead
 
347
     space around it.  Oh well, life is hard. */
 
348
  deadx = ((x2-x1) - mw * mvals.width)  / 2;
 
349
  deady = ((y2-y1) - mh * mvals.height) / 2;
 
350
 
 
351
  maz = g_new0 (guchar, mw * mh);
 
352
 
 
353
#ifdef MAZE_DEBUG
 
354
  printf("x:  %d\ty:  %d\nmw: %d\tmh: %d\ndx: %d\tdy: %d\nwidth:%d\theight: %d\n",
 
355
         (x2 - x1), (y2 - y1), mw, mh, deadx, deady, mvals.width, mvals.height);
 
356
#endif
 
357
 
 
358
  /* Sanity check: */
 
359
  switch (mvals.algorithm)
 
360
    {
 
361
    case DEPTH_FIRST:
 
362
    case PRIMS_ALGORITHM:
 
363
      break;
 
364
    default:
 
365
      g_warning ("maze: Invalid algorithm choice %d", mvals.algorithm);
 
366
    }
 
367
 
 
368
  if (mvals.tile)
 
369
    {
 
370
      switch (mvals.algorithm)
 
371
        {
 
372
        case DEPTH_FIRST:
 
373
          mazegen_tileable (0, maz, mw, mh, mvals.seed);
 
374
          break;
 
375
 
 
376
        case PRIMS_ALGORITHM:
 
377
          prim_tileable (maz, mw, mh);
 
378
          break;
 
379
 
 
380
        default:
 
381
          break;
 
382
        }
 
383
    }
 
384
  else
 
385
    {
 
386
      /* not tileable */
 
387
      if (active_selection)
 
388
        {
 
389
          /* Mask and draw mazes until there's no
 
390
           * more room left. */
 
391
          mask_maze (drawable->drawable_id,
 
392
                     maz, mw, mh, x1, x2, y1, y2, deadx, deady);
 
393
 
 
394
          for (maz_yy = mw; maz_yy < (mh * mw); maz_yy += 2 * mw)
 
395
            {
 
396
              for (maz_xx = 1; maz_xx < mw; maz_xx += 2)
 
397
                {
 
398
                  if (maz[maz_yy + maz_xx] == 0)
 
399
                    {
 
400
                      switch (mvals.algorithm)
 
401
                        {
 
402
                        case DEPTH_FIRST:
 
403
                          mazegen (maz_yy+maz_xx, maz, mw, mh, mvals.seed);
 
404
                          break;
 
405
 
 
406
                        case PRIMS_ALGORITHM:
 
407
                          prim (maz_yy+maz_xx, maz, mw, mh);
 
408
                          break;
 
409
 
 
410
                        default:
 
411
                          break;
 
412
                        }
 
413
                    }
 
414
                }
 
415
            }
 
416
        }
 
417
      else
 
418
        {
 
419
          /* No active selection. */
 
420
          pos = mw + 1;
 
421
 
 
422
          switch (mvals.algorithm)
 
423
            {
 
424
            case DEPTH_FIRST:
 
425
              mazegen (pos, maz, mw, mh, mvals.seed);
 
426
              break;
 
427
 
 
428
            case PRIMS_ALGORITHM:
 
429
              prim (pos, maz, mw, mh);
 
430
              break;
 
431
 
 
432
            default:
 
433
              break;
 
434
            }
 
435
        }
 
436
    }
 
437
 
 
438
  /************** Begin Drawing *********************/
 
439
 
 
440
  /* Initialize pixel region (?) */
 
441
  gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1),
 
442
                       TRUE, TRUE);
 
443
 
 
444
  progress = 0;
 
445
  max_progress = (x2 - x1) * (y2 - y1);
 
446
 
 
447
  /* Get the foreground and background colors */
 
448
  get_colors (drawable, fg, bg);
 
449
 
 
450
  gimp_progress_init (_("Drawing Maze..."));
 
451
 
 
452
  for (pr = gimp_pixel_rgns_register (1, &dest_rgn);
 
453
       pr != NULL;
 
454
       pr = gimp_pixel_rgns_process (pr))
 
455
    {
 
456
      x = dest_rgn.x - x1 - deadx;
 
457
      y = dest_rgn.y - y1 - deady;
 
458
 
 
459
      /* First boxes by edge of tile must be handled specially
 
460
         because they may have started on a previous tile,
 
461
         unbeknownst to us. */
 
462
 
 
463
      dx = mvals.width - (x % mvals.width);
 
464
      dy = mvals.height - (y % mvals.height);
 
465
      maz_x = x/mvals.width;
 
466
      maz_row = mw * (y/mvals.height);
 
467
 
 
468
      /* Draws the upper-left [split] box */
 
469
      drawbox (&dest_rgn, 0, 0, dx, dy,
 
470
               (maz[maz_row + maz_x] == IN) ? fg : bg);
 
471
 
 
472
      maz_xx=maz_x + 1;
 
473
      /* Draw the top row [split] boxes */
 
474
      for (xx=dx; xx < dest_rgn.w; xx+=mvals.width)
 
475
        {
 
476
          drawbox (&dest_rgn, xx, 0, mvals.width, dy,
 
477
                   (maz[maz_row + maz_xx++] == IN) ? fg : bg);
 
478
        }
 
479
 
 
480
      maz_yy = maz_row + mw;
 
481
      /* Left column */
 
482
      for (yy = dy; yy < dest_rgn.h; yy += mvals.height)
 
483
        {
 
484
          drawbox (&dest_rgn, 0, yy, dx, mvals.height,
 
485
                   (maz[maz_yy + maz_x] == IN) ? fg : bg);
 
486
          maz_yy += mw;
 
487
        }
 
488
 
 
489
      maz_x++;
 
490
      /* Everything else */
 
491
      for (yy = dy; yy < dest_rgn.h; yy += mvals.height)
 
492
        {
 
493
          maz_xx = maz_x; maz_row+=mw;
 
494
 
 
495
          for (xx = dx; xx < dest_rgn.w; xx += mvals.width)
 
496
            {
 
497
              drawbox (&dest_rgn, xx, yy, mvals.width, mvals.height,
 
498
                       (maz[maz_row + maz_xx++] == IN) ? fg : bg);
 
499
            }
 
500
        }
 
501
 
 
502
      progress += dest_rgn.w * dest_rgn.h;
 
503
      gimp_progress_update ((double) progress / (double) max_progress);
 
504
      /* Indicate progress in drawing. */
 
505
    }
 
506
 
 
507
  gimp_drawable_flush (drawable);
 
508
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
 
509
  gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1));
 
510
}
 
511
 
 
512
/* Shaped mazes: */
 
513
/* With
 
514
 * Depth first: Nonzero cells will not be connected to or visited.
 
515
 * Prim's Algorithm:
 
516
 *  Cells that are not IN will not be connected to.
 
517
 *  Cells that are not OUT will not be converted to FRONTIER.
 
518
 *
 
519
 * So we'll put unavailable cells in a non-zero non-in non-out class
 
520
 * called MASKED.
 
521
 */
 
522
 
 
523
/* But first...  A little discussion about cells. */
 
524
 
 
525
/* In the eyes of the generation algorithms, the world is made up of
 
526
 * two sorts of things: Cells, and the walls between them.  Walls can
 
527
 * be knocked out, and then you have a passage between cells.  The
 
528
 * drawing routine has a simpler view of life...  Everything is a
 
529
 * pixel.  Or a block of pixels.  It makes no distinction between
 
530
 * passages, walls, and cells.
 
531
 *
 
532
 *  We may also make the distinction between two different types of
 
533
 * passages: horizontal and vertical.  With that in mind, a
 
534
 * part of the world looks something like this:
 
535
 *
 
536
 * @-@-@-@-  Where @ is a cell, | is a vertical passage, and - is a
 
537
 * | | | |   horizontal passsage.
 
538
 * @-@-@-@-
 
539
 * | | | |   Remember, the maze generation routines will not rest
 
540
 *          until the maze is full, that is, every cell is connected
 
541
 * to another.  Already, we can determine a few things about the final
 
542
 * maze.  We know which blocks will be cells, which blocks may become
 
543
 * passages (and we know what sort), and we also notice that there are
 
544
 * some blocks that will never be either cells or passages.
 
545
 *
 
546
 * Now, back to our masking routine...  To save a little time, lets
 
547
 * just take sample points from the block.  We'll sample a point from
 
548
 * the top and the bottom of vertical passages, left/right for
 
549
 * horizontal, and, hmm, left/right/top/bottom for cells.  And of
 
550
 * course, we needn't concern ourselves with the others.  We could
 
551
 * also sample the midpoint of each...
 
552
 * Then what we'll do is see if the average is higher than some magic
 
553
 * threshold number, and if so, we let maze happen there.  Otherwise
 
554
 * we mask it out.
 
555
 */
 
556
 
 
557
/* And, uh, that's on the TODO list.  Looks like I spent so much time
 
558
 * writing comments I haven't left enough to implement the code.  :)
 
559
 * Right now we only sample one point. */
 
560
static void
 
561
mask_maze (gint32 drawable_ID, guchar *maz, guint mw, guint mh,
 
562
           gint x1, gint x2, gint y1, gint y2, gint deadx, gint deady)
 
563
{
 
564
  gint32 selection_ID;
 
565
  GimpPixelRgn sel_rgn;
 
566
  gint xx0=0, yy0=0, xoff, yoff;
 
567
  guint xx=0, yy=0;
 
568
  guint foo=0;
 
569
 
 
570
  gint cur_row, cur_col;
 
571
  gint x1half, x2half, y1half, y2half;
 
572
  guchar *linebuf;
 
573
 
 
574
  if ((selection_ID =
 
575
       gimp_image_get_selection (gimp_drawable_get_image (drawable_ID))) == -1)
 
576
    return;
 
577
 
 
578
  gimp_pixel_rgn_init (&sel_rgn, gimp_drawable_get (selection_ID),
 
579
                       x1, y1, (x2-x1), (y2-y1),
 
580
                       FALSE, FALSE);
 
581
  gimp_drawable_offsets (drawable_ID, &xoff, &yoff);
 
582
 
 
583
  /* Special cases:  If mw or mh < 3 */
 
584
  /* FIXME (Currently works, but inefficiently.) */
 
585
 
 
586
  /* mw && mh => 3 */
 
587
 
 
588
  linebuf = g_new (guchar, sel_rgn.w * sel_rgn.bpp);
 
589
 
 
590
  xx0 = x1 + deadx + mvals.width  + xoff;
 
591
  yy0 = y1 + deady + mvals.height + yoff;
 
592
 
 
593
  x1half = mvals.width / 2;
 
594
  x2half = mvals.width - 1;
 
595
 
 
596
  y1half = mvals.height / 2;
 
597
  y2half = mvals.height - 1;
 
598
 
 
599
  /* Here, yy is with respect to the drawable (or something),
 
600
     whereas xx is with respect to the row buffer. */
 
601
 
 
602
  yy = yy0 + y1half;
 
603
 
 
604
  for (cur_row=1; cur_row < mh; cur_row += 2)
 
605
    {
 
606
      gimp_pixel_rgn_get_row (&sel_rgn, linebuf, x1+xoff, yy, (x2 - x1));
 
607
 
 
608
      cur_col = 1; xx = mvals.width;
 
609
 
 
610
      while (cur_col < mw)
 
611
        {
 
612
          /* Cell: */
 
613
          maz[cur_row * mw + cur_col] =
 
614
            (linebuf[xx] + linebuf[xx + x1half] + linebuf[xx+x2half]) / 5;
 
615
 
 
616
          cur_col += 1;
 
617
          xx += mvals.width;
 
618
 
 
619
          /* Passage: */
 
620
          if (cur_col < mw)
 
621
            maz[cur_row * mw + cur_col] =
 
622
              (linebuf[xx] + linebuf[xx + x1half] + linebuf[xx+x2half]) / 3;
 
623
 
 
624
          cur_col += 1;
 
625
          xx += mvals.width;
 
626
 
 
627
        } /* next col */
 
628
 
 
629
      yy += 2 * mvals.height;
 
630
 
 
631
    } /* next cur_row += 2 */
 
632
 
 
633
  /* Done doing horizontal scans, change this from a row buffer to
 
634
     a column buffer. */
 
635
  g_free (linebuf);
 
636
  linebuf = g_new (guchar, sel_rgn.h * sel_rgn.bpp);
 
637
 
 
638
  /* Now xx is with respect to the drawable (or whatever),
 
639
     and yy is with respect to the row buffer. */
 
640
 
 
641
  xx=xx0 + x1half;
 
642
  for (cur_col = 1; cur_col < mw; cur_col += 2)
 
643
    {
 
644
      gimp_pixel_rgn_get_col (&sel_rgn, linebuf, xx, y1, (y2-y1));
 
645
 
 
646
      cur_row = 1; yy = mvals.height;
 
647
 
 
648
      while (cur_row < mh)
 
649
        {
 
650
          /* Cell: */
 
651
          maz[cur_row * mw + cur_col] +=
 
652
            (linebuf[yy] + linebuf[yy+y2half]) / 5;
 
653
 
 
654
          cur_row += 1;
 
655
          yy += mvals.height;
 
656
 
 
657
          /* Passage: */
 
658
          if (cur_row < mh)
 
659
            maz[cur_row * mw + cur_col] =
 
660
              (linebuf[yy] + linebuf[yy + y1half] + linebuf[yy+y2half]) / 3;
 
661
 
 
662
          cur_row += 1;
 
663
          yy += mvals.height;
 
664
        } /* next cur_row */
 
665
 
 
666
      xx += 2 * mvals.width;
 
667
 
 
668
    } /* next cur_col */
 
669
 
 
670
  g_free (linebuf);
 
671
 
 
672
  /* Do the alpha -> masked conversion. */
 
673
 
 
674
  for (yy = 0; yy < mh; yy++)
 
675
    {
 
676
      for (xx = 0; xx < mw; xx++)
 
677
        {
 
678
          maz[foo] = ( maz[foo] < MAZE_ALPHA_THRESHOLD ) ? MASKED : OUT;
 
679
          foo++;
 
680
        }
 
681
    }
 
682
}
 
683
 
 
684
 
 
685
/* The attempt to implement this with tiles: (it wasn't fun) */
 
686
 
 
687
#if 0
 
688
 
 
689
{
 
690
  /* Tiles make my life decidedly difficult here.  There are too
 
691
   * many special cases...  "What if a tile starts less/more than
 
692
   * halfway through a block?  What if we get a narrow edge-tile
 
693
   * that..." etc, etc.  I shall investigate other options.
 
694
   * Possibly a row buffer, or can we use something other than this
 
695
   * black-magic gimp_pixel_rgns_register call to get tiles of
 
696
   * different sizes?  Now that'd be nice...  */
 
697
 
 
698
  for (pr = gimp_pixel_rgns_register (1, &sel_rgn);
 
699
       pr != NULL;
 
700
       pr = gimp_pixel_rgns_process (pr))
 
701
    {
 
702
      /* This gives us coordinates relative to the starting point
 
703
       * of the maze grid.  Negative values happen here if there
 
704
       * is dead space. */
 
705
      x = sel_rgn.x - x1 - deadx;
 
706
      y = sel_rgn.y - y1 - deady;
 
707
 
 
708
      /* These coordinates are relative to the current tile. */
 
709
      /* This starts us off at the first block boundary in the
 
710
       * tile. */
 
711
 
 
712
      /* e.g. with x=16 and width=10.
 
713
       * 16 % 10 = 6
 
714
       * 10 - 6 = 4
 
715
 
 
716
  x: 6789!123456789!123456789!12
 
717
     ....|.........|.........|..
 
718
 xx: 0123456789!123456789!123456
 
719
 
 
720
 So to start on the boundary, begin at 4.
 
721
 
 
722
 For the case x=0, 10-0=10. So xx0 will always between 1 and width. */
 
723
 
 
724
      xx0 = mvals.width  - (x % mvals.width);
 
725
      yy0 = mvals.height - (y % mvals.height);
 
726
 
 
727
      /* Find the corresponding row and column in the maze. */
 
728
      maz_x = (x+xx0)/mvals.width;
 
729
      maz_row = mw * ((y + yy0)/mvals.height);
 
730
 
 
731
      for (yy = yy0 * sel_rgn.rowstride;
 
732
           yy < sel_rgn.h * sel_rgn.rowstride;
 
733
           yy += (mvals.height * sel_rgn.rowstride))
 
734
        {
 
735
          maz_xx = maz_x;
 
736
          for (xx = xx0 * sel_rgn.bpp;
 
737
               xx < sel_rgn.w;
 
738
               xx += mvals.width * sel_rgn.bpp)
 
739
            {
 
740
              if (sel_rgn.data[yy+xx] < MAZE_ALPHA_THRESHOLD)
 
741
                maz[maz_row+maz_xx]=MASKED;
 
742
              maz_xx++;
 
743
            }
 
744
 
 
745
          maz_row += mw;
 
746
        }
 
747
 
 
748
    } /* next pr sel_rgn tile thing */
 
749
#ifdef MAZE_DEBUG
 
750
  /* maze_dump(maz,mw,mh); */
 
751
#endif
 
752
}
 
753
 
 
754
#endif /* 0 */