/* The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "gimpbrush.h" #include "gimpbrushlist.h" #include "gimpsignal.h" #include "gimprc.h" #include "brush_header.h" #include "libgimp/gimpintl.h" enum{ DIRTY, RENAME, LAST_SIGNAL }; static guint gimp_brush_signals[LAST_SIGNAL]; static GimpObjectClass* parent_class; static void gimp_brush_destroy(GtkObject *object) { GimpBrush* brush=GIMP_BRUSH(object); if (brush->filename) g_free(brush->filename); if (brush->name) g_free(brush->name); if (brush->mask) temp_buf_free(brush->mask); GTK_OBJECT_CLASS(parent_class)->destroy (object); } static void gimp_brush_class_init (GimpBrushClass *klass) { GtkObjectClass *object_class; GtkType type; object_class = GTK_OBJECT_CLASS(klass); parent_class = gtk_type_class (gimp_object_get_type ()); type=object_class->type; object_class->destroy = gimp_brush_destroy; gimp_brush_signals[DIRTY] = gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0, gimp_sigtype_void); gimp_brush_signals[RENAME] = gimp_signal_new ("rename", GTK_RUN_FIRST, type, 0, gimp_sigtype_void); gtk_object_class_add_signals (object_class, gimp_brush_signals, LAST_SIGNAL); } void gimp_brush_init(GimpBrush *brush) { brush->filename = NULL; brush->name = NULL; brush->spacing = 20; brush->mask = NULL; brush->x_axis.x = 15.0; brush->x_axis.y = 0.0; brush->y_axis.x = 0.0; brush->y_axis.y = 15.0; } GtkType gimp_brush_get_type (void) { static GtkType type = 0; if(!type) { static const GtkTypeInfo info = { "GimpBrush", sizeof (GimpBrush), sizeof (GimpBrushClass), (GtkClassInitFunc) gimp_brush_class_init, (GtkObjectInitFunc) gimp_brush_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL }; type = gtk_type_unique (gimp_object_get_type (), &info); } return type; } GimpBrush * gimp_brush_new (char *filename) { GimpBrush *brush=GIMP_BRUSH(gtk_type_new(gimp_brush_get_type ())); gimp_brush_load(brush, filename); return brush; } TempBuf * gimp_brush_get_mask (GimpBrush *brush) { g_return_val_if_fail(GIMP_IS_BRUSH(brush), NULL); return brush->mask; } char * gimp_brush_get_name (GimpBrush *brush) { g_return_val_if_fail(GIMP_IS_BRUSH(brush), NULL); return brush->name; } void gimp_brush_set_name (GimpBrush *brush, char *name) { g_return_if_fail(GIMP_IS_BRUSH(brush)); if (strcmp(brush->name, name) == 0) return; if (brush->name) g_free(brush->name); brush->name = g_strdup(name); gtk_signal_emit(GTK_OBJECT(brush), gimp_brush_signals[RENAME]); } int gimp_brush_get_spacing (GimpBrush *brush) { g_return_val_if_fail (brush != NULL, 0); g_return_val_if_fail (GIMP_IS_BRUSH (brush), 0); return brush->spacing; } void gimp_brush_set_spacing (GimpBrush *brush, int spacing) { g_return_if_fail (brush != NULL); g_return_if_fail (GIMP_IS_BRUSH (brush)); brush->spacing = spacing; } void gimp_brush_load(GimpBrush *brush, char *filename) { FILE * fp; brush->filename = g_strdup (filename); /* Open the requested file */ if (! (fp = fopen (filename, "rb"))) { gimp_object_destroy (brush); return; } gimp_brush_load_brush(brush,fp,filename); /* Clean up */ fclose (fp); /* Swap the brush to disk (if we're being stingy with memory) */ if (stingy_memory_use) temp_buf_swap (brush->mask); } int gimp_brush_load_brush(GimpBrush *brush, FILE* fp, char* filename) { int bn_size; unsigned char buf [sz_BrushHeader]; BrushHeader header; unsigned int * hp; int i; /* Read in the header size */ if ((fread (buf, 1, sz_BrushHeader, fp)) < sz_BrushHeader) { fclose (fp); gimp_object_destroy (brush); return 0; } /* rearrange the bytes in each unsigned int */ hp = (unsigned int *) &header; for (i = 0; i < (sz_BrushHeader / 4); i++) hp [i] = (buf [i * 4] << 24) + (buf [i * 4 + 1] << 16) + (buf [i * 4 + 2] << 8) + (buf [i * 4 + 3]); /* Check for correct file format */ if (header.magic_number != GBRUSH_MAGIC) { if (header.version != 1) { fclose (fp); gimp_object_destroy (brush); return 0; } } if (header.version == 1) { /* If this is a version 1 brush, set the fp back 8 bytes */ fseek (fp, -8, SEEK_CUR); header.header_size += 8; /* spacing is not defined in version 1 */ header.spacing = 25; } /* Read in the brush name */ if ((bn_size = (header.header_size - sz_BrushHeader))) { brush->name = (char *) g_malloc (sizeof (char) * bn_size); if ((fread (brush->name, 1, bn_size, fp)) < bn_size) { g_message (_("Error in GIMP brush file...aborting.")); fclose (fp); gimp_object_destroy (brush); return 0; } } else brush->name = g_strdup (_("Unnamed")); switch(header.version) { case 1: case 2: /* Get a new brush mask */ brush->mask = temp_buf_new (header.width, header.height, header.bytes, 0, 0, NULL); brush->spacing = header.spacing; /* set up spacing axis */ brush->x_axis.x = header.width / 2.0; brush->x_axis.y = 0.0; brush->y_axis.x = 0.0; brush->y_axis.y = header.height / 2.0; /* Read the brush mask data */ if ((fread (temp_buf_data (brush->mask), 1, header.width * header.height, fp)) < header.width * header.height) g_message (_("GIMP brush file appears to be truncated.")); break; default: g_message (_("Unknown brush format version #%d in \"%s\"\n"), header.version, filename); fclose (fp); gimp_object_destroy (brush); return 0; } return 1; }