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

« back to all changes in this revision

Viewing changes to app/base/temp-buf.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
18
18
 
19
19
#include "config.h"
20
20
 
21
 
#include <errno.h>
22
 
#include <stdlib.h>
23
 
#include <stdio.h>
24
21
#include <string.h>
25
 
#include <sys/types.h>
26
 
#ifdef HAVE_UNISTD_H
27
 
#include <unistd.h>
28
 
#endif
29
22
 
30
23
#include <glib-object.h>
31
24
 
32
 
#ifdef G_OS_WIN32
33
 
#include <process.h>            /* For _getpid() */
34
 
#endif
35
 
 
36
25
#include "libgimpbase/gimpbase.h"
37
26
#include "libgimpcolor/gimpcolor.h"
38
27
 
39
28
#include "base-types.h"
40
29
 
41
 
#include "config/gimpbaseconfig.h"
42
 
#include "config/gimpconfig-path.h"
 
30
#include "paint-funcs/paint-funcs.h"
43
31
 
44
32
#include "pixel-region.h"
45
33
#include "temp-buf.h"
46
34
 
47
 
#include "paint-funcs/paint-funcs.h"
48
 
 
49
 
 
50
 
static guchar * temp_buf_allocate (guint    size);
51
 
static void     temp_buf_to_color (TempBuf *src_buf,
52
 
                                   TempBuf *dest_buf);
53
 
static void     temp_buf_to_gray  (TempBuf *src_buf,
54
 
                                   TempBuf *dest_buf);
55
 
 
56
 
 
57
 
#ifdef __GNUC__
58
 
#warning FIXME: extern GimpBaseConfig *base_config;
59
 
#endif
60
 
extern GimpBaseConfig *base_config;
61
 
 
62
 
 
63
 
/*  Memory management  */
64
 
 
65
 
static guchar *
66
 
temp_buf_allocate (guint size)
67
 
{
68
 
  return g_new (guchar, size);
69
 
}
70
 
 
71
 
 
72
 
/*  The conversion routines  */
73
 
 
74
 
static void
75
 
temp_buf_to_color (TempBuf *src_buf,
76
 
                   TempBuf *dest_buf)
77
 
{
78
 
  guchar *src;
79
 
  guchar *dest;
80
 
  glong   num_pixels;
81
 
 
82
 
  src  = temp_buf_data (src_buf);
83
 
  dest = temp_buf_data (dest_buf);
84
 
 
85
 
  num_pixels = src_buf->width * src_buf->height;
86
 
 
87
 
  switch (dest_buf->bytes)
88
 
    {
89
 
    case 3:
90
 
      g_return_if_fail (src_buf->bytes == 1);
91
 
      while (num_pixels--)
92
 
        {
93
 
          guchar tmpch;
94
 
          *dest++ = tmpch = *src++;
95
 
          *dest++ = tmpch;
96
 
          *dest++ = tmpch;
97
 
        }
98
 
      break;
99
 
 
100
 
    case 4:
101
 
      g_return_if_fail (src_buf->bytes == 2);
102
 
      while (num_pixels--)
103
 
        {
104
 
          guchar tmpch;
105
 
          *dest++ = tmpch = *src++;
106
 
          *dest++ = tmpch;
107
 
          *dest++ = tmpch;
108
 
 
109
 
          *dest++ = *src++;  /* alpha channel */
110
 
        }
111
 
      break;
112
 
 
113
 
    default:
114
 
      g_return_if_reached ();
115
 
      break;
116
 
    }
117
 
}
118
 
 
119
 
static void
120
 
temp_buf_to_gray (TempBuf *src_buf,
121
 
                  TempBuf *dest_buf)
122
 
