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

« back to all changes in this revision

Viewing changes to app/core/gimppalette.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 <stdlib.h>
22
 
#include <stdio.h>
23
21
#include <string.h>
24
 
#include <errno.h>
25
 
#ifdef HAVE_UNISTD_H
26
 
#include <unistd.h>
27
 
#endif
28
22
 
29
23
#include <glib-object.h>
30
24
 
35
29
 
36
30
#include "base/temp-buf.h"
37
31
 
 
32
#include "gimp-utils.h"
38
33
#include "gimppalette.h"
 
34
#include "gimppalette-load.h"
 
35
#include "gimppalette-save.h"
39
36
 
40
37
#include "gimp-intl.h"
41
38
 
 
39
#define EPSILON 1e-10
42
40
 
43
41
/*  local function prototypes  */
44
42
 
45
 
static void       gimp_palette_class_init       (GimpPaletteClass  *klass);
46
 
static void       gimp_palette_init             (GimpPalette       *palette);
47
 
 
48
43
static void       gimp_palette_finalize         (GObject           *object);
49
44
 
50
45
static gint64     gimp_palette_get_memsize      (GimpObject        *object,
63
58
                                                 gint              *popup_width,
64
59
                                                 gint              *popup_height);
65
60
static TempBuf  * gimp_palette_get_new_preview  (GimpViewable      *viewable,
 
61
                                                 GimpContext       *context,
66
62
                                                 gint               width,
67
63
                                                 gint               height);
68
64
static gchar    * gimp_palette_get_description  (GimpViewable      *viewable,
69
65
                                                 gchar            **tooltip);
70
 
static gboolean   gimp_palette_save             (GimpData          *data,
71
 
                                                 GError           **error);
72
66
static gchar    * gimp_palette_get_extension    (GimpData          *data);
73
 
static GimpData * gimp_palette_duplicate        (GimpData          *data,
74
 
                                                 gboolean           stingy_memory_use);
 
67
static GimpData * gimp_palette_duplicate        (GimpData          *data);
75
68
 
76
69
static void       gimp_palette_entry_free       (GimpPaletteEntry  *entry);
77
 
 
78
 
 
79
 
/*  private variables  */
80
 
 
81
 
static GimpDataClass *parent_class = NULL;
82
 
 
83
 
 
84
 
GType
85
 
gimp_palette_get_type (void)
86
 
{
87
 
  static GType palette_type = 0;
88
 
 
89
 
  if (! palette_type)
90
 
    {
91
 
      static const GTypeInfo palette_info =
92
 
      {
93
 
        sizeof (GimpPaletteClass),
94
 
        (GBaseInitFunc) NULL,
95
 
        (GBaseFinalizeFunc) NULL,
96
 
        (GClassInitFunc) gimp_palette_class_init,
97
 
        NULL,           /* class_finalize */
98
 
        NULL,           /* class_data     */
99
 
        sizeof (GimpPalette),
100
 
        0,              /* n_preallocs    */
101
 
        (GInstanceInitFunc) gimp_palette_init,
102
 
      };
103
 
 
104
 
      palette_type = g_type_register_static (GIMP_TYPE_DATA,
105
 
                                             "GimpPalette",
106
 
                                             &palette_info, 0);
107
 
    }
108
 
 
109
 
  return palette_type;
110
 
}
 
70
static gint64     gimp_palette_entry_get_memsize(GimpPaletteEntry  *entry,
 
71
                                                 gint64            *gui_size);
 
72
 
 
73
 
 
74
G_DEFINE_TYPE (GimpPalette, gimp_palette, GIMP_TYPE_DATA)
 
75
 
 
76
#define parent_class gimp_palette_parent_class
 
77
 
111
78
 
112
79
static void
113
80
gimp_palette_class_init (GimpPaletteClass *klass)
117
84
  GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
118
85
  GimpDataClass     *data_class        = GIMP_DATA_CLASS (klass);
119
86
 
120
 
  parent_class = g_type_class_peek_parent (klass);
121
 
 
122
87
  object_class->finalize           = gimp_palette_finalize;
123
88
 
124
89
  gimp_object_class->get_memsize   = gimp_palette_get_memsize;
162
127
                          gint64     *gui_size)
