static void gimp_vectors_mod_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { GimpVectorsModUndo *vectors_mod_undo = GIMP_VECTORS_MOD_UNDO (undo); GimpVectors *vectors = GIMP_VECTORS (GIMP_ITEM_UNDO (undo)->item); GimpVectors *temp; GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); temp = vectors_mod_undo->vectors; vectors_mod_undo->vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), G_TYPE_FROM_INSTANCE (vectors), FALSE)); gimp_vectors_freeze (vectors); gimp_vectors_copy_strokes (temp, vectors); GIMP_ITEM (vectors)->width = GIMP_ITEM (temp)->width; GIMP_ITEM (vectors)->height = GIMP_ITEM (temp)->height; GIMP_ITEM (vectors)->offset_x = GIMP_ITEM (temp)->offset_x; GIMP_ITEM (vectors)->offset_y = GIMP_ITEM (temp)->offset_y; g_object_unref (temp); gimp_vectors_thaw (vectors); }
static void gimp_vectors_transform (GimpItem *item, GimpContext *context, const GimpMatrix3 *matrix, GimpTransformDirection direction, GimpInterpolationType interpolation_type, GimpTransformResize clip_result, GimpProgress *progress) { GimpVectors *vectors = GIMP_VECTORS (item); GimpMatrix3 local_matrix; GList *list; gimp_vectors_freeze (vectors); gimp_image_undo_push_vectors_mod (gimp_item_get_image (item), _("Transform Path"), vectors); local_matrix = *matrix; if (direction == GIMP_TRANSFORM_BACKWARD) gimp_matrix3_invert (&local_matrix); for (list = vectors->strokes; list; list = g_list_next (list)) { GimpStroke *stroke = list->data; gimp_stroke_transform (stroke, &local_matrix); } gimp_vectors_thaw (vectors); }
static void gimp_vectors_rotate (GimpItem *item, GimpContext *context, GimpRotationType rotate_type, gdouble center_x, gdouble center_y, gboolean clip_result) { GimpVectors *vectors = GIMP_VECTORS (item); GList *list; GimpMatrix3 matrix; gimp_matrix3_identity (&matrix); gimp_transform_matrix_rotate (&matrix, rotate_type, center_x, center_y); gimp_vectors_freeze (vectors); gimp_image_undo_push_vectors_mod (gimp_item_get_image (item), _("Rotate Path"), vectors); for (list = vectors->strokes; list; list = g_list_next (list)) { GimpStroke *stroke = list->data; gimp_stroke_transform (stroke, &matrix); } gimp_vectors_thaw (vectors); }
static void gimp_vectors_resize (GimpItem *item, GimpContext *context, gint new_width, gint new_height, gint offset_x, gint offset_y) { GimpVectors *vectors = GIMP_VECTORS (item); GimpImage *image = gimp_item_get_image (item); GList *list; gimp_vectors_freeze (vectors); if (gimp_item_is_attached (item)) gimp_image_undo_push_vectors_mod (image, NULL, vectors); for (list = vectors->strokes; list; list = g_list_next (list)) { GimpStroke *stroke = list->data; gimp_stroke_translate (stroke, offset_x, offset_y); } GIMP_ITEM_CLASS (parent_class)->resize (item, context, gimp_image_get_width (image), gimp_image_get_height (image), 0, 0); gimp_vectors_thaw (vectors); }
GimpVectors * gimp_vectors_get_parent (GimpVectors *vectors) { g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL); return GIMP_VECTORS (gimp_viewable_get_parent (GIMP_VIEWABLE (vectors))); }
static void gimp_vectors_translate (GimpItem *item, gint offset_x, gint offset_y, gboolean push_undo) { GimpVectors *vectors = GIMP_VECTORS (item); GList *list; gimp_vectors_freeze (vectors); if (push_undo) gimp_image_undo_push_vectors_mod (gimp_item_get_image (item), _("Move Path"), vectors); for (list = vectors->strokes; list; list = g_list_next (list)) { GimpStroke *stroke = list->data; gimp_stroke_translate (stroke, offset_x, offset_y); } gimp_vectors_thaw (vectors); }
static GimpVectors * gimp_image_duplicate_vectors (GimpImage *image, GimpImage *new_image) { GimpVectors *active_vectors = NULL; GList *list; gint count; for (list = gimp_image_get_vectors_iter (image), count = 0; list; list = g_list_next (list)) { GimpVectors *vectors = list->data; GimpVectors *new_vectors; new_vectors = GIMP_VECTORS (gimp_image_duplicate_item (GIMP_ITEM (vectors), new_image)); if (gimp_image_get_active_vectors (image) == vectors) active_vectors = new_vectors; gimp_image_add_vectors (new_image, new_vectors, NULL, count++, FALSE); } return active_vectors; }
static gboolean gimp_vectors_stroke (GimpItem *item, GimpDrawable *drawable, GimpStrokeOptions *stroke_options, gboolean push_undo, GimpProgress *progress, GError **error) { GimpVectors *vectors = GIMP_VECTORS (item); gboolean retval = FALSE; if (! vectors->strokes) { g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, _("Not enough points to stroke")); return FALSE; } switch (gimp_stroke_options_get_method (stroke_options)) { case GIMP_STROKE_METHOD_LIBART: retval = gimp_drawable_stroke_vectors (drawable, stroke_options, vectors, push_undo, error); break; case GIMP_STROKE_METHOD_PAINT_CORE: { GimpPaintInfo *paint_info; GimpPaintCore *core; GimpPaintOptions *paint_options; gboolean emulate_dynamics; paint_info = gimp_context_get_paint_info (GIMP_CONTEXT (stroke_options)); core = g_object_new (paint_info->paint_type, NULL); paint_options = gimp_stroke_options_get_paint_options (stroke_options); emulate_dynamics = gimp_stroke_options_get_emulate_dynamics (stroke_options); retval = gimp_paint_core_stroke_vectors (core, drawable, paint_options, emulate_dynamics, vectors, push_undo, error); g_object_unref (core); } break; default: g_return_val_if_reached (FALSE); } return retval; }
TempBuf * gimp_vectors_get_new_preview (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpVectors *vectors; GimpItem *item; GimpStroke *cur_stroke; gdouble xscale, yscale; guchar *data; TempBuf *temp_buf; guchar white[1] = { 255 }; vectors = GIMP_VECTORS (viewable); item = GIMP_ITEM (viewable); xscale = ((gdouble) width) / gimp_image_get_width (item->image); yscale = ((gdouble) height) / gimp_image_get_height (item->image); temp_buf = temp_buf_new (width, height, 1, 0, 0, white); data = temp_buf_data (temp_buf); for (cur_stroke = gimp_vectors_stroke_get_next (vectors, NULL); cur_stroke; cur_stroke = gimp_vectors_stroke_get_next (vectors, cur_stroke)) { GArray *coords; gboolean closed; gint i; coords = gimp_stroke_interpolate (cur_stroke, 0.5, &closed); if (coords) { for (i = 0; i < coords->len; i++) { GimpCoords point; gint x, y; point = g_array_index (coords, GimpCoords, i); x = ROUND (point.x * xscale); y = ROUND (point.y * yscale); if (x >= 0 && y >= 0 && x < width && y < height) data[y * width + x] = 0; } g_array_free (coords, TRUE); } } return temp_buf; }
static GimpItem * gimp_vectors_duplicate (GimpItem *item, GType new_type) { GimpItem *new_item; g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_VECTORS), NULL); new_item = GIMP_ITEM_CLASS (parent_class)->duplicate (item, new_type); if (GIMP_IS_VECTORS (new_item)) { GimpVectors *vectors = GIMP_VECTORS (item); GimpVectors *new_vectors = GIMP_VECTORS (new_item); gimp_vectors_copy_strokes (vectors, new_vectors); } return new_item; }
void vectors_duplicate_cmd_callback (GtkAction *action, gpointer data) { GimpImage *image; GimpVectors *vectors; GimpVectors *new_vectors; return_if_no_vectors (image, vectors, data); new_vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), G_TYPE_FROM_INSTANCE (vectors))); gimp_image_add_vectors (image, new_vectors, -1); gimp_image_flush (image); }
static GObject * gimp_vectors_mod_undo_constructor (GType type, guint n_params, GObjectConstructParam *params) { GObject *object; GimpVectorsModUndo *vectors_mod_undo; GimpVectors *vectors; object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params); vectors_mod_undo = GIMP_VECTORS_MOD_UNDO (object); g_assert (GIMP_IS_VECTORS (GIMP_ITEM_UNDO (object)->item)); vectors = GIMP_VECTORS (GIMP_ITEM_UNDO (object)->item); vectors_mod_undo->vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), G_TYPE_FROM_INSTANCE (vectors), FALSE)); return object; }
GimpVectors * gimp_vectors_new (GimpImage *image, const gchar *name) { GimpVectors *vectors; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); vectors = GIMP_VECTORS (gimp_item_new (GIMP_TYPE_VECTORS, image, name, 0, 0, gimp_image_get_width (image), gimp_image_get_height (image))); return vectors; }
static gint64 gimp_vectors_get_memsize (GimpObject *object, gint64 *gui_size) { GimpVectors *vectors; GList *list; gint64 memsize = 0; vectors = GIMP_VECTORS (object); for (list = vectors->strokes; list; list = g_list_next (list)) memsize += (gimp_object_get_memsize (GIMP_OBJECT (list->data), gui_size) + sizeof (GList)); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static void gimp_vectors_to_selection (GimpItem *item, GimpChannelOps op, gboolean antialias, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y) { GimpVectors *vectors = GIMP_VECTORS (item); GimpImage *image = gimp_item_get_image (item); gimp_channel_select_vectors (gimp_image_get_mask (image), GIMP_ITEM_GET_CLASS (item)->to_selection_desc, vectors, op, antialias, feather, feather_radius_x, feather_radius_x, TRUE); }
static void gimp_vectors_prop_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { #if 0 GimpVectorsPropUndo *vectors_prop_undo = GIMP_VECTORS_PROP_UNDO (undo); GimpVectors *vectors = GIMP_VECTORS (GIMP_ITEM_UNDO (undo)->item); #endif GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); switch (undo->undo_type) { default: gimp_assert_not_reached (); } }
static void gimp_vectors_finalize (GObject *object) { GimpVectors *vectors = GIMP_VECTORS (object); if (vectors->bezier_desc) { gimp_bezier_desc_free (vectors->bezier_desc); vectors->bezier_desc = NULL; } if (vectors->strokes) { g_list_free_full (vectors->strokes, (GDestroyNotify) g_object_unref); vectors->strokes = NULL; } G_OBJECT_CLASS (parent_class)->finalize (object); }
static GString * gimp_vectors_export (const GimpImage *image, const GimpVectors *vectors) { GString *str = g_string_new (NULL); g_string_append_printf (str, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\"\n" " \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n" "\n" "<svg xmlns=\"http://www.w3.org/2000/svg\"\n"); g_string_append (str, " "); gimp_vectors_export_image_size (image, str); g_string_append_c (str, '\n'); g_string_append_printf (str, " viewBox=\"0 0 %d %d\">\n", gimp_image_get_width (image), gimp_image_get_height (image)); if (vectors) { gimp_vectors_export_path (vectors, str); } else { GList *list; for (list = gimp_image_get_vectors_iter (image); list; list = list->next) { gimp_vectors_export_path (GIMP_VECTORS (list->data), str); } } g_string_append (str, "</svg>\n"); return str; }
void vectors_duplicate_cmd_callback (GtkAction *action, gpointer data) { GimpImage *image; GimpVectors *vectors; GimpVectors *new_vectors; return_if_no_vectors (image, vectors, data); new_vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), G_TYPE_FROM_INSTANCE (vectors))); /* use the actual parent here, not GIMP_IMAGE_ACTIVE_PARENT because * the latter would add a duplicated group inside itself instead of * above it */ gimp_image_add_vectors (image, new_vectors, gimp_vectors_get_parent (vectors), -1, TRUE); gimp_image_flush (image); }
static void gimp_display_shell_drop_vectors (GtkWidget *widget, gint x, gint y, GimpViewable *viewable, gpointer data) { GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data); GimpImage *image = gimp_display_get_image (shell->display); GimpItem *new_item; GIMP_LOG (DND, NULL); if (shell->display->gimp->busy) return; if (! image) return; new_item = gimp_item_convert (GIMP_ITEM (viewable), image, G_TYPE_FROM_INSTANCE (viewable)); if (new_item) { GimpVectors *new_vectors = GIMP_VECTORS (new_item); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, _("Drop New Path")); gimp_image_add_vectors (image, new_vectors, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE); gimp_image_undo_group_end (image); gimp_display_shell_dnd_flush (shell, image); } }
static guchar * gimp_vectors_tree_view_drag_svg (GtkWidget *widget, gsize *svg_data_len, gpointer data) { GimpItemTreeView *view = GIMP_ITEM_TREE_VIEW (data); GimpImage *image = gimp_item_tree_view_get_image (view); GimpItem *item; gchar *svg_data = NULL; item = GIMP_ITEM_TREE_VIEW_GET_CLASS (view)->get_active_item (image); *svg_data_len = 0; if (item) { svg_data = gimp_vectors_export_string (image, GIMP_VECTORS (item)); if (svg_data) *svg_data_len = strlen (svg_data); } return (guchar *) svg_data; }
static void gimp_vectors_tree_view_drop_svg (GimpContainerTreeView *tree_view, const gchar *svg_data, gsize svg_data_len, GimpViewable *dest_viewable, GtkTreeViewDropPosition drop_pos) { GimpItemTreeView *view = GIMP_ITEM_TREE_VIEW (tree_view); GimpImage *image = view->image; gint index = -1; GError *error = NULL; if (image->gimp->be_verbose) g_print ("%s: SVG dropped (len = %d)\n", G_STRFUNC, (gint) svg_data_len); if (dest_viewable) { index = gimp_image_get_vectors_index (image, GIMP_VECTORS (dest_viewable)); if (drop_pos == GTK_TREE_VIEW_DROP_AFTER) index++; } if (! gimp_vectors_import_buffer (image, svg_data, svg_data_len, TRUE, TRUE, index, NULL, &error)) { gimp_message (image->gimp, G_OBJECT (tree_view), GIMP_MESSAGE_ERROR, "%s", error->message); g_clear_error (&error); } else { gimp_image_flush (image); } }
static void gimp_vectors_scale (GimpItem *item, gint new_width, gint new_height, gint new_offset_x, gint new_offset_y, GimpInterpolationType interpolation_type, GimpProgress *progress) { GimpVectors *vectors = GIMP_VECTORS (item); GimpImage *image = gimp_item_get_image (item); GList *list; gimp_vectors_freeze (vectors); if (gimp_item_is_attached (item)) gimp_image_undo_push_vectors_mod (image, NULL, vectors); for (list = vectors->strokes; list; list = g_list_next (list)) { GimpStroke *stroke = list->data; gimp_stroke_scale (stroke, (gdouble) new_width / (gdouble) gimp_item_get_width (item), (gdouble) new_height / (gdouble) gimp_item_get_height (item)); gimp_stroke_translate (stroke, new_offset_x, new_offset_y); } GIMP_ITEM_CLASS (parent_class)->scale (item, gimp_image_get_width (image), gimp_image_get_height (image), 0, 0, interpolation_type, progress); gimp_vectors_thaw (vectors); }
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; }
static void gimp_align_tool_draw (GimpDrawTool *draw_tool) { GimpAlignTool *align_tool = GIMP_ALIGN_TOOL (draw_tool); GList *list; gint x, y, w, h; /* draw rubber-band rectangle */ x = MIN (align_tool->x2, align_tool->x1); y = MIN (align_tool->y2, align_tool->y1); w = MAX (align_tool->x2, align_tool->x1) - x; h = MAX (align_tool->y2, align_tool->y1) - y; gimp_draw_tool_add_rectangle (draw_tool, FALSE, x, y, w, h); for (list = align_tool->selected_objects; list; list = g_list_next (list)) { if (GIMP_IS_ITEM (list->data)) { GimpItem *item = list->data; if (GIMP_IS_VECTORS (item)) { gdouble x1_f, y1_f, x2_f, y2_f; gimp_vectors_bounds (GIMP_VECTORS (item), &x1_f, &y1_f, &x2_f, &y2_f); x = ROUND (x1_f); y = ROUND (y1_f); w = ROUND (x2_f - x1_f); h = ROUND (y2_f - y1_f); } else { gimp_item_get_offset (item, &x, &y); w = gimp_item_get_width (item); h = gimp_item_get_height (item); } gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, x, y, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_HANDLE_ANCHOR_NORTH_WEST); gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, x + w, y, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_HANDLE_ANCHOR_NORTH_EAST); gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, x, y + h, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_HANDLE_ANCHOR_SOUTH_WEST); gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, x + w, y + h, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_HANDLE_ANCHOR_SOUTH_EAST); } else if (GIMP_IS_GUIDE (list->data)) { GimpGuide *guide = list->data; GimpImage *image = gimp_display_get_image (GIMP_TOOL (draw_tool)->display); gint x, y; gint w, h; switch (gimp_guide_get_orientation (guide)) { case GIMP_ORIENTATION_VERTICAL: x = gimp_guide_get_position (guide); h = gimp_image_get_height (image); gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, x, h, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_HANDLE_ANCHOR_SOUTH); gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, x, 0, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_HANDLE_ANCHOR_NORTH); break; case GIMP_ORIENTATION_HORIZONTAL: y = gimp_guide_get_position (guide); w = gimp_image_get_width (image); gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, w, y, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_HANDLE_ANCHOR_EAST); gimp_draw_tool_add_handle (draw_tool, GIMP_HANDLE_FILLED_SQUARE, 0, y, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_TOOL_HANDLE_SIZE_SMALL, GIMP_HANDLE_ANCHOR_WEST); break; default: break; } } } }
GimpVectors * gimp_image_merge_visible_vectors (GimpImage *image, GError **error) { GList *list = NULL; GSList *merge_list = NULL; GSList *cur_item = NULL; GimpVectors *vectors = NULL; GimpVectors *target_vectors = NULL; gchar *name = NULL; gint pos = 0; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); for (list = GIMP_LIST (image->vectors)->list; list; list = g_list_next (list)) { vectors = list->data; if (gimp_item_get_visible (GIMP_ITEM (vectors))) merge_list = g_slist_append (merge_list, vectors); } if (merge_list && merge_list->next) { gimp_set_busy (image->gimp); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_VECTORS_MERGE, _("Merge Visible Paths")); cur_item = merge_list; vectors = GIMP_VECTORS (cur_item->data); name = g_strdup (gimp_object_get_name (GIMP_OBJECT (vectors))); target_vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), GIMP_TYPE_VECTORS)); pos = gimp_image_get_vectors_index (image, vectors); gimp_image_remove_vectors (image, vectors); cur_item = cur_item->next; while (cur_item) { vectors = GIMP_VECTORS (cur_item->data); gimp_vectors_add_strokes (vectors, target_vectors); gimp_image_remove_vectors (image, vectors); cur_item = g_slist_next (cur_item); } gimp_object_take_name (GIMP_OBJECT (target_vectors), name); g_slist_free (merge_list); gimp_image_add_vectors (image, target_vectors, pos); gimp_unset_busy (image->gimp); gimp_image_undo_group_end (image); return target_vectors; } else { g_set_error (error, 0, 0, _("Not enough visible paths for a merge. " "There must be at least two.")); return NULL; } }
GimpVectors * gimp_image_merge_visible_vectors (GimpImage *image, GError **error) { GList *list; GList *merge_list = NULL; GimpVectors *vectors; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); for (list = gimp_image_get_vectors_iter (image); list; list = g_list_next (list)) { vectors = list->data; if (gimp_item_get_visible (GIMP_ITEM (vectors))) merge_list = g_list_prepend (merge_list, vectors); } merge_list = g_list_reverse (merge_list); if (merge_list && merge_list->next) { GimpVectors *target_vectors; gchar *name; gint pos; gimp_set_busy (image->gimp); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_VECTORS_MERGE, C_("undo-type", "Merge Visible Paths")); vectors = GIMP_VECTORS (merge_list->data); name = g_strdup (gimp_object_get_name (vectors)); pos = gimp_item_get_index (GIMP_ITEM (vectors)); target_vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors), GIMP_TYPE_VECTORS)); gimp_image_remove_vectors (image, vectors, TRUE, NULL); for (list = g_list_next (merge_list); list; list = g_list_next (list)) { vectors = list->data; gimp_vectors_add_strokes (vectors, target_vectors); gimp_image_remove_vectors (image, vectors, TRUE, NULL); } gimp_object_take_name (GIMP_OBJECT (target_vectors), name); g_list_free (merge_list); /* FIXME tree */ gimp_image_add_vectors (image, target_vectors, NULL, pos, TRUE); gimp_unset_busy (image->gimp); gimp_image_undo_group_end (image); return target_vectors; } else { g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, _("Not enough visible paths for a merge. " "There must be at least two.")); return NULL; } }
static void compute_offset (GObject *object, GimpAlignmentType alignment) { gint object_offset_x = 0; gint object_offset_y = 0; gint object_height = 0; gint object_width = 0; gint offset = 0; if (GIMP_IS_IMAGE (object)) { GimpImage *image = GIMP_IMAGE (object); object_offset_x = 0; object_offset_y = 0; object_height = gimp_image_get_height (image); object_width = gimp_image_get_width (image); } else if (GIMP_IS_CHANNEL (object)) { /* for channels, we use the bounds of the visible area, not the layer bounds. This includes the selection channel */ GimpChannel *channel = GIMP_CHANNEL (object); if (gimp_channel_is_empty (channel)) { /* fall back on using the offsets instead */ GimpItem *item = GIMP_ITEM (object); gimp_item_get_offset (item, &object_offset_x, &object_offset_y); object_width = gimp_item_get_width (item); object_height = gimp_item_get_height (item); } else { gint x1, x2, y1, y2; gimp_channel_bounds (channel, &x1, &y1, &x2, &y2); object_offset_x = x1; object_offset_y = y1; object_width = x2 - x1; object_height = y2 - y1; } } else if (GIMP_IS_ITEM (object)) { GimpItem *item = GIMP_ITEM (object); if (GIMP_IS_VECTORS (object)) { gdouble x1_f, y1_f, x2_f, y2_f; gimp_vectors_bounds (GIMP_VECTORS (item), &x1_f, &y1_f, &x2_f, &y2_f); object_offset_x = ROUND (x1_f); object_offset_y = ROUND (y1_f); object_height = ROUND (y2_f - y1_f); object_width = ROUND (x2_f - x1_f); } else { gimp_item_get_offset (item, &object_offset_x, &object_offset_y); object_width = gimp_item_get_width (item); object_height = gimp_item_get_height (item); } } else if (GIMP_IS_GUIDE (object)) { GimpGuide *guide = GIMP_GUIDE (object); switch (gimp_guide_get_orientation (guide)) { case GIMP_ORIENTATION_VERTICAL: object_offset_x = gimp_guide_get_position (guide); object_width = 0; break; case GIMP_ORIENTATION_HORIZONTAL: object_offset_y = gimp_guide_get_position (guide); object_height = 0; break; default: break; } } else { g_printerr ("Alignment object is not an image, item or guide.\n"); } switch (alignment) { case GIMP_ALIGN_LEFT: case GIMP_ARRANGE_LEFT: offset = object_offset_x; break; case GIMP_ALIGN_HCENTER: case GIMP_ARRANGE_HCENTER: offset = object_offset_x + object_width/2; break; case GIMP_ALIGN_RIGHT: case GIMP_ARRANGE_RIGHT: offset = object_offset_x + object_width; break; case GIMP_ALIGN_TOP: case GIMP_ARRANGE_TOP: offset = object_offset_y; break; case GIMP_ALIGN_VCENTER: case GIMP_ARRANGE_VCENTER: offset = object_offset_y + object_height/2; break; case GIMP_ALIGN_BOTTOM: case GIMP_ARRANGE_BOTTOM: offset = object_offset_y + object_height; break; default: g_assert_not_reached (); } g_object_set_data (object, "align-offset", GINT_TO_POINTER (offset)); }
static gboolean gimp_vectors_bounds (GimpItem *item, gdouble *x, gdouble *y, gdouble *width, gdouble *height) { GimpVectors *vectors = GIMP_VECTORS (item); if (! vectors->bounds_valid) { GimpStroke *stroke; vectors->bounds_empty = TRUE; vectors->bounds_x1 = vectors->bounds_x2 = 0.0; vectors->bounds_y1 = vectors->bounds_y2 = 0.0; for (stroke = gimp_vectors_stroke_get_next (vectors, NULL); stroke; stroke = gimp_vectors_stroke_get_next (vectors, stroke)) { GArray *stroke_coords; gboolean closed; stroke_coords = gimp_stroke_interpolate (stroke, 1.0, &closed); if (stroke_coords) { GimpCoords point; gint i; if (vectors->bounds_empty && stroke_coords->len > 0) { point = g_array_index (stroke_coords, GimpCoords, 0); vectors->bounds_x1 = vectors->bounds_x2 = point.x; vectors->bounds_y1 = vectors->bounds_y2 = point.y; vectors->bounds_empty = FALSE; } for (i = 0; i < stroke_coords->len; i++) { point = g_array_index (stroke_coords, GimpCoords, i); vectors->bounds_x1 = MIN (vectors->bounds_x1, point.x); vectors->bounds_y1 = MIN (vectors->bounds_y1, point.y); vectors->bounds_x2 = MAX (vectors->bounds_x2, point.x); vectors->bounds_y2 = MAX (vectors->bounds_y2, point.y); } g_array_free (stroke_coords, TRUE); } } vectors->bounds_valid = TRUE; } *x = vectors->bounds_x1; *y = vectors->bounds_y1; *width = vectors->bounds_x2 - vectors->bounds_x1; *height = vectors->bounds_y2 - vectors->bounds_y1; return ! vectors->bounds_empty; }