Exemple #1
0
/* Converts items from one image to another */
static void
file_open_convert_items (GimpImage   *dest_image,
                         const gchar *basename,
                         GList       *items)
{
  GList *list;

  for (list = items; list; list = g_list_next (list))
    {
      GimpItem *src = list->data;
      GimpItem *item;

      item = gimp_item_convert (src, dest_image, G_TYPE_FROM_INSTANCE (src));

      if (g_list_length (items) == 1)
        {
          gimp_object_set_name (GIMP_OBJECT (item), basename);
        }
      else
        {
          gimp_object_set_name (GIMP_OBJECT (item),
                                gimp_object_get_name (src));
        }

      list->data = item;
    }
}
static void
palette_import_response (GtkWidget    *widget,
                         gint          response_id,
                         ImportDialog *dialog)
{
  Gimp *gimp = dialog->context->gimp;

  palette_import_image_changed (dialog->context, NULL, dialog);

  if (dialog->palette)
    {
      if (response_id == GTK_RESPONSE_OK)
        {
          const gchar *name = gtk_entry_get_text (GTK_ENTRY (dialog->entry));

          if (name && *name)
            gimp_object_set_name (GIMP_OBJECT (dialog->palette), name);

          gimp_container_add (gimp_data_factory_get_container (gimp->palette_factory),
                              GIMP_OBJECT (dialog->palette));
        }
    }

  gtk_widget_destroy (dialog->dialog);
}
Exemple #3
0
const gchar *
gimp_edit_named_copy_visible (GimpImage    *image,
                              const gchar  *name,
                              GimpContext  *context,
                              GError      **error)
{
  GimpBuffer *buffer;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
  g_return_val_if_fail (name != NULL, NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);

  buffer = gimp_edit_extract (image, GIMP_PICKABLE (image),
                              context, FALSE, error);

  if (buffer)
    {
      gimp_object_set_name (GIMP_OBJECT (buffer), name);
      gimp_container_add (image->gimp->named_buffers, GIMP_OBJECT (buffer));
      g_object_unref (buffer);

      return gimp_object_get_name (buffer);
    }

  return NULL;
}
static void
gimp_image_map_config_set_property (GObject      *object,
                                    guint         property_id,
                                    const GValue *value,
                                    GParamSpec   *pspec)
{
  GimpImageMapConfig *config = GIMP_IMAGE_MAP_CONFIG (object);

  switch (property_id)
    {
    case PROP_TIME:
      config->time = g_value_get_uint (value);

      if (config->time > 0)
        {
          time_t     t;
          struct tm  tm;
          gchar      buf[64];
          gchar     *name;

          t = config->time;
          tm = *localtime (&t);
          strftime (buf, sizeof (buf), "%Y-%m-%d %H:%M:%S", &tm);

          name = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL);
          gimp_object_set_name (GIMP_OBJECT (config), name);
          g_free (name);
        }
      break;

   default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}