163
128
{
164
129
  GimpPalette *palette = GIMP_PALETTE (object);
165
 
  GList       *list;
166
130
  gint64       memsize = 0;
167
131
 
168
 
  for (list = palette->colors; list; list = g_list_next (list))
169
 
    {
170
 
      GimpPaletteEntry *entry = list->data;
171
 
 
172
 
      memsize += sizeof (GList) + sizeof (GimpPaletteEntry);
173
 
 
174
 
      if (entry->name)
175
 
        memsize += strlen (entry->name) + 1;
176
 
    }
 
132
  memsize += gimp_g_list_get_memsize_foreach (palette->colors,
 
133
                                              (GimpMemsizeFunc)
 
134
                                              gimp_palette_entry_get_memsize,
 
135
                                              gui_size);
177
136
 
178
137
  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
179
138
                                                                  gui_size);
226
185
 
227
186
static TempBuf *
228
187
gimp_palette_get_new_preview (GimpViewable *viewable,
 
188
                              GimpContext  *context,
229
189
                              gint          width,
230
190
                              gint          height)
231
191
{
295
255
{
296
256
  GimpPalette *palette = GIMP_PALETTE (viewable);
297
257
 
298
 
  if (tooltip)
299
 
    *tooltip = NULL;
300
 
 
301
258
  return g_strdup_printf ("%s (%d)",
302
259
                          GIMP_OBJECT (palette)->name,
303
260
                          palette->n_colors);
304
261
}
305
262
 
306
263
GimpData *
307
 
gimp_palette_new (const gchar *name,
308
 
                  gboolean     stingy_memory_use)
 
264
gimp_palette_new (const gchar *name)
309
265
{
310
266
  g_return_val_if_fail (name != NULL, NULL);
311
267
  g_return_val_if_fail (*name != '\0', NULL);
322
278
 
323
279
  if (! standard_palette)
324
280
    {
325
 
      standard_palette = gimp_palette_new ("Standard", FALSE);
 
281
      standard_palette = gimp_palette_new ("Standard");
326
282
 
327
283
      standard_palette->dirty = FALSE;
328
284
      gimp_data_make_internal (standard_palette);
333
289
  return standard_palette;
334
290
}
335
291
 
336
 
GList *
337
 
gimp_palette_load (const gchar  *filename,
338
 
                   gboolean      stingy_memory_use,
339
 
                   GError      **error)
340
 
{
341
 
  GimpPalette      *palette;
342
 
  GimpPaletteEntry *entry;
343
 
  gchar             str[1024];
344
 
  gchar            *tok;
345
 
  FILE             *file;
346
 
  gint              r, g, b;
347
 
  gint              linenum;
348
 
 
349
 
  g_return_val_if_fail (filename != NULL, NULL);
350
 
  g_return_val_if_fail (g_path_is_absolute (filename), NULL);
351
 
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
352
 
 
353
 
  r = g = b = 0;
354
 
 
355
 
  file = fopen (filename, "r");
356
 
 
357
 
  if (! file)
358
 
    {
359
 
      g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_OPEN,
360
 
                   _("Could not open '%s' for reading: %s"),
361
 
                   gimp_filename_to_utf8 (filename), g_strerror (errno));
362
 
      return NULL;
363
 
    }
364
 
 
365
 
  linenum = 0;
366
 
 
367
 
  fread (str, 13, 1, file);
368
 
  str[13] = '\0';
369
 
  linenum++;
370
 
  if (strcmp (str, "GIMP Palette\n"))
371
 
    {
372
 
      /* bad magic, but maybe it has \r\n at the end of lines? */
373
 
      if (!strcmp (str, "GIMP Palette\r"))
374
 
        g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
375
 
                     _("Fatal parse error in palette file '%s': "
376
 
                       "Missing magic header.\n"
377
 
                       "Does this file need converting from DOS?"),
378
 
                     gimp_filename_to_utf8 (filename));
379
 
      else
380
 
        g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
381
 
                     _("Fatal parse error in palette file '%s': "
382
 
                       "Missing magic header."),
383
 
                     gimp_filename_to_utf8 (filename));
384
 
 
385
 
      fclose (file);
386
 
 
387
 
      return NULL;
388
 
    }
389
 
 
390
 
  palette = g_object_new (GIMP_TYPE_PALETTE, NULL);
391
 
 
392
 
  if (! fgets (str, sizeof (str), file))
393
 
    {
394
 
      g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
395
 
                   _("Fatal parse error in palette file '%s': "
396
 
                     "Read error in line %d."),
397
 
                   gimp_filename_to_utf8 (filename), linenum);
398
 
      fclose (file);
399
 
      g_object_unref (palette);
400
 
      return NULL;
401
 
    }
402
 
 
403
 
  linenum++;
404
 
 
405
 
  if (! strncmp (str, "Name: ", strlen ("Name: ")))