{
123
 
  guchar *src;
124
 
  guchar *dest;
125
 
  glong   num_pixels;
126
 
  gfloat  pix;
127
 
 
128
 
  src  = temp_buf_data (src_buf);
129
 
  dest = temp_buf_data (dest_buf);
130
 
 
131
 
  num_pixels = src_buf->width * src_buf->height;
132
 
 
133
 
  switch (dest_buf->bytes)
134
 
    {
135
 
    case 1:
136
 
      g_return_if_fail (src_buf->bytes == 3);
137
 
      while (num_pixels--)
138
 
        {
139
 
          pix = GIMP_RGB_INTENSITY (src[0], src[1], src[2]) + 0.5;
140
 
          *dest++ = (guchar) pix;
141
 
 
142
 
          src += 3;
143
 
        }
144
 
      break;
145
 
 
146
 
    case 2:
147
 
      g_return_if_fail (src_buf->bytes == 4);
148
 
      while (num_pixels--)
149
 
        {
150
 
          pix = GIMP_RGB_INTENSITY (src[0], src[1], src[2]) + 0.5;
151
 
          *dest++ = (guchar) pix;
152
 
 
153
 
          *dest++ = src[3];  /* alpha channel */
154
 
 
155
 
          src += 4;
156
 
        }
157
 
      break;
158
 
 
159
 
    default:
160
 
      g_return_if_reached ();
161
 
      break;
162
 
    }
163
 
}
 
35
 
 
36
static void  temp_buf_to_color (TempBuf *src_buf,
 
37
                                TempBuf *dest_buf);
 
38
static void  temp_buf_to_gray  (TempBuf *src_buf,
 
39
                                TempBuf *dest_buf);
 
40
 
164
41
 
165
42
TempBuf *
166
 
temp_buf_new (gint    width,
167
 
              gint    height,
168
 
              gint    bytes,
169
 
              gint    x,
170
 
              gint    y,
171
 
              guchar *col)
 
43
temp_buf_new (gint          width,
 
44
              gint          height,
 
45
              gint          bytes,
 
46
              gint          x,
 
47
              gint          y,
 
48
              const guchar *color)