Exemple #5
0
const gchar *
gimp_edit_named_cut (GimpImage     *image,
                     const gchar   *name,
                     GimpDrawable  *drawable,
                     GimpContext   *context,
                     GError       **error)
{
  GimpBuffer *buffer;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
  g_return_val_if_fail (name != NULL, NULL);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);

  buffer = gimp_edit_extract (image, GIMP_PICKABLE (drawable),
                              context, TRUE, error);

  if (buffer)
    {
      gimp_object_set_name (GIMP_OBJECT (buffer), name);
      gimp_container_add (image->gimp->named_buffers, GIMP_OBJECT (buffer));
      g_object_unref (buffer);

      return gimp_object_get_name (buffer);
    }

  return NULL;
}
GimpLayer *
gimp_image_merge_group_layer (GimpImage      *image,
                              GimpGroupLayer *group)
{
  GimpLayer *parent;
  GimpLayer *layer;
  gint       index;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
  g_return_val_if_fail (GIMP_IS_GROUP_LAYER (group), NULL);
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (group)), NULL);
  g_return_val_if_fail (gimp_item_get_image (GIMP_ITEM (group)) == image, NULL);

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE,
                               C_("undo-type", "Merge Layer Group"));

  parent = gimp_layer_get_parent (GIMP_LAYER (group));
  index  = gimp_item_get_index (GIMP_ITEM (group));

  layer = GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (group),
                                           GIMP_TYPE_LAYER));

  gimp_object_set_name (GIMP_OBJECT (layer), gimp_object_get_name (group));

  gimp_image_remove_layer (image, GIMP_LAYER (group), TRUE, NULL);
  gimp_image_add_layer (image, layer, parent, index, TRUE);

  gimp_image_undo_group_end (image);

  return layer;
}
Exemple #7
0
static void
gimp_device_info_constructed (GObject *object)
{
  GimpDeviceInfo *info = GIMP_DEVICE_INFO (object);
  Gimp           *gimp;

  G_OBJECT_CLASS (parent_class)->constructed (object);

  g_assert ((info->device == NULL         && info->display == NULL) ||
            (GDK_IS_DEVICE (info->device) && GDK_IS_DISPLAY (info->display)));

  gimp = GIMP_CONTEXT (object)->gimp;

  if (info->device)
    {
      g_object_set_data (G_OBJECT (info->device), GIMP_DEVICE_INFO_DATA_KEY,
                         info);

      gimp_object_set_name (GIMP_OBJECT (info), info->device->name);

      info->mode    = info->device->mode;
      info->n_axes  = info->device->num_axes;
      info->n_keys  = info->device->num_keys;
    }

  gimp_context_define_properties (GIMP_CONTEXT (object),
                                  GIMP_DEVICE_INFO_CONTEXT_MASK,
                                  FALSE);
  gimp_context_copy_properties (gimp_get_user_context (gimp),
                                GIMP_CONTEXT (object),
                                GIMP_DEVICE_INFO_CONTEXT_MASK);

  gimp_context_set_serialize_properties (GIMP_CONTEXT (object),
                                         GIMP_DEVICE_INFO_CONTEXT_MASK);

  /*  FIXME: this is ugly and needs to be done via "notify" once
   *  the contexts' properties are dynamic.
   */
  g_signal_connect (object, "foreground-changed",
                    G_CALLBACK (gimp_device_info_changed),
                    NULL);
  g_signal_connect (object, "background-changed",
                    G_CALLBACK (gimp_device_info_changed),
                    NULL);
  g_signal_connect (object, "tool-changed",
                    G_CALLBACK (gimp_device_info_changed),
                    NULL);
  g_signal_connect (object, "brush-changed",
                    G_CALLBACK (gimp_device_info_changed),
                    NULL);
  g_signal_connect (object, "pattern-changed",
                    G_CALLBACK (gimp_device_info_changed),
                    NULL);
  g_signal_connect (object, "gradient-changed",
                    G_CALLBACK (gimp_device_info_changed),
                    NULL);
}
Exemple #8
0
void
gimp_fonts_init (Gimp *gimp)
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));

  gimp->fonts = gimp_font_list_new (72.0, 72.0);
  gimp_object_set_name (GIMP_OBJECT (gimp->fonts), "fonts");

  g_signal_connect_swapped (gimp->config, "notify::font-path",
                            G_CALLBACK (gimp_fonts_load), gimp);
}
Exemple #9
0
static gboolean
gimp_item_real_rename (GimpItem     *item,
                       const gchar  *new_name,
                       const gchar  *undo_desc,
                       GError      **error)
{
  if (gimp_item_is_attached (item))
    gimp_image_undo_push_item_rename (item->image, undo_desc, item);

  gimp_object_set_name (GIMP_OBJECT (item), new_name);

  return TRUE;
}
Exemple #10
0
static void
gimp_tool_preset_set_property (GObject      *object,
                               guint         property_id,
                               const GValue *value,
                               GParamSpec   *pspec)
{
  GimpToolPreset *tool_preset = GIMP_TOOL_PRESET (object);

  switch (property_id)
    {
    case PROP_NAME:
      gimp_object_set_name (GIMP_OBJECT (tool_preset),
                            g_value_get_string (value));
      break;

    case PROP_GIMP:
      tool_preset->gimp = g_value_get_object (value); /* don't ref */
      break;

    case PROP_TOOL_OPTIONS:
      gimp_tool_preset_set_options (tool_preset,
                                    GIMP_TOOL_OPTIONS (g_value_get_object (value)));
      break;

    case PROP_USE_FG_BG:
      tool_preset->use_fg_bg = g_value_get_boolean (value);
      break;
    case PROP_USE_BRUSH:
      tool_preset->use_brush = g_value_get_boolean (value);
      break;
    case PROP_USE_DYNAMICS:
      tool_preset->use_dynamics = g_value_get_boolean (value);
      break;
    case PROP_USE_PATTERN:
      tool_preset->use_pattern = g_value_get_boolean (value);
      break;
    case PROP_USE_PALETTE:
      tool_preset->use_palette = g_value_get_boolean (value);
      break;
    case PROP_USE_GRADIENT:
      tool_preset->use_gradient = g_value_get_boolean (value);
      break;
    case PROP_USE_FONT:
      tool_preset->use_font = g_value_get_boolean (value);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}
Exemple #11
0
static void
gimp_template_view_tree_name_edited (GtkCellRendererText *cell,
                                     const gchar         *path_str,
                                     const gchar         *new_name,
                                     GimpTemplateView    *view)
{
  GimpContainerTreeView *tree_view;
  GtkTreePath           *path;
  GtkTreeIter            iter;

  tree_view = GIMP_CONTAINER_TREE_VIEW (GIMP_CONTAINER_EDITOR (view)->view);

  path = gtk_tree_path_new_from_string (path_str);

  if (gtk_tree_model_get_iter (tree_view->model, &iter, path))
    {
      GimpViewRenderer *renderer;
      GimpObject       *object;
      const gchar      *old_name;

      gtk_tree_model_get (tree_view->model, &iter,
                          GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
                          -1);

      object = GIMP_OBJECT (renderer->viewable);

      old_name = gimp_object_get_name (object);

      if (! old_name) old_name = "";
      if (! new_name) new_name = "";

      if (strcmp (old_name, new_name))
        {
          gimp_object_set_name (object, new_name);
        }
      else
        {
          gchar *name = gimp_viewable_get_description (renderer->viewable,
                                                       NULL);

          gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), &iter,
                              GIMP_CONTAINER_TREE_STORE_COLUMN_NAME, name,
                              -1);
          g_free (name);
        }

      g_object_unref (renderer);
    }

  gtk_tree_path_free (path);
}
Exemple #12
0
/**
 * gimp_item_configure:
 * @item:     The #GimpItem to configure.
 * @image:    The #GimpImage to which the item belongs.
 * @offset_x: The X offset to assign the item.
 * @offset_y: The Y offset to assign the item.
 * @width:    The width to assign the item.
 * @height:   The height to assign the item.
 * @name:     The name to assign the item.
 *
 * This function is used to configure a new item.  First, if the item
 * does not already have an ID, it is assigned the next available
 * one, and then inserted into the Item Hash Table.  Next, it is
 * given basic item properties as specified by the arguments.
 */
