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

« back to all changes in this revision

Viewing changes to app/paint-funcs/paint-funcs.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The GIMP -- an image manipulation program
 
1
/* GIMP - The GNU Image Manipulation Program
2
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify
42
42
#define RANDOM_SEED   314159265
43
43
#define EPSILON       0.0001
44
44
 
45
 
 
46
 
typedef enum
47
 
{
48
 
  MinifyX_MinifyY,
49
 
  MinifyX_MagnifyY,
50
 
  MagnifyX_MinifyY,
51
 
  MagnifyX_MagnifyY
52
 
} ScaleType;
 
45
#define LOG_1_255     -5.541263545    /*  log (1.0 / 255.0)  */
53
46
 
54
47
 
55
48
/*  Layer modes information  */
56
49
typedef struct _LayerMode LayerMode;
57
50
struct _LayerMode
58
51
{
59
 
  guint   affect_alpha     : 1; /*  does the layer mode affect the alpha channel  */
60
 
  guint   increase_opacity : 1; /*  layer mode can increase opacity */
61
 
  guint   decrease_opacity : 1; /*  layer mode can decrease opacity */
 
52
  const guint   affect_alpha     : 1; /*  does the layer mode affect the
 
53
                                          alpha channel  */
 
54
  const guint   increase_opacity : 1; /*  layer mode can increase opacity */
 
55
  const guint   decrease_opacity : 1; /*  layer mode can decrease opacity */
62
56
};
63
57
 
64
58
static const LayerMode layer_modes[] =
65
 
                               /* This must obviously be in the same
66
 
                                * order as the corresponding values
67
 
                                 * in the GimpLayerModeEffects enumeration.
68
 
                                */
 
59
  /* This must be in the same order as the
 
60
   * corresponding values in GimpLayerModeEffects.
 
61
   */
69
62
{
70
63
  { TRUE,  TRUE,  FALSE, },  /*  GIMP_NORMAL_MODE        */
71
64
  { TRUE,  TRUE,  FALSE, },  /*  GIMP_DISSOLVE_MODE      */
95
88
  { TRUE,  TRUE,  FALSE, }   /*  GIMP_ANTI_ERASE_MODE    */
96
89
};
97
90
 
 
91
 
98
92
typedef void (* LayerModeFunc) (struct apply_layer_mode_struct *);
99
 
static LayerModeFunc layer_mode_funcs[] =
 
93
 
 
94
static const LayerModeFunc layer_mode_funcs[] =
100
95
{
101
96
  layer_normal_mode,
102
97
  layer_dissolve_mode,
132
127
 
133
128
/*  Local function prototypes  */
134
129
 
135
 
static gint *   make_curve               (gdouble        sigma,
136
 
                                          guint         *length);
 
130
static gint *   make_curve               (gdouble         sigma_square,
 
131
                                          gint           *length);
137
132
static gdouble  cubic                    (gdouble         dx,
138
133
                                          gint            jm1,
139
134
                                          gint            j,
140
135
                                          gint            jp1,
141
136
                                          gint            jp2);
142
 
static void     apply_layer_mode_replace (guchar         *src1,
143
 
                                          guchar         *src2,
 
137
static void     apply_layer_mode_replace (const guchar   *src1,
 
138
                                          const guchar   *src2,
144
139
                                          guchar         *dest,
145
 
                                          guchar         *mask,
 
140
                                          const guchar   *mask,
146
141
                                          gint            x,
147
142
                                          gint            y,
148
143
                                          guint           opacity,
151
146
                                          guint           bytes2,
152
147
                                          const gboolean *affect);
153
148
 
154
 
static inline void rotate_pointers       (guchar         **p,
155
 
                                          guint32          n);
156
 
 
157
 
 
 
149
static inline void rotate_pointers       (guchar        **p,
 
150
                                          guint32         n);
158
151
 
159
152
static void
160
153
update_tile_rowhints (Tile *tile,
161
154
                      gint  ymin,
162
155
                      gint  ymax)
163
156
{
164
 
  gint         bpp, ewidth;
165
 
  gint         x, y;
166
 
  guchar      *ptr;
167
 
  guchar       alpha;
168
 
  TileRowHint  thishint;
 
157
  const guchar *ptr;
 
158
  gint          bpp, ewidth;
 
159
  gint          x, y;
169
160
 
170
161
#ifdef HINTS_SANITY
171
162
  g_assert (tile != NULL);
176
167
  bpp = tile_bpp (tile);
177
168
  ewidth = tile_ewidth (tile);
178
169
 
179
 
  if (bpp == 1 || bpp == 3)
 
170
  switch (bpp)
180
171
    {
 
172
    case 1:
 
173
    case 3:
181
174
      for (y = ymin; y <= ymax; y++)
182
175
        tile_set_rowhint (tile, y, TILEROWHINT_OPAQUE);
183
 
 
184
 
      return;
185
 
    }
186
 
 
187
 
  if (bpp == 4)
188
 
    {
 
176
      break;
 
177
 
 
178
    case 4:
189
179
#ifdef HINTS_SANITY
190
180
      g_assert (tile != NULL);
191
181
#endif
198
188
 
199
189
      for (y = ymin; y <= ymax; y++)
200
190
        {
201
 
          thishint = tile_get_rowhint (tile, y);
 
191
          TileRowHint hint = tile_get_rowhint (tile, y);
202
192
 
203
193
#ifdef HINTS_SANITY
204
 
          if (thishint == TILEROWHINT_BROKEN)
 
194
          if (hint == TILEROWHINT_BROKEN)
205
195
            g_error ("BROKEN y=%d", y);
206
 
          if (thishint == TILEROWHINT_OUTOFRANGE)
 
196
          if (hint == TILEROWHINT_OUTOFRANGE)
207
197
            g_error ("OOR y=%d", y);
208
 
          if (thishint == TILEROWHINT_UNDEFINED)
 
198
          if (hint == TILEROWHINT_UNDEFINED)
209
199
            g_error ("UNDEFINED y=%d - bpp=%d ew=%d eh=%d",
210
200
                     y, bpp, ewidth, eheight);
211
201
#endif
212
202
 
213
203
#ifdef HINTS_SANITY
214
 
          if (thishint == TILEROWHINT_TRANSPARENT ||
215
 
              thishint == TILEROWHINT_MIXED ||
216
 
              thishint == TILEROWHINT_OPAQUE)
 
204
          if (hint == TILEROWHINT_TRANSPARENT ||
 
205
              hint == TILEROWHINT_MIXED ||
 
206
              hint == TILEROWHINT_OPAQUE)
217
207
            {
218
208
              goto next_row4;
219
209
            }
220
210
 
221
 
          if (thishint != TILEROWHINT_UNKNOWN)
 
211
          if (hint != TILEROWHINT_UNKNOWN)
222
212
            {
223
213
              g_error ("MEGABOGUS y=%d - bpp=%d ew=%d eh=%d",
224
214
                       y, bpp, ewidth, eheight);
225
215
            }
226
216
#endif
227
217
 
228
 
          if (thishint == TILEROWHINT_UNKNOWN)
 
218
          if (hint == TILEROWHINT_UNKNOWN)
229
219
            {
230
 
              alpha = ptr[3];
 
220
              const guchar alpha = ptr[3];
231
221
 
232
222
              /* row is all-opaque or all-transparent? */
233
223
              if (alpha == 0 || alpha == 255)
243
233
                            }
244
234
                        }
245
235
                    }
 
236
 
246
237
                  tile_set_rowhint (tile, y,
247
238
                                    (alpha == 0) ?
248
239
                                    TILEROWHINT_TRANSPARENT :
257
248
        next_row4:
258
249
          ptr += 4 * ewidth;
259
250
        }
260
 
 
261
 
      return;
262
 
    }
263
 
 
264
 
  if (bpp == 2)
265
 
    {
 
251
      break;
 
252
 
 
253
    case 2:
266
254
#ifdef HINTS_SANITY
267
255
      g_assert (tile != NULL);
268
256
#endif
275
263
 
276
264
      for (y = ymin; y <= ymax; y++)
277
265
        {
278
 
          thishint = tile_get_rowhint (tile, y);
 
266
          TileRowHint hint = tile_get_rowhint (tile, y);
279
267
 
280
268
#ifdef HINTS_SANITY
281
 
          if (thishint == TILEROWHINT_BROKEN)
 
269
          if (hint == TILEROWHINT_BROKEN)
282
270
            g_error ("BROKEN y=%d",y);
283
 
          if (thishint == TILEROWHINT_OUTOFRANGE)
 
271
          if (hint == TILEROWHINT_OUTOFRANGE)
284
272
            g_error ("OOR y=%d",y);
285
 
          if (thishint == TILEROWHINT_UNDEFINED)
 
273
          if (hint == TILEROWHINT_UNDEFINED)
286
274
            g_error ("UNDEFINED y=%d - bpp=%d ew=%d eh=%d",
287
275
                     y, bpp, ewidth, eheight);
288
276
#endif
289
277
 
290
278
#ifdef HINTS_SANITY
291
 
          if (thishint == TILEROWHINT_TRANSPARENT ||
292
 
              thishint == TILEROWHINT_MIXED ||
293
 
              thishint == TILEROWHINT_OPAQUE)
 
279
          if (hint == TILEROWHINT_TRANSPARENT ||
 
280
              hint == TILEROWHINT_MIXED ||
 
281
              hint == TILEROWHINT_OPAQUE)
294
282
            {
295
283
              goto next_row2;
296
284
            }
297
285
 
298
 
          if (thishint != TILEROWHINT_UNKNOWN)
 
286
          if (hint != TILEROWHINT_UNKNOWN)
299
287
            {
300
288
              g_error ("MEGABOGUS y=%d - bpp=%d ew=%d eh=%d",
301
289
                       y, bpp, ewidth, eheight);
302
290
            }
303
291
#endif
304
292
 
305
 
          if (thishint == TILEROWHINT_UNKNOWN)
 
293
          if (hint == TILEROWHINT_UNKNOWN)
306
294
            {
307
 
              alpha = ptr[1];
 
295
              const guchar alpha = ptr[1];
308
296
 
309
297
              /* row is all-opaque or all-transparent? */
310
298
              if (alpha == 0 || alpha == 255)
313
301
                    {
314
302
                      for (x = 1; x < ewidth; x++)
315
303
                        {
316
 
                          if (ptr[x*2 + 1] != alpha)
 
304
                          if (ptr[x * 2 + 1] != alpha)
317
305
                            {
318
306
                              tile_set_rowhint (tile, y, TILEROWHINT_MIXED);
319
307
                              goto next_row2;
334
322
        next_row2:
335
323
          ptr += 2 * ewidth;
336
324
        }
 
325
      break;
337
326
 
338
 
      return;
 
327
    default:
 
328
      g_return_if_reached ();
 
329
      break;
339
330
    }
340
 
 
341
 
  g_warning ("update_tile_rowhints: Don't know about tiles with bpp==%d", bpp);
342
331
}
343
332
 
344
333
 
345
334
/*
346
335
 * The equations: g(r) = exp (- r^2 / (2 * sigma^2))
347
 
 *                   r = sqrt (x^2 + y ^2)
 
336
 *                   r = sqrt (x^2 + y^2)
348
337
 */
349
338
 
350
339
static gint *
351
 
make_curve (gdouble  sigma,
352
 
            guint   *length)
 
340
make_curve (gdouble  sigma_square,
 
341
            gint    *length)
353
342
{
354
 
  gint    *curve;
355
 
  gdouble  sigma2;
356
 
  gdouble  l;
357
 
  gint     temp;
358
 
  gint     i, n;
 
343
  const gdouble sigma2 = 2 * sigma_square;
 
344
  const gdouble l      = sqrt (-sigma2 * LOG_1_255);
359
345
 
360
 
  sigma2 = 2 * sigma * sigma;
361
 
  l = sqrt (-sigma2 * log (1.0 / 255.0));
 
346
  gint *curve;
 
347
  gint  i, n;
362
348
 
363
349
  n = ceil (l) * 2;
364
350
  if ((n % 2) == 0)
372
358
 
373
359
  for (i = 1; i <= *length; i++)
374
360
    {
375
 
      temp = (gint) (exp (- (i * i) / sigma2) * 255);
 
361
      gint temp = (gint) (exp (- SQR (i) / sigma2) * 255);
 
362
 
376
363
      curve[-i] = temp;
377
364
      curve[i] = temp;
378
365
    }
405
392
              *dest++ = (i - j);
406
393
              *dest++ = last;
407
394
            }
 
395
 
408
396
          start = i;
409
397
          last = *src;
410
398
        }
 
399
 
411
400
      src += bytes;
412
401
    }
413
402
 
432
421
                     ( - jm1 + jp1 ) ) * dx + (j + j) ) / 2.0;
433
422
}
434
423
 
 
424
 
435
425
/*********************/
436
426
/*  FUNCTIONS        */
437
427
/*********************/
472
462
                                    guint           length,
473
463
                                    guint           bytes)