406
 
    {
407
 
      gchar *utf8;
408
 
 
409
 
      utf8 = gimp_any_to_utf8 (&str[strlen ("Name: ")], -1,
410
 
                               _("Invalid UTF-8 string in palette file '%s'"),
411
 
                               gimp_filename_to_utf8 (filename));
412
 
      g_strstrip (utf8);
413
 
 
414
 
      gimp_object_set_name (GIMP_OBJECT (palette), utf8);
415
 
      g_free (utf8);
416
 
 
417
 
      if (! fgets (str, sizeof (str), file))
418
 
        {
419
 
          g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
420
 
                       _("Fatal parse error in palette file '%s': "
421
 
                         "Read error in line %d."),
422
 
                       gimp_filename_to_utf8 (filename), linenum);
423
 
          fclose (file);
424
 
          g_object_unref (palette);
425
 
          return NULL;
426
 
        }
427
 
 
428
 
      linenum++;
429
 
 
430
 
      if (! strncmp (str, "Columns: ", strlen ("Columns: ")))
431
 
        {
432
 
          gint columns;
433
 
 
434
 
          columns = atoi (g_strstrip (&str[strlen ("Columns: ")]));
435
 
 
436
 
          if (columns < 0 || columns > 256)
437
 
            {
438
 
              g_message (_("Reading palette file '%s': "
439
 
                           "Invalid number of columns in line %d. "
440
 
                           "Using default value."),
441
 
                         gimp_filename_to_utf8 (filename), linenum);
442
 
              columns = 0;
443
 
            }
444
 
 
445
 
          palette->n_columns = columns;
446
 
 
447
 
          if (! fgets (str, sizeof (str), file))
448
 
            {
449
 
              g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
450
 
                           _("Fatal parse error in palette file '%s': "
451
 
                             "Read error in line %d."),
452
 
                           gimp_filename_to_utf8 (filename), linenum);
453
 
              fclose (file);
454
 
              g_object_unref (palette);
455
 
              return NULL;
456
 
            }
457
 
 
458
 
          linenum++;
459
 
        }
460
 
    }
461
 
  else /* old palette format */
462
 
    {
463
 
      gchar *basename;
464
 
      gchar *utf8;
465
 
 
466
 
      basename = g_path_get_basename (filename);
467
 
 
468
 
      utf8 = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL);
469
 
      g_free (basename);
470
 
 
471
 
      gimp_object_set_name (GIMP_OBJECT (palette), utf8);
472
 
      g_free (utf8);
473
 
    }
474
 
 
475
 
  while (! feof (file))
476
 
    {
477
 
      if (str[0] != '#')
478
 
        {
479
 
          tok = strtok (str, " \t");
480
 
          if (tok)
481
 
            r = atoi (tok);
482
 
          else
483
 
            /* maybe we should just abort? */
484
 
            g_message (_("Reading palette file '%s': "
485
 
                         "Missing RED component in line %d."),
486
 
                       gimp_filename_to_utf8 (filename), linenum);
487
 
 
488
 
          tok = strtok (NULL, " \t");
489
 
          if (tok)
490
 
            g = atoi (tok);
491
 
          else
492
 
            g_message (_("Reading palette '%s': "
493
 
                         "Missing GREEN component in line %d."),
494
 
                       gimp_filename_to_utf8 (filename), linenum);
495
 
 
496
 
          tok = strtok (NULL, " \t");
497
 
          if (tok)
498
 
            b = atoi (tok);
499
 
          else
500
 
            g_message (_("Reading palette file '%s': "
501
 
                         "Missing BLUE component in line %d."),
502
 
                       gimp_filename_to_utf8 (filename), linenum);
503
 
 
504
 
          /* optional name */
505
 
          tok = strtok (NULL, "\n");
506
 
 
507
 
          if (r < 0 || r > 255 ||
508
 
              g < 0 || g > 255 ||
509
 
              b < 0 || b > 255)
510
 
            g_message (_("Reading palette file '%s': "
511
 
                         "RGB value out of range in line %d."),
512
 
                       gimp_filename_to_utf8 (filename), linenum);
513
 
 
514
 
          /* don't call gimp_palette_add_entry here, it's rather inefficient */
515
 
          entry = g_new0 (GimpPaletteEntry, 1);
516
 
 
517
 
          gimp_rgba_set_uchar (&entry->color,
518
 
                               (guchar) r,
519
 
                               (guchar) g,
520
 
                               (guchar) b,
521
 
                               255);
522
 
 
523
 
          entry->name     = g_strdup (tok ? tok : _("Untitled"));
524
 
          entry->position = palette->n_colors;
525
 
 
526
 
          palette->colors = g_list_prepend (palette->colors, entry);
527
 
          palette->n_colors++;
528
 
        }
529
 
 
530
 
      if (! fgets (str, sizeof (str), file))
531
 
        {
532
 
          if (feof (file))
533
 
            break;
534
 
 
535
 
          g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
536
 
                       _("Fatal parse error in palette file '%s': "
537
 
                         "Read error in line %d."),
538
 
                       gimp_filename_to_utf8 (filename), linenum);
539
 
          fclose (file);
540
 
          g_object_unref (palette);
541
 
          return NULL;
542
 
        }