172
49
{
173
 
  glong    i;
174
 
  guchar  *data;
175
50
  TempBuf *temp;
176
51
 
177
52
  g_return_val_if_fail (width > 0 && height > 0, NULL);
179
54
 
180
55
  temp = g_new (TempBuf, 1);
181
56
 
182
 
  temp->width    = width;
183
 
  temp->height   = height;
184
 
  temp->bytes    = bytes;
185
 
  temp->x        = x;
186
 
  temp->y        = y;
187
 
  temp->swapped  = FALSE;
188
 
  temp->filename = NULL;
 
57
  temp->width  = width;
 
58
  temp->height = height;
 
59
  temp->bytes  = bytes;
 
60
  temp->x      = x;
 
61
  temp->y      = y;
189
62
 
190
 
  temp->data = data = temp_buf_allocate (width * height * bytes);
 
63
  temp->data = g_new (guchar, width * height * bytes);
191
64
 
192
65
  /*  initialize the data  */
193
 
  if (col)
 
66
  if (color)
194
67
    {
 
68
      glong i;
 
69
 
195
70
      /* First check if we can save a lot of work */
196
71
      for (i = 1; i < bytes; i++)
197
72
        {
198
 
          if (col[0] != col[i])
 
73
          if (color[0] != color[i])
199
74
            break;
200
75
        }
201
76
 
202
77
      if (i == bytes)
203
78
        {
204
 
          memset (data, *col, width * height * bytes);
 
79
          memset (temp->data, *color, width * height * bytes);
205
80
        }
206
81
      else /* No, we cannot */
207
82
        {
208
 
          guchar *dptr = data;
 
83
          guchar *dptr = temp->data;
209
84
 
210
85
          /* Fill the first row */
211
86
          for (i = width - 1; i >= 0; --i)
212
87
            {
213
 
              guchar *init = col;
214
 
              gint    j    = bytes;
 
88
              const guchar *c = color;
 
89
              gint          j = bytes;
215
90
 
216
91
              while (j--)
217
 
                *dptr++ = *init++;
 
92
                *dptr++ = *c++;
218
93
            }
219
94
 
220
95
          /* Now copy from it (we set bytes to bytes-per-row now) */
222
97
 
223
98
          while (--height)
224
99
            {
225
 
              memcpy (dptr, data, bytes);
 
100
              memcpy (dptr, temp->data, bytes);
226
101
              dptr += bytes;
227
102
            }
228
103
        }
236
111
 
237
112
TempBuf *
238
113
temp_buf_new_check (gint           width,
239
 
                    gint           height,
240
 
                    GimpCheckType  check_type,
241
 
                    GimpCheckSize  check_size)
 
114
                    gint           height,
 
115
                    GimpCheckType  check_type,
 
116
                    GimpCheckSize  check_size)
242
117
{
243
 
  TempBuf *newbuf;
 
118
  TempBuf *new;
244
119
  guchar  *data;
245
120
  guchar   check_shift = 0;
246
121
  guchar   check_mod   = 0;
268
143
 
269
144
  gimp_checks_get_shades (check_type, &check_light, &check_dark);
270
145
 
271
 
  newbuf = temp_buf_new (width, height, 3, 0, 0, NULL);
272
 
  data = temp_buf_data (newbuf);
 
146
  new = temp_buf_new (width, height, 3, 0, 0, NULL);
 
147
  data = temp_buf_data (new);
273
148
 
274
149
  for (y = 0; y < height; y++)
275
150
    {
276
 
      guchar check_dark  = y >> check_shift;
277
 
      guchar color = (check_dark & 0x1) ? check_light : check_dark;
 
151
      guchar check_dark = y >> check_shift;
 
152
      guchar color      = (check_dark & 0x1) ? check_light : check_dark;
278
153
 
279
154
      for (x = 0; x < width; x++)
280
 
        {
 
155
        {
281
156
          *data++ = color;
282
157
          *data++ = color;
283
158
          *data++ = color;
290
165
        }
291
166
    }
292
167
 
293
 
  return newbuf;
 
168
  return new;
294
169
}
295
170
 
296
171
TempBuf *
297
172
temp_buf_copy (TempBuf *src,
298
 
               TempBuf *dest)
 
173
               TempBuf *dest)
299
174
{
300
 
  glong length;
301
 
 
302
175
  g_return_val_if_fail (src != NULL, NULL);
303
176
  g_return_val_if_fail (! dest || (dest->width  == src->width &&
304
177
                                   dest->height == src->height), NULL);
305
178
 
306
179
  if (! dest)
307
 
    {
308
 
      dest = temp_buf_new (src->width, src->height, src->bytes, 0, 0, NULL);
309
 
    }
 
180
    dest = temp_buf_new (src->width, src->height, src->bytes, 0, 0, NULL);
310
181
 
311
182
  if (src->bytes != dest->bytes)
312
183
    {
323
194
    }
324
195
  else
325
196
    {
326
 
      /* make the copy */
327
 
      length = src->width * src->height * src->bytes;
328
 
      memcpy (temp_buf_data (dest), temp_buf_data (src), length);
 
197
      memcpy (temp_buf_data (dest),
 
198
              temp_buf_data (src),
 
199
              src->width * src->height * src->bytes);
329
200
    }
330
201
 
331
202
  return dest;
333
204
 
334
205
TempBuf *
335
206
temp_buf_resize (TempBuf *buf,
336
 
                 gint     bytes,
337
 
                 gint     x,
338
 
                 gint     y,
339
 
                 gint     width,
340
 
                 gint     height)
 
207
                 gint     bytes,
 
208
                 gint     x,
 
209
                 gint     y,
 
210
                 gint     width,
 
211
                 gint     height)
341
212
{
342
 
  gint size;
343
 
 
344
213
  g_return_val_if_fail (width > 0 && height > 0, NULL);
345
214
 
346
 
  /*  calculate the requested size  */
347
 
  size = width * height * bytes;
348
 
 
349
 
  /*  First, configure the canvas buffer  */
350
 
  if (!buf)
 
215
  if (! buf)
351
216
    {
352
217
      buf = temp_buf_new (width, height, bytes, x, y, NULL);
353
218
    }
354
219
  else
355
220
    {
 
221
      gsize size = width * height * bytes;
 
222
 
356
223
      if (size != (buf->width * buf->height * buf->bytes))
357
224
        {
358
 
          /*  Make sure the temp buf is unswapped  */
359
 
          temp_buf_unswap (buf);
360
 
 
361
 
          /*  Reallocate the data for it  */
362
225
          buf->data = g_renew (guchar, buf->data, size);
363
226
        }
364
227
 
365
 
      /*  Make sure the temp buf fields are valid  */
366
228
      buf->x      = x;
367
229
      buf->y      = y;
368
230
      buf->width  = width;
375
237
 
376
238
TempBuf *
377
239
temp_buf_scale (TempBuf *src,
378
 
                gint     new_width,
379
 
                gint     new_height)
 
240
                gint     new_width,
 
241
                gint     new_height)
380
242
{
 
243
  TempBuf *dest;
 
244
  guchar  *src_data;
 
245
  guchar  *dest_data;
 
246
  gdouble  x_ratio;
 
247
  gdouble  y_ratio;
381
248
  gint     loop1;
382
249
  gint     loop2;
383
 
  gdouble  x_ratio;
384
 
  gdouble  y_ratio;
385
 
  guchar  *src_data;
386
 
  guchar  *dest_data;
387
 
  TempBuf *dest;
388
250
 
389
251
  g_return_val_if_fail (src != NULL, NULL);
390
252
  g_return_val_if_fail (new_width > 0 && new_height > 0, NULL);
391
253
 
392
254
  dest = temp_buf_new (new_width,
393
 
                       new_height,
394
 
                       src->bytes,
395
 
                       0, 0, NULL);
 
255
                       new_height,
 
256
                       src->bytes,
 
257
                       0, 0, NULL);
396
258
 
397
259
  src_data  = temp_buf_data (src);
398
260
  dest_data = temp_buf_data (dest);
403
265
  for (loop1 = 0 ; loop1 < new_height ; loop1++)
404
266
    {
405
267
      for (loop2 = 0 ; loop2 < new_width ; loop2++)
406
 
        {
407
 
          gint    i;
408
 
          guchar *src_pixel;
409
 
          guchar *dest_pixel;
410
 
 
411
 
          src_pixel = src_data +
412
 
            (gint) (loop2 * x_ratio) * src->bytes +
413
 
            (gint) (loop1 * y_ratio) * src->bytes * src->width;
414
 
 
415
 
          dest_pixel = dest_data +
416
 
            (loop2 + loop1 * new_width) * src->bytes;
417
 
 
418
 
          for (i = 0 ; i < src->bytes; i++)
419
 
            *dest_pixel++ = *src_pixel++;
420
 
        }
 
268
        {
 
269
          guchar *src_pixel;
 
270
          guchar *dest_pixel;
 
271
          gint    i;
 
272
 
 
273
          src_pixel = src_data +
 
274
            (gint) (loop2 * x_ratio) * src->bytes +
 
275
            (gint) (loop1 * y_ratio) * src->bytes * src->width;
 
276
 
 
277
          dest_pixel = dest_data +
 
278
            (loop2 + loop1 * new_width) * src->bytes;
 
279
 
 
280
          for (i = 0 ; i < src->bytes; i++)
 
281
            *dest_pixel++ = *src_pixel++;
 
282
        }
421
283
    }
422
284
 
423
285
  return dest;
425
287
 
426
288
TempBuf *
427
289
temp_buf_copy_area (TempBuf *src,
428
 
                    TempBuf *dest,
429
 
                    gint     x,
430
 
                    gint     y,
431
 
                    gint     width,
432
 
                    gint     height,
433
 
                    gint     dest_x,
434
 
                    gint     dest_y)
 
290
                    TempBuf *dest,
 
291
                    gint     x,
 
292
                    gint     y,
 
293
                    gint     width,
 
294
                    gint     height,
 
295
                    gint     dest_x,
 
296
                    gint     dest_y)
435
297
{
436
298
  TempBuf     *new;
437
299
  PixelRegion  srcPR  = { 0, };
463
325
  if (! dest)
464
326
    {
465
327
      new = temp_buf_new (width  + dest_x,
466
 
                          height + dest_y,
467
 
                          src->bytes,
468
 
                          0, 0,
469
 
                          empty);
 
328
                          height + dest_y,
 
329
                          src->bytes,
 
330
                          0, 0,
 
331
                          empty);
470
332
    }
471
333
  else
472
334
    {
474
336
    }
475
337
 
476
338
  /*  Copy the region  */
477
 
  srcPR.bytes     = src->bytes;
478
 
  srcPR.w         = width;
479
 
  srcPR.h         = height;
480
 
  srcPR.rowstride = src->bytes * src->width;
481
 
  srcPR.data      = temp_buf_data (src) + (y1 * srcPR.rowstride +
482
 
                                           x1 * srcPR.bytes);
483
 
 
484
 
  destPR.bytes     = dest->bytes;
485
 
  destPR.rowstride = new->bytes * new->width;
486
 
  destPR.data      = temp_buf_data (new) + (dest_y * destPR.rowstride +
487
 
                                            dest_x * destPR.bytes);
 
339
  pixel_region_init_temp_buf (&srcPR,  src, x1, y1, width, height);
 
340
  pixel_region_init_temp_buf (&destPR, new, dest_x, dest_y, width, height);
488
341
 
489
342
  copy_region (&srcPR, &destPR);
490
343
 
499
352
  if (temp_buf->data)
500
353
    g_free (temp_buf->data);
501
354
 
502
 
  if (temp_buf->swapped)
503
 
    temp_buf_swap_free (temp_buf);
504
 
 
505
355
  g_free (temp_buf);
506
356
}
507
357
 