474
464
{
475
 
  gint          b;
476
 
  guchar        new_alpha;
477
 
  const guchar *m;
478
 
  gint          tmp;
 
465
  gint  b;
 
466
  gint  tmp;
479
467
 
480
468
  if (mask)
481
469
    {
482
 
      m = mask;
 
470
      const guchar *m = mask;
 
471
 
483
472
      while (length --)
484
473
        {
485
 
          new_alpha = INT_MULT(*m , opacity, tmp);
 
474
          guchar  new_alpha = INT_MULT(*m , opacity, tmp);
486
475
 
487
476
          for (b = 0; b < bytes; b++)
488
477
            dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
498
487
    {
499
488
      while (length --)
500
489
        {
501
 
          new_alpha = opacity;
 
490
          guchar  new_alpha = opacity;
502
491
 
503
492
          for (b = 0; b < bytes; b++)
504
493
            dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
521
510
                                      guint           length,
522
511
                                      guint           bytes)
523
512
{
524
 
  gint   b, alpha;
525
 
  guchar new_alpha;
526
 
  gint   src2_bytes;
527
 
  glong  tmp;
528
 
  const guchar *m;
529
 
 
530
 
  alpha = 1;
531
 
  src2_bytes = 2;
 
513
  const gint alpha      = 1;
 
514
  const gint src2_bytes = 2;
 
515
  glong      tmp;
 
516
  gint       b;
532
517
 
533
518
  if (mask)
534
519
    {
535
 
      m = mask;
 
520
      const guchar *m = mask;
 
521
 
536
522
      while (length --)
537
523
        {
538
 
          new_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
 
524
          guchar new_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
539
525
 
540
526
          for (b = 0; b < bytes; b++)
541
527
            dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
551
537
    {
552
538
      while (length --)
553
539
        {
554
 
          new_alpha = INT_MULT(src2[alpha], opacity, tmp);
 
540
          guchar new_alpha = INT_MULT(src2[alpha], opacity, tmp);
555
541
 
556
542
          for (b = 0; b < bytes; b++)
557
543
            dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
574
560
                                        guint           length,
575
561
                                        guint           bytes)
576
562
{
577
 
  const guchar * m;
578
 
  gint   b, alpha;
579
 
  guchar new_alpha;
580
 
  glong  tmp;
581
 
 
582
 
  alpha = 1;
583
 
 
584
 
  if (mask)
585
 
    {
586
 
      m = mask;
587
 
 
588
 
      while (length --)
589
 
        {
590
 
          new_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
591
 
 
592
 
          for (b = 0; b < alpha; b++)
593
 
            dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
594
 
 
595
 
          dest[alpha] = (affect[alpha] && new_alpha > 127) ?
596
 
            OPAQUE_OPACITY : src1[alpha];
597
 
 
598
 
          m++;
599
 
 
600
 
          src1 += bytes;
601
 
          src2 += bytes;
602
 
          dest += bytes;
603
 
        }
604
 
    }
605
 
  else
606
 
    {
607
 
      while (length --)
608
 
        {
609
 
          new_alpha = INT_MULT(src2[alpha], opacity, tmp);
610
 
 
611
 
          for (b = 0; b < alpha; b++)
612
 
            dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
613
 
 
614
 
          dest[alpha] = (affect[alpha] && new_alpha > 127) ?
615
 
            OPAQUE_OPACITY : src1[alpha];
616
 
 
617
 
          src1 += bytes;
618
 
          src2 += bytes;
 
563
  const gint alpha = 1;
 
564
  gint       b;
 
565
  glong      tmp;
 
566
 
 
567
  if (mask)
 
568
    {
 
569
      const guchar *m = mask;
 
570
 
 
571
      while (length --)
 
572
        {
 
573
          guchar new_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
 
574
 
 
575
          for (b = 0; b < alpha; b++)
 
576
            dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
 
577
 
 
578
          dest[alpha] = (affect[alpha] && new_alpha > 127) ?
 
579
            OPAQUE_OPACITY : src1[alpha];
 
580
 
 
581
          m++;
 
582
 
 
583
          src1 += bytes;
 
584
          src2 += bytes;
 
585
          dest += bytes;
 
586
        }
 
587
    }
 
588
  else
 
589
    {
 
590
      while (length --)
 
591
        {
 
592
          guchar new_alpha = INT_MULT(src2[alpha], opacity, tmp);
 
593
 
 
594
          for (b = 0; b < alpha; b++)
 
595
            dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
 
596
 
 
597
          dest[alpha] = (affect[alpha] && new_alpha > 127) ?
 
598
            OPAQUE_OPACITY : src1[alpha];
 
599
 
 
600
          src1 += bytes;
 
601
          src2 += bytes;
 
602
          dest += bytes;
 
603
        }
 
604
    }
 
605
}
 
606
 
 
607
 
 
608
void
 
609
combine_inten_a_and_indexed_pixels (const guchar *src1,
 
610
                                    const guchar *src2,
 
611
                                    guchar       *dest,
 
612
                                    const guchar *mask,
 
613
                                    const guchar *cmap,
 
614
                                    guint         opacity,
 
615
                                    guint         length,
 
616
                                    guint         bytes)
 
617
{
 
618
  const gint src2_bytes = 1;
 
619
  gint       b;
 
620
  glong      tmp;
 
621
 
 
622
  if (mask)
 
623
    {
 
624
      const guchar *m = mask;
 
625
 
 
626
      while (length --)
 
627
        {
 
628
          gint   index     = src2[0] * 3;
 
629
          guchar new_alpha = INT_MULT3(255, *m, opacity, tmp);
 
630
 
 
631
          for (b = 0; b < bytes-1; b++)
 
632
            dest[b] = (new_alpha > 127) ? cmap[index + b] : src1[b];
 
633
 
 
634
          dest[b] = (new_alpha > 127) ? OPAQUE_OPACITY : src1[b];
 
635
          /*  alpha channel is opaque  */
 
636
 
 
637
          m++;
 
638
 
 
639
          src1 += bytes;
 
640
          src2 += src2_bytes;
 
641
          dest += bytes;
 
642
        }
 
643
    }
 
644
  else
 
645
    {
 
646
      while (length --)
 
647
        {
 
648
          gint   index     = src2[0] * 3;
 
649
          guchar new_alpha = INT_MULT(255, opacity, tmp);
 
650
 
 
651
          for (b = 0; b < bytes-1; b++)
 
652
            dest[b] = (new_alpha > 127) ? cmap[index + b] : src1[b];
 
653
 
 
654
          dest[b] = (new_alpha > 127) ? OPAQUE_OPACITY : src1[b];
 
655
          /*  alpha channel is opaque  */
 
656
 
 
657
          /* m++; /Per */
 
658
 
 
659
          src1 += bytes;
 
660
          src2 += src2_bytes;
619
661
          dest += bytes;
620
662
        }
621
663
    }
632
674
                                      guint         length,
633
675
                                      guint         bytes)
634
676
{
635
 
  gint   b, alpha;
636
 
  guchar new_alpha;
637
 
  gint   src2_bytes;
638
 
  gint   index;
639
 
  glong  tmp;
640
 
  const guchar *m;
641
 
 
642
 
  alpha = 1;
643
 
  src2_bytes = 2;
 
677
  const gint alpha = 1;
 
678
  const gint src2_bytes = 2;
 
679
  gint       b;
 
680
  glong      tmp;
644
681
 
645
682
  if (mask)
646
683
    {
647
 
      m = mask;
 
684
      const guchar *m = mask;
648
685
 
649
686
      while (length --)
650
687
        {
651
 
          new_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
652
 
 
653
 
          index = src2[0] * 3;
 
688
          gint   index     = src2[0] * 3;
 
689
          guchar new_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
654
690
 
655
691
          for (b = 0; b < bytes-1; b++)
656
692
            dest[b] = (new_alpha > 127) ? cmap[index + b] : src1[b];
669
705
    {
670
706
      while (length --)
671
707
        {
672
 
          new_alpha = INT_MULT(src2[alpha], opacity, tmp);
673
 
 
674
 
          index = src2[0] * 3;
 
708
          gint   index     = src2[0] * 3;
 
709
          guchar new_alpha = INT_MULT(src2[alpha], opacity, tmp);
675
710
 
676
711
          for (b = 0; b < bytes-1; b++)
677
712
            dest[b] = (new_alpha > 127) ? cmap[index + b] : src1[b];
699
734
                                guint           length,
700
735
                                guint           bytes)
701
736
{
702
 
  const guchar * m;
703
 
  gint   b;
704
 
  guchar new_alpha;
705
 
  gint   tmp;
 
737
  gint  b;
 
738
  gint  tmp;
706
739
 
707
740
  if (mask)
708
741
    {
709
 
      m = mask;
 
742
      const guchar * m = mask;
 
743
 
710
744
      while (length --)
711
745
        {
712
 
          new_alpha = INT_MULT(*m, opacity, tmp);
 
746
          guchar new_alpha = INT_MULT(*m, opacity, tmp);
713
747
 
714
748
          for (b = 0; b < bytes; b++)
715
749
            dest[b] = (affect[b]) ?
716
750
              INT_BLEND(src2[b], src1[b], new_alpha, tmp) :
717
 
            src1[b];
 
751
              src1[b];
718
752
 
719
753
          m++;
720
754
 
731
765
          for (b = 0; b < bytes; b++)
732
766
            dest[b] = (affect[b]) ?
733
767
              INT_BLEND(src2[b], src1[b], opacity, tmp) :
734
 
            src1[b];
 
768
              src1[b];
735
769
 
736
770
          src1 += bytes;
737
771
          src2 += bytes;
751
785
                                  guint           length,
752
786
                                  guint           bytes)
753
787
{
754
 
  gint   alpha, b;
755
 
  gint   src2_bytes;
756
 
  guchar new_alpha;
757
 
  const guchar   *m;
 
788
  const gint      alpha      = bytes;
 
789
  const gint      src2_bytes = bytes + 1;
 
790
  gint            b;
758
791
  register glong  t1;
759
792
 
760
 
  alpha = bytes;
761
 
  src2_bytes = bytes + 1;
762
 
 
763
793
  if (mask)
764
794
    {
765
 
      m = mask;
 
795
      const guchar *m = mask;
 
796
 
766
797
      while (length --)
767
798
        {
768
 
          new_alpha = INT_MULT3(src2[alpha], *m, opacity, t1);
 
799
          guchar new_alpha = INT_MULT3(src2[alpha], *m, opacity, t1);
769
800
 
770
801
          for (b = 0; b < bytes; b++)
771
802
            dest[b] = (affect[b]) ?
781
812
  else
782
813
    {
783
814
      if (bytes == 3 && affect[0] && affect[1] && affect[2])
784
 
        while (length --)
785
815
        {
786
 
          new_alpha = INT_MULT(src2[alpha],opacity,t1);
787
 
          dest[0] = INT_BLEND(src2[0] , src1[0] , new_alpha, t1);
788
 
          dest[1] = INT_BLEND(src2[1] , src1[1] , new_alpha, t1);
789
 
          dest[2] = INT_BLEND(src2[2] , src1[2] , new_alpha, t1);
790
 
          src1 += bytes;
791
 
          src2 += src2_bytes;
792
 
          dest += bytes;
 
816
          while (length --)
 
817
            {
 
818
              guchar new_alpha = INT_MULT(src2[alpha],opacity,t1);
 
819
 
 
820
              dest[0] = INT_BLEND(src2[0] , src1[0] , new_alpha, t1);
 
821
              dest[1] = INT_BLEND(src2[1] , src1[1] , new_alpha, t1);
 
822
              dest[2] = INT_BLEND(src2[2] , src1[2] , new_alpha, t1);
 
823
              src1 += bytes;
 
824
              src2 += src2_bytes;
 
825
              dest += bytes;
 
826
            }
793
827
        }
794
828
      else
795
 
        while (length --)
796
829
        {
797
 
          new_alpha = INT_MULT(src2[alpha],opacity,t1);
798
 
          for (b = 0; b < bytes; b++)
799
 
            dest[b] = (affect[b]) ?
800
 
              INT_BLEND(src2[b] , src1[b] , new_alpha, t1) :
801
 
            src1[b];
802
 
 
803
 
          src1 += bytes;
804
 
          src2 += src2_bytes;
805
 
          dest += bytes;
 
830
          while (length --)
 
831
            {
 
832
              guchar new_alpha = INT_MULT(src2[alpha],opacity,t1);
 
833
 
 
834
              for (b = 0; b < bytes; b++)
 
835
                dest[b] = (affect[b]) ?
 
836
                  INT_BLEND(src2[b] , src1[b] , new_alpha, t1) :
 
837
                  src1[b];
 
838
 
 
839
              src1 += bytes;
 
840
              src2 += src2_bytes;
 
841
              dest += bytes;
 
842
            }
806
843
        }
807
844
    }
808
845
}
890
927
                                  guint           length,
891
928
                                  guint           bytes)        /*  4 or 2 depending on RGBA or GRAYA  */
892
929
{
893
 
  gint          alpha, b;
894
 
  gint          src2_bytes;
895
 
  guchar        src2_alpha;
896
 
  guchar        new_alpha;
897
 
  const guchar *m;
898
 
  gfloat        ratio, compl_ratio;
 
930
  const gint    src2_bytes = bytes - 1;
 
931
  const gint    alpha      = bytes - 1;
 
932
  gint          b;
 
933
  gfloat        ratio;
 
934
  gfloat        compl_ratio;
899
935
  glong         tmp;
900
936
 
901
 
  src2_bytes = bytes - 1;
902
 
  alpha = bytes - 1;
903
 
 
904
937
  if (mask)
905
938
    {
906
 
      m = mask;
 
939
      const guchar *m = mask;
 
940
 
907
941
      if (opacity == OPAQUE_OPACITY) /* HAS MASK, FULL OPACITY */
908
942
        {
909
943
          while (length--)
910
944
            {
911
 
              src2_alpha = *m;
912
 
              new_alpha = src1[alpha] +
913
 
                INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
 
945
              guchar src2_alpha = *m;
 
946
              guchar new_alpha  =
 
947
                src1[alpha] + INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
 
948
 
914
949
              alphify (src2_alpha, new_alpha);
915
950
 
916
951
              if (mode_affect)
933
968
        {
934
969
          while (length--)
935
970
            {
936
 
              src2_alpha = INT_MULT(*m, opacity, tmp);
937
 
              new_alpha = src1[alpha] +
938
 
                INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
 
971
              guchar src2_alpha = INT_MULT(*m, opacity, tmp);
 
972
              guchar new_alpha  =
 
973
                src1[alpha] + INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
 
974
 
939
975
              alphify (src2_alpha, new_alpha);
940
976
 
941
977
              if (mode_affect)
959
995
    {
960
996
      while (length --)
961
997
        {
962
 
          src2_alpha = opacity;
963
 
          new_alpha = src1[alpha] +
964
 
            INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
 
998
          guchar src2_alpha = opacity;
 
999
          guchar new_alpha  =
 
1000
            src1[alpha] + INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
 
1001
 
965
1002
          alphify (src2_alpha, new_alpha);
966
1003
 
967
1004
          if (mode_affect)
988
1025
                                    guint           length,
989
1026
                                    guint           bytes)  /*  4 or 2 depending on RGBA or GRAYA  */
990
1027
{
991
 
  guint b;
992
 
  guchar src2_alpha;
993
 
  guchar new_alpha;
994
 
  gfloat ratio, compl_ratio;
995
 
  glong tmp;
996
1028
  const guint alpha = bytes - 1;
 
1029
  guint       b;
 
1030
  gfloat      ratio;
 
1031
  gfloat      compl_ratio;
 
1032
  glong       tmp;
997
1033
 
998
1034
  if (mask)
999
1035
    {
1001
1037
 
1002
1038
      if (opacity == OPAQUE_OPACITY) /* HAS MASK, FULL OPACITY */
1003
1039
        {
1004
 
          const gint* mask_ip;
1005
 
          gint i,j;
 
1040
          const gint *mask_ip;
 
1041
          gint        i, j;
1006
1042
 
1007
 
          if (length >= sizeof(int))
 
1043
          if (length >= sizeof (gint))
1008
1044
            {
1009
1045
              /* HEAD */
1010
 
              i =  (GPOINTER_TO_INT(m) & (sizeof(int)-1));
 
1046
              i =  (GPOINTER_TO_INT(m) & (sizeof (gint) - 1));
 
1047
 
1011
1048
              if (i != 0)
1012
1049
                {
1013
 
                  i = sizeof(int) - i;
 
1050
                  i = sizeof (gint) - i;
1014
1051
                  length -= i;
 
1052
 
1015
1053
                  while (i--)
1016
1054
                    {
1017
1055
                      /* GUTS */
1018
 
                      src2_alpha = INT_MULT(src2[alpha], *m, tmp);
1019
 
                      new_alpha = src1[alpha] +
 
1056
                      guchar src2_alpha = INT_MULT(src2[alpha], *m, tmp);
 
1057
                      guchar new_alpha  =
 
1058
                        src1[alpha] +
1020
1059
                        INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
1021
1060
 
1022
1061
                      alphify (src2_alpha, new_alpha);
1040
1079
                }
1041
1080
 
1042
1081
              /* BODY */
1043
 
              mask_ip = (const gint *)m;
1044
 
              i = length / sizeof(int);
1045
 
              length %= sizeof(int);
 
1082
              mask_ip = (const gint *) m;
 
1083
              i = length / sizeof (gint);
 
1084
              length %= sizeof (gint);
 
1085
 
1046
1086
              while (i--)
1047
1087
                {
1048
1088
                  if (*mask_ip)
1049
1089
                    {
1050
 
                      m = (const guchar*)mask_ip;
1051
 
                      j = sizeof(int);
 
1090
                      m = (const guchar *) mask_ip;
 
1091
                      j = sizeof (gint);
 
1092
 
1052
1093
                      while (j--)
1053
1094
                        {
1054
1095
                          /* GUTS */
1055
 
                          src2_alpha = INT_MULT(src2[alpha], *m, tmp);
1056
 
                          new_alpha = src1[alpha] +
 
1096
                          guchar src2_alpha = INT_MULT(src2[alpha], *m, tmp);
 
1097
                          guchar new_alpha  =
 
1098
                            src1[alpha] +
1057
1099
                            INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
1058
1100
 
1059
1101
                          alphify (src2_alpha, new_alpha);
1077
1119
                    }
1078
1120
                  else
1079
1121
                    {
1080
 
                      j = bytes * sizeof(int);
 
1122
                      j = bytes * sizeof (gint);
1081
1123
                      src2 += j;
1082
1124
                      while (j--)
1083
1125
                        {
1087
1129
                  mask_ip++;
1088
1130
                }
1089
1131
 
1090
 
              m = (const guchar*)mask_ip;
 
1132
              m = (const guchar *) mask_ip;
1091
1133
            }
1092
1134
 
1093
1135
          /* TAIL */
1094
1136
          while (length--)
1095
1137
            {
1096
1138
              /* GUTS */
1097
 
              src2_alpha = INT_MULT(src2[alpha], *m, tmp);
1098
 
              new_alpha = src1[alpha] +
1099
 
                INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
 
1139
              guchar src2_alpha = INT_MULT(src2[alpha], *m, tmp);
 
1140
              guchar new_alpha  =
 
1141
                src1[alpha] + INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
1100
1142
 
1101
1143
              alphify (src2_alpha, new_alpha);
1102
1144
 
1119
1161
        }
1120
1162
      else /* HAS MASK, SEMI-OPACITY */
1121
1163
        {
1122
 
          const gint* mask_ip;
1123
 
          gint i,j;
 
1164
          const gint *mask_ip;
 
1165
          gint        i,j;
1124
1166
 
1125
 
          if (length >= sizeof(int))
 
1167
          if (length >= sizeof (gint))
1126
1168
            {
1127
1169
              /* HEAD */
1128
 
              i = (GPOINTER_TO_INT(m) & (sizeof(int)-1));
 
1170
              i = (GPOINTER_TO_INT(m) & (sizeof (gint) - 1));
1129
1171
              if (i != 0)
1130
1172
                {
1131
 
                  i = sizeof(int) - i;
 
1173
                  i = sizeof (gint) - i;
1132
1174
                  length -= i;
 
1175
 
1133
1176
                  while (i--)
1134
1177
                    {
1135
1178
                      /* GUTS */
1136
 
                      src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
1137
 
                      new_alpha = src1[alpha] +
 
1179
                      guchar src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
 
1180
                      guchar new_alpha  =
 
1181
                        src1[alpha] +
1138
1182
                        INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
1139
1183
 
1140
1184
                      alphify (src2_alpha, new_alpha);
1158
1202
                }
1159
1203
 
1160
1204
              /* BODY */
1161
 
              mask_ip = (const gint *)m;
1162
 
              i = length / sizeof(int);
1163
 
              length %= sizeof(int);
 
1205
              mask_ip = (const gint *) m;
 
1206
              i = length / sizeof (gint);
 
1207
              length %= sizeof(gint);
 
1208
 
1164
1209
              while (i--)
1165
1210
                {
1166
1211
                  if (*mask_ip)
1167
1212
                    {
1168
 
                      m = (const guchar*)mask_ip;
1169
 
                      j = sizeof(int);
1170
 
                      while (j--)
 
1213
                      m = (const guchar *) mask_ip;
 
1214
                      j = sizeof (gint);
 
1215
 
 
1216
                     while (j--)
1171
1217
                        {
1172
1218
                          /* GUTS */
1173
 
                          src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
1174
 
                          new_alpha = src1[alpha] +
 
1219
                          guchar src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
 
1220
                          guchar new_alpha  =
 
1221
                            src1[alpha] +
1175
1222
                            INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
1176
1223
 
1177
1224
                          alphify (src2_alpha, new_alpha);
1195
1242
                    }
1196
1243
                  else
1197
1244
                    {
1198
 
                      j = bytes * sizeof(int);
 
1245
                      j = bytes * sizeof (gint);
1199
1246
                      src2 += j;
 
1247
 
1200
1248
                      while (j--)
1201
1249
                        {
1202
1250
                          *(dest++) = *(src1++);
1205
1253
                  mask_ip++;
1206
1254
                }
1207
1255
 
1208
 
              m = (const guchar*)mask_ip;
 
1256
              m = (const guchar *) mask_ip;
1209
1257
            }
1210
1258
 
1211
1259
          /* TAIL */
1212
1260
          while (length--)
1213
1261
            {
1214
1262
              /* GUTS */
1215
 
              src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
1216
 
              new_alpha = src1[alpha] +
 
1263
              guchar src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
 
1264
              guchar new_alpha  =
 
1265
                src1[alpha] +
1217
1266
                INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
1218
1267
 
1219
1268
              alphify (src2_alpha, new_alpha);
1242
1291
        {
1243
1292
          while (length --)
1244
1293
            {
1245
 
              src2_alpha = src2[alpha];
1246
 
              new_alpha = src1[alpha] +
 
1294
              guchar src2_alpha = src2[alpha];
 
1295
              guchar new_alpha  =
 
1296
                src1[alpha] +
1247
1297
                INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
1248
1298
 
1249
1299
              alphify (src2_alpha, new_alpha);
1267
1317
        {
1268
1318
          while (length --)
1269
1319
            {
1270
 
              src2_alpha = INT_MULT(src2[alpha], opacity, tmp);
1271
 
              new_alpha = src1[alpha] +
1272
 
                INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
 
1320
              guchar src2_alpha = INT_MULT(src2[alpha], opacity, tmp);
 
1321
              guchar new_alpha  =
 
1322
                src1[alpha] + INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
1273
1323
 
1274
1324
              alphify (src2_alpha, new_alpha);
1275
1325
 
1301
1351
                                         guint         length,
1302
1352
                                         guint         bytes)
1303
1353
{
1304
 
  gint   alpha, b;
1305
 
  guchar channel_alpha;
1306
 
  guchar new_alpha;
1307
 
  guchar compl_alpha;
1308
 
  gint   t, s;
 
1354
  const gint alpha = bytes - 1;
 
1355
  gint       b;
 
1356
  gint       t, s;
1309
1357
 
1310
 
  alpha = bytes - 1;
1311
1358
  while (length --)
1312
1359
    {
1313
 
      channel_alpha = INT_MULT (255 - *channel, opacity, t);
 
1360
      guchar channel_alpha = INT_MULT (255 - *channel, opacity, t);
 
1361
 
1314
1362
      if (channel_alpha)
1315
1363
        {
1316
 
          new_alpha = src[alpha] + INT_MULT ((255 - src[alpha]), channel_alpha, t);
 
1364
          guchar compl_alpha;
 
1365
          guchar new_alpha =
 
1366
            src[alpha] + INT_MULT ((255 - src[alpha]), channel_alpha, t);
1317
1367
 
1318
1368
          if (new_alpha != 255)
1319
1369
            channel_alpha = (channel_alpha * 255) / new_alpha;
 
1370
 
1320
1371
          compl_alpha = 255 - channel_alpha;
1321
1372
 
1322
1373
          for (b = 0; b < alpha; b++)
1323
1374
            dest[b] = INT_MULT (col[b], channel_alpha, t) +
1324
1375
              INT_MULT (src[b], compl_alpha, s);
 
1376
 
1325
1377
          dest[b] = new_alpha;
1326
1378
        }
1327
1379
      else
1328
 
        memcpy(dest, src, bytes);
 
1380
        {
 
1381
          memcpy(dest, src, bytes);
 
1382
        }
1329
1383
 
1330
1384
      /*  advance pointers  */
1331
1385
      src+=bytes;
1344
1398
                                              guint         length,
1345
1399
                                              guint         bytes)
1346
1400
{
1347
 
  gint   alpha, b;
1348
 
  guchar channel_alpha;
1349
 
  guchar new_alpha;
1350
 
  guchar compl_alpha;
1351
 
  gint   t, s;
 
1401
  const gint alpha = bytes - 1;
 
1402
  gint       b;
 
1403
  gint       t, s;
1352
1404
 
1353
 
  alpha = bytes - 1;
1354
1405
  while (length --)
1355
1406
    {
1356
 
      channel_alpha = INT_MULT (*channel, opacity, t);
 
1407
      guchar channel_alpha = INT_MULT (*channel, opacity, t);
 
1408
 
1357
1409
      if (channel_alpha)
1358
1410
        {
1359
 
          new_alpha = src[alpha] + INT_MULT ((255 - src[alpha]), channel_alpha, t);
 
1411
          guchar compl_alpha;
 
1412
          guchar new_alpha =
 
1413
            src[alpha] + INT_MULT ((255 - src[alpha]), channel_alpha, t);
1360
1414
 
1361
1415
          if (new_alpha != 255)
1362
1416
            channel_alpha = (channel_alpha * 255) / new_alpha;
 
1417
 
1363
1418
          compl_alpha = 255 - channel_alpha;
1364
1419
 
1365
1420
          for (b = 0; b < alpha; b++)
1366
1421
            dest[b] = INT_MULT (col[b], channel_alpha, t) +
1367
1422
              INT_MULT (src[b], compl_alpha, s);
 
1423
 
1368
1424
          dest[b] = new_alpha;
1369
1425
        }
1370
1426
      else
1394
1450
                     guint           bytes1,
1395
1451
                     guint           bytes2)
1396
1452
{
1397
 
  /* FIXME: Is this supposed to be different than in the other functions? */
1398
 
  const guint alpha = bytes1 - 1;
1399
 
  guint        b;
1400
 
  guchar        src1_alpha;
1401
 
  guchar        src2_alpha;
1402
 
  guchar        new_alpha;
1403
 
  const guchar *m;
1404
 
  gfloat        ratio, compl_ratio;
 
1453
  const guint   alpha = bytes1 - 1;
 
1454
  const guchar *m     = mask ? mask : &no_mask;
 
1455
  guint         b;
 
1456
  gfloat        ratio;
 
1457
  gfloat        compl_ratio;
1405
1458
  glong         tmp;
1406
1459
 
1407
 
  if (mask)
1408
 
    m = mask;
1409
 
  else
1410
 
    m = &no_mask;
1411
 
 
1412
1460
  while (length --)
1413
1461
    {
1414
 
      src1_alpha = src1[alpha];
1415
 
      src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
1416
 
      new_alpha = src2_alpha +
1417
 
        INT_MULT((255 - src2_alpha), src1_alpha, tmp);
 
1462
      guchar src1_alpha = src1[alpha];
 
1463
      guchar src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
 
1464
      guchar new_alpha  =
 
1465
        src2_alpha + INT_MULT((255 - src2_alpha), src1_alpha, tmp);
 
1466
 
1418
1467
      if (new_alpha)
1419
1468
        ratio = (float) src1_alpha / new_alpha;
1420
1469
      else
1421
1470
        ratio = 0.0;
 
1471
 
1422
1472
      compl_ratio = 1.0 - ratio;
1423
1473
 
1424
1474
      for (b = 0; b < alpha; b++)
1454
1504
                       guint           bytes1,
1455
1505
                       guint           bytes2)
1456
1506
{
1457
 
  const guint alpha = bytes1 - 1;
1458
 
  guint b;
1459
 
  guchar        src1_alpha;
1460
 
  guchar        src2_alpha;
1461
 
  guchar        new_alpha;
1462
 
  const guchar *m;
 
1507
  const guint   alpha = bytes1 - 1;
 
1508
  const guchar *m     = mask ? mask : &no_mask;
 
1509
  guint         b;
1463
1510
  glong         tmp;
1464
1511
 
1465
 
  if (mask)
1466
 
    m = mask;
1467
 
  else
1468
 
    m = &no_mask;
1469
 
 
1470
1512
  /*  the alpha channel  */
1471
1513
 
1472
1514
  while (length --)
1473
1515
    {
1474
 
      src1_alpha = src1[alpha];
1475
 
      src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
1476
 
      new_alpha = (src2_alpha > 127) ? OPAQUE_OPACITY : TRANSPARENT_OPACITY;
 
1516
      guchar src1_alpha = src1[alpha];
 
1517
      guchar src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
 
1518
      guchar new_alpha  =
 
1519
        (src2_alpha > 127) ? OPAQUE_OPACITY : TRANSPARENT_OPACITY;
1477
1520
 
1478
1521
      for (b = 0; b < bytes1; b++)
1479
 
        dest[b] = (affect[b] && new_alpha == OPAQUE_OPACITY && (src1_alpha > 127)) ?
 
1522
        dest[b] =
 
1523
          (affect[b] && new_alpha == OPAQUE_OPACITY && (src1_alpha > 127)) ?
1480
1524
          src2[b] : src1[b];
1481
1525
 
1482
1526
      if (mask)
1506
1550
{
1507
1551
  const guint has_alpha1 = HAS_ALPHA (bytes1);
1508
1552
  const guint has_alpha2 = HAS_ALPHA (bytes2);
1509
 
  const guint bytes = MIN (bytes1, bytes2);
 
1553
  const guint bytes      = MIN (bytes1, bytes2);
1510
1554
  guint b;
1511
1555
  gint  tmp;
1512
1556
 
1513
1557
  if (mask)
1514
1558
    {
1515
 
      guchar        mask_alpha;
1516
1559
      const guchar *m = mask;
1517
1560
 
1518
1561
      while (length --)
1519
1562
        {
1520
 
          mask_alpha = INT_MULT(*m, opacity, tmp);
 
1563
          guchar mask_alpha = INT_MULT(*m, opacity, tmp);
1521
1564
 
1522
1565
          for (b = 0; b < bytes; b++)
1523
1566
            dest[b] = (affect[b]) ?
1570
1613
                        guint           bytes1,
1571
1614
                        guint           bytes2)
1572
1615
{
1573
 
  const guint has_alpha1 = HAS_ALPHA (bytes1);
1574
 
  const guint has_alpha2 = HAS_ALPHA (bytes2);
1575
 
  const guint bytes = MIN (bytes1, bytes2);
1576
 
  const guchar *m;
1577
 
  guint b;
1578
 
  guchar        mask_alpha;
 
1616
  const guint   has_alpha1 = HAS_ALPHA (bytes1);
 
1617
  const guint   has_alpha2 = HAS_ALPHA (bytes2);
 
1618
  const guint   bytes      = MIN (bytes1, bytes2);
 
1619
  const guchar *m          = mask ? mask : &no_mask;
 
1620
  guint         b;
1579
1621
  gint          tmp;
1580
1622
 
1581
 
  if (mask)
1582
 
    m = mask;
1583
 
  else
1584
 
    m = &no_mask;
1585
 
 
1586
1623
  while (length --)
1587
1624
    {
1588
 
      mask_alpha = INT_MULT(*m, opacity, tmp);
 
1625
      guchar mask_alpha = INT_MULT(*m, opacity, tmp);
1589
1626
 
1590
1627
      for (b = 0; b < bytes; b++)
1591
1628
        dest[b] = (affect[b] && mask_alpha) ? src2[b] : src1[b];
1617
1654
                    guint           bytes)
1618
1655
{
1619
1656
  const guint alpha = bytes - 1;
1620
 
  guint b;
1621
 
  guchar     src2_alpha;
1622
 
  glong      tmp;
 
1657
  guint       b;
 
1658
  guchar      src2_alpha;
 
1659
  glong       tmp;
1623
1660
 
1624
1661
  if (mask)
1625
1662
    {
1674
1711
                      guint           length,
1675
1712
                      guint           bytes)
1676
1713
{
1677
 
  const guint alpha = bytes - 1;
1678
 
  const guchar *m;
1679
 
  guchar src2_alpha;
1680
 
  guint b;
1681
 
  glong tmp;
1682
 
 
1683
 
  if (mask)
1684
 
    m = mask;
1685
 
  else
1686
 
    m = &no_mask;
 
1714
  const guint   alpha = bytes - 1;
 
1715
  const guchar *m     = mask ? mask : &no_mask;
 
1716
  guchar        src2_alpha;
 
1717
  guint         b;
 
1718
  glong         tmp;
1687
1719
 
1688
1720
  while (length --)
1689
1721
    {
1702
1734
    }
1703
1735
}
1704
1736
 
1705
 
void
 
1737
static inline void
1706
1738
anti_erase_inten_pixels (const guchar   *src1,
1707
1739
                         const guchar   *src2,
1708
1740
                         guchar         *dest,
1712
1744
                         guint           length,
1713
1745
                         guint           bytes)
1714
1746
{
1715
 
  gint          alpha, b;
 
1747
  const gint    alpha = bytes - 1;
 
1748
  const guchar *m     = mask ? mask : &no_mask;
 
1749
  gint          b;
1716
1750
  guchar        src2_alpha;
1717
 
  const guchar *m;
1718
1751
  glong         tmp;
1719
1752
 
1720
 
  if (mask)
1721
 
    m = mask;
1722
 
  else
1723
 
    m = &no_mask;
1724
 
 
1725
 
  alpha = bytes - 1;
1726
1753
  while (length --)
1727
1754
    {
1728
1755
      for (b = 0; b < alpha; b++)
1729
1756
        dest[b] = src1[b];
1730
1757
 
1731
 
      src2_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
1732
 
      dest[alpha] = src1[alpha] + INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
 
1758
      src2_alpha  = INT_MULT3(src2[alpha], *m, opacity, tmp);
 
1759
      dest[alpha] =
 
1760
        src1[alpha] + INT_MULT((255 - src1[alpha]), src2_alpha, tmp);
1733
1761
 
1734
1762
      if (mask)
1735
1763
        m++;
1741
1769
}
1742
1770
 
1743
1771
 
1744
 
void
 
1772
static inline void
1745
1773
anti_erase_indexed_pixels (const guchar   *src1,
1746
1774
                           const guchar   *src2,
1747
1775
                           guchar         *dest,
1751
1779
                           guint           length,
1752
1780
                           guint           bytes)
1753
1781
{
1754
 
  gint          alpha, b;
 
1782
  const guint   alpha = bytes - 1;
 
1783
  const guchar *m     = mask ? mask : &no_mask;
 
1784
  gint          b;
1755
1785
  guchar        src2_alpha;
1756
 
  const guchar *m;
1757
1786
  glong         tmp;
1758
1787
 
1759
 
  if (mask)
1760
 
    m = mask;
1761
 
  else
1762
 
    m = &no_mask;
1763
 
 
1764
 
  alpha = bytes - 1;
1765
1788
  while (length --)
1766
1789
    {
1767
1790
      for (b = 0; b < alpha; b++)
1780
1803
}
1781
1804
 
1782
1805
 
1783
 
static void
 
1806
static inline void
1784
1807
color_erase_helper (GimpRGB       *src,
1785
1808
                    const GimpRGB *color)
1786
1809
{
1845
1868
}
1846
1869
 
1847
1870
 
1848
 
void
 
1871
static inline void
1849
1872
color_erase_inten_pixels (const guchar   *src1,
1850
1873
                          const guchar   *src2,
1851
1874
                          guchar         *dest,
1855
1878
                          guint           length,
1856
1879
                          guint           bytes)
1857
1880
{
 
1881
  const guchar *m     = mask ? mask : &no_mask;
1858
1882
  guchar        src2_alpha;
1859
 
  const guchar *m;
1860
1883
  glong         tmp;
1861
1884
  GimpRGB       bgcolor, color;
1862
1885
 
1863
 
  if (mask)
1864
 
    m = mask;
1865
 
  else
1866
 
    m = &no_mask;
1867
 
 
1868
1886
  while (length --)
1869
1887
    {
1870
1888
      switch (bytes)
1915
1933
                           const guchar *bg,
1916
1934
                           gboolean      cut,
1917
1935
                           guint         length,
1918
 
                           guint         bytes,
1919
 
                           gboolean      has_alpha)
 
1936
                           guint         src_bytes,
 
1937
                           guint         dest_bytes)
1920
1938
{
1921
 
  gint          b, alpha;
1922
 
  gint          dest_bytes;
1923
 
  const guchar *m;
 
1939
  const gint    alpha = HAS_ALPHA (src_bytes) ? src_bytes - 1 : src_bytes;
 
1940
  const guchar *m     = mask ? mask : &no_mask;
 
1941
  gint          b;
1924
1942
  gint          tmp;
1925
1943
 
1926
 
  if (mask)
1927
 
    m = mask;
1928
 
  else
1929
 
    m = &no_mask;
1930
 
 
1931
 
  alpha = (has_alpha) ? bytes - 1 : bytes;
1932
 
  dest_bytes = (has_alpha) ? bytes : bytes + 1;
1933
1944
  while (length --)
1934
1945
    {
1935
1946
      for (b = 0; b < alpha; b++)
1936
1947
        dest[b] = src[b];
1937
1948
 
1938
 
      if (has_alpha)
 
1949
      if (HAS_ALPHA (src_bytes))
1939
1950
        {
1940
1951
          dest[alpha] = INT_MULT(*m, src[alpha], tmp);
1941
1952
          if (cut)
1943
1954
        }
1944
1955
      else
1945
1956
        {
1946
 
          dest[alpha] = *m;
 
1957
          if (HAS_ALPHA (dest_bytes))
 
1958
            dest[alpha] = *m;
 
1959
 
1947
1960
          if (cut)
1948
 
            for (b = 0; b < bytes; b++)
 
1961
            for (b = 0; b < src_bytes; b++)
1949
1962
              src[b] = INT_BLEND(bg[b], src[b], *m, tmp);
1950
1963
        }
1951
1964
 
1952
1965
      if (mask)
1953
1966
        m++;
1954
1967
 
1955
 
      src += bytes;
 
1968
      src += src_bytes;
1956
1969
      dest += dest_bytes;
1957
1970
    }
1958
1971
}
1966
1979
                             const guchar *bg,
1967
1980
                             gboolean      cut,
1968
1981
                             guint         length,
1969
 
                             guint         bytes,
1970
 
                             gboolean      has_alpha)
 
1982
                             guint         src_bytes,
 
1983
                             guint         dest_bytes)
1971
1984
{
 
1985
  const guchar *m = mask ? mask : &no_mask;
1972
1986
  gint          b;
1973
 
  gint          index;
1974
 
  const guchar *m;
1975
1987
  gint          t;
1976
1988
 
1977
 
  if (mask)
1978
 
    m = mask;
1979
 
  else
1980
 
    m = &no_mask;
1981
 
 
1982
1989
  while (length --)
1983
1990
    {
1984
 
      index = src[0] * 3;
 
1991
      gint index = src[0] * 3;
 
1992
 
1985
1993
      for (b = 0; b < 3; b++)
1986
1994
        dest[b] = cmap[index + b];
1987
1995
 
1988
 
      if (has_alpha)
 
1996
      if (HAS_ALPHA (src_bytes))
1989
1997
        {
1990
1998
          dest[3] = INT_MULT (*m, src[1], t);
1991
1999
          if (cut)
1993
2001
        }
1994
2002
      else
1995
2003
        {
1996
 
          dest[3] = *m;
 
2004
          if (HAS_ALPHA (dest_bytes))
 
2005
            dest[3] = *m;
 
2006
 
1997
2007
          if (cut)
1998
2008
            src[0] = (*m > 127) ? bg[0] : src[0];
1999
2009
        }
2001
2011
      if (mask)
2002
2012
        m++;
2003
2013
 
2004
 
      src += bytes;
2005
 
      dest += 4;
 
2014
      src += src_bytes;
 
2015
      dest += dest_bytes;
2006
2016
    }
2007
2017
}
2008
2018
 
2015
2025
color_region (PixelRegion  *dest,
2016
2026
              const guchar *col)
2017
2027
{
2018
 
  gint    h;
2019
 
  guchar *s;
2020
 
  void   *pr;
 
2028
  gpointer pr;
2021
2029
 
2022
2030
  for (pr = pixel_regions_register (1, dest);
2023
2031
       pr != NULL;
2024
2032
       pr = pixel_regions_process (pr))
2025
2033
    {
2026
 
      h = dest->h;
2027
 
      s = dest->data;
 
2034
      guchar *s = dest->data;
 
2035
      gint    h = dest->h;
2028
2036
 
2029
2037
      if (dest->w * dest->bytes == dest->rowstride)
2030
2038
        {
2039
2047
          while (h--)
2040
2048
            {
2041
2049
              color_pixels (s, col, dest->w, dest->bytes);
 
2050
 
2042
2051
              s += dest->rowstride;
2043
2052
            }
2044
2053
        }
2050
2059
                   PixelRegion  *mask,
2051
2060
                   const guchar *col)
2052
2061
{
2053
 
  gint    h;
2054
 
  guchar *d;
2055
 
  guchar *m;
2056
 
  void   *pr;
 
2062
  gpointer pr;
2057
2063
 
2058
2064
  for (pr = pixel_regions_register (2, dest, mask);
2059
2065
       pr != NULL;
2060
2066
       pr = pixel_regions_process (pr))
2061
2067
    {
2062
 
      h = dest->h;
2063
 
      d = dest->data;
2064
 
      m = mask->data;
 
2068
      guchar       *d = dest->data;
 
2069
      const guchar *m = mask->data;
 
2070
      gint          h = dest->h;
2065
2071
 
2066
2072
      if (dest->w * dest->bytes == dest->rowstride &&
2067
2073
          mask->w * mask->bytes == mask->rowstride)
2077
2083
          while (h--)
2078
2084
            {
2079
2085
              color_pixels_mask (d, m, col, dest->w, dest->bytes);
 
2086
 
2080
2087
              d += dest->rowstride;
2081
2088
              m += mask->rowstride;
2082
2089
            }
2091
2098
                gint          off_x,
2092
2099
                gint          off_y)
2093
2100
{
2094
 
  gint    y;
2095
 
  guchar *d;
2096
 
  guchar *m = NULL;
2097
 
  void   *pr;
 
2101
  gpointer pr;
2098
2102
 
2099
2103
  for (pr = pixel_regions_register (2, dest, mask);
2100
2104
       pr != NULL;
2101
2105
       pr = pixel_regions_process (pr))
2102
2106
    {
2103
 
      d = dest->data;
2104
 
 
2105
 
      if (mask)
2106
 
        m = mask->data;
 
2107
      guchar       *d = dest->data;
 
2108
      const guchar *m = mask ? mask->data : NULL;
 
2109
      gint          y;
2107
2110
 
2108
2111
      for (y = 0; y < dest->h; y++)
2109
2112
        {
2110
2113
          pattern_pixels_mask (d, m, pattern, dest->w, dest->bytes,
2111
2114
                               off_x + dest->x,
2112
2115
                               off_y + dest->y + y);
 
2116
 
2113
2117
          d += dest->rowstride;
2114
2118
 
2115
2119
          if (mask)
2124
2128
              PixelRegion *dest,
2125
2129
              guchar       blend)
2126
2130
{
2127
 
  gint    h;
2128
 
  guchar *s1, *s2, * d;
2129
 
  void   *pr;
 
2131
  gpointer pr;
2130
2132
 
2131
2133
  for (pr = pixel_regions_register (3, src1, src2, dest);
2132
2134
       pr != NULL;
2133
2135
       pr = pixel_regions_process (pr))
2134
2136
    {
2135
 
      s1 = src1->data;
2136
 
      s2 = src2->data;
2137
 
      d = dest->data;
2138
 
      h = src1->h;
 
2137
      const guchar *s1 = src1->data;
 
2138
      const guchar *s2 = src2->data;
 
2139
      guchar       *d  = dest->data;
 
2140
      gint          h  = src1->h;
2139
2141
 
2140
2142
      while (h --)
2141
2143
        {
2142
2144
          blend_pixels (s1, s2, d, blend, src1->w, src1->bytes);
 
2145
 
2143
2146
          s1 += src1->rowstride;
2144
2147
          s2 += src2->rowstride;
2145
2148
          d += dest->rowstride;
2154
2157
              guchar      *color,
2155
2158
              guchar       blend)
2156
2159
{
2157
 
  gint    h;
2158
 
  guchar *s, * d;
2159
 
 
2160
 
  s = src->data;
2161
 
  d = dest->data;
2162
 
  h = src->h;
 
2160
  const guchar *s = src->data;
 
2161
  guchar       *d = dest->data;
 
2162
  gint          h = src->h;
2163
2163
 
2164
2164
  while (h --)
2165
2165
    {
2166
 
/*      blend_pixels (s, d, col, blend, src->w, src->bytes);*/
 
2166
      blend_pixels (s, d, color, blend, src->w, src->bytes);
 
2167
 
2167
2168
      s += src->rowstride;
2168
2169
      d += dest->rowstride;
2169
2170
    }
2174
2175
copy_region (PixelRegion *src,
2175
2176
             PixelRegion *dest)
2176
2177
{
2177
 
  gint    h;
2178
 
  gint    pixelwidth;
2179
 
  guchar *s, *d;
2180
 
  void   *pr;
 
2178
  gpointer pr;
2181
2179
 
2182
2180
#ifdef COWSHOW
2183
2181
  fputc ('[',stderr);
2198
2196
#ifdef COWSHOW
2199
2197
          fputc('!',stderr);
2200
2198
#endif
2201
 
          tile_manager_map_over_tile (dest->tiles, dest->curtile, src->curtile);
 
2199
          tile_manager_map_over_tile (dest->tiles,
 
2200
                                      dest->curtile, src->curtile);
2202
2201
        }
2203
2202
      else
2204
2203
        {
 
2204
          const guchar *s      = src->data;
 
2205
          guchar       *d      = dest->data;
 
2206
          gint          h      = src->h;
 
2207
          gint          pixels = src->w * src->bytes;
 
2208
 
2205
2209
#ifdef COWSHOW
2206
2210
          fputc ('.',stderr);
2207
2211
#endif
2208
 
          pixelwidth = src->w * src->bytes;
2209
 
          s = src->data;
2210
 
          d = dest->data;
2211
 
          h = src->h;
2212
2212
 
2213
2213
          while (h --)
2214
2214
            {
2215
 
              memcpy (d, s, pixelwidth);
 
2215
              memcpy (d, s, pixels);
 
2216
 
2216
2217
              s += src->rowstride;
2217
2218
              d += dest->rowstride;
2218
2219
            }
2229
2230
copy_region_nocow (PixelRegion *src,
2230
2231
                   PixelRegion *dest)
2231
2232
{
2232
 
  gint    h;
2233
 
  gint    pixelwidth;
2234
 
  guchar *s, *d;
2235
 
  void   *pr;
 
2233
  gpointer pr;
2236
2234
 
2237
2235
  for (pr = pixel_regions_register (2, src, dest);
2238
2236
       pr != NULL;
2239
2237
       pr = pixel_regions_process (pr))
2240
2238
    {
2241
 
      pixelwidth = src->w * src->bytes;
2242
 
      s = src->data;
2243
 
      d = dest->data;
2244
 
      h = src->h;
 
2239
      const guchar *s      = src->data;
 
2240
      guchar       *d      = dest->data;
 
2241
      gint          pixels = src->w * src->bytes;
 
2242
      gint          h      = src->h;
2245
2243
 
2246
2244
      while (h --)
2247
2245
        {
2248
 
          memcpy (d, s, pixelwidth);
 
2246
          memcpy (d, s, pixels);
 
2247
 
2249
2248
          s += src->rowstride;
2250
2249
          d += dest->rowstride;
2251
2250
        }
2257
2256
add_alpha_region (PixelRegion *src,
2258
2257
                  PixelRegion *dest)
2259
2258
{
2260
 
  gint    h;
2261
 
  guchar *s, *d;
2262
 
  void   *pr;
 
2259
  gpointer pr;
2263
2260
 
2264
2261
  for (pr = pixel_regions_register (2, src, dest);
2265
2262
       pr != NULL;
2266
2263
       pr = pixel_regions_process (pr))
2267
2264
    {
2268
 
      s = src->data;
2269
 
      d = dest->data;
2270
 
      h = src->h;
 
2265
      const guchar *s = src->data;
 
2266
      guchar       *d = dest->data;
 
2267
      gint          h = src->h;
2271
2268
 
2272
2269
      while (h --)
2273
2270
        {
2274
2271
          add_alpha_pixels (s, d, src->w, src->bytes);
 
2272
 
2275
2273
          s += src->rowstride;
2276
2274
          d += dest->rowstride;
2277
2275
        }
2284
2282
                PixelRegion *dest,
2285
2283
                guchar      *bg)
2286
2284
{
2287
 
  gint    h;
2288
 
  guchar *s, *d;
2289
 
  void   *pr;
 
2285
  gpointer pr;
2290
2286
 
2291
2287
  for (pr = pixel_regions_register (2, src, dest);
2292
2288
       pr != NULL;
2293
2289
       pr = pixel_regions_process (pr))
2294
2290
    {
2295
 
      s = src->data;
2296
 
      d = dest->data;
2297
 
      h = src->h;
 
2291
      const guchar *s = src->data;
 
2292
      guchar       *d = dest->data;
 
2293
      gint          h = src->h;
2298
2294
 
2299
2295
      while (h --)
2300
2296
        {
2311
2307
                      PixelRegion *mask,
2312
2308
                      PixelRegion *dest)
2313
2309
{
2314
 
  gint h;
2315
 
  guchar * s, * m, * d;
2316
 
  void * pr;
 
2310
  gpointer pr;
2317
2311
 
2318
 
  for (pr = pixel_regions_register (3, src, mask, dest); pr != NULL; pr = pixel_regions_process (pr))
 
2312
  for (pr = pixel_regions_register (3, src, mask, dest);
 
2313
       pr != NULL;
 
2314
       pr = pixel_regions_process (pr))
2319
2315
    {
2320
 
      s = src->data;
2321
 
      d = dest->data;
2322
 
      if (mask)
2323
 
        m = mask->data;
2324
 
      else
2325
 
        m = NULL;
 
2316
      const guchar *m = mask ? mask->data : NULL;
 
2317
      const guchar *s = src->data;
 
2318
      guchar       *d = dest->data;
 
2319
      gint          h = src->h;
2326
2320
 
2327
 
      h = src->h;
2328
2321
      while (h --)
2329
2322
        {
2330
2323
          extract_alpha_pixels (s, m, d, src->w, src->bytes);
 
2324
 
2331
2325
          s += src->rowstride;
2332
2326
          d += dest->rowstride;
2333
2327
          if (mask)
2338
2332
 
2339
2333
 
2340
2334
void
2341
 
extract_from_region (PixelRegion *src,
2342
 
                     PixelRegion *dest,
2343
 
                     PixelRegion *mask,
2344
 
                     guchar      *cmap,
2345
 
                     guchar      *bg,
2346
 
                     gint         type,
2347
 
                     gboolean     has_alpha,
2348
 
                     gboolean     cut)
 
2335
extract_from_region (PixelRegion       *src,
 
2336
                     PixelRegion       *dest,
 
2337
                     PixelRegion       *mask,
 
2338
                     const guchar      *cmap,
 
2339
                     const guchar      *bg,
 
2340
                     GimpImageBaseType  type,
 
2341
                     gboolean           cut)
2349
2342
{
2350
 
  gint    h;
2351
 
  guchar *s, *d, *m;
2352
 
  void   *pr;
 
2343
  gpointer pr;
2353
2344
 
2354
2345
  for (pr = pixel_regions_register (3, src, dest, mask);
2355
2346
       pr != NULL;
2356
2347
       pr = pixel_regions_process (pr))
2357
2348
    {
2358
 
      s = src->data;
2359
 
      d = dest->data;
2360
 
      m = (mask) ? mask->data : NULL;
2361
 
      h = src->h;
 
2349
      const guchar *m = mask ? mask->data : NULL;
 
2350
      guchar       *s = src->data;
 
2351
      guchar       *d = dest->data;
 
2352
      gint          h = src->h;
2362
2353
 
2363
2354
      while (h --)
2364
2355
        {
2365
2356
          switch (type)
2366
2357
            {
2367
 
            case 0:  /*  RGB      */
2368
 
            case 1:  /*  GRAY     */
 
2358
            case GIMP_RGB:
 
2359
            case GIMP_GRAY:
2369
2360
              extract_from_inten_pixels (s, d, m, bg, cut, src->w,
2370
 
                                         src->bytes, has_alpha);
 
2361
                                         src->bytes, dest->bytes);
2371
2362
              break;
2372
 
            case 2:  /*  INDEXED  */
 
2363
 
 
2364
            case GIMP_INDEXED:
2373
2365
              extract_from_indexed_pixels (s, d, m, cmap, bg, cut, src->w,
2374
 
                                           src->bytes, has_alpha);
 
2366
                                           src->bytes, dest->bytes);
2375
2367
              break;
2376
2368
            }
2377
2369
 
2387
2379
void
2388
2380
convolve_region (PixelRegion         *srcR,
2389
2381
                 PixelRegion         *destR,
2390
 
                 gfloat              *matrix,
 
2382
                 const gfloat        *matrix,
2391
2383
                 gint                 size,
2392
2384
                 gdouble              divisor,
2393
2385
                 GimpConvolutionType  mode,
2395
2387
{
2396
2388
  /*  Convolve the src image using the convolution matrix, writing to dest  */
2397
2389
  /*  Convolve is not tile-enabled--use accordingly  */
2398
 
  guchar  *src, *s_row, *s;
2399
 
  guchar  *dest, *d;
2400
 
  gfloat  *m;
2401
 
  gdouble  total [4];
2402
 
  gint     b, bytes;
2403
 
  gint     alpha, a_byte;
2404
 
  gint     length;
2405
 
  gint     wraparound;
2406
 
  gint     margin;      /*  margin imposed by size of conv. matrix  */
2407
 
  gint     i, j;
2408
 
  gint     x, y;
2409
 
  gint     offset;
2410
 
  gdouble  matrixsum = 0.0;
2411
 
  gdouble  weighted_divisor, mult_alpha;
 
2390
  guchar       *src, *s_row, *s;
 
2391
  guchar       *dest, *d;
 
2392
  const gfloat *m;
 
2393
  gdouble       total [4];
 
2394
  gint          b, bytes;
 
2395
  gint          alpha, a_byte;
 
2396
  gint          length;
 
2397
  gint          wraparound;
 
2398
  gint          margin;      /*  margin imposed by size of conv. matrix  */
 
2399
  gint          i, j;
 
2400
  gint          x, y;
 
2401
  gint          offset;
 
2402
  gdouble       matrixsum = 0.0;
 
2403
  gdouble       weighted_divisor, mult_alpha;
2412
2404
 
2413
2405
  /*  If the mode is NEGATIVE_CONVOL, the offset should be 128  */
2414
2406
  if (mode == GIMP_NEGATIVE_CONVOL)
2669
2661
                      gdouble      radius_x,
2670
2662
                      gdouble      radius_y)
2671
2663
{
2672
 
  gdouble std_dev;
2673
2664
  glong   width, height;
2674
2665
  guint   bytes;
2675
2666
  guchar *src, *sp;
2676
2667
  guchar *dest, *dp;
2677
2668
  guchar *data;
2678
 
  gint   *buf, *b;
 
2669
  guint  *buf, *b;
2679
2670
  gint    pixels;
2680
2671
  gint    total;
2681
2672
  gint    i, row, col;
2687
2678
  gint    alpha;
2688
2679
  gint    initial_p, initial_m;
2689
2680
 
2690
 
  if (radius_x == 0.0 && radius_y == 0.0) return;    /* zero blur is a no-op */
 
2681
  if (radius_x == 0.0 && radius_y == 0.0)
 
2682
    return;
2691
2683
 
2692
2684
  /*  allocate the result buffer  */
2693
2685
  length = MAX (srcR->w, srcR->h) * srcR->bytes;
2700
2692
  bytes = srcR->bytes;
2701
2693
  alpha = bytes - 1;
2702
2694
 
2703
 
  buf = g_new (gint, MAX (width, height) * 2);
 
2695
  buf = g_new (guint, MAX (width, height) * 2);
2704
2696
 
2705
2697
  if (radius_y != 0.0)
2706
2698
    {
2707
 
      std_dev = sqrt (-(radius_y * radius_y) / (2 * log (1.0 / 255.0)));
2708
 
      curve = make_curve (std_dev, &length);
 
2699
      curve = make_curve (- SQR (radius_y) / (2 * LOG_1_255), &length);
 
2700
 
2709
2701
      sum = g_new (gint, 2 * length + 1);
2710
2702
      sum[0] = 0;
2711
2703
 
2712
 
      for (i = 1; i <= length*2; i++)
 
2704
      for (i = 1; i <= length * 2; i++)
2713
2705
        sum[i] = curve[i - length - 1] + sum[i - 1];
 
2706
 
2714
2707
      sum += length;
2715
2708
 
2716
2709
      total = sum[length] - sum[-length];
2764
2757
 
2765
2758
  if (radius_x != 0.0)
2766
2759
    {
2767
 
      std_dev = sqrt (-(radius_x * radius_x) / (2 * log (1.0 / 255.0)));
2768
 
      curve = make_curve (std_dev, &length);
 
2760
      curve = make_curve (- SQR (radius_x) / (2 * LOG_1_255), &length);
 
2761
 
2769
2762
      sum = g_new (gint, 2 * length + 1);
2770
2763
      sum[0] = 0;
2771
2764
 
2772
2765
      for (i = 1; i <= length * 2; i++)
2773
2766
        sum[i] = curve[i - length - 1] + sum[i - 1];
 
2767
 
2774
2768
      sum += length;
2775
2769
 
2776
2770
      total = sum[length] - sum[-length];
2802
2796
              while (i < end)
2803
2797
                {
2804
2798
                  pixels = b[0];
 
2799
 
2805
2800
                  i += pixels;
2806
2801
                  if (i > end)
2807
2802
                    i = end;
 
2803
 
2808
2804
                  val += b[1] * (sum[i] - sum[start]);
2809
2805
                  b += (pixels * 2);
2810
2806
                  start = i;
2829
2825
  g_free (buf);
2830
2826
}
2831
2827
 
2832
 
 
2833
 
/* non-interpolating scale_region.  [adam]
2834
 
 */
2835
 
static void
2836
 
scale_region_no_resample (PixelRegion *srcPR,
2837
 
                          PixelRegion *destPR)
2838
 
{
2839
 
  gint   *x_src_offsets;
2840
 
  gint   *y_src_offsets;
2841
 
  guchar *src;
2842
 
  guchar *dest;
2843
 
  gint    width, height, orig_width, orig_height;
2844
 
  gint    last_src_y;
2845
 
  gint    row_bytes;
2846
 
  gint    x, y, b;
2847
 
  gchar   bytes;
2848
 
 
2849
 
  orig_width = srcPR->w;
2850
 
  orig_height = srcPR->h;
2851
 
 
2852
 
  width = destPR->w;
2853
 
  height = destPR->h;
2854
 
 
2855
 
  bytes = srcPR->bytes;
2856
 
 
2857
 
  /*  the data pointers...  */
2858
 
  x_src_offsets = g_new (gint, width * bytes);
2859
 
  y_src_offsets = g_new (gint, height);
2860
 
  src  = g_new (guchar, orig_width * bytes);
2861
 
  dest = g_new (guchar, width * bytes);
2862
 
 
2863
 
  /*  pre-calc the scale tables  */
2864
 
  for (b = 0; b < bytes; b++)
2865
 
    for (x = 0; x < width; x++)
2866
 
      x_src_offsets [b + x * bytes] =
2867
 
        b + bytes * ((x * orig_width + orig_width / 2) / width);
2868
 
 
2869
 
  for (y = 0; y < height; y++)
2870
 
    y_src_offsets [y] = (y * orig_height + orig_height / 2) / height;
2871
 
 
2872
 
  /*  do the scaling  */
2873
 
  row_bytes = width * bytes;
2874
 
  last_src_y = -1;
2875
 
  for (y = 0; y < height; y++)
2876
 
    {
2877
 
      /* if the source of this line was the same as the source
2878
 
       *  of the last line, there's no point in re-rescaling.
2879
 
       */
2880
 
      if (y_src_offsets[y] != last_src_y)
2881
 
        {
2882
 
          pixel_region_get_row (srcPR, 0, y_src_offsets[y], orig_width, src, 1);
2883
 
          for (x = 0; x < row_bytes ; x++)
2884
 
            {
2885
 
              dest[x] = src[x_src_offsets[x]];
2886
 
            }
2887
 
          last_src_y = y_src_offsets[y];
2888
 
        }
2889
 
 
2890
 
      pixel_region_set_row (destPR, 0, y, width, dest);
2891
 
    }
2892
 
 
2893
 
  g_free (x_src_offsets);
2894
 
  g_free (y_src_offsets);
2895
 
  g_free (src);
2896
 
  g_free (dest);
2897
 
}
2898
 
 
2899
 
 
2900
 
static void
2901
 
get_premultiplied_double_row (PixelRegion *srcPR,
2902
 
                              gint         x,
2903
 
                              gint         y,
2904
 
                              gint         w,
2905
 
                              gdouble     *row,
2906
 
                              guchar      *tmp_src,
2907
 
                              gint         n)
2908
 
{
2909
 
  gint b;
2910
 
  gint bytes = srcPR->bytes;
2911
 
 
2912
 
  pixel_region_get_row (srcPR, x, y, w, tmp_src, n);
2913
 
 
2914
 
  if (pixel_region_has_alpha (srcPR))
2915
 
    {
2916
 
      /* premultiply the alpha into the double array */
2917
 
      gdouble *irow  = row;
2918
 
      gint     alpha = bytes - 1;
2919
 
      gdouble  mod_alpha;
2920
 
 
2921
 
      for (x = 0; x < w; x++)
2922
 
        {
2923
 
          mod_alpha = tmp_src[alpha] / 255.0;
2924
 
          for (b = 0; b < alpha; b++)
2925
 
            irow[b] = mod_alpha * tmp_src[b];
2926
 
          irow[b] = tmp_src[alpha];
2927
 
          irow += bytes;
2928
 
          tmp_src += bytes;
2929
 
        }
2930
 
    }
2931
 
  else /* no alpha */
2932
 
    {
2933
 
      for (x = 0; x < w * bytes; x++)
2934
 
        row[x] = tmp_src[x];
2935
 
    }
2936
 
 
2937
 
  /* set the off edge pixels to their nearest neighbor */
2938
 
  for (b = 0; b < 2 * bytes; b++)
2939
 
    row[b - 2 * bytes] = row[b % bytes];
2940
 
  for (b = 0; b < bytes * 2; b++)
2941
 
    row[b + w * bytes] = row[(w - 1) * bytes + b % bytes];
2942
 
}
2943
 
 
2944
 
 
2945
 
static void
2946
 
expand_line (gdouble               *dest,
2947
 
             gdouble               *src,
2948
 
             gint                   bytes,
2949
 
             gint                   old_width,
2950
 
             gint                   width,
2951
 
             GimpInterpolationType  interp)
2952
 
{
2953
 
  gdouble  ratio;
2954
 
  gint     x,b;
2955
 
  gint     src_col;
2956
 
  gdouble  frac;
2957
 
  gdouble *s;
2958
 
 
2959
 
  ratio = old_width / (gdouble) width;
2960
 
 
2961
 
  /* we can overflow src's boundaries, so we expect our caller to have
2962
 
     allocated extra space for us to do so safely (see scale_region ()) */
2963
 
 
2964
 
  /* this could be optimized much more by precalculating the coefficients for
2965
 
     each x */
2966
 
  switch(interp)
2967
 
    {
2968
 
    case GIMP_INTERPOLATION_CUBIC:
2969
 
      for (x = 0; x < width; x++)
2970
 
        {
2971
 
          src_col = ((int) (x * ratio + 2.0 - 0.5)) - 2;
2972
 
          /* +2, -2 is there because (int) rounds towards 0 and we need
2973
 
             to round down */
2974
 
          frac = (x * ratio - 0.5) - src_col;
2975
 
          s = &src[src_col * bytes];
2976
 
          for (b = 0; b < bytes; b++)
2977
 
            dest[b] = cubic (frac, s[b - bytes], s[b], s[b + bytes],
2978
 
                             s[b + bytes * 2]);
2979
 
          dest += bytes;
2980
 
        }
2981
 
 
2982
 
      break;
2983
 
 
2984
 
    case GIMP_INTERPOLATION_LINEAR:
2985
 
      for (x = 0; x < width; x++)
2986
 
        {
2987
 
          src_col = ((int) (x * ratio + 2.0 - 0.5)) - 2;
2988
 
          /* +2, -2 is there because (int) rounds towards 0 and we need
2989
 
             to round down */
2990
 
          frac = (x * ratio - 0.5) - src_col;
2991
 
          s = &src[src_col * bytes];
2992
 
          for (b = 0; b < bytes; b++)
2993
 
            dest[b] = ((s[b + bytes] - s[b]) * frac + s[b]);
2994
 
          dest += bytes;
2995
 
        }
2996
 
      break;
2997
 
 
2998
 
    case GIMP_INTERPOLATION_NONE:
2999
 
      g_assert_not_reached ();
3000
 
      break;
3001
 
    }
3002
 
}
3003
 
 
3004
 
 
3005
 
static void
3006
 
shrink_line (gdouble               *dest,
3007
 
             gdouble               *src,
3008
 
             gint                   bytes,
3009
 
             gint                   old_width,
3010
 
             gint                   width,
3011
 
             GimpInterpolationType  interp)
3012
 
{
3013
 
  gint          x;
3014
 
  gint          b;
3015
 
  gdouble      *srcp;
3016
 
  gdouble      *destp;
3017
 
  gdouble       accum[4];
3018
 
  gdouble       slice;
3019
 
  const gdouble avg_ratio = (gdouble) width / old_width;
3020
 
  const gdouble inv_width = 1.0 / width;
3021
 
  gint          slicepos;      /* slice position relative to width */
3022
 
 
3023
 
#if 0
3024
 
  g_printerr ("shrink_line bytes=%d old_width=%d width=%d interp=%d "
3025
 
              "avg_ratio=%f\n",
3026
 
              bytes, old_width, width, interp, avg_ratio);
3027
 
#endif
3028
 
 
3029
 
  g_return_if_fail (bytes <= 4);
3030
 
 
3031
 
  /* This algorithm calculates the weighted average of pixel data that
3032
 
     each output pixel must receive, taking into account that it always
3033
 
     scales down, i.e. there's always more than one input pixel per each
3034
 
     output pixel.  */
3035
 
 
3036
 
  srcp = src;
3037
 
  destp = dest;
3038
 
 
3039
 
  slicepos = 0;
3040
 
 
3041
 
  /* Initialize accum to the first pixel slice.  As there is no partial
3042
 
     pixel at start, that value is 0.  The source data is interleaved, so
3043
 
     we maintain BYTES accumulators at the same time to deal with that
3044
 
     many channels simultaneously.  */
3045
 
  for (b = 0; b < bytes; b++)
3046
 
    accum[b] = 0.0;
3047
 
 
3048
 
  for (x = 0; x < width; x++)
3049
 
    {
3050
 
      /* Accumulate whole pixels.  */
3051
 
      do
3052
 
        {
3053
 
          for (b = 0; b < bytes; b++)
3054
 
            accum[b] += *srcp++;
3055
 
 
3056
 
          slicepos += width;
3057
 
        }
3058
 
      while (slicepos < old_width);
3059
 
      slicepos -= old_width;
3060
 
 
3061
 
      if (! (slicepos < width))
3062
 
        g_warning ("Assertion (slicepos < width) failed. Please report.");
3063
 
 
3064
 
      if (slicepos == 0)
3065
 
        {
3066
 
          /* Simplest case: we have reached a whole pixel boundary.  Store
3067
 
             the average value per channel and reset the accumulators for
3068
 
             the next round.
3069
 
 
3070
 
             The main reason to treat this case separately is to avoid an
3071
 
             access to out-of-bounds memory for the first pixel.  */
3072
 
          for (b = 0; b < bytes; b++)
3073
 
            {
3074
 
              *destp++ = accum[b] * avg_ratio;
3075
 
              accum[b] = 0.0;
3076
 
            }
3077
 
        }
3078
 
      else
3079
 
        {
3080
 
          for (b = 0; b < bytes; b++)
3081
 
            {
3082
 
              /* We have accumulated a whole pixel per channel where just a
3083
 
                 slice of it was needed.  Subtract now the previous pixel's
3084
 
                 extra slice.  */
3085
 
              slice = srcp[- bytes + b] * slicepos * inv_width;
3086
 
              *destp++ = (accum[b] - slice) * avg_ratio;
3087
 
 
3088
 
              /* That slice is the initial value for the next round.  */
3089
 
              accum[b] = slice;
3090
 
            }
3091
 
        }
3092
 
    }
3093
 
 
3094
 
  /* Sanity check: srcp should point to the next-to-last position, and
3095
 
     slicepos should be zero.  */
3096
 
  if (! (srcp - src == old_width * bytes && slicepos == 0))
3097
 
    g_warning ("Assertion (srcp - src == old_width * bytes && slicepos == 0)"
3098
 
               " failed. Please report.");
3099
 
}
3100
 
 
3101
2828
static inline void
3102
2829
rotate_pointers (guchar  **p,
3103
2830
                 guint32   n)
3106
2833
  guchar  *tmp;
3107
2834
 
3108
2835
  tmp = p[0];
3109
 
  for (i = 0; i < n-1; i++)
3110
 
    {
3111
 
      p[i] = p[i+1];
3112
 
    }
 
2836
 
 
2837
  for (i = 0; i < n - 1; i++)
 
2838
    p[i] = p[i + 1];
 
2839
 
3113
2840
  p[i] = tmp;
3114
2841
}
3115
2842
 
3116
 
static void
3117
 
get_scaled_row (gdouble              **src,
3118
 
                gint                   y,
3119
 
                gint                   new_width,
3120
 
                PixelRegion           *srcPR,
3121
 
                gdouble               *row,
3122
 
                guchar                *src_tmp,
3123
 
                GimpInterpolationType  interpolation_type)
3124
 
{
3125
 
  /* get the necesary lines from the source image, scale them,
3126
 
     and put them into src[] */
3127
 
  rotate_pointers ((gpointer) src, 4);
3128
 
  if (y < 0)
3129
 
    y = 0;
3130
 
  if (y < srcPR->h)
3131
 
    {
3132
 
      get_premultiplied_double_row (srcPR, 0, y, srcPR->w,
3133
 
                                    row, src_tmp, 1);
3134
 
      if (new_width > srcPR->w)
3135
 
        expand_line(src[3], row, srcPR->bytes,
3136
 
                    srcPR->w, new_width, interpolation_type);
3137
 
      else if (srcPR->w > new_width)
3138
 
        shrink_line(src[3], row, srcPR->bytes,
3139
 
                    srcPR->w, new_width, interpolation_type);
3140
 
      else /* no scailing needed */
3141
 
        memcpy(src[3], row, sizeof (gdouble) * new_width * srcPR->bytes);
3142
 
    }
3143
 
  else
3144
 
    memcpy(src[3], src[2], sizeof (gdouble) * new_width * srcPR->bytes);
3145
 
}
3146
 
 
3147
 
void
3148
 
scale_region (PixelRegion           *srcPR,
3149
 
              PixelRegion           *destPR,
3150
 
              GimpInterpolationType  interpolation,
3151
 
              GimpProgressFunc       progress_callback,
3152
 
              gpointer               progress_data)
3153
 
{
3154
 
  gdouble *src[4];
3155
 
  guchar  *src_tmp;
3156
 
  guchar  *dest;
3157
 
  gdouble *row, *accum;
3158
 
  gint     bytes, b;
3159
 
  gint     width, height;
3160
 
  gint     orig_width, orig_height;
3161
 
  gdouble  y_rat;
3162
 
  gint     i;
3163
 
  gint     old_y = -4;
3164
 
  gint     new_y;
3165
 
  gint     x, y;
3166
 
 
3167
 
  if (interpolation == GIMP_INTERPOLATION_NONE)
3168
 
    {
3169
 
      scale_region_no_resample (srcPR, destPR);
3170
 
      return;
3171
 
    }
3172
 
 
3173
 
  orig_width = srcPR->w;
3174
 
  orig_height = srcPR->h;
3175
 
 
3176
 
  width = destPR->w;
3177
 
  height = destPR->h;
3178
 
 
3179
 
#if 0
3180
 
  g_printerr ("scale_region: (%d x %d) -> (%d x %d)\n",
3181
 
              orig_width, orig_height, width, height);
3182
 
#endif
3183
 
 
3184
 
  /*  find the ratios of old y to new y  */
3185
 
  y_rat = (gdouble) orig_height / (gdouble) height;
3186
 
 
3187
 
  bytes = destPR->bytes;
3188
 
 
3189
 
  /*  the data pointers...  */
3190
 
  for (i = 0; i < 4; i++)
3191
 
    src[i] = g_new (gdouble, width * bytes);
3192
 
 
3193
 
  dest = g_new (guchar, width * bytes);
3194
 
 
3195
 
  src_tmp = g_new (guchar, orig_width * bytes);
3196
 
 
3197
 
  /* offset the row pointer by 2*bytes so the range of the array
3198
 
     is [-2*bytes] to [(orig_width + 2)*bytes] */
3199
 
  row = g_new (gdouble, (orig_width + 2 * 2) * bytes);
3200
 
  row += bytes * 2;
3201
 
 
3202
 
  accum = g_new (gdouble, width * bytes);
3203
 
 
3204
 
  /*  Scale the selected region  */
3205
 
 
3206
 
  for (y = 0; y < height; y++)
3207
 
    {
3208
 
      if (progress_callback && !(y & 0xf))
3209
 
        (* progress_callback) (0, height, y, progress_data);
3210
 
 
3211
 
      if (height < orig_height)
3212
 
        {
3213
 
          gint          max;
3214
 
          gdouble       frac;
3215
 
          const gdouble inv_ratio = 1.0 / y_rat;
3216
 
 
3217
 
          if (y == 0) /* load the first row if this is the first time through */
3218
 
            get_scaled_row (&src[0], 0, width, srcPR, row,
3219
 
                            src_tmp,
3220
 
                            interpolation);
3221
 
          new_y = (int) (y * y_rat);
3222
 
          frac = 1.0 - (y * y_rat - new_y);
3223
 
          for (x = 0; x < width * bytes; x++)
3224
 
            accum[x] = src[3][x] * frac;
3225
 
 
3226
 
          max = (int) ((y + 1) * y_rat) - new_y - 1;
3227
 
 
3228
 
          get_scaled_row (&src[0], ++new_y, width, srcPR, row,
3229
 
                          src_tmp,
3230
 
                          interpolation);
3231
 
 
3232
 
          while (max > 0)
3233
 
            {
3234
 
              for (x = 0; x < width * bytes; x++)
3235
 
                accum[x] += src[3][x];
3236
 
              get_scaled_row (&src[0], ++new_y, width, srcPR, row,
3237
 
                              src_tmp,
3238
 
                              interpolation);
3239
 
              max--;
3240
 
            }
3241
 
          frac = (y + 1) * y_rat - ((int) ((y + 1) * y_rat));
3242
 
          for (x = 0; x < width * bytes; x++)
3243
 
            {
3244
 
              accum[x] += frac * src[3][x];
3245
 
              accum[x] *= inv_ratio;
3246
 
            }
3247
 
        }
3248
 
      else if (height > orig_height)
3249
 
        {
3250
 
          new_y = floor (y * y_rat - 0.5);
3251
 
 
3252
 
          while (old_y <= new_y)
3253
 
            {
3254
 
              /* get the necesary lines from the source image, scale them,
3255
 
                 and put them into src[] */
3256
 
              get_scaled_row (&src[0], old_y + 2, width, srcPR, row,
3257
 
                              src_tmp,
3258
 
                              interpolation);
3259
 
              old_y++;
3260
 
            }
3261
 
 
3262
 
          switch (interpolation)
3263
 
            {
3264
 
            case GIMP_INTERPOLATION_CUBIC:
3265
 
              {
3266
 
                gdouble p0, p1, p2, p3;
3267
 
                gdouble dy = (y * y_rat - 0.5) - new_y;
3268
 
 
3269
 
                p0 = cubic (dy, 1, 0, 0, 0);
3270
 
                p1 = cubic (dy, 0, 1, 0, 0);
3271
 
                p2 = cubic (dy, 0, 0, 1, 0);
3272
 
                p3 = cubic (dy, 0, 0, 0, 1);
3273
 
                for (x = 0; x < width * bytes; x++)
3274
 
                  accum[x] = (p0 * src[0][x] + p1 * src[1][x] +
3275
 
                              p2 * src[2][x] + p3 * src[3][x]);
3276
 
              }
3277
 
 
3278
 
              break;
3279
 
 
3280
 
            case GIMP_INTERPOLATION_LINEAR:
3281
 
              {
3282
 
                gdouble idy = (y * y_rat - 0.5) - new_y;
3283
 
                gdouble dy = 1.0 - idy;
3284
 
 
3285
 
                for (x = 0; x < width * bytes; x++)
3286
 
                  accum[x] = dy * src[1][x] + idy * src[2][x];
3287
 
              }
3288
 
 
3289
 
              break;
3290
 
 
3291
 
            case GIMP_INTERPOLATION_NONE:
3292
 
              g_assert_not_reached ();
3293
 
              break;
3294
 
            }
3295
 
        }
3296
 
      else /* height == orig_height */
3297
 
        {
3298
 
          get_scaled_row (&src[0], y, width, srcPR, row,
3299
 
                          src_tmp,
3300
 
                          interpolation);
3301
 
          memcpy (accum, src[3], sizeof (gdouble) * width * bytes);
3302
 
        }
3303
 
 
3304
 
      if (pixel_region_has_alpha (srcPR))
3305
 
        {
3306
 
          /* unmultiply the alpha */
3307
 
          gdouble  inv_alpha;
3308
 
          gdouble *p = accum;
3309
 
          gint     alpha = bytes - 1;
3310
 
          gint     result;
3311
 
          guchar  *d = dest;
3312
 
 
3313
 
          for (x = 0; x < width; x++)
3314
 
            {
3315
 
              if (p[alpha] > 0.001)
3316
 
                {
3317
 
                  inv_alpha = 255.0 / p[alpha];
3318
 
                  for (b = 0; b < alpha; b++)
3319
 
                    {
3320
 
                      result = RINT (inv_alpha * p[b]);
3321
 
                      if (result < 0)
3322
 
                        d[b] = 0;
3323
 
                      else if (result > 255)
3324
 
                        d[b] = 255;
3325
 
                      else
3326
 
                        d[b] = result;
3327
 
                    }
3328
 
                  result = RINT (p[alpha]);
3329
 
                  if (result > 255)
3330
 
                    d[alpha] = 255;
3331
 
                  else
3332
 
                    d[alpha] = result;
3333
 
                }
3334
 
              else /* alpha <= 0 */
3335
 
                for (b = 0; b <= alpha; b++)
3336
 
                  d[b] = 0;
3337
 
 
3338
 
              d += bytes;
3339
 
              p += bytes;
3340
 
            }
3341
 
        }
3342
 
      else
3343
 
        {
3344
 
          gint w = width * bytes;
3345
 
 
3346
 
          for (x = 0; x < w; x++)
3347
 
            {
3348
 
              if (accum[x] < 0.0)
3349
 
                dest[x] = 0;
3350
 
              else if (accum[x] > 255.0)
3351
 
                dest[x] = 255;
3352
 
              else
3353
 
                dest[x] = RINT (accum[x]);
3354
 
            }
3355
 
        }
3356
 
      pixel_region_set_row (destPR, 0, y, width, dest);
3357
 
    }
3358
 
 
3359
 
  /*  free up temporary arrays  */
3360
 
  g_free (accum);
3361
 
  for (i = 0; i < 4; i++)
3362
 
    g_free (src[i]);
3363
 
  g_free (src_tmp);
3364
 
  g_free (dest);
3365
 
 
3366
 
  row -= 2 * bytes;
3367
 
  g_free (row);
3368
 
}
3369
 
 
3370
 
void
3371
 
subsample_region (PixelRegion *srcPR,
3372
 
                  PixelRegion *destPR,
3373
 
                  gint         subsample)
3374
 
{
3375
 
  guchar  *src,  *s;
3376
 
  guchar  *dest, *d;
3377
 
  gdouble *row,  *r;
3378
 
  gint destwidth;
3379
 
  gint src_row, src_col;
3380
 
  gint bytes, b;
3381
 
  gint width, height;
3382
 
  gint orig_width, orig_height;
3383
 
  gdouble x_rat, y_rat;
3384
 
  gdouble x_cum, y_cum;
3385
 
  gdouble x_last, y_last;
3386
 
  gdouble * x_frac, y_frac, tot_frac;
3387
 
  gint i, j;
3388
 
  gint frac;
3389
 
  gint advance_dest;
3390
 
 
3391
 
  orig_width = srcPR->w / subsample;
3392
 
  orig_height = srcPR->h / subsample;
3393
 
  width = destPR->w;
3394
 
  height = destPR->h;
3395
 
 
3396
 
#if 0
3397
 
  g_printerr ("subsample_region: (%d x %d) -> (%d x %d)\n",
3398
 
              orig_width, orig_height, width, height);
3399
 
#endif
3400
 
 
3401
 
  /*  Some calculations...  */
3402
 
  bytes = destPR->bytes;
3403
 
  destwidth = destPR->rowstride;
3404
 
 
3405
 
  /*  the data pointers...  */
3406
 
  src  = g_new (guchar, orig_width * bytes);
3407
 
  dest = destPR->data;
3408
 
 
3409
 
  /*  find the ratios of old x to new x and old y to new y  */
3410
 
  x_rat = (gdouble) orig_width / (gdouble) width;
3411
 
  y_rat = (gdouble) orig_height / (gdouble) height;
3412
 
 
3413
 
  /*  allocate an array to help with the calculations  */
3414
 
  row    = g_new (gdouble, width * bytes);
3415
 
  x_frac = g_new (gdouble, width + orig_width);
3416
 
 
3417
 
  /*  initialize the pre-calculated pixel fraction array  */
3418
 
  src_col = 0;
3419
 
  x_cum = (gdouble) src_col;
3420
 
  x_last = x_cum;
3421
 
 
3422
 
  for (i = 0; i < width + orig_width; i++)
3423
 
    {
3424
 
      if (x_cum + x_rat <= (src_col + 1 + EPSILON))
3425
 
        {
3426
 
          x_cum += x_rat;
3427
 
          x_frac[i] = x_cum - x_last;
3428
 
        }
3429
 
      else
3430
 
        {
3431
 
          src_col ++;
3432
 
          x_frac[i] = src_col - x_last;
3433
 
        }
3434
 
      x_last += x_frac[i];
3435
 
    }
3436
 
 
3437
 
  /*  clear the "row" array  */
3438
 
  memset (row, 0, sizeof (gdouble) * width * bytes);
3439
 
 
3440
 
  /*  counters...  */
3441
 
  src_row = 0;
3442
 
  y_cum = (gdouble) src_row;
3443
 
  y_last = y_cum;
3444
 
 
3445
 
  pixel_region_get_row (srcPR, 0, src_row * subsample, orig_width * subsample, src, subsample);
3446
 
 
3447
 
  /*  Scale the selected region  */
3448
 
  for (i = 0; i < height; )
3449
 
    {
3450
 
      src_col = 0;
3451
 
      x_cum = (gdouble) src_col;
3452
 
 
3453
 
      /* determine the fraction of the src pixel we are using for y */
3454
 
      if (y_cum + y_rat <= (src_row + 1 + EPSILON))
3455
 
        {
3456
 
          y_cum += y_rat;
3457
 
          y_frac = y_cum - y_last;
3458
 
          advance_dest = TRUE;
3459
 
        }
3460
 
      else
3461
 
        {
3462
 
          src_row ++;
3463
 
          y_frac = src_row - y_last;
3464
 
          advance_dest = FALSE;
3465
 
        }
3466
 
 
3467
 
      y_last += y_frac;
3468
 
 
3469
 
      s = src;
3470
 
      r = row;
3471
 
 
3472
 
      frac = 0;
3473
 
      j = width;
3474
 
 
3475
 
      while (j)
3476
 
        {
3477
 
          tot_frac = x_frac[frac++] * y_frac;
3478
 
 
3479
 
          for (b = 0; b < bytes; b++)
3480
 
            r[b] += s[b] * tot_frac;
3481
 
 
3482
 
          /*  increment the destination  */
3483
 
          if (x_cum + x_rat <= (src_col + 1 + EPSILON))
3484
 
            {
3485
 
              r += bytes;
3486
 
              x_cum += x_rat;
3487
 
              j--;
3488
 
            }
3489
 
 
3490
 
          /* increment the source */
3491
 
          else
3492
 
            {
3493
 
              s += bytes;
3494
 
              src_col++;
3495
 
            }
3496
 
        }
3497
 
 
3498
 
      if (advance_dest)
3499
 
        {
3500
 
          tot_frac = 1.0 / (x_rat * y_rat);
3501
 
 
3502
 
          /*  copy "row" to "dest"  */
3503
 
          d = dest;
3504
 
          r = row;
3505
 
 
3506
 
          j = width;
3507
 
          while (j--)
3508
 
            {
3509
 
              b = bytes;
3510
 
              while (b--)
3511
 
                *d++ = (guchar) (*r++ * tot_frac + 0.5);
3512
 
            }
3513
 
 
3514
 
          dest += destwidth;
3515
 
 
3516
 
          /*  clear the "row" array  */
3517
 
          memset (row, 0, sizeof (gdouble) * destwidth);
3518
 
 
3519
 
          i++;
3520
 
        }
3521
 
      else
3522
 
        pixel_region_get_row (srcPR, 0, src_row * subsample, orig_width * subsample, src, subsample);
3523
 
    }
3524
 
 
3525
 
  /*  free up temporary arrays  */
3526
 
  g_free (row);
3527
 
  g_free (x_frac);
3528
 
  g_free (src);
3529
 
}
3530
 
 
3531
2843
 
3532
2844
gfloat
3533
2845
shapeburst_region (PixelRegion      *srcPR,
3610
2922
                  while (boundary--)
3611
2923
                    {
3612
2924
                      src = *tile_data;
 
2925
 
3613
2926
                      if (src == 0)
3614
2927
                        {
3615
2928
                          min = k;
3616
2929
                          y = -1;
3617
2930
                          break;
3618
2931
                        }
 
2932
 
3619
2933
                      if (src < fraction)
3620
2934
                        fraction = src;
3621
2935
 
3636
2950
              if (min_left != min)
3637
2951
                {
3638
2952
                  prev_frac = (int) (255 * (min_prev - min));
 
2953
 
3639
2954
                  if (prev_frac == 255)
3640
2955
                    prev_frac = 0;
 
2956
 
3641
2957
                  fraction = MIN (fraction, prev_frac);
3642
2958
                }
 
2959
 
3643
2960
              min++;
3644
2961
            }
3645
2962
 
3650
2967
        }
3651
2968
 
3652
2969
      /*  set the dist row  */
3653
 
      pixel_region_set_row (distPR, distPR->x, distPR->y + i, distPR->w, (guchar *) distp_cur);
 
2970
      pixel_region_set_row (distPR,
 
2971
                            distPR->x, distPR->y + i, distPR->w,
 
2972
                            (guchar *) distp_cur);
3654
2973
 
3655
2974
      /*  swap pointers around  */
3656
2975
      tmp = distp_prev;
3674
2993
                guint16  xradius,
3675
2994
                guint16  yradius)
3676
2995
{
3677
 
  gint32 i;
3678
 
  gint32 diameter = xradius * 2 + 1;
 
2996
  gint32  i;
 
2997
  gint32  diameter = xradius * 2 + 1;
3679
2998
  gdouble tmp;
3680
2999
 
3681
3000
  for (i = 0; i < diameter; i++)
3687
3006
    else
3688
3007
      tmp = 0.0;
3689
3008
 
3690
 
    circ[i] = RINT (yradius / (gdouble) xradius *
3691
 
                    sqrt (xradius * xradius - tmp * tmp));
 
3009
    circ[i] = RINT (yradius /
 
3010
                    (gdouble) xradius * sqrt (SQR (xradius) - SQR (tmp)));
3692
3011
  }
3693
3012
}
3694
3013
 
3695
3014
void
3696
 
fatten_region (PixelRegion *src,
 
3015
fatten_region (PixelRegion *region,
3697
3016
               gint16       xradius,
3698
3017
               gint16       yradius)
3699
3018
{
3714
3033
  if (xradius <= 0 || yradius <= 0)
3715
3034
    return;
3716
3035
 
3717
 
  max = g_new (guchar *, src->w + 2 * xradius);
 
3036
  max = g_new (guchar *, region->w + 2 * xradius);
3718
3037
  buf = g_new (guchar *, yradius + 1);
 
3038
 
3719
3039
  for (i = 0; i < yradius + 1; i++)
3720
 
    {
3721
 
      buf[i] = g_new (guchar, src->w);
3722
 
    }
3723
 
  buffer = g_new (guchar, (src->w + 2 * xradius) * (yradius + 1));
3724
 
  for (i = 0; i < src->w + 2 * xradius; i++)
 
3040
    buf[i] = g_new (guchar, region->w);
 
3041
 
 
3042
  buffer = g_new (guchar, (region->w + 2 * xradius) * (yradius + 1));
 
3043
 
 
3044
  for (i = 0; i < region->w + 2 * xradius; i++)
3725
3045
    {
3726
3046
      if (i < xradius)
3727
3047
        max[i] = buffer;
3728
 
      else if (i < src->w + xradius)
 
3048
      else if (i < region->w + xradius)
3729
3049
        max[i] = &buffer[(yradius + 1) * (i - xradius)];
3730
3050
      else
3731
 
        max[i] = &buffer[(yradius + 1) * (src->w + xradius - 1)];
 
3051
        max[i] = &buffer[(yradius + 1) * (region->w + xradius - 1)];
3732
3052
 
3733
3053
      for (j = 0; j < xradius + 1; j++)
3734
3054
        max[i][j] = 0;
3735
3055
    }
 
3056
 
3736
3057
  /* offset the max pointer by xradius so the range of the array
3737
 
     is [-xradius] to [src->w + xradius] */
 
3058
     is [-xradius] to [region->w + xradius] */
3738
3059
  max += xradius;
3739
3060
 
3740
 
  out =  g_new (guchar, src->w);
 
3061
  out =  g_new (guchar, region->w);
3741
3062
 
3742
3063
  circ = g_new (gint16, 2 * xradius + 1);
3743
3064
  compute_border (circ, xradius, yradius);
3746
3067
     is [-xradius] to [xradius] */
3747
3068
  circ += xradius;
3748
3069
 
3749
 
  memset (buf[0], 0, src->w);
3750
 
  for (i = 0; i < yradius && i < src->h; i++) /* load top of image */
3751
 
    pixel_region_get_row (src, src->x, src->y + i, src->w, buf[i + 1], 1);
3752
 
 
3753
 
  for (x = 0; x < src->w; x++) /* set up max for top of image */
 
3070
  memset (buf[0], 0, region->w);
 
3071
 
 
3072
  for (i = 0; i < yradius && i < region->h; i++) /* load top of image */
 
3073
    pixel_region_get_row (region,
 
3074
                          region->x, region->y + i, region->w, buf[i + 1], 1);
 
3075
 
 
3076
  for (x = 0; x < region->w; x++) /* set up max for top of image */
3754
3077
    {
3755
3078
      max[x][0] = 0;         /* buf[0][x] is always 0 */
3756
3079
      max[x][1] = buf[1][x]; /* MAX (buf[1][x], max[x][0]) always = buf[1][x]*/
 
3080
 
3757
3081
      for (j = 2; j < yradius + 1; j++)
3758
3082
        max[x][j] = MAX(buf[j][x], max[x][j-1]);
3759
3083
    }
3760
3084
 
3761
 
  for (y = 0; y < src->h; y++)
 
3085
  for (y = 0; y < region->h; y++)
3762
3086
    {
3763
3087
      rotate_pointers (buf, yradius + 1);
3764
 
      if (y < src->h - (yradius))
3765
 
        pixel_region_get_row (src, src->x, src->y + y + yradius, src->w,
 
3088
 
 
3089
      if (y < region->h - (yradius))
 
3090
        pixel_region_get_row (region,
 
3091
                              region->x, region->y + y + yradius, region->w,
3766
3092
                              buf[yradius], 1);
3767
3093
      else
3768
 
        memset (buf[yradius], 0, src->w);
3769
 
      for (x = 0; x < src->w; x++) /* update max array */
 
3094
        memset (buf[yradius], 0, region->w);
 
3095
 
 
3096
      for (x = 0; x < region->w; x++) /* update max array */
3770
3097
        {
3771
3098
          for (i = yradius; i > 0; i--)
3772
 
            {
3773
 
              max[x][i] = MAX (MAX (max[x][i - 1], buf[i - 1][x]), buf[i][x]);
3774
 
            }
 
3099
            max[x][i] = MAX (MAX (max[x][i - 1], buf[i - 1][x]), buf[i][x]);
 
3100
 
3775
3101
          max[x][0] = buf[0][x];
3776
3102
        }
 
3103
 
3777
3104
      last_max = max[0][circ[-1]];
3778
3105
      last_index = 1;
3779
 
      for (x = 0; x < src->w; x++) /* render scan line */
 
3106
 
 
3107
      for (x = 0; x < region->w; x++) /* render scan line */
3780
3108
        {
3781
3109
          last_index--;
 
3110
 
3782
3111
          if (last_index >= 0)
3783
3112
            {
3784
3113
              if (last_max == 255)
3785
 
                out[x] = 255;
 
3114
                {
 
3115
                  out[x] = 255;
 
3116
                }
3786
3117
              else
3787
3118
                {
3788
3119
                  last_max = 0;
 
3120
 
3789
3121
                  for (i = xradius; i >= 0; i--)
3790
3122
                    if (last_max < max[x + i][circ[i]])
3791
3123
                      {
3792
3124
                        last_max = max[x + i][circ[i]];
3793
3125
                        last_index = i;
3794
3126
                      }
 
3127
 
3795
3128
                  out[x] = last_max;
3796
3129
                }
3797
3130
            }
3799
3132
            {
3800
3133
              last_index = xradius;
3801
3134
              last_max = max[x + xradius][circ[xradius]];
 
3135
 
3802
3136
              for (i = xradius - 1; i >= -xradius; i--)
3803
3137
                if (last_max < max[x + i][circ[i]])
3804
3138
                  {
3805
3139
                    last_max = max[x + i][circ[i]];
3806
3140
                    last_index = i;
3807
3141
                  }
 
3142
 
3808
3143
              out[x] = last_max;
3809
3144
            }
3810
3145
        }
3811
 
      pixel_region_set_row (src, src->x, src->y + y, src->w, out);
 
3146
 
 
3147
      pixel_region_set_row (region, region->x, region->y + y, region->w, out);
3812
3148
    }
 
3149
 
3813
3150
  /* undo the offsets to the pointers so we can free the malloced memmory */
3814
3151
  circ -= xradius;
3815
3152
  max -= xradius;
3817
3154
  g_free (circ);
3818
3155
  g_free (buffer);
3819
3156
  g_free (max);
 
3157
 
3820
3158
  for (i = 0; i < yradius + 1; i++)
3821
3159
    g_free (buf[i]);
 
3160
 
3822
3161
  g_free (buf);
3823
3162
  g_free (out);
3824
3163
}
3825
3164
 
3826
3165
void
3827
 
thin_region (PixelRegion *src,
 
3166
thin_region (PixelRegion *region,
3828
3167
             gint16       xradius,
3829
3168
             gint16       yradius,
3830
3169
             gboolean     edge_lock)
3850
3189
  if (xradius <= 0 || yradius <= 0)
3851
3190
    return;
3852
3191
 
3853
 
  max = g_new (guchar *, src->w + 2 * xradius);
3854
 
 
 
3192
  max = g_new (guchar *, region->w + 2 * xradius);
3855
3193
  buf = g_new (guchar *, yradius + 1);
 
3194
 
3856
3195
  for (i = 0; i < yradius + 1; i++)
3857
 
    {
3858
 
      buf[i] = g_new (guchar, src->w);
3859
 
    }
 
3196
    buf[i] = g_new (guchar, region->w);
3860
3197
 
3861
 
  buffer_size = (src->w + 2 * xradius + 1) * (yradius + 1);
 
3198
  buffer_size = (region->w + 2 * xradius + 1) * (yradius + 1);
3862
3199
  buffer = g_new (guchar, buffer_size);
 
3200
 
3863
3201
  if (edge_lock)
3864
3202
    memset(buffer, 255, buffer_size);
3865
3203
  else
3866
3204
    memset(buffer, 0, buffer_size);
3867
3205
 
3868
 
  for (i = 0; i < src->w + 2 * xradius; i++)
 
3206
  for (i = 0; i < region->w + 2 * xradius; i++)
3869
3207
    {
3870
3208
      if (i < xradius)
3871
 
        if (edge_lock)
3872
 
          max[i] = buffer;
3873
 
        else
3874
 
          max[i] = &buffer[(yradius + 1) * (src->w + xradius)];
3875
 
      else if (i < src->w + xradius)
3876
 
        max[i] = &buffer[(yradius + 1) * (i - xradius)];
 
3209
        {
 
3210
          if (edge_lock)
 
3211
            max[i] = buffer;
 
3212
          else
 
3213
            max[i] = &buffer[(yradius + 1) * (region->w + xradius)];
 
3214
        }
 
3215
      else if (i < region->w + xradius)
 
3216
        {
 
3217
          max[i] = &buffer[(yradius + 1) * (i - xradius)];
 
3218
        }
3877
3219
      else
3878
 
        if (edge_lock)
3879
 
          max[i] = &buffer[(yradius + 1) * (src->w + xradius - 1)];
3880
 
        else
3881
 
          max[i] = &buffer[(yradius + 1) * (src->w + xradius)];
 
3220
        {
 
3221
          if (edge_lock)
 
3222
            max[i] = &buffer[(yradius + 1) * (region->w + xradius - 1)];
 
3223
          else
 
3224
            max[i] = &buffer[(yradius + 1) * (region->w + xradius)];
 
3225
        }
3882
3226
    }
3883
 
  if (!edge_lock)
 
3227
 
 
3228
  if (! edge_lock)
3884
3229
    for (j = 0 ; j < xradius + 1; j++)
3885
3230
      max[0][j] = 0;
3886
3231
 
3887
3232
  /* offset the max pointer by xradius so the range of the array
3888
 
     is [-xradius] to [src->w + xradius] */
 
3233
     is [-xradius] to [region->w + xradius] */
3889
3234
  max += xradius;
3890
3235
 
3891
 
  out = g_new (guchar, src->w);
 
3236
  out = g_new (guchar, region->w);
3892
3237
 
3893
3238
  circ = g_new (gint16, 2 * xradius + 1);
3894
 
  compute_border(circ, xradius, yradius);
 
3239
  compute_border (circ, xradius, yradius);
3895
3240
 
3896
3241
 /* offset the circ pointer by xradius so the range of the array
3897
3242
    is [-xradius] to [xradius] */
3898
3243
  circ += xradius;
3899
3244
 
3900
 
  for (i = 0; i < yradius && i < src->h; i++) /* load top of image */
3901
 
    pixel_region_get_row (src, src->x, src->y + i, src->w, buf[i + 1], 1);
 
3245
  for (i = 0; i < yradius && i < region->h; i++) /* load top of image */
 
3246
    pixel_region_get_row (region,
 
3247
                          region->x, region->y + i, region->w, buf[i + 1], 1);
3902
3248
  if (edge_lock)
3903
 
    memcpy (buf[0], buf[1], src->w);
 
3249
    memcpy (buf[0], buf[1], region->w);
3904
3250
  else
3905
 
    memset (buf[0], 0, src->w);
3906
 
 
3907
 
 
3908
 
  for (x = 0; x < src->w; x++) /* set up max for top of image */
 
3251
    memset (buf[0], 0, region->w);
 
3252
 
 
3253
 
 
3254
  for (x = 0; x < region->w; x++) /* set up max for top of image */
3909
3255
    {
3910
3256
      max[x][0] = buf[0][x];
3911
3257
      for (j = 1; j < yradius + 1; j++)
3912
3258
        max[x][j] = MIN(buf[j][x], max[x][j-1]);
3913
3259
    }
3914
3260
 
3915
 
  for (y = 0; y < src->h; y++)
 
3261
  for (y = 0; y < region->h; y++)
3916
3262
    {
3917
3263
      rotate_pointers (buf, yradius + 1);
3918
 
      if (y < src->h - yradius)
3919
 
        pixel_region_get_row (src, src->x, src->y + y + yradius, src->w,
 
3264
      if (y < region->h - yradius)
 
3265
        pixel_region_get_row (region,
 
3266
                              region->x, region->y + y + yradius, region->w,
3920
3267
                              buf[yradius], 1);
3921
3268
      else if (edge_lock)
3922
 
        memcpy (buf[yradius], buf[yradius - 1], src->w);
 
3269
        memcpy (buf[yradius], buf[yradius - 1], region->w);
3923
3270
      else
3924
 
        memset (buf[yradius], 0, src->w);
 
3271
        memset (buf[yradius], 0, region->w);
3925
3272
 
3926
 
      for (x = 0 ; x < src->w; x++) /* update max array */
 
3273
      for (x = 0 ; x < region->w; x++) /* update max array */
3927
3274
        {
3928
3275
          for (i = yradius; i > 0; i--)
3929
3276
            {
3931
3278
            }
3932
3279
          max[x][0] = buf[0][x];
3933
3280
        }
 
3281
 
3934
3282
      last_max =  max[0][circ[-1]];
3935
3283
      last_index = 0;
3936
3284
 
3937
 
      for (x = 0 ; x < src->w; x++) /* render scan line */
 
3285
      for (x = 0 ; x < region->w; x++) /* render scan line */
3938
3286
        {
3939
3287
          last_index--;
 
3288
 
3940
3289
          if (last_index >= 0)
3941
3290
            {
3942
3291
              if (last_max == 0)
3943
 
                out[x] = 0;
 
3292
                {
 
3293
                  out[x] = 0;
 
3294
                }
3944
3295
              else
3945
3296
                {
3946
3297
                  last_max = 255;
 
3298
 
3947
3299
                  for (i = xradius; i >= 0; i--)
3948
3300
                    if (last_max > max[x + i][circ[i]])
3949
3301
                      {
3950
3302
                        last_max = max[x + i][circ[i]];
3951
3303
                        last_index = i;
3952
3304
                      }
 
3305
 
3953
3306
                  out[x] = last_max;
3954
3307
                }
3955
3308
            }
3957
3310
            {
3958
3311
              last_index = xradius;
3959
3312
              last_max = max[x + xradius][circ[xradius]];
 
3313
 
3960
3314
              for (i = xradius - 1; i >= -xradius; i--)
3961
3315
                if (last_max > max[x + i][circ[i]])
3962
3316
                  {
3963
3317
                    last_max = max[x + i][circ[i]];
3964
3318
                    last_index = i;
3965
3319
                  }
 
3320
 
3966
3321
              out[x] = last_max;
3967
3322
            }
3968
3323
        }
3969
 
      pixel_region_set_row (src, src->x, src->y + y, src->w, out);
 
3324
 
 
3325
      pixel_region_set_row (region, region->x, region->y + y, region->w, out);
3970
3326
    }
3971
3327
 
3972
3328
  /* undo the offsets to the pointers so we can free the malloced memmory */
3973
3329
  circ -= xradius;
3974
3330
  max -= xradius;
 
3331
 
3975
3332
  /* free the memmory */
3976
3333
  g_free (circ);
3977
3334
  g_free (buffer);
3978
3335
  g_free (max);
 
3336
 
3979
3337
  for (i = 0; i < yradius + 1; i++)
3980
3338
    g_free (buf[i]);
 
3339
 
3981
3340
  g_free (buf);
3982
3341
  g_free (out);
3983
3342
}
3984
3343
 
 
3344
/*  Simple convolution filter to smooth a mask (1bpp).  */
 
3345
void
 
3346
smooth_region (PixelRegion *region)
 
3347
{
 
3348
  gint      x, y;
 
3349
  gint      width;
 
3350
  gint      i;
 
3351
  guchar   *buf[3];
 
3352
  guchar   *out;
 
3353
 
 
3354
  width = region->w;
 
3355
 
 
3356
  for (i = 0; i < 3; i++)
 
3357
    buf[i] = g_new (guchar, width + 2);
 
3358
 
 
3359
  out = g_new (guchar, width);
 
3360
 
 
3361
  /* load top of image */
 
3362
  pixel_region_get_row (region, region->x, region->y, width, buf[0] + 1, 1);
 
3363
 
 
3364
  buf[0][0]         = buf[0][1];
 
3365
  buf[0][width + 1] = buf[0][width];
 
3366
 
 
3367
  memcpy (buf[1], buf[0], width + 2);
 
3368
 
 
3369
  for (y = 0; y < region->h; y++)
 
3370
    {
 
3371
      if (y + 1 < region->h)
 
3372
        {
 
3373
          pixel_region_get_row (region, region->x, region->y + y + 1, width,
 
3374
                                buf[2] + 1, 1);
 
3375
 
 
3376
          buf[2][0]         = buf[2][1];
 
3377
          buf[2][width + 1] = buf[2][width];
 
3378
        }
 
3379
      else
 
3380
        {
 
3381
          memcpy (buf[2], buf[1], width + 2);
 
3382
        }
 
3383
 
 
3384
      for (x = 0 ; x < width; x++)
 
3385
        {
 
3386
          gint value = (buf[0][x] + buf[0][x+1] + buf[0][x+2] +
 
3387
                        buf[1][x] + buf[2][x+1] + buf[1][x+2] +
 
3388
                        buf[2][x] + buf[1][x+1] + buf[2][x+2]);
 
3389
 
 
3390
          out[x] = value / 9;
 
3391
        }
 
3392
 
 
3393
      pixel_region_set_row (region, region->x, region->y + y, width, out);
 
3394
 
 
3395
      rotate_pointers (buf, 3);
 
3396
    }
 
3397
 
 
3398
  for (i = 0; i < 3; i++)
 
3399
    g_free (buf[i]);
 
3400
 
 
3401
  g_free (out);
 
3402
}
 
3403
 
 
3404
/*  Erode (radius 1 pixel) a mask (1bpp).  */
 
3405
void
 
3406
erode_region (PixelRegion *region)
 
3407
{
 
3408
  gint      x, y;
 
3409
  gint      width;
 
3410
  gint      i;
 
3411
  guchar   *buf[3];
 
3412
  guchar   *out;
 
3413
 
 
3414
  width = region->w;
 
3415
 
 
3416
  for (i = 0; i < 3; i++)
 
3417
    buf[i] = g_new (guchar, width + 2);
 
3418
 
 
3419
  out = g_new (guchar, width);
 
3420
 
 
3421
  /* load top of image */
 
3422
  pixel_region_get_row (region, region->x, region->y, width, buf[0] + 1, 1);
 
3423
 
 
3424
  buf[0][0]         = buf[0][1];
 
3425
  buf[0][width + 1] = buf[0][width];
 
3426
 
 
3427
  memcpy (buf[1], buf[0], width + 2);
 
3428
 
 
3429
  for (y = 0; y < region->h; y++)
 
3430
    {
 
3431
      if (y + 1 < region->h)
 
3432
        {
 
3433
          pixel_region_get_row (region, region->x, region->y + y + 1, width,
 
3434
                                buf[2] + 1, 1);
 
3435
 
 
3436
          buf[2][0]         = buf[2][1];
 
3437
          buf[2][width + 1] = buf[2][width];
 
3438
        }
 
3439
      else
 
3440
        {
 
3441
          memcpy (buf[2], buf[1], width + 2);
 
3442
        }
 
3443
 
 
3444
      for (x = 0 ; x < width; x++)
 
3445
        {
 
3446
          gint min = 255;
 
3447
 
 
3448
          if (buf[0][x+1] < min) min = buf[0][x+1];
 
3449
          if (buf[1][x]   < min) min = buf[1][x];
 
3450
          if (buf[1][x+1] < min) min = buf[1][x+1];
 
3451
          if (buf[1][x+2] < min) min = buf[1][x+2];
 
3452
          if (buf[2][x+1] < min) min = buf[2][x+1];
 
3453
 
 
3454
          out[x] = min;
 
3455
        }
 
3456
 
 
3457
      pixel_region_set_row (region, region->x, region->y + y, width, out);
 
3458
 
 
3459
      rotate_pointers (buf, 3);
 
3460
    }
 
3461
 
 
3462
  for (i = 0; i < 3; i++)
 
3463
    g_free (buf[i]);
 
3464
 
 
3465
  g_free (out);
 
3466
}
 
3467
 
 
3468
/*  Dilate (radius 1 pixel) a mask (1bpp).  */
 
3469
void
 
3470
dilate_region (PixelRegion *region)
 
3471
{
 
3472
  gint      x, y;
 
3473
  gint      width;
 
3474
  gint      i;
 
3475
  guchar   *buf[3];
 
3476
  guchar   *out;
 
3477
 
 
3478
  width = region->w;
 
3479
 
 
3480
  for (i = 0; i < 3; i++)
 
3481
    buf[i] = g_new (guchar, width + 2);
 
3482
 
 
3483
  out = g_new (guchar, width);
 
3484
 
 
3485
  /* load top of image */
 
3486
  pixel_region_get_row (region, region->x, region->y, width, buf[0] + 1, 1);
 
3487
 
 
3488
  buf[0][0]         = buf[0][1];
 
3489
  buf[0][width + 1] = buf[0][width];
 
3490
 
 
3491
  memcpy (buf[1], buf[0], width + 2);
 
3492
 
 
3493
  for (y = 0; y < region->h; y++)
 
3494
    {
 
3495
      if (y + 1 < region->h)
 
3496
        {
 
3497
          pixel_region_get_row (region, region->x, region->y + y + 1, width,
 
3498
                                buf[2] + 1, 1);
 
3499
 
 
3500
          buf[2][0]         = buf[2][1];
 
3501
          buf[2][width + 1] = buf[2][width];
 
3502
        }
 
3503
      else
 
3504
        {
 
3505
          memcpy (buf[2], buf[1], width + 2);
 
3506
        }
 
3507
 
 
3508
      for (x = 0 ; x < width; x++)
 
3509
        {
 
3510
          gint max = 0;
 
3511
 
 
3512
          if (buf[0][x+1] > max) max = buf[0][x+1];
 
3513
          if (buf[1][x]   > max) max = buf[1][x];
 
3514
          if (buf[1][x+1] > max) max = buf[1][x+1];
 
3515
          if (buf[1][x+2] > max) max = buf[1][x+2];
 
3516
          if (buf[2][x+1] > max) max = buf[2][x+1];
 
3517
 
 
3518
          out[x] = max;
 
3519
        }
 
3520
 
 
3521
      pixel_region_set_row (region, region->x, region->y + y, width, out);
 
3522
 
 
3523
      rotate_pointers (buf, 3);
 
3524
    }
 
3525
 
 
3526
  for (i = 0; i < 3; i++)
 
3527
    g_free (buf[i]);
 
3528
 
 
3529
  g_free (out);
 
3530
}
 
3531
 
 
3532
/* Computes whether pixels in `buf[1]', if they are selected, have neighbouring
 
3533
   pixels that are unselected. Put result in `transition'. */
3985
3534
static void
3986
 
compute_transition (guchar  *transition,
3987
 
                    guchar **buf,
3988
 
                    gint32   width)
 
3535
compute_transition (guchar    *transition,
 
3536
                    guchar   **buf,
 
3537
                    gint32     width,
 
3538
                    gboolean   edge_lock)
3989
3539
{
3990
3540
  register gint32 x = 0;
3991
3541
 
3992
3542
  if (width == 1)
3993
3543
    {
3994
 
      if (buf[1][x] > 127 && (buf[0][x] < 128 || buf[2][x] < 128))
3995
 
        transition[x] = 255;
 
3544
      if (buf[1][0] > 127 && (buf[0][0] < 128 || buf[2][0] < 128))
 
3545
        transition[0] = 255;
3996
3546
      else
3997
 
        transition[x] = 0;
 
3547
        transition[0] = 0;
3998
3548
      return;
3999
3549
    }
4000
 
  if (buf[1][x] > 127)
 
3550
 
 
3551
  if (buf[1][0] > 127 && edge_lock)
4001
3552
    {
4002
 
      if ( buf[0][x] < 128 || buf[0][x + 1] < 128 ||
4003
 
           buf[1][x + 1] < 128 ||
4004
 
           buf[2][x] < 128 || buf[2][x + 1] < 128 )
4005
 
        transition[x] = 255;
 
3553
      /* The pixel to the left (outside of the canvas) is considered selected,
 
3554
         so we check if there are any unselected pixels in neighbouring pixels
 
3555
         _on_ the canvas. */
 
3556
      if (buf[0][x] < 128 || buf[0][x + 1] < 128 ||
 
3557
                             buf[1][x + 1] < 128 ||
 
3558
          buf[2][x] < 128 || buf[2][x + 1] < 128 )
 
3559
        {
 
3560
          transition[x] = 255;
 
3561
        }
4006
3562
      else
4007
 
        transition[x] = 0;
 
3563
        {
 
3564
          transition[x] = 0;
 
3565
        }
 
3566
    }
 
3567
  else if (buf[1][0] > 127 && !edge_lock)
 
3568
    {
 
3569
      /* We must not care about neighbouring pixels on the image canvas since
 
3570
         there always are unselected pixels to the left (which is outside of
 
3571
         the image canvas). */
 
3572
      transition[x] = 255;
4008
3573
    }
4009
3574
  else
4010
 
    transition[x] = 0;
 
3575
    {
 
3576
      transition[x] = 0;
 
3577
    }
 
3578
 
4011
3579
  for (x = 1; x < width - 1; x++)
4012
3580
    {
4013
3581
      if (buf[1][x] >= 128)
4014
3582
        {
4015
3583
          if (buf[0][x - 1] < 128 || buf[0][x] < 128 || buf[0][x + 1] < 128 ||
4016
 
              buf[1][x - 1] < 128           ||          buf[1][x + 1] < 128 ||
 
3584
              buf[1][x - 1] < 128 ||                    buf[1][x + 1] < 128 ||
4017
3585
              buf[2][x - 1] < 128 || buf[2][x] < 128 || buf[2][x + 1] < 128)
4018
3586
            transition[x] = 255;
4019
3587
          else
4020
3588
            transition[x] = 0;
4021
3589
        }
4022
3590
      else
4023
 
        transition[x] = 0;
 
3591
        {
 
3592
          transition[x] = 0;
 
3593
        }
4024
3594
    }
4025
 
  if (buf[1][x] >= 128)
 
3595
 
 
3596
  if (buf[1][width - 1] >= 128 && edge_lock)
4026
3597
    {
 
3598
      /* The pixel to the right (outside of the canvas) is considered selected,
 
3599
         so we check if there are any unselected pixels in neighbouring pixels
 
3600
         _on_ the canvas. */
4027
3601
      if ( buf[0][x - 1] < 128 || buf[0][x] < 128 ||
4028
3602
           buf[1][x - 1] < 128 ||
4029
3603
           buf[2][x - 1] < 128 || buf[2][x] < 128)
4030
 
        transition[x] = 255;
 
3604
        {
 
3605
          transition[width - 1] = 255;
 
3606
        }
4031
3607
      else
4032
 
        transition[x] = 0;
 
3608
        {
 
3609
          transition[width - 1] = 0;
 
3610
        }
 
3611
    }
 
3612
  else if (buf[1][width - 1] >= 128 && !edge_lock)
 
3613
    {
 
3614
      /* We must not care about neighbouring pixels on the image canvas since
 
3615
         there always are unselected pixels to the right (which is outside of
 
3616
         the image canvas). */
 
3617
      transition[width - 1] = 255;
4033
3618
    }
4034
3619
  else
4035
 
    transition[x] = 0;
 
3620
    {
 
3621
      transition[width - 1] = 0;
 
3622
    }
4036
3623
}
4037
3624
 
4038
3625
void
4039
3626
border_region (PixelRegion *src,
4040
3627
               gint16       xradius,
4041
 
               gint16       yradius)
 
3628
               gint16       yradius,
 
3629
               gboolean     feather,
 
3630
               gboolean     edge_lock)
4042
3631
{
4043
3632
  /*
4044
3633
     This function has no bugs, but if you imagine some you can
4045
3634
     blame them on jaycox@gimp.org
4046
3635
  */
 
3636
 
4047
3637
  register gint32 i, j, x, y;
 
3638
 
 
3639
  /* A cache used in the algorithm as it works its way down. `buf[1]' is the
 
3640
     current row. Thus, at algorithm initialization, `buf[0]' represents the
 
3641
     row 'above' the first row of the region. */
4048
3642
  guchar  *buf[3];
 
3643
 
 
3644
  /* The resulting selection is calculated row by row, and this buffer holds the
 
3645
     output for each individual row, on each iteration. */
4049
3646
  guchar  *out;
 
3647
 
 
3648
  /* Keeps track of transitional pixels (pixels that are selected and have
 
3649
     unselected neighbouring pixels). */
 
3650
  guchar **transition;
 
3651
 
 
3652
  /* TODO: Figure out role clearly in algorithm. */
4050
3653
  gint16  *max;
 
3654
 
 
3655
  /* TODO: Figure out role clearly in algorithm. */
4051
3656
  guchar **density;
4052
 
  guchar **transition;
 
3657
 
4053
3658
  guchar   last_max;
4054
3659
  gint16   last_index;
4055
3660
 
4059
3664
      return;
4060
3665
    }
4061
3666
 
 
3667
  /* A border without a width is no border at all; return an empty region. */
4062
3668
  if (xradius == 0 || yradius == 0)
4063
3669
    {
4064
3670
      guchar color[] = "\0\0\0\0";
4067
3673
      return;
4068
3674
    }
4069
3675
 
4070
 
  if (xradius == 1 && yradius == 1) /* optimize this case specifically */
 
3676
  /* optimize this case specifically */
 
3677
  if (xradius == 1 && yradius == 1)
4071
3678
    {
4072
3679
      guchar *transition;
4073
3680
      guchar *source[3];
4077
3684
 
4078
3685
      transition = g_new (guchar, src->w);
4079
3686
 
4080
 
      pixel_region_get_row (src, src->x, src->y + 0, src->w, source[0], 1);
4081
 
      memcpy (source[1], source[0], src->w);
 
3687
      /* With `edge_lock', initialize row above image as selected, otherwise,
 
3688
         initialize as unselected. */
 
3689
      memset (source[0], edge_lock ? 255 : 0, src->w);
 
3690
 
 
3691
      pixel_region_get_row (src, src->x, src->y + 0, src->w, source[1], 1);
 
3692
 
4082
3693
      if (src->h > 1)
4083
3694
        pixel_region_get_row (src, src->x, src->y + 1, src->w, source[2], 1);
4084
3695
      else
4085
3696
        memcpy (source[2], source[1], src->w);
4086
3697
 
4087
 
      compute_transition (transition, source, src->w);
 
3698
      compute_transition (transition, source, src->w, edge_lock);
4088
3699
      pixel_region_set_row (src, src->x, src->y , src->w, transition);
4089
3700
 
4090
3701
      for (y = 1; y < src->h; y++)
4091
3702
        {
4092
3703
          rotate_pointers (source, 3);
 
3704
 
4093
3705
          if (y + 1 < src->h)
4094
 
            pixel_region_get_row (src, src->x, src->y + y + 1, src->w,
4095
 
                                  source[2], 1);
 
3706
            {
 
3707
              pixel_region_get_row (src, src->x, src->y + y + 1, src->w,
 
3708
                                    source[2], 1);
 
3709
            }
4096
3710
          else
4097
 
            memcpy(source[2], source[1], src->w);
4098
 
          compute_transition (transition, source, src->w);
 
3711
            {
 
3712
              /* Depending on `edge_lock', set the row below the image as either
 
3713
                 selected or non-selected. */
 
3714
              memset(source[2], edge_lock ? 255 : 0, src->w);
 
3715
            }
 
3716
 
 
3717
          compute_transition (transition, source, src->w, edge_lock);
4099
3718
          pixel_region_set_row (src, src->x, src->y + y, src->w, transition);
4100
3719
        }
4101
3720
 
4102
3721
      for (i = 0; i < 3; i++)
4103
3722
        g_free (source[i]);
 
3723
 
4104
3724
      g_free (transition);
 
3725
 
 
3726
      /* Finnished handling the radius = 1 special case, return here. */
4105
3727
      return;
4106
3728
    }
4107
3729
 
4108
3730
  max = g_new (gint16, src->w + 2 * xradius);
 
3731
 
4109
3732
  for (i = 0; i < (src->w + 2 * xradius); i++)
4110
3733
    max[i] = yradius + 2;
 
3734
 
4111
3735
  max += xradius;
4112
3736
 
4113
3737
  for (i = 0; i < 3; i++)
4114
3738
    buf[i] = g_new (guchar, src->w);
4115
3739
 
4116
3740
  transition = g_new (guchar *, yradius + 1);
 
3741
 
4117
3742
  for (i = 0; i < yradius + 1; i++)
4118
3743
    {
4119
3744
      transition[i] = g_new (guchar, src->w + 2 * xradius);
4120
3745
      memset(transition[i], 0, src->w + 2 * xradius);
4121
3746
      transition[i] += xradius;
4122
3747
    }
 
3748
 
4123
3749
  out = g_new (guchar, src->w);
 
3750
 
4124
3751
  density = g_new (guchar *, 2 * xradius + 1);
4125
3752
  density += xradius;
4126
3753
 
4127
 
  for (x = 0; x < (xradius + 1); x++) /* allocate density[][] */
 
3754
   /* allocate density[][] */
 
3755
  for (x = 0; x < (xradius + 1); x++)
4128
3756
    {
4129
3757
      density[ x]  = g_new (guchar, 2 * yradius + 1);
4130
3758
      density[ x] += yradius;
4131
3759
      density[-x]  = density[x];
4132
3760
    }
4133
 
  for (x = 0; x < (xradius + 1); x++) /* compute density[][] */
 
3761
 
 
3762
  /* compute density[][] */
 
3763
  for (x = 0; x < (xradius + 1); x++)
4134
3764
    {
4135
3765
      register gdouble tmpx, tmpy, dist;
4136
3766
      guchar a;
4150
3780
            tmpy = y + 0.5;
4151
3781
          else
4152
3782
            tmpy = 0.0;
 
3783
 
4153
3784
          dist = ((tmpy * tmpy) / (yradius * yradius) +
4154
3785
                  (tmpx * tmpx) / (xradius * xradius));
 
3786
 
4155
3787
          if (dist < 1.0)
4156
 
            a = 255 * (1.0 - sqrt (dist));
 
3788
            {
 
3789
              if (feather)
 
3790
                a = 255 * (1.0 - sqrt (dist));
 
3791
              else
 
3792
                a = 255;
 
3793
            }
4157
3794
          else
4158
 
            a = 0;
 
3795
            {
 
3796
              a = 0;
 
3797
            }
 
3798
 
4159
3799
          density[ x][ y] = a;
4160
3800
          density[ x][-y] = a;
4161
3801
          density[-x][ y] = a;
4162
3802
          density[-x][-y] = a;
4163
3803
        }
4164
3804
    }
4165
 
  pixel_region_get_row (src, src->x, src->y + 0, src->w, buf[0], 1);
4166
 
  memcpy (buf[1], buf[0], src->w);
 
3805
 
 
3806
  /* Since the algorithm considerers `buf[0]' to be 'over' the row currently
 
3807
     calculated, we must start with `buf[0]' as non-selected if there is no
 
3808
     `edge_lock. If there is an 'edge_lock', initialize the first row to
 
3809
     'selected'. Refer to bug #350009. */
 
3810
  memset (buf[0], edge_lock ? 255 : 0, src->w);
 
3811
  pixel_region_get_row (src, src->x, src->y + 0, src->w, buf[1], 1);
 
3812
 
4167
3813
  if (src->h > 1)
4168
3814
    pixel_region_get_row (src, src->x, src->y + 1, src->w, buf[2], 1);
4169
3815
  else
4170
3816
    memcpy (buf[2], buf[1], src->w);
4171
 
  compute_transition (transition[1], buf, src->w);
4172
 
 
4173
 
  for (y = 1; y < yradius && y + 1 < src->h; y++) /* set up top of image */
 
3817
 
 
3818
  compute_transition (transition[1], buf, src->w, edge_lock);
 
3819
 
 
3820
   /* set up top of image */
 
3821
  for (y = 1; y < yradius && y + 1 < src->h; y++)
4174
3822
    {
4175
3823
      rotate_pointers (buf, 3);
4176
3824
      pixel_region_get_row (src, src->x, src->y + y + 1, src->w, buf[2], 1);
4177
 
      compute_transition (transition[y + 1], buf, src->w);
 
3825
      compute_transition (transition[y + 1], buf, src->w, edge_lock);
4178
3826
    }
4179
 
  for (x = 0; x < src->w; x++) /* set up max[] for top of image */
 
3827
 
 
3828
  /* set up max[] for top of image */
 
3829
  for (x = 0; x < src->w; x++)
4180
3830
    {
4181
3831
      max[x] = -(yradius + 7);
 
3832
 
4182
3833
      for (j = 1; j < yradius + 1; j++)
4183
3834
        if (transition[j][x])
4184
3835
          {
4186
3837
            break;
4187
3838
          }
4188
3839
    }
4189
 
  for (y = 0; y < src->h; y++) /* main calculation loop */
 
3840
 
 
3841
  /* main calculation loop */
 
3842
  for (y = 0; y < src->h; y++)
4190
3843
    {
4191
3844
      rotate_pointers (buf, 3);
4192
3845
      rotate_pointers (transition, yradius + 1);
 
3846
 
4193
3847
      if (y < src->h - (yradius + 1))
4194
3848
        {
4195
3849
          pixel_region_get_row (src, src->x, src->y + y + yradius + 1, src->w,
4196
3850
                                buf[2], 1);
4197
 
          compute_transition (transition[yradius], buf, src->w);
 
3851
          compute_transition (transition[yradius], buf, src->w, edge_lock);
4198
3852
        }
4199
3853
      else
4200
 
        memcpy (transition[yradius], transition[yradius - 1], src->w);
 
3854
        {
 
3855
          if (edge_lock)
 
3856
            {
 
3857
              memcpy (transition[yradius], transition[yradius - 1], src->w);
 
3858
            }
 
3859
          else
 
3860
            {
 
3861
              /* No edge lock, set everything 'below canvas' as seen from the
 
3862
                 algorithm as unselected. */
 
3863
              memset (buf[2], 0, src->w);
 
3864
              compute_transition (transition[yradius], buf, src->w, edge_lock);
 
3865
            }
 
3866
        }
4201
3867
 
4202
 
      for (x = 0; x < src->w; x++) /* update max array */
 
3868
       /* update max array */
 
3869
      for (x = 0; x < src->w; x++)
4203
3870
        {
4204
3871
          if (max[x] < 1)
4205
3872
            {
4211
3878
                    max[x]--;
4212
3879
                }
4213
3880
              else
4214
 
                if (transition[-max[x]][x])
4215
 
                  max[x] = -max[x];
4216
 
                else if (transition[-max[x] + 1][x])
4217
 
                  max[x] = -max[x] + 1;
4218
 
                else
4219
 
                  max[x]--;
 
3881
                {
 
3882
                  if (transition[-max[x]][x])
 
3883
                    max[x] = -max[x];
 
3884
                  else if (transition[-max[x] + 1][x])
 
3885
                    max[x] = -max[x] + 1;
 
3886
                  else
 
3887
                    max[x]--;
 
3888
                }
4220
3889
            }
4221
3890
          else
4222
 
            max[x]--;
 
3891
            {
 
3892
              max[x]--;
 
3893
            }
 
3894
 
4223
3895
          if (max[x] < -yradius - 1)
4224
3896
            max[x] = -yradius - 1;
4225
3897
        }
 
3898
 
4226
3899
      last_max =  max[0][density[-1]];
4227
3900
      last_index = 1;
4228
 
      for (x = 0 ; x < src->w; x++) /* render scan line */
 
3901
 
 
3902
       /* render scan line */
 
3903
      for (x = 0 ; x < src->w; x++)
4229
3904
        {
4230
3905
          last_index--;
 
3906
 
4231
3907
          if (last_index >= 0)
4232
3908
            {
4233
3909
              last_max = 0;
 
3910
 
4234
3911
              for (i = xradius; i >= 0; i--)
4235
3912
                if (max[x + i] <= yradius && max[x + i] >= -yradius &&
4236
3913
                    density[i][max[x+i]] > last_max)
4238
3915
                    last_max = density[i][max[x + i]];
4239
3916
                    last_index = i;
4240
3917
                  }
 
3918
 
4241
3919
              out[x] = last_max;
4242
3920
            }
4243
3921
          else
4244
3922
            {
4245
3923
              last_max = 0;
 
3924
 
4246
3925
              for (i = xradius; i >= -xradius; i--)
4247
3926
                if (max[x + i] <= yradius && max[x + i] >= -yradius &&
4248
3927
                    density[i][max[x + i]] > last_max)
4250
3929
                    last_max = density[i][max[x + i]];
4251
3930
                    last_index = i;
4252
3931
                  }
 
3932
 
4253
3933
              out[x] = last_max;
4254
3934
            }
 
3935
 
4255
3936
          if (last_max == 0)
4256
3937
            {
4257
3938
              for (i = x + 1; i < src->w; i++)
4259
3940
                  if (max[i] >= -yradius)
4260
3941
                    break;
4261
3942
                }
 
3943
 
4262
3944
              if (i - x > xradius)
4263
3945
                {
4264
3946
                  for (; x < i - xradius; x++)
4265
3947
                    out[x] = 0;
 
3948
 
4266
3949
                  x--;
4267
3950
                }
 
3951
 
4268
3952
              last_index = xradius;
4269
3953
            }
4270
3954
        }
 
3955
 
4271
3956
      pixel_region_set_row (src, src->x, src->y + y, src->w, out);
4272
3957
    }
 
3958
 
4273
3959
  g_free (out);
4274
3960
 
4275
3961
  for (i = 0; i < 3; i++)
4283
3969
      transition[i] -= xradius;
4284
3970
      g_free (transition[i]);
4285
3971
    }
 
3972
 
4286
3973
  g_free (transition);
4287
3974
 
4288
3975
  for (i = 0; i < xradius + 1 ; i++)
4290
3977
      density[i] -= yradius;
4291
3978
      g_free (density[i]);
4292
3979
    }
 
3980
 
4293
3981
  density -= xradius;
4294
3982
  g_free (density);
4295
3983
}
4298
3986
swap_region (PixelRegion *src,
4299
3987
             PixelRegion *dest)
4300
3988
{
4301
 
  gint h;
4302
 
  gint length;
4303
 
  guchar * s, * d;
4304
 
  void * pr;
 
3989
  gpointer pr;
4305
3990
 
4306
3991
  for (pr = pixel_regions_register (2, src, dest);
4307
3992
       pr != NULL;
4308
3993
       pr = pixel_regions_process (pr))
4309
3994
    {
4310
 
      s = src->data;
4311
 
      h = src->h;
4312
 
      d = dest->data;
4313
 
      length = src->w * src->bytes;
 
3995
      guchar *s      = src->data;
 
3996
      guchar *d      = dest->data;
 
3997
      gint    pixels = src->w * src->bytes;
 
3998
      gint    h      = src->h;
4314
3999
 
4315
4000
      while (h --)
4316
4001
        {
4317
 
          swap_pixels (s, d, length);
 
4002
          swap_pixels (s, d, pixels);
 
4003
 
4318
4004
          s += src->rowstride;
4319
4005
          d += dest->rowstride;
4320
4006
        }
4322
4008
}
4323
4009
 
4324
4010
 
 
4011
/* Computes whether pixels in `buf[1]' have neighbouring pixels that are
 
4012
   unselected. Put result in `transition'. */
4325
4013
static void
4326
4014
apply_mask_to_sub_region (gint        *opacityp,
4327
4015
                          PixelRegion *src,
4328
4016
                          PixelRegion *mask)
4329
4017
{
4330
 
  gint    h;
4331
 
  guchar *s;
4332
 
  guchar *m;
4333
 
  guint   opacity = *opacityp;
4334
 
 
4335
 
  s = src->data;
4336
 
  m = mask->data;
4337
 
  h = src->h;
4338
 
 
4339
 
  while (h --)
 
4018
  guchar       *s       = src->data;
 
4019
  const guchar *m       = mask->data;
 
4020
  gint          h       = src->h;
 
4021
  guint         opacity = *opacityp;
 
4022
 
 
4023
  while (h--)
4340
4024
    {
4341
4025
      apply_mask_to_alpha_channel (s, m, opacity, src->w, src->bytes);
4342
4026
      s += src->rowstride;
4349
4033
                      PixelRegion *mask,
4350
4034
                      guint        opacity)
4351
4035
{
4352
 
  pixel_regions_process_parallel ((p_func)apply_mask_to_sub_region,
 
4036
  pixel_regions_process_parallel ((PixelProcessorFunc)
 
4037
                                  apply_mask_to_sub_region,
4353
4038
                                  &opacity, 2, src, mask);
4354
4039
}
4355
4040
 
4359
4044
                                     PixelRegion *src,
4360
4045
                                     PixelRegion *mask)
4361
4046
{
4362
 
  gint    h;
4363
 
  guchar *s;
4364
 
  guchar *m;
4365
 
  guint   opacity = *opacityp;
4366
 
 
4367
 
  s = src->data;
4368
 
  m = mask->data;
4369
 
  h = src->h;
4370
 
 
4371
 
  while (h --)
 
4047
  guchar       *s       = src->data;
 
4048
  const guchar *m       = mask->data;
 
4049
  gint          h       = src->h;
 
4050
  guint         opacity = *opacityp;
 
4051
 
 
4052
  while (h--)
4372
4053
    {
4373
 
      combine_mask_and_alpha_channel_stipple (s, m, opacity, src->w, src->bytes);
 
4054
      combine_mask_and_alpha_channel_stipple (s, m, opacity,
 
4055
                                              src->w, src->bytes);
4374
4056
      s += src->rowstride;
4375
4057
      m += mask->rowstride;
4376
4058
    }
4382
4064
                                    PixelRegion *src,
4383
4065
                                    PixelRegion *mask)
4384
4066
{
4385
 
  gint    h;
4386
 
  guchar *s;
4387
 
  guchar *m;
4388
 
  guint   opacity = *opacityp;
4389
 
 
4390
 
  s = src->data;
4391
 
  m = mask->data;
4392
 
  h = src->h;
4393
 
 
4394
 
  while (h --)
 
4067
  guchar       *s       = src->data;
 
4068
  const guchar *m       = mask->data;
 
4069
  gint          h       = src->h;
 
4070
  guint         opacity = *opacityp;
 
4071
 
 
4072
  while (h--)
4395
4073
    {
4396
4074
      combine_mask_and_alpha_channel_stroke (s, m, opacity, src->w, src->bytes);
4397
4075
      s += src->rowstride;
4407
4085
                         gboolean     stipple)
4408
4086
{
4409
4087
  if (stipple)
4410
 
    pixel_regions_process_parallel ((p_func)combine_mask_and_sub_region_stipple,
 
4088
    pixel_regions_process_parallel ((PixelProcessorFunc)
 
4089
                                    combine_mask_and_sub_region_stipple,
4411
4090
                                    &opacity, 2, src, mask);
4412
4091
  else
4413
 
    pixel_regions_process_parallel ((p_func)combine_mask_and_sub_region_stroke,
 
4092
    pixel_regions_process_parallel ((PixelProcessorFunc)
 
4093
                                    combine_mask_and_sub_region_stroke,
4414
4094
                                    &opacity, 2, src, mask);
4415
4095
}
4416
4096
 
4419
4099
copy_gray_to_region (PixelRegion *src,
4420
4100
                     PixelRegion *dest)
4421
4101
{
4422
 
  gint    h;
4423
 
  guchar *s;
4424
 
  guchar *d;
4425
 
  void   *pr;
 
4102
  gpointer pr;
4426
4103
 
4427
4104
  for (pr = pixel_regions_register (2, src, dest);
4428
4105
       pr != NULL;
4429
4106
       pr = pixel_regions_process (pr))
4430
4107
    {
4431
 
      s = src->data;
4432
 
      d = dest->data;
4433
 
      h = src->h;
 
4108
      const guchar *s = src->data;
 
4109
      guchar       *d = dest->data;
 
4110
      gint          h = src->h;
4434
4111
 
4435
 
      while (h --)
 
4112
      while (h--)
4436
4113
        {
4437
4114
          copy_gray_to_inten_a_pixels (s, d, src->w, dest->bytes);
 
4115
 
4438
4116
          s += src->rowstride;
4439
4117
          d += dest->rowstride;
4440
4118
        }
4446
4124
                PixelRegion *dest,
4447
4125
                guint        pixel)
4448
4126
{
4449
 
  gint    h;
4450
 
  guchar *s;
4451
 
  guchar *d;
4452
 
  void   *pr;
4453
 
 
4454
 
  for (pr = pixel_regions_register (2, src, dest);
4455
 
       pr != NULL;
4456
 
       pr = pixel_regions_process (pr))
4457
 
    {
4458
 
      s = src->data;
4459
 
      d = dest->data;
4460
 
      h = src->h;
4461
 
 
4462
 
      while (h --)
4463
 
        {
4464
 
          component_pixels (s, d, src->w, src->bytes, pixel);
 
4127
  gpointer pr;
 
4128
 
 
4129
  for (pr = pixel_regions_register (2, src, dest);
 
4130
       pr != NULL;
 
4131
       pr = pixel_regions_process (pr))
 
4132
    {
 
4133
      const guchar *s = src->data;
 
4134
      guchar       *d = dest->data;
 
4135
      gint          h = src->h;
 
4136
 
 
4137
      while (h--)
 
4138
        {
 
4139
          copy_component_pixels (s, d, src->w, src->bytes, pixel);
 
4140
          s += src->rowstride;
 
4141
          d += dest->rowstride;
 
4142
        }
 
4143
    }
 
4144
}
 
4145
 
 
4146
void
 
4147
copy_color (PixelRegion *src,
 
4148
            PixelRegion *dest)
 
4149
{
 
4150
  gpointer pr;
 
4151
 
 
4152
  for (pr = pixel_regions_register (2, src, dest);
 
4153
       pr != NULL;
 
4154
       pr = pixel_regions_process (pr))
 
4155
    {
 
4156
      const guchar *s = src->data;
 
4157
      guchar       *d = dest->data;
 
4158
      gint          h = src->h;
 
4159
 
 
4160
      while (h--)
 
4161
        {
 
4162
          copy_color_pixels (s, d, src->w, src->bytes);
4465
4163
          s += src->rowstride;
4466
4164
          d += dest->rowstride;
4467
4165
        }
4473
4171
  guint                 opacity;
4474
4172
  GimpLayerModeEffects  mode;
4475
4173
  const gboolean       *affect;
4476
 
  InitialMode                type;
 
4174
  InitialMode           type;
4477
4175
  guchar               *data;
4478
4176
};
4479
4177
 
4480
 
void
 
4178
static void
4481
4179
initial_sub_region (struct initial_regions_struct *st,
4482
4180
                    PixelRegion                   *src,
4483
4181
                    PixelRegion                   *dest,
4610
4308
            }
4611
4309
          else
4612
4310
            {
4613
 
              initial_inten_a_pixels (s, d, m, opacity, affect, src->w, src->bytes);
 
4311
              initial_inten_a_pixels (s, d, m,
 
4312
                                      opacity, affect, src->w, src->bytes);
4614
4313
            }
4615
4314
          break;
4616
4315
        }
4640
4339
  st.type    = type;
4641
4340
  st.data    = data;
4642
4341
 
4643
 
  pixel_regions_process_parallel ((p_func)initial_sub_region, &st, 3,
4644
 
                                    src, dest, mask);
 
4342
  pixel_regions_process_parallel ((PixelProcessorFunc) initial_sub_region,
 
4343
                                  &st, 3, src, dest, mask);
4645
4344
}
4646
4345
 
4647
4346
struct combine_regions_struct
4703
4402
  guchar               *data;
4704
4403
  guint                 opacity;
4705
4404
  guint                 layer_mode_opacity;
4706
 
  guchar               *layer_mode_mask;
 
4405
  const guchar         *layer_mode_mask;
4707
4406
  GimpLayerModeEffects  mode;
4708
4407
  const gboolean       *affect;
4709
4408
  guint                 h;
4711
4410
  CombinationMode       type;
4712
4411
  gboolean              mode_affect = FALSE;
4713
4412
  guchar               *s, *s1, *s2;
4714
 
  guchar               *d, *m;
 
4413
  guchar               *d;
 
4414
  const guchar         *m;
4715
4415
  guchar               *buf;
4716
4416
  gboolean              opacity_quickskip_possible;
4717
4417
  gboolean              transparency_quickskip_possible;
4790
4490
      /*  apply the paint mode based on the combination type & mode  */
4791
4491
      switch (type)
4792
4492
        {
 
4493
        case COMBINE_INTEN_A_INDEXED:
4793
4494
        case COMBINE_INTEN_A_INDEXED_A:
4794
4495
        case COMBINE_INTEN_A_CHANNEL_MASK:
4795
4496
        case COMBINE_INTEN_A_CHANNEL_SELECTION:
4842
4543
                ctx.dissolve.y       = src1->y + h;
4843
4544
                ctx.dissolve.opacity = layer_mode_opacity;
4844
4545
 
4845
 
                mode_affect = gimp_composite_operation_effects[mode].affect_opacity;
 
4546
                mode_affect =
 
4547
                  gimp_composite_operation_effects[mode].affect_opacity;
 
4548
 
4846
4549
                gimp_composite_dispatch (&ctx);
 
4550
 
4847
4551
                s = ctx.D;
4848
4552
                combine = (ctx.combine == NO_COMBINATION) ? type : ctx.combine;
4849
4553
              }
4903
4607
                                                  src1->bytes);
4904
4608
          break;
4905
4609
 
 
4610
        case COMBINE_INTEN_A_INDEXED:
 
4611
          /*  assume the data passed to this procedure is the
 
4612
           *  indexed layer's colormap
 
4613
           */
 
4614
          combine_inten_a_and_indexed_pixels (s1, s2, d, m, data, opacity,
 
4615
                                              src1->w, dest->bytes);
 
4616
          break;
 
4617
 
4906
4618
        case COMBINE_INTEN_A_INDEXED_A:
4907
4619
          /*  assume the data passed to this procedure is the
4908
4620
           *  indexed layer's colormap
5056
4768
      has_alpha1 = has_alpha2 = FALSE;
5057
4769
      break;
5058
4770
    case COMBINE_INTEN_A_INTEN:
 
4771
    case COMBINE_INTEN_A_INDEXED:
5059
4772
      has_alpha1 = TRUE;
5060
4773
      has_alpha2 = FALSE;
5061
4774
      break;
5117
4830
 
5118
4831
  /* Start the actual processing.
5119
4832
   */
5120
 
  pixel_regions_process_parallel ((p_func)combine_sub_region, &st, 4,
5121
 
                                    src1, src2, dest, mask);
 
4833
  pixel_regions_process_parallel ((PixelProcessorFunc) combine_sub_region,
 
4834
                                  &st, 4, src1, src2, dest, mask);
5122
4835
}
5123
4836
 
5124
4837
void
5131
4844
                         const gboolean  *affect,
5132
4845
                         CombinationMode  type)
5133
4846
{
5134
 
  guint    h;
5135
 
  guchar  *s1;
5136
 
  guchar  *s2;
5137
 
  guchar  *d;
5138
 
  guchar  *m;
5139
4847
  gpointer pr;
5140
4848
 
5141
4849
  for (pr = pixel_regions_register (4, src1, src2, dest, mask);
5142
4850
       pr != NULL;
5143
4851
       pr = pixel_regions_process (pr))
5144
4852
    {
5145
 
      s1 = src1->data;
5146
 
      s2 = src2->data;
5147
 
      d = dest->data;
5148
 
      m = mask->data;
 
4853
      const guchar  *s1 = src1->data;
 
4854
      const guchar  *s2 = src2->data;
 
4855
      guchar        *d  = dest->data;
 
4856
      const guchar  *m  = mask->data;
 
4857
      guint          h;
5149
4858
 
5150
4859
      for (h = 0; h < src1->h; h++)
5151
4860
        {
5164
4873
}
5165
4874
 
5166
4875
static void
5167
 
apply_layer_mode_replace (guchar         *src1,
5168
 
                          guchar         *src2,
 
4876
apply_layer_mode_replace (const guchar   *src1,
 
4877
                          const guchar   *src2,
5169
4878
                          guchar         *dest,
5170
 
                          guchar         *mask,
 
4879
                          const guchar   *mask,
5171
4880
                          gint            x,
5172
4881
                          gint            y,
5173
4882
                          guint           opacity,
5176
4885
                          guint           bytes2,
5177
4886
                          const gboolean *affect)
5178
4887
{
5179
 
  replace_pixels (src1, src2, dest, mask, length, opacity, affect, bytes1, bytes2);
 
4888
  replace_pixels (src1, src2, dest, mask, length,
 
4889
                  opacity, affect, bytes1, bytes2);
5180
4890
}