543
 
 
544
 
      linenum++;
545
 
    }
546
 
 
547
 
  fclose (file);
548
 
 
549
 
  palette->colors = g_list_reverse (palette->colors);
550
 
 
551
 
  return g_list_prepend (NULL, palette);
552
 
}
553
 
 
554
 
static gboolean
555
 
gimp_palette_save (GimpData  *data,
556
 
                   GError   **error)
557
 
{
558
 
  GimpPalette *palette = GIMP_PALETTE (data);
559
 
  GList       *list;
560
 
  FILE        *file;
561
 
 
562
 
  file = fopen (data->filename, "w");
563
 
 
564
 
  if (! file)
565
 
    {
566
 
      g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_OPEN,
567
 
                   _("Could not open '%s' for writing: %s"),
568
 
                   gimp_filename_to_utf8 (data->filename),
569
 
                   g_strerror (errno));
570
 
      return FALSE;
571
 
    }
572
 
 
573
 
  fprintf (file, "GIMP Palette\n");
574
 
  fprintf (file, "Name: %s\n", GIMP_OBJECT (palette)->name);
575
 
  fprintf (file, "Columns: %d\n#\n", CLAMP (palette->n_columns, 0, 256));
576
 
 
577
 
  for (list = palette->colors; list; list = g_list_next (list))
578
 
    {
579
 
      GimpPaletteEntry *entry = list->data;
580
 
      guchar            r, g, b;
581
 
 
582
 
      gimp_rgb_get_uchar (&entry->color, &r, &g, &b);
583
 
 
584
 
      fprintf (file, "%3d %3d %3d\t%s\n", r, g, b, entry->name);
585
 
    }
586
 
 
587
 
  fclose (file);
588
 
 
589
 
  return TRUE;
590
 
}
591
 
 
592
292
static gchar *
593
293
gimp_palette_get_extension (GimpData *data)
594
294
{
596
296
}
597
297
 
598
298
static GimpData *
599
 
gimp_palette_duplicate (GimpData *data,
600
 
                        gboolean  stingy_memory_use)
 
299
gimp_palette_duplicate (GimpData *data)
601
300
{
602
301
  GimpPalette *palette = GIMP_PALETTE (data);
603
302
  GimpPalette *new;
611
310
    {
612
311
      GimpPaletteEntry *entry = list->data;
613
312
 
614
 
      gimp_palette_add_entry (new, entry->name, &entry->color);
 
313
      gimp_palette_add_entry (new, -1, entry->name, &entry->color);
615
314
    }
616
315
 
617
316
  return GIMP_DATA (new);
619
318
 
620
319
GimpPaletteEntry *
621
320
gimp_palette_add_entry (GimpPalette   *palette,
 
321
                        gint           position,
622
322
                        const gchar   *name,
623
323
                        const GimpRGB *color)
624
324
{
629
329
 
630
330
  entry = g_new0 (GimpPaletteEntry, 1);
631
331
 
632
 
  entry->color    = *color;
633
 
 
634
 
  entry->name     = g_strdup (name ? name : _("Untitled"));
635
 
  entry->position = palette->n_colors;
636
 
 
637
 
  palette->colors    = g_list_append (palette->colors, entry);
 
332
  entry->color = *color;
 
333
  entry->name  = g_strdup (name ? name : _("Untitled"));
 
334
 
 
335
  if (position < 0 || position >= palette->n_colors)
 
336
    {
 
337
      entry->position = palette->n_colors;
 
338
      palette->colors = g_list_append (palette->colors, entry);
 
339
    }
 
340
  else
 
341
    {
 
342
      GList *list;
 
343
 
 
344
      entry->position = position;
 
345
      palette->colors = g_list_insert (palette->colors, entry, position);
 
346
 
 
347
      /* renumber the displaced entries */
 
348
      for (list = g_list_nth (palette->colors, position + 1);
 
349
           list;
 
350
           list = g_list_next (list))
 
351
        {
 
352
          GimpPaletteEntry *entry2 = list->data;
 
353
 
 
354
          entry2->position += 1;
 
355
        }
 
356
    }
 
357
 
638
358
  palette->n_colors += 1;
639
359
 
640
 
  /*  will make the palette dirty too  */
641
 
  gimp_object_name_changed (GIMP_OBJECT (palette));
 
360
  gimp_data_dirty (GIMP_DATA (palette));
642
361
 
643
362
  return entry;
644
363
}
671
390
          entry->position = pos++;
672
391
        }