508
358
guchar *
509
359
temp_buf_data (TempBuf *temp_buf)
510
360
{
511
 
  if (temp_buf->swapped)
512
 
    temp_buf_unswap (temp_buf);
513
 
 
514
361
  return temp_buf->data;
515
362
}
516
363
 
517
364
guchar *
518
365
temp_buf_data_clear (TempBuf *temp_buf)
519
366
{
520
 
  g_return_val_if_fail (temp_buf != NULL, NULL);
521
 
 
522
 
  if (temp_buf->swapped)
523
 
    temp_buf_unswap (temp_buf);
524
 
 
525
367
  memset (temp_buf->data, 0,
526
 
          temp_buf->height * temp_buf->width * temp_buf->bytes);
 
368
          temp_buf->height * temp_buf->width * temp_buf->bytes);
527
369
 
528
370
  return temp_buf->data;
529
371
}
535
377
 
536
378
  g_return_val_if_fail (temp_buf != NULL, 0);
537
379
 
538
 
  memsize += sizeof (TempBuf);
539
 
 
540
 
  if (temp_buf->swapped)
541
 
    {
542
 
      memsize += strlen (temp_buf->filename) + 1;
543
 
    }
544
 
  else
545
 
    {
546
 
      memsize += ((gsize) temp_buf->bytes *
547
 
                          temp_buf->width *
548
 
                          temp_buf->height);
549
 
    }
 
