1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29
#include <glib-object.h>
31
#include "libgimpbase/gimpbase.h"
32
#include "libgimpcolor/gimpcolor.h"
34
#include "core-types.h"
36
#include "base/temp-buf.h"
38
#include "gimppalette.h"
40
#include "gimp-intl.h"
43
/* local function prototypes */
45
static void gimp_palette_class_init (GimpPaletteClass *klass);
46
static void gimp_palette_init (GimpPalette *palette);
48
static void gimp_palette_finalize (GObject *object);
50
static gint64 gimp_palette_get_memsize (GimpObject *object,
53
static void gimp_palette_get_preview_size (GimpViewable *viewable,
59
static gboolean gimp_palette_get_popup_size (GimpViewable *viewable,
65
static TempBuf * gimp_palette_get_new_preview (GimpViewable *viewable,
68
static gchar * gimp_palette_get_description (GimpViewable *viewable,
70
static gboolean gimp_palette_save (GimpData *data,
72
static gchar * gimp_palette_get_extension (GimpData *data);
73
static GimpData * gimp_palette_duplicate (GimpData *data,
74
gboolean stingy_memory_use);
76
static void gimp_palette_entry_free (GimpPaletteEntry *entry);
79
/* private variables */
81
static GimpDataClass *parent_class = NULL;
85
gimp_palette_get_type (void)
87
static GType palette_type = 0;
91
static const GTypeInfo palette_info =
93
sizeof (GimpPaletteClass),
95
(GBaseFinalizeFunc) NULL,
96
(GClassInitFunc) gimp_palette_class_init,
97
NULL, /* class_finalize */
98
NULL, /* class_data */
101
(GInstanceInitFunc) gimp_palette_init,
104
palette_type = g_type_register_static (GIMP_TYPE_DATA,
113
gimp_palette_class_init (GimpPaletteClass *klass)
115
GObjectClass *object_class = G_OBJECT_CLASS (klass);
116
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
117
GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
118
GimpDataClass *data_class = GIMP_DATA_CLASS (klass);
120
parent_class = g_type_class_peek_parent (klass);
122
object_class->finalize = gimp_palette_finalize;
124
gimp_object_class->get_memsize = gimp_palette_get_memsize;
126
viewable_class->default_stock_id = "gtk-select-color";
127
viewable_class->get_preview_size = gimp_palette_get_preview_size;
128
viewable_class->get_popup_size = gimp_palette_get_popup_size;
129
viewable_class->get_new_preview = gimp_palette_get_new_preview;
130
viewable_class->get_description = gimp_palette_get_description;
132
data_class->save = gimp_palette_save;
133
data_class->get_extension = gimp_palette_get_extension;
134
data_class->duplicate = gimp_palette_duplicate;
138
gimp_palette_init (GimpPalette *palette)
140
palette->colors = NULL;
141
palette->n_colors = 0;
142
palette->n_columns = 0;
146
gimp_palette_finalize (GObject *object)
148
GimpPalette *palette = GIMP_PALETTE (object);
152
g_list_foreach (palette->colors, (GFunc) gimp_palette_entry_free, NULL);
153
g_list_free (palette->colors);
154
palette->colors = NULL;
157
G_OBJECT_CLASS (parent_class)->finalize (object);
161
gimp_palette_get_memsize (GimpObject *object,
164
GimpPalette *palette = GIMP_PALETTE (object);
168
for (list = palette->colors; list; list = g_list_next (list))
170
GimpPaletteEntry *entry = list->data;
172
memsize += sizeof (GList) + sizeof (GimpPaletteEntry);
175
memsize += strlen (entry->name) + 1;
178
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
183
gimp_palette_get_preview_size (GimpViewable *viewable,
186
gboolean dot_for_dot,
195
gimp_palette_get_popup_size (GimpViewable *viewable,
198
gboolean dot_for_dot,
202
GimpPalette *palette = GIMP_PALETTE (viewable);
206
if (! palette->n_colors)
209
if (palette->n_columns)
210
p_width = palette->n_columns;
212
p_width = MIN (palette->n_colors, 16);
214
p_height = MAX (1, palette->n_colors / p_width);
216
if (p_width * 4 > width || p_height * 4 > height)
218
*popup_width = p_width * 4;
219
*popup_height = p_height * 4;
228
gimp_palette_get_new_preview (GimpViewable *viewable,
232
GimpPalette *palette = GIMP_PALETTE (viewable);
237
guchar white[3] = { 255, 255, 255 };
243
temp_buf = temp_buf_new (width, height, 3, 0, 0, white);
245
if (palette->n_columns > 1)
246
cell_size = MAX (4, width / palette->n_columns);
250
columns = width / cell_size;
251
rows = height / cell_size;
253
buf = temp_buf_data (temp_buf);
254
b = g_new (guchar, width * 3);
256
list = palette->colors;
258
for (y = 0; y < rows && list; y++)
262
memset (b, 255, width * 3);
264
for (x = 0; x < columns && list; x++)
266
GimpPaletteEntry *entry = list->data;
268
list = g_list_next (list);
270
gimp_rgb_get_uchar (&entry->color,
271
&b[x * cell_size * 3 + 0],
272
&b[x * cell_size * 3 + 1],
273
&b[x * cell_size * 3 + 2]);
275
for (i = 1; i < cell_size; i++)
277
b[(x * cell_size + i) * 3 + 0] = b[(x * cell_size) * 3 + 0];
278
b[(x * cell_size + i) * 3 + 1] = b[(x * cell_size) * 3 + 1];
279
b[(x * cell_size + i) * 3 + 2] = b[(x * cell_size) * 3 + 2];
283
for (i = 0; i < cell_size; i++)
284
memcpy (buf + ((y * cell_size + i) * width) * 3, b, width * 3);
293
gimp_palette_get_description (GimpViewable *viewable,
296
GimpPalette *palette = GIMP_PALETTE (viewable);
301
return g_strdup_printf ("%s (%d)",
302
GIMP_OBJECT (palette)->name,
307
gimp_palette_new (const gchar *name,
308
gboolean stingy_memory_use)
310
g_return_val_if_fail (name != NULL, NULL);
311
g_return_val_if_fail (*name != '\0', NULL);
313
return g_object_new (GIMP_TYPE_PALETTE,
319
gimp_palette_get_standard (void)
321
static GimpData *standard_palette = NULL;
323
if (! standard_palette)
325
standard_palette = gimp_palette_new ("Standard", FALSE);
327
standard_palette->dirty = FALSE;
328
gimp_data_make_internal (standard_palette);
330
g_object_ref (standard_palette);
333
return standard_palette;
337
gimp_palette_load (const gchar *filename,
338
gboolean stingy_memory_use,
341
GimpPalette *palette;
342
GimpPaletteEntry *entry;
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);
355
file = fopen (filename, "r");
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));
367
fread (str, 13, 1, file);
370
if (strcmp (str, "GIMP Palette\n"))
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));
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));
390
palette = g_object_new (GIMP_TYPE_PALETTE, NULL);
392
if (! fgets (str, sizeof (str), file))
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);
399
g_object_unref (palette);
405
if (! strncmp (str, "Name: ", strlen ("Name: ")))
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));
414
gimp_object_set_name (GIMP_OBJECT (palette), utf8);
417
if (! fgets (str, sizeof (str), file))
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);
424
g_object_unref (palette);
430
if (! strncmp (str, "Columns: ", strlen ("Columns: ")))
434
columns = atoi (g_strstrip (&str[strlen ("Columns: ")]));
436
if (columns < 0 || columns > 256)
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);
445
palette->n_columns = columns;
447
if (! fgets (str, sizeof (str), file))
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);
454
g_object_unref (palette);
461
else /* old palette format */
466
basename = g_path_get_basename (filename);
468
utf8 = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL);
471
gimp_object_set_name (GIMP_OBJECT (palette), utf8);
475
while (! feof (file))
479
tok = strtok (str, " \t");
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);
488
tok = strtok (NULL, " \t");
492
g_message (_("Reading palette '%s': "
493
"Missing GREEN component in line %d."),
494
gimp_filename_to_utf8 (filename), linenum);
496
tok = strtok (NULL, " \t");
500
g_message (_("Reading palette file '%s': "
501
"Missing BLUE component in line %d."),
502
gimp_filename_to_utf8 (filename), linenum);
505
tok = strtok (NULL, "\n");
507
if (r < 0 || r > 255 ||
510
g_message (_("Reading palette file '%s': "
511
"RGB value out of range in line %d."),
512
gimp_filename_to_utf8 (filename), linenum);
514
/* don't call gimp_palette_add_entry here, it's rather inefficient */
515
entry = g_new0 (GimpPaletteEntry, 1);
517
gimp_rgba_set_uchar (&entry->color,
523
entry->name = g_strdup (tok ? tok : _("Untitled"));
524
entry->position = palette->n_colors;
526
palette->colors = g_list_prepend (palette->colors, entry);
530
if (! fgets (str, sizeof (str), file))
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);
540
g_object_unref (palette);
549
palette->colors = g_list_reverse (palette->colors);
551
return g_list_prepend (NULL, palette);
555
gimp_palette_save (GimpData *data,
558
GimpPalette *palette = GIMP_PALETTE (data);
562
file = fopen (data->filename, "w");
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),
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));
577
for (list = palette->colors; list; list = g_list_next (list))
579
GimpPaletteEntry *entry = list->data;
582
gimp_rgb_get_uchar (&entry->color, &r, &g, &b);
584
fprintf (file, "%3d %3d %3d\t%s\n", r, g, b, entry->name);
593
gimp_palette_get_extension (GimpData *data)
595
return GIMP_PALETTE_FILE_EXTENSION;
599
gimp_palette_duplicate (GimpData *data,
600
gboolean stingy_memory_use)
602
GimpPalette *palette = GIMP_PALETTE (data);
606
new = g_object_new (GIMP_TYPE_PALETTE, NULL);
608
new->n_columns = palette->n_columns;
610
for (list = palette->colors; list; list = g_list_next (list))
612
GimpPaletteEntry *entry = list->data;
614
gimp_palette_add_entry (new, entry->name, &entry->color);
617
return GIMP_DATA (new);
621
gimp_palette_add_entry (GimpPalette *palette,
623
const GimpRGB *color)
625
GimpPaletteEntry *entry;
627
g_return_val_if_fail (GIMP_IS_PALETTE (palette), NULL);
628
g_return_val_if_fail (color != NULL, NULL);
630
entry = g_new0 (GimpPaletteEntry, 1);
632
entry->color = *color;
634
entry->name = g_strdup (name ? name : _("Untitled"));
635
entry->position = palette->n_colors;
637
palette->colors = g_list_append (palette->colors, entry);
638
palette->n_colors += 1;
640
/* will make the palette dirty too */
641
gimp_object_name_changed (GIMP_OBJECT (palette));
647
gimp_palette_delete_entry (GimpPalette *palette,
648
GimpPaletteEntry *entry)
653
g_return_if_fail (GIMP_IS_PALETTE (palette));
654
g_return_if_fail (entry != NULL);
656
if (g_list_find (palette->colors, entry))
658
pos = entry->position;
659
gimp_palette_entry_free (entry);
661
palette->colors = g_list_remove (palette->colors, entry);
665
for (list = g_list_nth (palette->colors, pos);
667
list = g_list_next (list))
669
entry = (GimpPaletteEntry *) list->data;
671
entry->position = pos++;
674
/* will make the palette dirty too */
675
gimp_object_name_changed (GIMP_OBJECT (palette));
680
gimp_palette_set_n_columns (GimpPalette *palette,
683
g_return_if_fail (GIMP_IS_PALETTE (palette));
685
n_columns = CLAMP (n_columns, 0, 64);
687
if (palette->n_columns != n_columns)
689
palette->n_columns = n_columns;
691
gimp_data_dirty (GIMP_DATA (palette));
696
gimp_palette_get_n_columns (GimpPalette *palette)
698
g_return_val_if_fail (GIMP_IS_PALETTE (palette), 0);
700
return palette->n_columns;
704
/* private functions */
707
gimp_palette_entry_free (GimpPaletteEntry *entry)
709
g_return_if_fail (entry != NULL);
711
g_free (entry->name);