void
gimp_item_configure (GimpItem    *item,
                     GimpImage   *image,
                     gint         offset_x,
                     gint         offset_y,
                     gint         width,
                     gint         height,
                     const gchar *name)
{
  g_return_if_fail (GIMP_IS_ITEM (item));
  g_return_if_fail (GIMP_IS_IMAGE (image));

  g_object_freeze_notify (G_OBJECT (item));

  if (item->ID == 0)
    {
      do
        {
          item->ID = image->gimp->next_item_ID++;

          if (image->gimp->next_item_ID == G_MAXINT)
            image->gimp->next_item_ID = 1;
        }
      while (g_hash_table_lookup (image->gimp->item_table,
                                  GINT_TO_POINTER (item->ID)));

      g_hash_table_insert (image->gimp->item_table,
                           GINT_TO_POINTER (item->ID),
                           item);

      gimp_item_set_image (item, image);

      g_object_notify (G_OBJECT (item), "id");
    }

  item->width    = width;
  item->height   = height;
  item->offset_x = offset_x;
  item->offset_y = offset_y;

  g_object_notify (G_OBJECT (item), "width");
  g_object_notify (G_OBJECT (item), "height");

  if (name)
    gimp_object_set_name (GIMP_OBJECT (item), name);
  else
    gimp_object_set_static_name (GIMP_OBJECT (item), _("Unnamed"));

  g_object_thaw_notify (G_OBJECT (item));
}
Exemple #13
0
static GimpItem *
gimp_image_duplicate_item (GimpItem  *item,
                           GimpImage *new_image)
{
  GimpItem *new_item;

  new_item = gimp_item_convert (item, new_image,
                                G_TYPE_FROM_INSTANCE (item));

  /*  Make sure the copied item doesn't say: "<old item> copy"  */
  gimp_object_set_name (GIMP_OBJECT (new_item),
                        gimp_object_get_name (item));

  return new_item;
}
Exemple #14
0
static void
gimp_thumb_box_create_thumbnail (GimpThumbBox      *box,
                                 const gchar       *uri,
                                 GimpThumbnailSize  size,
                                 gboolean           force,
                                 GimpProgress      *progress)
{
  gchar         *filename = file_utils_filename_from_uri (uri);
  GimpThumbnail *thumb;
  gchar         *basename;

  if (filename)
    {
      gboolean regular = g_file_test (filename, G_FILE_TEST_IS_REGULAR);

      g_free (filename);

      if (! regular)
        return;
    }

  thumb = gimp_imagefile_get_thumbnail (box->imagefile);

  basename = file_utils_uri_display_basename (uri);
  gtk_label_set_text (GTK_LABEL (box->filename), basename);
  g_free (basename);

  gimp_object_set_name (GIMP_OBJECT (box->imagefile), uri);

  if (force ||
      (gimp_thumbnail_peek_thumb (thumb, size) < GIMP_THUMB_STATE_FAILED &&
       ! gimp_thumbnail_has_failed (thumb)))
    {
      GError *error = NULL;

      if (! gimp_imagefile_create_thumbnail (box->imagefile, box->context,
                                             progress,
                                             size, ! force, &error))
        {
          gimp_message_literal (box->context->gimp,
				G_OBJECT (progress), GIMP_MESSAGE_ERROR,
				error->message);
          g_clear_error (&error);
        }
    }
}
Exemple #15
0
static void
gimp_object_set_property (GObject      *object,
                          guint         property_id,
                          const GValue *value,
                          GParamSpec   *pspec)
{
  GimpObject *gimp_object = GIMP_OBJECT (object);

  switch (property_id)
    {
    case PROP_NAME:
      gimp_object_set_name (gimp_object, g_value_get_string (value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}
Exemple #16
0
GimpDialogFactory *
gimp_dialog_factory_new (const gchar       *name,
                         GimpContext       *context,
                         GimpMenuFactory   *menu_factory,
                         GimpDialogNewFunc  new_dock_func,
                         gboolean           toggle_visibility)
{
  GimpDialogFactory *factory;
  gpointer           key;

  g_return_val_if_fail (name != NULL, NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
  g_return_val_if_fail (! menu_factory || GIMP_IS_MENU_FACTORY (menu_factory),
                        NULL);

  if (gimp_dialog_factory_from_name (name))
    {
      g_warning ("%s: dialog factory \"%s\" already exists",
                 G_STRFUNC, name);
      return NULL;
    }

  factory = g_object_new (GIMP_TYPE_DIALOG_FACTORY, NULL);

  gimp_object_set_name (GIMP_OBJECT (factory), name);

  /*  hack to keep the toolbox on the pool position  */
  if (strcmp (name, "toolbox") == 0)
    key = "";
  else
    key = GIMP_OBJECT (factory)->name;

  g_hash_table_insert (GIMP_DIALOG_FACTORY_GET_CLASS (factory)->factories,
                       key, factory);

  factory->context           = context;
  factory->menu_factory      = menu_factory;
  factory->new_dock_func     = new_dock_func;
  factory->toggle_visibility = toggle_visibility;

  return factory;
}
Exemple #17
0
static GimpValueArray *
palette_rename_invoker (GimpProcedure         *procedure,
                        Gimp                  *gimp,
                        GimpContext           *context,
                        GimpProgress          *progress,
                        const GimpValueArray  *args,
                        GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  const gchar *name;
  const gchar *new_name;
  gchar *actual_name = NULL;

  name = g_value_get_string (gimp_value_array_index (args, 0));
  new_name = g_value_get_string (gimp_value_array_index (args, 1));

  if (success)
    {
      GimpPalette *palette = gimp_pdb_get_palette (gimp, name, TRUE, error);

      if (palette)
        {
          gimp_object_set_name (GIMP_OBJECT (palette), new_name);
          actual_name = g_strdup (gimp_object_get_name (palette));
        }
      else
        success = FALSE;
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    g_value_take_string (gimp_value_array_index (return_vals, 1), actual_name);

  return return_vals;
}
Exemple #18
0
static GValueArray *
buffer_rename_invoker (GimpProcedure     *procedure,
                       Gimp              *gimp,
                       GimpContext       *context,
                       GimpProgress      *progress,
                       const GValueArray *args)
{
  gboolean success = TRUE;
  GValueArray *return_vals;
  const gchar *buffer_name;
  const gchar *new_name;
  gchar *real_name = NULL;

  buffer_name = g_value_get_string (&args->values[0]);
  new_name = g_value_get_string (&args->values[1]);

  if (success)
    {
      GimpBuffer *buffer = (GimpBuffer *)
        gimp_container_get_child_by_name (gimp->named_buffers, buffer_name);

      if (buffer)
        {
          gimp_object_set_name (GIMP_OBJECT (buffer), new_name);
          real_name = g_strdup (gimp_object_get_name (GIMP_OBJECT (buffer)));
        }
      else
        success = FALSE;
    }

  return_vals = gimp_procedure_get_return_values (procedure, success);

  if (success)
    g_value_take_string (&return_vals->values[1], real_name);

  return return_vals;
}
Exemple #19
0
static GValueArray *
palette_rename_invoker (GimpProcedure     *procedure,
                        Gimp              *gimp,
                        GimpContext       *context,
                        GimpProgress      *progress,
                        const GValueArray *args)
{
  gboolean success = TRUE;
  GValueArray *return_vals;
  const gchar *name;
  const gchar *new_name;
  gchar *actual_name = NULL;

  name = g_value_get_string (&args->values[0]);
  new_name = g_value_get_string (&args->values[1]);

  if (success)
    {
      GimpPalette *palette = (GimpPalette *)
        gimp_container_get_child_by_name (gimp->palette_factory->container, name);

      if (palette && GIMP_DATA (palette)->writable)
        {
          gimp_object_set_name (GIMP_OBJECT (palette), new_name);
          actual_name = g_strdup (gimp_object_get_name (GIMP_OBJECT (palette)));
        }
      else
        success = FALSE;
    }

  return_vals = gimp_procedure_get_return_values (procedure, success);

  if (success)
    g_value_take_string (&return_vals->values[1], actual_name);

  return return_vals;
}
Exemple #20
0
static GimpLayer *
gimp_image_duplicate_layers (GimpImage *image,
                             GimpImage *new_image)
{
  GimpLayer *active_layer = NULL;
  GList     *list;
  gint       count;

  for (list = gimp_image_get_layer_iter (image), count = 0;
       list;
       list = g_list_next (list))
    {
      GimpLayer *layer = list->data;
      GimpLayer *new_layer;

      if (gimp_layer_is_floating_sel (layer))
        continue;

      new_layer = GIMP_LAYER (gimp_image_duplicate_item (GIMP_ITEM (layer),
                                                         new_image));

      /*  Make sure that if the layer has a layer mask,
       *  its name isn't screwed up
       */
      if (new_layer->mask)
        gimp_object_set_name (GIMP_OBJECT (new_layer->mask),
                              gimp_object_get_name (layer->mask));

      if (gimp_image_get_active_layer (image) == layer)
        active_layer = new_layer;

      gimp_image_add_layer (new_image, new_layer,
                            NULL, count++, FALSE);
    }

  return active_layer;
}
Exemple #21
0
static void
gimp_image_duplicate_floating_sel (GimpImage *image,
                                   GimpImage *new_image)
{
  GimpLayer     *floating_sel;
  GimpDrawable  *floating_sel_drawable;
  GList         *floating_sel_path;
  GimpItemStack *new_item_stack;
  GimpLayer     *new_floating_sel;
  GimpDrawable  *new_floating_sel_drawable;

  floating_sel = gimp_image_get_floating_selection (image);

  if (! floating_sel)
    return;

  floating_sel_drawable = gimp_layer_get_floating_sel_drawable (floating_sel);

  if (GIMP_IS_LAYER_MASK (floating_sel_drawable))
    {
      GimpLayer *layer;

      layer = gimp_layer_mask_get_layer (GIMP_LAYER_MASK (floating_sel_drawable));

      floating_sel_path = gimp_item_get_path (GIMP_ITEM (layer));

      new_item_stack = GIMP_ITEM_STACK (gimp_image_get_layers (new_image));
    }
  else
    {
      floating_sel_path = gimp_item_get_path (GIMP_ITEM (floating_sel_drawable));

      if (GIMP_IS_LAYER (floating_sel_drawable))
        new_item_stack = GIMP_ITEM_STACK (gimp_image_get_layers (new_image));
      else
        new_item_stack = GIMP_ITEM_STACK (gimp_image_get_channels (new_image));
    }

  /*  adjust path[0] for the floating layer missing in new_image  */
  floating_sel_path->data =
    GUINT_TO_POINTER (GPOINTER_TO_UINT (floating_sel_path->data) - 1);

  if (GIMP_IS_LAYER (floating_sel_drawable))
    {
      new_floating_sel =
        GIMP_LAYER (gimp_image_duplicate_item (GIMP_ITEM (floating_sel),
                                               new_image));
    }
  else
    {
      /*  can't use gimp_item_convert() for floating selections of channels
       *  or layer masks because they maybe don't have a normal layer's type
       */
      new_floating_sel =
        GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (floating_sel),
                                         G_TYPE_FROM_INSTANCE (floating_sel)));
      gimp_item_set_image (GIMP_ITEM (new_floating_sel), new_image);

      gimp_object_set_name (GIMP_OBJECT (new_floating_sel),
                            gimp_object_get_name (floating_sel));
    }

  /*  Make sure the copied layer doesn't say: "<old layer> copy"  */
  gimp_object_set_name (GIMP_OBJECT (new_floating_sel),
                        gimp_object_get_name (floating_sel));

  new_floating_sel_drawable =
    GIMP_DRAWABLE (gimp_item_stack_get_item_by_path (new_item_stack,
                                                     floating_sel_path));

  if (GIMP_IS_LAYER_MASK (floating_sel_drawable))
    new_floating_sel_drawable =
      GIMP_DRAWABLE (gimp_layer_get_mask (GIMP_LAYER (new_floating_sel_drawable)));

  floating_sel_attach (new_floating_sel, new_floating_sel_drawable);

  g_list_free (floating_sel_path);
}
GList *
gimp_brush_pipe_load (GimpContext  *context,
                      const gchar  *filename,
                      GError      **error)
{
  GimpBrushPipe     *pipe = NULL;
  GimpPixPipeParams  params;
  gint               i;
  gint               num_of_brushes = 0;
  gint               totalcells;
  gchar             *paramstring;
  GString           *buffer;
  gchar              c;
  gint               fd;

  g_return_val_if_fail (filename != NULL, NULL);
  g_return_val_if_fail (g_path_is_absolute (filename), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);

  fd = g_open (filename, O_RDONLY | _O_BINARY, 0);

  if (fd == -1)
    {
      g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_OPEN,
                   _("Could not open '%s' for reading: %s"),
                   gimp_filename_to_utf8 (filename), g_strerror (errno));
      return NULL;
    }

  /* The file format starts with a painfully simple text header */

  /*  get the name  */
  buffer = g_string_new (NULL);
  while (read (fd, &c, 1) == 1 && c != '\n' && buffer->len < 1024)
    g_string_append_c (buffer, c);

  if (buffer->len > 0 && buffer->len < 1024)
    {
      gchar *utf8 =
        gimp_any_to_utf8 (buffer->str, buffer->len,
                          _("Invalid UTF-8 string in brush file '%s'."),
                          gimp_filename_to_utf8 (filename));

      pipe = g_object_new (GIMP_TYPE_BRUSH_PIPE,
                           "name",      utf8,
                           "mime-type", "image/x-gimp-gih",
                           NULL);

      g_free (utf8);
    }

  g_string_free (buffer, TRUE);

  if (! pipe)
    {
      g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
                   _("Fatal parse error in brush file '%s': "
                     "File is corrupt."),
                   gimp_filename_to_utf8 (filename));
      close (fd);
      return NULL;
    }

  /*  get the number of brushes  */
  buffer = g_string_new (NULL);
  while (read (fd, &c, 1) == 1 && c != '\n' && buffer->len < 1024)
    g_string_append_c (buffer, c);

  if (buffer->len > 0 && buffer->len < 1024)
    {
      num_of_brushes = strtol (buffer->str, &paramstring, 10);
    }

  if (num_of_brushes < 1)
    {
      g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
                   _("Fatal parse error in brush file '%s': "
                     "File is corrupt."),
                   gimp_filename_to_utf8 (filename));
      close (fd);
      g_object_unref (pipe);
      g_string_free (buffer, TRUE);
      return NULL;
    }

  while (*paramstring && g_ascii_isspace (*paramstring))
    paramstring++;

  if (*paramstring)
    {
      gimp_pixpipe_params_init (&params);
      gimp_pixpipe_params_parse (paramstring, &params);

      pipe->dimension = params.dim;
      pipe->rank      = g_new0 (gint, pipe->dimension);
      pipe->select    = g_new0 (PipeSelectModes, pipe->dimension);
      pipe->index     = g_new0 (gint, pipe->dimension);

      /* placement is not used at all ?? */
      if (params.free_placement_string)
        g_free (params.placement);

      for (i = 0; i < pipe->dimension; i++)
        {
          pipe->rank[i] = MAX (1, params.rank[i]);
          if (strcmp (params.selection[i], "incremental") == 0)
            pipe->select[i] = PIPE_SELECT_INCREMENTAL;
          else if (strcmp (params.selection[i], "angular") == 0)
            pipe->select[i] = PIPE_SELECT_ANGULAR;
          else if (strcmp (params.selection[i], "velocity") == 0)
            pipe->select[i] = PIPE_SELECT_VELOCITY;
          else if (strcmp (params.selection[i], "random") == 0)
            pipe->select[i] = PIPE_SELECT_RANDOM;
          else if (strcmp (params.selection[i], "pressure") == 0)
            pipe->select[i] = PIPE_SELECT_PRESSURE;
          else if (strcmp (params.selection[i], "xtilt") == 0)
            pipe->select[i] = PIPE_SELECT_TILT_X;
          else if (strcmp (params.selection[i], "ytilt") == 0)
            pipe->select[i] = PIPE_SELECT_TILT_Y;
          else
            pipe->select[i] = PIPE_SELECT_CONSTANT;
          if (params.free_selection_string)
            g_free (params.selection[i]);
          pipe->index[i] = 0;
        }
    }
  else
    {
      pipe->dimension = 1;
      pipe->rank      = g_new (gint, 1);
      pipe->rank[0]   = num_of_brushes;
      pipe->select    = g_new (PipeSelectModes, 1);
      pipe->select[0] = PIPE_SELECT_INCREMENTAL;
      pipe->index     = g_new (gint, 1);
      pipe->index[0]  = 0;
    }

  g_string_free (buffer, TRUE);

  totalcells = 1;                /* Not all necessarily present, maybe */
  for (i = 0; i < pipe->dimension; i++)
    totalcells *= pipe->rank[i];
  pipe->stride = g_new0 (gint, pipe->dimension);
  for (i = 0; i < pipe->dimension; i++)
    {
      if (i == 0)
        pipe->stride[i] = totalcells / pipe->rank[i];
      else
        pipe->stride[i] = pipe->stride[i-1] / pipe->rank[i];
    }
  g_assert (pipe->stride[pipe->dimension-1] == 1);

  pipe->brushes = g_new0 (GimpBrush *, num_of_brushes);

  while (pipe->n_brushes < num_of_brushes)
    {
      GError *my_error = NULL;

      pipe->brushes[pipe->n_brushes] = gimp_brush_load_brush (context,
                                                              fd, filename,
                                                              &my_error);

      if (pipe->brushes[pipe->n_brushes])
        {
          gimp_object_set_name (GIMP_OBJECT (pipe->brushes[pipe->n_brushes]),
                                NULL);
        }
      else
        {
          g_propagate_error (error, my_error);
          close (fd);
          g_object_unref (pipe);
          return NULL;
        }

      pipe->n_brushes++;
    }

  close (fd);

  /* Current brush is the first one. */
  pipe->current = pipe->brushes[0];

  /*  just to satisfy the code that relies on this crap  */
  GIMP_BRUSH (pipe)->spacing  = pipe->current->spacing;
  GIMP_BRUSH (pipe)->x_axis   = pipe->current->x_axis;
  GIMP_BRUSH (pipe)->y_axis   = pipe->current->y_axis;
  GIMP_BRUSH (pipe)->mask     = pipe->current->mask;
  GIMP_BRUSH (pipe)->pixmap   = pipe->current->pixmap;

  return g_list_prepend (NULL, pipe);
}
GimpImage *
gimp_image_duplicate (GimpImage *image)
{
  GimpImage    *new_image;
  GimpLayer    *floating_layer;
  GList        *list;
  GimpLayer    *active_layer              = NULL;
  GimpChannel  *active_channel            = NULL;
  GimpVectors  *active_vectors            = NULL;
  GimpDrawable *new_floating_sel_drawable = NULL;
  GimpDrawable *floating_sel_drawable     = NULL;
  gchar        *filename;
  gint          count;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);

  gimp_set_busy_until_idle (image->gimp);

  /*  Create a new image  */
  new_image = gimp_create_image (image->gimp,
                                 image->width, image->height,
                                 image->base_type,
                                 FALSE);
  gimp_image_undo_disable (new_image);

  /*  Store the folder to be used by the save dialog  */
  filename = gimp_image_get_filename (image);
  if (filename)
    {
      g_object_set_data_full (G_OBJECT (new_image), "gimp-image-dirname",
                              g_path_get_dirname (filename),
                              (GDestroyNotify) g_free);
      g_free (filename);
    }

  /*  Copy the colormap if necessary  */
  if (new_image->base_type == GIMP_INDEXED)
    gimp_image_set_colormap (new_image,
                             gimp_image_get_colormap (image),
                             gimp_image_get_colormap_size (image),
                             FALSE);

  /*  Copy resolution information  */
  new_image->xresolution     = image->xresolution;
  new_image->yresolution     = image->yresolution;
  new_image->resolution_unit = image->resolution_unit;

  /*  Copy floating layer  */
  floating_layer = gimp_image_floating_sel (image);
  if (floating_layer)
    {
      floating_sel_relax (floating_layer, FALSE);

      floating_sel_drawable = floating_layer->fs.drawable;
      floating_layer = NULL;
    }

  /*  Copy the layers  */
  for (list = GIMP_LIST (image->layers)->list, count = 0;
       list;
       list = g_list_next (list))
    {
      GimpLayer *layer = list->data;
      GimpLayer *new_layer;

      new_layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (layer),
                                                 new_image,
                                                 G_TYPE_FROM_INSTANCE (layer),
                                                 FALSE));

      /*  Make sure the copied layer doesn't say: "<old layer> copy"  */
      gimp_object_set_name (GIMP_OBJECT (new_layer),
                            gimp_object_get_name (GIMP_OBJECT (layer)));

      /*  Make sure that if the layer has a layer mask,
       *  its name isn't screwed up
       */
      if (new_layer->mask)
        gimp_object_set_name (GIMP_OBJECT (new_layer->mask),
                              gimp_object_get_name (GIMP_OBJECT (layer->mask)));

      if (gimp_image_get_active_layer (image) == layer)
        active_layer = new_layer;

      if (image->floating_sel == layer)
        floating_layer = new_layer;

      if (floating_sel_drawable == GIMP_DRAWABLE (layer))
        new_floating_sel_drawable = GIMP_DRAWABLE (new_layer);

      if (floating_layer != new_layer)
        gimp_image_add_layer (new_image, new_layer, count++);
    }

  /*  Copy the channels  */
  for (list = GIMP_LIST (image->channels)->list, count = 0;
       list;
       list = g_list_next (list))
    {
      GimpChannel *channel = list->data;
      GimpChannel *new_channel;

      new_channel =
        GIMP_CHANNEL (gimp_item_convert (GIMP_ITEM (channel),
                                         new_image,
                                         G_TYPE_FROM_INSTANCE (channel),
                                         FALSE));

      /*  Make sure the copied channel doesn't say: "<old channel> copy"  */
      gimp_object_set_name (GIMP_OBJECT (new_channel),
                            gimp_object_get_name (GIMP_OBJECT (channel)));

      if (gimp_image_get_active_channel (image) == channel)
        active_channel = (new_channel);

      if (floating_sel_drawable == GIMP_DRAWABLE (channel))
        new_floating_sel_drawable = GIMP_DRAWABLE (new_channel);

      gimp_image_add_channel (new_image, new_channel, count++);
    }

  /*  Copy any vectors  */
  for (list = GIMP_LIST (image->vectors)->list, count = 0;
       list;
       list = g_list_next (list))
    {
      GimpVectors *vectors = list->data;
      GimpVectors *new_vectors;

      new_vectors =
        GIMP_VECTORS (gimp_item_convert (GIMP_ITEM (vectors),
                                         new_image,
                                         G_TYPE_FROM_INSTANCE (vectors),
                                         FALSE));

      /*  Make sure the copied vectors doesn't say: "<old vectors> copy"  */
      gimp_object_set_name (GIMP_OBJECT (new_vectors),
                            gimp_object_get_name (GIMP_OBJECT (vectors)));

      if (gimp_image_get_active_vectors (image) == vectors)
        active_vectors = new_vectors;

      gimp_image_add_vectors (new_image, new_vectors, count++);
    }

  /*  Copy the selection mask  */
  {
    TileManager *src_tiles;
    TileManager *dest_tiles;
    PixelRegion  srcPR, destPR;

    src_tiles  =
      gimp_drawable_get_tiles (GIMP_DRAWABLE (image->selection_mask));
    dest_tiles =
      gimp_drawable_get_tiles (GIMP_DRAWABLE (new_image->selection_mask));

    pixel_region_init (&srcPR, src_tiles,
                       0, 0, image->width, image->height, FALSE);
    pixel_region_init (&destPR, dest_tiles,
                       0, 0, image->width, image->height, TRUE);

    copy_region (&srcPR, &destPR);

    new_image->selection_mask->bounds_known   = FALSE;
    new_image->selection_mask->boundary_known = FALSE;
  }

  if (floating_layer)
    floating_sel_attach (floating_layer, new_floating_sel_drawable);

  /*  Set active layer, active channel, active vectors  */
  if (active_layer)
    gimp_image_set_active_layer (new_image, active_layer);

  if (active_channel)
    gimp_image_set_active_channel (new_image, active_channel);

  if (active_vectors)
    gimp_image_set_active_vectors (new_image, active_vectors);

  /*  Copy state of all color channels  */
  for (count = 0; count < MAX_CHANNELS; count++)
    {
      new_image->visible[count] = image->visible[count];
      new_image->active[count]  = image->active[count];
    }

  /*  Copy any guides  */
  for (list = image->guides; list; list = g_list_next (list))
    {
      GimpGuide *guide    = list->data;
      gint       position = gimp_guide_get_position (guide);

      switch (gimp_guide_get_orientation (guide))
        {
        case GIMP_ORIENTATION_HORIZONTAL:
          gimp_image_add_hguide (new_image, position, FALSE);
          break;

        case GIMP_ORIENTATION_VERTICAL:
          gimp_image_add_vguide (new_image, position, FALSE);
          break;

        default:
          g_error ("Unknown guide orientation.\n");
        }
    }

  /*  Copy any sample points  */
  for (list = image->sample_points; list; list = g_list_next (list))
    {
      GimpSamplePoint *sample_point = list->data;

      gimp_image_add_sample_point_at_pos (new_image,
                                          sample_point->x,
                                          sample_point->y,
                                          FALSE);
    }

  /*  Copy the grid  */
  if (image->grid)
    gimp_image_set_grid (new_image, image->grid, FALSE);

  /*  Copy the quick mask info  */
  new_image->quick_mask_state    = image->quick_mask_state;
  new_image->quick_mask_inverted = image->quick_mask_inverted;
  new_image->quick_mask_color    = image->quick_mask_color;

  /*  Copy parasites  */
  if (image->parasites)
    {
      g_object_unref (new_image->parasites);
      new_image->parasites = gimp_parasite_list_copy (image->parasites);
    }

  gimp_image_undo_enable (new_image);

  return new_image;
}