380
  memsize += (sizeof (TempBuf)
 
381
              + (gsize) temp_buf->bytes * temp_buf->width * temp_buf->height);
550
382
 
551
383
  return memsize;
552
384
}
553
385
 
554
386
 
555
 
/******************************************************************
556
 
 *  Mask buffer functions                                         *
557
 
 ******************************************************************/
558
 
 
559
 
 
560
 
MaskBuf *
561
 
mask_buf_new (gint width,
562
 
              gint height)
563
 
{
564
 
  static guchar empty = 0;
565
 
 
566
 
  return temp_buf_new (width, height, 1, 0, 0, &empty);
567
 
}
568
 
 
569
 
void
570
 
mask_buf_free (MaskBuf *mask)
571
 
{
572
 
  temp_buf_free ((TempBuf *) mask);
573
 
}
574
 
 
575
 
guchar *
576
 
mask_buf_data (MaskBuf *mask_buf)
577
 
{
578
 
  return temp_buf_data ((TempBuf *) mask_buf);
579
 
}
580
 
 
581
 
guchar *
582
 
mask_buf_data_clear (MaskBuf *mask_buf)
583
 
{
584
 
  return temp_buf_data_clear ((TempBuf *) mask_buf);
585
 
}
586
 
 
587
 
 
588
 