673
392
 
674
 
      /*  will make the palette dirty too  */
675
 
      gimp_object_name_changed (GIMP_OBJECT (palette));
 
393
      gimp_data_dirty (GIMP_DATA (palette));
676
394
    }
677
395
}
678
396
 
679
397
void
680
 
gimp_palette_set_n_columns (GimpPalette *palette,
681
 
                            gint         n_columns)
 
398
gimp_palette_set_columns (GimpPalette *palette,
 
399
                          gint         columns)
682
400
{
683
401
  g_return_if_fail (GIMP_IS_PALETTE (palette));
684
402
 
685
 
  n_columns = CLAMP (n_columns, 0, 64);
 
403
  columns = CLAMP (columns, 0, 64);
686
404
 
687
 
  if (palette->n_columns != n_columns)
 
405
  if (palette->n_columns != columns)
688
406
    {
689
 
      palette->n_columns = n_columns;
 
407
      palette->n_columns = columns;
690
408
 
691
409
      gimp_data_dirty (GIMP_DATA (palette));
692
410
    }
693
411
}
694
412
 
695
413
gint
696
 
gimp_palette_get_n_columns  (GimpPalette *palette)
 
414
gimp_palette_get_columns  (GimpPalette *palette)
697
415
{
698
416
  g_return_val_if_fail (GIMP_IS_PALETTE (palette), 0);
699
417
 
700
418
  return palette->n_columns;
701
419
}
702
420
 
 
421
GimpPaletteEntry *
 
422
gimp_palette_find_entry (GimpPalette      *palette,
 
423
                         const GimpRGB    *color,
 
424
                         GimpPaletteEntry *start_from)
 
425
{
 
426
  GimpPaletteEntry *entry;
 
427
 
 
428
  g_return_val_if_fail (GIMP_IS_PALETTE (palette), NULL);
 
429
  g_return_val_if_fail (color != NULL, NULL);
 
430
  g_return_val_if_fail (palette->n_colors > 0, NULL);
 
431
 
 
432
  if (! start_from)
 
433
    {
 
434
      GList *list;
 
435
 
 
436
      /* search from the start */
 
437
 
 
438
      for (list = palette->colors; list; list = g_list_next (list))
 
439
        {
 
440
          entry = (GimpPaletteEntry *) list->data;
 
441
          if (gimp_rgb_distance (&entry->color, color) < EPSILON)
 
442
            return entry;
 
443
        }
 
444
    }
 
445
  else if (gimp_rgb_distance (&start_from->color, color) < EPSILON)
 
446
    {
 
447
      return start_from;
 
448
    }
 
449
  else
 
450
    {
 
451
      GList *old = g_list_find (palette->colors, start_from);
 
452
      GList *next;
 
453
      GList *prev;
 
454
 
 
455
      g_return_val_if_fail (old != NULL, NULL);
 
456
 
 
457
      next = old->next;
 
458
      prev = old->prev;
 
459
 
 
460
      /* proximity-based search */
 
461
 
 
462
      while (next || prev)
 
463
        {
 
464
          if (next)
 
465
            {
 
466
              entry = (GimpPaletteEntry *) next->data;
 
467
              if (gimp_rgb_distance (&entry->color, color) < EPSILON)
 
468
                return entry;
 
469
 
 
470
              next = next->next;
 
471
            }
 
472
 
 
473
          if (prev)
 
474
            {
 
475
              entry = (GimpPaletteEntry *) prev->data;
 
476
              if (gimp_rgb_distance (&entry->color, color) < EPSILON)
 
477
                return entry;
 
478
 
 
479
              prev = prev->prev;
 
480
            }
 
481
        }
 
482
    }
 
483
 
 
484
  return NULL;
 
485
}
 
486
 
703
487
 
704
488
/*  private functions  */
705
489
 
711
495
  g_free (entry->name);
712
496
  g_free (entry);
713
497
}
 
498
 
 
499
static gint64
 
500
gimp_palette_entry_get_memsize (GimpPaletteEntry *entry,
 
501
                                gint64           *gui_size)
 
502
{
 
503
  gint64 memsize = sizeof (GimpPaletteEntry);
 
504
 
 
505
  if (entry->name)
 
506
    memsize += strlen (entry->name) + 1;
 
507
 
 
508
  return memsize;
 
509
}