/******************************************************************
589
 
 *  temp buffer disk caching functions                            *
590
 
 ******************************************************************/
591
 
 
592
 
/*  NOTES:
593
 
 *  Disk caching is setup as follows:
594
 
 *    On a call to temp_buf_swap, the TempBuf parameter is stored
595
 
 *    in a temporary variable called cached_in_memory.
596
 
 *    On the next call to temp_buf_swap, if cached_in_memory is non-null,
597
 
 *    cached_in_memory is moved to disk, and the latest TempBuf parameter
598
 
 *    is stored in cached_in_memory.  This method keeps the latest TempBuf
599
 
 *    structure in memory instead of moving it directly to disk as requested.
600
 
 *    On a call to temp_buf_unswap, if cached_in_memory is non-null, it is
601
 
 *    compared against the requested TempBuf.  If they are the same, nothing
602
 
 *    must be moved in from disk since it still resides in memory.  However,
603
 
 *    if the two pointers are different, the requested TempBuf is retrieved
604
 
 *    from disk.  In the former case, cached_in_memory is set to NULL;
605
 
 *    in the latter case, cached_in_memory is left unchanged.
606
 
 *    If temp_buf_swap_free is called, cached_in_memory must be checked
607
 
 *    against the temp buf being freed.  If they are the same, then
608
 
 *    cached_in_memory must be set to NULL;
609
 
 *
610
 
 *  In the case where memory usage is set to "stingy":
611
 
 *    temp bufs are not cached in memory at all, they go right to disk.
612
 
 */
613
 
 
614
 
 
615
 
/*  a static counter for generating unique filenames
616
 
 */
617
 
static gint tmp_file_index = 0;
618
 
 
619
 
 
620
 
/*  a static pointer which keeps track of the last request for
621
 
 *  a swapped buffer
622
 
 */
623
 
static TempBuf *cached_in_memory = NULL;
624
 
 
625
 
 
626
 
static gchar *
627
 
generate_unique_tmp_filename (GimpBaseConfig *config)
628
 
{
629
 
  pid_t  pid;
630
 
  gchar *tmpdir;
631
 
  gchar *tmpfile;
632
 
  gchar *path;
633
 
 
634
 
  tmpdir = gimp_config_path_expand (config->temp_path, TRUE, NULL);
635
 
 
636
 
  pid = getpid ();
637
 
 
638
 
  tmpfile = g_strdup_printf ("gimp%d.%d",
639
 
                             (gint) pid,
640
 
                             tmp_file_index++);
641
 
 
642
 
  path = g_build_filename (tmpdir, tmpfile, NULL);
643
 
 
644
 
  g_free (tmpfile);
645
 
  g_free (tmpdir);
646
 
 
647
 
  return path;
648
 
}
649
 
 
650
 
void
651
 
temp_buf_swap (TempBuf *buf)
652
 
{
653
 
  TempBuf *swap;
654
 
  gchar   *filename;
655
 
  FILE    *fp;
656
 
 
657
 
  if (!buf || buf->swapped)
658
 
    return;
659
 
 
660
 
  /*  Set the swapped flag  */
661
 
  buf->swapped = TRUE;
662
 
 
663
 
  if (base_config->stingy_memory_use)
664
 
    {
665
 
      swap = buf;
666
 
    }
667
 
  else
668
 
    {
669
 
      swap = cached_in_memory;
670
 
      cached_in_memory = buf;
671
 
    }
672
 
 
673
 
  /*  For the case where there is no temp buf ready
674
 
   *  to be moved to disk, return
675
 
   */
676
 
  if (! swap)
677
 
    return;
678
 
 
679
 
  /*  Get a unique filename for caching the data to a UNIX file  */
680
 
  filename = generate_unique_tmp_filename (base_config);
681
 
 
682
 
  /*  Check if generated filename is valid  */
683
 
  if (g_file_test (filename, G_FILE_TEST_IS_DIR))
684
 
    {
685
 
      g_message ("Error in temp buf caching: \"%s\" is a directory (cannot overwrite)",
686
 
                 gimp_filename_to_utf8 (filename));
687
 
      g_free (filename);
688
 
      return;
689
 
    }
690
 
 
691
 
  /*  Open file for overwrite  */
692
 
  if ((fp = fopen (filename, "wb")))
693
 
    {
694
 
      gsize blocks_written;
695
 
 
696
 
      blocks_written = fwrite (swap->data,
697
 
                               swap->width * swap->height * swap->bytes, 1,
698
 
                               fp);
699
 
 
700
 
      /* Check whether all bytes were written and fclose() was able
701
 
         to flush its buffers */
702
 
      if ((0 != fclose (fp)) || (1 != blocks_written))
703
 
        {
704
 
          unlink (filename);
705
 
          perror ("Write error on temp buf");
706
 
          g_message ("Cannot write \"%s\"",
707
 
                     gimp_filename_to_utf8 (filename));
708
 
          g_free (filename);
709
 
          return;
710
 
        }
711
 
    }
712
 
  else
713
 
    {
714
 
      unlink (filename);
715
 
      perror ("Error in temp buf caching");
716
 
      g_message ("Cannot write \"%s\"",
717
 
                 gimp_filename_to_utf8 (filename));
718
 
      g_free (filename);
719
 
      return;
720
 
    }
721
 
  /*  Finally, free the buffer's data  */
722
 
  g_free (swap->data);
723
 
  swap->data = NULL;
724
 
 
725
 
  swap->filename = filename;
726
 
}
727
 
 
728
 
void
729
 
temp_buf_unswap (TempBuf *buf)
730
 
{
731
 
  FILE     *fp;
732
 
  gboolean  succ = FALSE;
733
 
 
734
 
  if (!buf || !buf->swapped)
735
 
    return;
736
 
 
737
 
  /*  Set the swapped flag  */
738
 
  buf->swapped = FALSE;
739
 
 
740
 
  /*  If the requested temp buf is still in memory, simply return  */
741
 
  if (cached_in_memory == buf)
742
 
    {
743
 
      cached_in_memory = NULL;
744
 
      return;
745
 
    }
746
 
 
747
 
  /*  Allocate memory for the buffer's data  */
748
 
  buf->data   = temp_buf_allocate (buf->width * buf->height * buf->bytes);
749
 
 
750
 
  if (g_file_test (buf->filename, G_FILE_TEST_IS_REGULAR))
751
 
    {
752
 
      if ((fp = fopen (buf->filename, "rb")))
753
 
        {
754
 
          gsize blocks_read;
755
 
 
756
 
          blocks_read = fread (buf->data,
757
 
                               buf->width * buf->height * buf->bytes, 1,
758
 
                               fp);
759
 
 
760
 
          fclose (fp);
761
 
          if (blocks_read != 1)
762
 
            perror ("Read error on temp buf");
763
 
          else
764
 
            succ = TRUE;
765
 
        }
766
 
      else
767
 
        perror ("Error in temp buf caching");
768
 
 
769
 
      /*  Delete the swap file  */
770
 
      unlink (buf->filename);
771
 
    }
772
 
 
773
 
  if (!succ)
774
 
    g_message ("Error in temp buf caching: "
775
 
               "information swapped to disk was lost!");
776
 
 
777
 
  g_free (buf->filename);   /*  free filename  */
778
 
  buf->filename = NULL;
779
 
}
780
 
 
781
 
void
782
 
temp_buf_swap_free (TempBuf *buf)
783
 
{
784
 
  if (!buf->swapped)
785
 
    return;
786
 
 
787
 
  /*  Set the swapped flag  */
788
 
  buf->swapped = FALSE;
789
 
 
790
 
  /*  If the requested temp buf is cached in memory...  */
791
 
  if (cached_in_memory == buf)
792
 
    {
793
 
      cached_in_memory = NULL;
794
 
      return;
795
 
    }
796
 
 
797
 
  /*  Find out if the filename of the swapped data is an existing file... */
798
 
  if (g_file_test (buf->filename, G_FILE_TEST_IS_REGULAR))
799
 
    {
800
 
      /*  Delete the swap file  */
801
 
      unlink (buf->filename);
802
 
    }
803
 
  else
804
 
    g_message ("Error in temp buf disk swapping: "
805
 
               "information swapped to disk was lost!");
806
 
 
807
 
  if (buf->filename)
808
 
    g_free (buf->filename);   /*  free filename  */
809
 
  buf->filename = NULL;
810
 
}
811
 
 
812
 
void
813
 
swapping_free (void)
814
 
{
815
 
  if (cached_in_memory)
816
 
    temp_buf_free (cached_in_memory);
 
387
/*  The conversion routines  */
 
388
 
 
389
static void
 
390
temp_buf_to_color (TempBuf *src_buf,
 
391
                   TempBuf *dest_buf)
 
392
{
 
393
  guchar *src;
 
394
  guchar *dest;
 
395
  glong   num_pixels;
 
396
 
 
397
  src  = temp_buf_data (src_buf);
 
398
  dest = temp_buf_data (dest_buf);
 
399
 
 
400
  num_pixels = src_buf->width * src_buf->height;
 
401
 
 
402
  switch (dest_buf->bytes)
 
403
    {
 
404
    case 3:
 
405
      g_return_if_fail (src_buf->bytes == 1);
 
406
      while (num_pixels--)
 
407
        {
 
408
          guchar tmp;
 
409
 
 
410
          *dest++ = tmp = *src++;
 
411
          *dest++ = tmp;
 
412
          *dest++ = tmp;
 
413
        }
 
414
      break;
 
415
 
 
416
    case 4:
 
417
      g_return_if_fail (src_buf->bytes == 2);
 
418
      while (num_pixels--)
 
419
        {
 
420
          guchar tmp;
 
421
 
 
422
          *dest++ = tmp = *src++;
 
423
          *dest++ = tmp;
 
424
          *dest++ = tmp;
 
425
 
 
426
          *dest++ = *src++;  /* alpha channel */
 
427
        }
 
428
      break;
 
429
 
 
430
    default:
 
431
      g_return_if_reached ();
 
432
      break;
 
433
    }
 
434
}
 
435
 
 
436
static void
 
437
temp_buf_to_gray (TempBuf *src_buf,
 
438
                  TempBuf *dest_buf)
 
439
{
 
440
  const guchar *src;
 
441
  guchar       *dest;
 
442
  glong         num_pixels;
 
443
 
 
444
  src  = temp_buf_data (src_buf);
 
445
  dest = temp_buf_data (dest_buf);
 
446
 
 
447
  num_pixels = src_buf->width * src_buf->height;
 
448
 
 
449
  switch (dest_buf->bytes)
 
450
    {
 
451
    case 1:
 
452
      g_return_if_fail (src_buf->bytes == 3);
 
453
      while (num_pixels--)
 
454
        {
 
455
          gint lum = GIMP_RGB_LUMINANCE (src[0], src[1], src[2]) + 0.5;
 
456
 
 
457
          *dest++ = (guchar) lum;
 
458
 
 
459
          src += 3;
 
460
        }
 
461
      break;
 
462
 
 
463
    case 2:
 
464
      g_return_if_fail (src_buf->bytes == 4);
 
465
      while (num_pixels--)
 
466
        {
 
467
          gint lum = GIMP_RGB_LUMINANCE (src[0], src[1], src[2]) + 0.5;
 
468
 
 
469
          *dest++ = (guchar) lum;
 
470
          *dest++ = src[3];  /* alpha channel */
 
471
 
 
472
          src += 4;
 
473
        }
 
474
      break;
 
475
 
 
476
    default:
 
477
      g_return_if_reached ();
 
478
      break;
 
479
    }
817
480
}