gimp/app/vectors/gimpvectors.c

1223 lines
40 KiB
C
Raw Normal View History

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectors.c
* Copyright (C) 2002 Simon Budig <simon@gimp.org>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <cairo.h>
#include <gegl.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "libgimpcolor/gimpcolor.h"
#include "libgimpmath/gimpmath.h"
#include "vectors-types.h"
#include "core/gimp.h"
#include "core/gimp-transform-utils.h"
#include "core/gimpbezierdesc.h"
#include "core/gimpchannel-select.h"
#include "core/gimpcontainer.h"
#include "core/gimpcontext.h"
#include "core/gimpdrawable-fill.h"
#include "core/gimpdrawable-stroke.h"
#include "core/gimperror.h"
#include "core/gimpimage.h"
#include "core/gimpimage-undo-push.h"
#include "core/gimpmarshal.h"
added new virtual function GimpItem::stroke(). 2003-09-01 Michael Natterer <mitch@gimp.org> * app/core/gimpitem.[ch]: added new virtual function GimpItem::stroke(). * app/core/gimpchannel.c * app/vectors/gimpvectors.c: implement GimpItem::stroke(). * app/core/gimpimage-mask.[ch] (gimp_image_mask_stroke): changed signature to match gimp_item_stroke() (the selection mask *really* should be a GimpChannel subclass). Removed global variable "gboolean gimp_image_mask_stroking"... * app/core/gimpimage.[ch]: ...and added "gboolean mask_stroking" to the GimpImage struct. * app/gui/vectors-commands.[ch]: removed vectors_stroke_vectors(). * app/widgets/widgets-types.h: removed GimpStrokeItemFunc typedef. * app/widgets/gimpvectorstreeview.[ch]: removed "stroke_item_func" member and use gimp_item_stroke() instead. * app/gui/dialogs-constructors.c (dialogs_vectors_list_view_new) * app/gui/edit-commands.c (edit_stroke_cmd_callback) * app/gui/vectors-commands. (vectors_stroke_cmd_callback) * app/widgets/gimpselectioneditor.c (gimp_selection_editor_stroke_clicked) * tools/pdbgen/pdb/edit.pdb (gimp_edit_stroke): changed accordingly. * app/pdb/edit_cmds.c: regenerated. Note that there is no GUI for "stroke channel", although it would be utterly cool to have one, since currently slelection stroking cannot be masked by a selection (because we stroke the selection). Anyway, if anyone has an idea how to trigger "stroke channel" with another drawable active (the one to stroke to), please let me know...
2003-09-02 01:56:44 +08:00
#include "core/gimppaintinfo.h"
#include "core/gimpstrokeoptions.h"
added new virtual function GimpItem::stroke(). 2003-09-01 Michael Natterer <mitch@gimp.org> * app/core/gimpitem.[ch]: added new virtual function GimpItem::stroke(). * app/core/gimpchannel.c * app/vectors/gimpvectors.c: implement GimpItem::stroke(). * app/core/gimpimage-mask.[ch] (gimp_image_mask_stroke): changed signature to match gimp_item_stroke() (the selection mask *really* should be a GimpChannel subclass). Removed global variable "gboolean gimp_image_mask_stroking"... * app/core/gimpimage.[ch]: ...and added "gboolean mask_stroking" to the GimpImage struct. * app/gui/vectors-commands.[ch]: removed vectors_stroke_vectors(). * app/widgets/widgets-types.h: removed GimpStrokeItemFunc typedef. * app/widgets/gimpvectorstreeview.[ch]: removed "stroke_item_func" member and use gimp_item_stroke() instead. * app/gui/dialogs-constructors.c (dialogs_vectors_list_view_new) * app/gui/edit-commands.c (edit_stroke_cmd_callback) * app/gui/vectors-commands. (vectors_stroke_cmd_callback) * app/widgets/gimpselectioneditor.c (gimp_selection_editor_stroke_clicked) * tools/pdbgen/pdb/edit.pdb (gimp_edit_stroke): changed accordingly. * app/pdb/edit_cmds.c: regenerated. Note that there is no GUI for "stroke channel", although it would be utterly cool to have one, since currently slelection stroking cannot be masked by a selection (because we stroke the selection). Anyway, if anyone has an idea how to trigger "stroke channel" with another drawable active (the one to stroke to), please let me know...
2003-09-02 01:56:44 +08:00
#include "paint/gimppaintcore-stroke.h"
#include "paint/gimppaintoptions.h"
#include "gimpanchor.h"
#include "gimpstroke.h"
#include "gimpvectors.h"
#include "gimpvectors-preview.h"
#include "gimp-intl.h"
enum
{
FREEZE,
THAW,
LAST_SIGNAL
};
static void gimp_vectors_finalize (GObject *object);
static gint64 gimp_vectors_get_memsize (GimpObject *object,
gint64 *gui_size);
static gboolean gimp_vectors_is_attached (GimpItem *item);
static GimpItemTree * gimp_vectors_get_tree (GimpItem *item);
static gboolean gimp_vectors_bounds (GimpItem *item,
gdouble *x,
gdouble *y,
gdouble *width,
gdouble *height);
static GimpItem * gimp_vectors_duplicate (GimpItem *item,
GType new_type);
static void gimp_vectors_convert (GimpItem *item,
GimpImage *dest_image,
GType old_type);
static void gimp_vectors_translate (GimpItem *item,
gint offset_x,
gint offset_y,
gboolean push_undo);
static void gimp_vectors_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interp_type,
GimpProgress *progress);
static void gimp_vectors_resize (GimpItem *item,
GimpContext *context,
GimpFillType fill_type,
gint new_width,
gint new_height,
gint offset_x,
gint offset_y);
static void gimp_vectors_flip (GimpItem *item,
GimpContext *context,
GimpOrientationType flip_type,
gdouble axis,
gboolean clip_result);
static void gimp_vectors_rotate (GimpItem *item,
GimpContext *context,
GimpRotationType rotate_type,
gdouble center_x,
gdouble center_y,
gboolean clip_result);
static void gimp_vectors_transform (GimpItem *item,
GimpContext *context,
const GimpMatrix3 *matrix,
GimpTransformDirection direction,
GimpInterpolationType interp_type,
GimpTransformResize clip_result,
GimpProgress *progress);
static gboolean gimp_vectors_fill (GimpItem *item,
GimpDrawable *drawable,
GimpFillOptions *fill_options,
gboolean push_undo,
GimpProgress *progress,
GError **error);
static gboolean gimp_vectors_stroke (GimpItem *item,
GimpDrawable *drawable,
GimpStrokeOptions *stroke_options,
gboolean push_undo,
GimpProgress *progress,
GError **error);
static void gimp_vectors_to_selection (GimpItem *item,
GimpChannelOps op,
gboolean antialias,
gboolean feather,
gdouble feather_radius_x,
gdouble feather_radius_y);
added new virtual function GimpItem::stroke(). 2003-09-01 Michael Natterer <mitch@gimp.org> * app/core/gimpitem.[ch]: added new virtual function GimpItem::stroke(). * app/core/gimpchannel.c * app/vectors/gimpvectors.c: implement GimpItem::stroke(). * app/core/gimpimage-mask.[ch] (gimp_image_mask_stroke): changed signature to match gimp_item_stroke() (the selection mask *really* should be a GimpChannel subclass). Removed global variable "gboolean gimp_image_mask_stroking"... * app/core/gimpimage.[ch]: ...and added "gboolean mask_stroking" to the GimpImage struct. * app/gui/vectors-commands.[ch]: removed vectors_stroke_vectors(). * app/widgets/widgets-types.h: removed GimpStrokeItemFunc typedef. * app/widgets/gimpvectorstreeview.[ch]: removed "stroke_item_func" member and use gimp_item_stroke() instead. * app/gui/dialogs-constructors.c (dialogs_vectors_list_view_new) * app/gui/edit-commands.c (edit_stroke_cmd_callback) * app/gui/vectors-commands. (vectors_stroke_cmd_callback) * app/widgets/gimpselectioneditor.c (gimp_selection_editor_stroke_clicked) * tools/pdbgen/pdb/edit.pdb (gimp_edit_stroke): changed accordingly. * app/pdb/edit_cmds.c: regenerated. Note that there is no GUI for "stroke channel", although it would be utterly cool to have one, since currently slelection stroking cannot be masked by a selection (because we stroke the selection). Anyway, if anyone has an idea how to trigger "stroke channel" with another drawable active (the one to stroke to), please let me know...
2003-09-02 01:56:44 +08:00
static void gimp_vectors_real_freeze (GimpVectors *vectors);
static void gimp_vectors_real_thaw (GimpVectors *vectors);
static void gimp_vectors_real_stroke_add (GimpVectors *vectors,
GimpStroke *stroke);
static void gimp_vectors_real_stroke_remove (GimpVectors *vectors,
GimpStroke *stroke);
static GimpStroke * gimp_vectors_real_stroke_get (GimpVectors *vectors,
const GimpCoords *coord);
static GimpStroke *gimp_vectors_real_stroke_get_next(GimpVectors *vectors,
GimpStroke *prev);
static gdouble gimp_vectors_real_stroke_get_length (GimpVectors *vectors,
GimpStroke *prev);
static GimpAnchor * gimp_vectors_real_anchor_get (GimpVectors *vectors,
const GimpCoords *coord,
GimpStroke **ret_stroke);
static void gimp_vectors_real_anchor_delete (GimpVectors *vectors,
GimpAnchor *anchor);
static gdouble gimp_vectors_real_get_length (GimpVectors *vectors,
const GimpAnchor *start);
static gdouble gimp_vectors_real_get_distance (GimpVectors *vectors,
const GimpCoords *coord);
static gint gimp_vectors_real_interpolate (GimpVectors *vectors,
GimpStroke *stroke,
gdouble precision,
gint max_points,
GimpCoords *ret_coords);
static GimpBezierDesc * gimp_vectors_make_bezier (GimpVectors *vectors);
static GimpBezierDesc * gimp_vectors_real_make_bezier (GimpVectors *vectors);
G_DEFINE_TYPE (GimpVectors, gimp_vectors, GIMP_TYPE_ITEM)
#define parent_class gimp_vectors_parent_class
static guint gimp_vectors_signals[LAST_SIGNAL] = { 0 };
static void
gimp_vectors_class_init (GimpVectorsClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
GimpItemClass *item_class = GIMP_ITEM_CLASS (klass);
gimp_vectors_signals[FREEZE] =
g_signal_new ("freeze",
G_TYPE_FROM_CLASS (klass),
2010-09-17 05:27:25 +08:00
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GimpVectorsClass, freeze),
NULL, NULL,
gimp_marshal_VOID__VOID,
G_TYPE_NONE, 0);
gimp_vectors_signals[THAW] =
g_signal_new ("thaw",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpVectorsClass, thaw),
NULL, NULL,
gimp_marshal_VOID__VOID,
G_TYPE_NONE, 0);
object_class->finalize = gimp_vectors_finalize;
gimp_object_class->get_memsize = gimp_vectors_get_memsize;
viewable_class->get_new_preview = gimp_vectors_get_new_preview;
viewable_class->default_icon_name = "gimp-path";
item_class->is_attached = gimp_vectors_is_attached;
item_class->get_tree = gimp_vectors_get_tree;
item_class->bounds = gimp_vectors_bounds;
item_class->duplicate = gimp_vectors_duplicate;
item_class->convert = gimp_vectors_convert;
item_class->translate = gimp_vectors_translate;
item_class->scale = gimp_vectors_scale;
item_class->resize = gimp_vectors_resize;
item_class->flip = gimp_vectors_flip;
item_class->rotate = gimp_vectors_rotate;
item_class->transform = gimp_vectors_transform;
item_class->fill = gimp_vectors_fill;
item_class->stroke = gimp_vectors_stroke;
item_class->to_selection = gimp_vectors_to_selection;
item_class->default_name = _("Path");
item_class->rename_desc = C_("undo-type", "Rename Path");
item_class->translate_desc = C_("undo-type", "Move Path");
item_class->scale_desc = C_("undo-type", "Scale Path");
item_class->resize_desc = C_("undo-type", "Resize Path");
item_class->flip_desc = C_("undo-type", "Flip Path");
item_class->rotate_desc = C_("undo-type", "Rotate Path");
item_class->transform_desc = C_("undo-type", "Transform Path");
item_class->fill_desc = C_("undo-type", "Fill Path");
item_class->stroke_desc = C_("undo-type", "Stroke Path");
item_class->to_selection_desc = C_("undo-type", "Path to Selection");
item_class->reorder_desc = C_("undo-type", "Reorder Path");
item_class->raise_desc = C_("undo-type", "Raise Path");
item_class->raise_to_top_desc = C_("undo-type", "Raise Path to Top");
item_class->lower_desc = C_("undo-type", "Lower Path");
item_class->lower_to_bottom_desc = C_("undo-type", "Lower Path to Bottom");
item_class->raise_failed = _("Path cannot be raised higher.");
item_class->lower_failed = _("Path cannot be lowered more.");
klass->freeze = gimp_vectors_real_freeze;
klass->thaw = gimp_vectors_real_thaw;
klass->stroke_add = gimp_vectors_real_stroke_add;
klass->stroke_remove = gimp_vectors_real_stroke_remove;
klass->stroke_get = gimp_vectors_real_stroke_get;
klass->stroke_get_next = gimp_vectors_real_stroke_get_next;
klass->stroke_get_length = gimp_vectors_real_stroke_get_length;
klass->anchor_get = gimp_vectors_real_anchor_get;
klass->anchor_delete = gimp_vectors_real_anchor_delete;
klass->get_length = gimp_vectors_real_get_length;
klass->get_distance = gimp_vectors_real_get_distance;
klass->interpolate = gimp_vectors_real_interpolate;
klass->make_bezier = gimp_vectors_real_make_bezier;
}
static void
gimp_vectors_init (GimpVectors *vectors)
{
gimp_item_set_visible (GIMP_ITEM (vectors), FALSE, FALSE);
2016-01-25 13:21:27 +08:00
vectors->strokes = g_queue_new ();
vectors->stroke_to_list = g_hash_table_new (g_direct_hash, g_direct_equal);
vectors->last_stroke_ID = 0;
vectors->freeze_count = 0;
vectors->precision = 0.2;
vectors->bezier_desc = NULL;
vectors->bounds_valid = FALSE;
}
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)
{
2016-01-25 13:21:27 +08:00
g_queue_free_full (vectors->strokes, (GDestroyNotify) g_object_unref);
vectors->strokes = NULL;
}
if (vectors->stroke_to_list)
{
g_hash_table_destroy (vectors->stroke_to_list);
vectors->stroke_to_list = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gint64
changed GimpObject::get_memsize() to return a second value named 2003-08-25 Michael Natterer <mitch@gimp.org> * app/core/gimpobject.[ch]: changed GimpObject::get_memsize() to return a second value named "gui_size", where the primary return value is the "constant" actual size (as long as no operation is performed on the object), and the second "gui_size" return value is the size of temporary stuff like preview caches or boundary segments (which may change asynchronously, even if the object is on the undo stack). * app/core/gimp.c * app/core/gimpbrush.c * app/core/gimpbrushpipe.c * app/core/gimpbuffer.c * app/core/gimpchannel.c * app/core/gimpcontainer.c * app/core/gimpcontext.c * app/core/gimpdata.c * app/core/gimpdatafactory.c * app/core/gimpdrawable.c * app/core/gimpgradient.c * app/core/gimpimage-undo.c * app/core/gimpimage.c * app/core/gimpitem.c * app/core/gimplayer.c * app/core/gimplist.c * app/core/gimppalette.c * app/core/gimpparasitelist.c * app/core/gimppattern.c * app/core/gimpundo.c * app/core/gimpundostack.c * app/core/gimpviewable.c * app/text/gimptextlayer.c * app/vectors/gimpstroke.c * app/vectors/gimpvectors.c: changed get_memsize() implementations accordingly. * app/display/gimpdisplayshell-title.c * app/gui/debug-commands.c * app/widgets/gimppreview.c: changed callers accordingly. * app/core/gimpimage-undo-push.c: changed layer, channel, vectors and layer_mask undo steps to add/subtract the size of the resp. objects whenever they take/drop ownership of them. Ignore the objects' "gui_size" to get identical sizes on adding/subtracting. Fixes bug #120429.
2003-08-25 18:49:33 +08:00
gimp_vectors_get_memsize (GimpObject *object,
gint64 *gui_size)
{
GimpVectors *vectors;
GList *list;
gint64 memsize = 0;
vectors = GIMP_VECTORS (object);
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; list; list = g_list_next (list))
changed GimpObject::get_memsize() to return a second value named 2003-08-25 Michael Natterer <mitch@gimp.org> * app/core/gimpobject.[ch]: changed GimpObject::get_memsize() to return a second value named "gui_size", where the primary return value is the "constant" actual size (as long as no operation is performed on the object), and the second "gui_size" return value is the size of temporary stuff like preview caches or boundary segments (which may change asynchronously, even if the object is on the undo stack). * app/core/gimp.c * app/core/gimpbrush.c * app/core/gimpbrushpipe.c * app/core/gimpbuffer.c * app/core/gimpchannel.c * app/core/gimpcontainer.c * app/core/gimpcontext.c * app/core/gimpdata.c * app/core/gimpdatafactory.c * app/core/gimpdrawable.c * app/core/gimpgradient.c * app/core/gimpimage-undo.c * app/core/gimpimage.c * app/core/gimpitem.c * app/core/gimplayer.c * app/core/gimplist.c * app/core/gimppalette.c * app/core/gimpparasitelist.c * app/core/gimppattern.c * app/core/gimpundo.c * app/core/gimpundostack.c * app/core/gimpviewable.c * app/text/gimptextlayer.c * app/vectors/gimpstroke.c * app/vectors/gimpvectors.c: changed get_memsize() implementations accordingly. * app/display/gimpdisplayshell-title.c * app/gui/debug-commands.c * app/widgets/gimppreview.c: changed callers accordingly. * app/core/gimpimage-undo-push.c: changed layer, channel, vectors and layer_mask undo steps to add/subtract the size of the resp. objects whenever they take/drop ownership of them. Ignore the objects' "gui_size" to get identical sizes on adding/subtracting. Fixes bug #120429.
2003-08-25 18:49:33 +08:00
memsize += (gimp_object_get_memsize (GIMP_OBJECT (list->data), gui_size) +
sizeof (GList));
changed GimpObject::get_memsize() to return a second value named 2003-08-25 Michael Natterer <mitch@gimp.org> * app/core/gimpobject.[ch]: changed GimpObject::get_memsize() to return a second value named "gui_size", where the primary return value is the "constant" actual size (as long as no operation is performed on the object), and the second "gui_size" return value is the size of temporary stuff like preview caches or boundary segments (which may change asynchronously, even if the object is on the undo stack). * app/core/gimp.c * app/core/gimpbrush.c * app/core/gimpbrushpipe.c * app/core/gimpbuffer.c * app/core/gimpchannel.c * app/core/gimpcontainer.c * app/core/gimpcontext.c * app/core/gimpdata.c * app/core/gimpdatafactory.c * app/core/gimpdrawable.c * app/core/gimpgradient.c * app/core/gimpimage-undo.c * app/core/gimpimage.c * app/core/gimpitem.c * app/core/gimplayer.c * app/core/gimplist.c * app/core/gimppalette.c * app/core/gimpparasitelist.c * app/core/gimppattern.c * app/core/gimpundo.c * app/core/gimpundostack.c * app/core/gimpviewable.c * app/text/gimptextlayer.c * app/vectors/gimpstroke.c * app/vectors/gimpvectors.c: changed get_memsize() implementations accordingly. * app/display/gimpdisplayshell-title.c * app/gui/debug-commands.c * app/widgets/gimppreview.c: changed callers accordingly. * app/core/gimpimage-undo-push.c: changed layer, channel, vectors and layer_mask undo steps to add/subtract the size of the resp. objects whenever they take/drop ownership of them. Ignore the objects' "gui_size" to get identical sizes on adding/subtracting. Fixes bug #120429.
2003-08-25 18:49:33 +08:00
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
gui_size);
}
static gboolean
gimp_vectors_is_attached (GimpItem *item)
{
GimpImage *image = gimp_item_get_image (item);
return (GIMP_IS_IMAGE (image) &&
gimp_container_have (gimp_image_get_vectors (image),
GIMP_OBJECT (item)));
}
static GimpItemTree *
gimp_vectors_get_tree (GimpItem *item)
{
if (gimp_item_is_attached (item))
{
GimpImage *image = gimp_item_get_image (item);
return gimp_image_get_vectors_tree (image);
}
return NULL;
}
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;
}
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;
}
static void
gimp_vectors_convert (GimpItem *item,
GimpImage *dest_image,
GType old_type)
{
gimp_item_set_size (item,
gimp_image_get_width (dest_image),
gimp_image_get_height (dest_image));
GIMP_ITEM_CLASS (parent_class)->convert (item, dest_image, old_type);
}
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);
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; list; list = g_list_next (list))
{
GimpStroke *stroke = list->data;
gimp_stroke_translate (stroke, offset_x, offset_y);
}
gimp_vectors_thaw (vectors);
}
static void
gimp_vectors_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interpolation_type,
Redid the whole internal progress stuff: don't pass around 2004-08-10 Michael Natterer <mitch@gimp.org> Redid the whole internal progress stuff: don't pass around progress_callback and progress_data; instead, provide a pointer to a GimpProgressInterface which can be implemented by a variety of backends. Addresses (but not yet fixes) bugs #6010, #97266 and #135185. * app/display/Makefile.am * app/display/gimpprogress.[ch]: removed the old progress hack. * app/core/Makefile.am * app/core/core-types.h * app/core/gimpprogress.[ch]: implement GimpProgressInterface. * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpprogressdialog.[ch]: the standalone progress dialog as widget implementing GimpProgressInterface. * app/display/gimpdisplay.c * app/display/gimpstatusbar.[ch] * app/widgets/gimpfiledialog.[ch] * app/widgets/gimpthumbbox.[ch]: added GimpProgressInterface implementation to these classes. * app/core/gimp-gui.[ch] * app/gui/gui-vtable.c: replaced the old progress vtable entries by two new to create and destroy a GimpProgressDialog in case no other progress is available. * app/pdb/procedural_db.[ch] * app/plug-in/plug-in-run.[ch] * tools/pdbgen/app.pl: pass a GimpProgress to all PDB wrappers and all plug-ins. * app/plug-in/plug-in.[ch] * app/plug-in/plug-ins.c * app/plug-in/plug-in-message.c * app/plug-in/plug-in-progress.c: handle the case there the plug-in was crated with a progress as well as the case where it wasn't. * app/app_procs.c * app/batch.c * app/xcf/xcf.c * app/file/file-open.[ch] * app/file/file-save.[ch] * app/widgets/gimphelp.c * app/widgets/gimpbrushselect.c * app/widgets/gimpfontselect.c * app/widgets/gimpgradientselect.c * app/widgets/gimppaletteselect.c * app/widgets/gimppatternselect.c: changed accordingly. * app/core/gimpimagefile.[ch] * app/display/gimpdisplayshell-dnd.c * app/gui/file-open-dialog.c * app/gui/file-open-location-dialog.c * app/gui/file-save-dialog.c * app/widgets/gimplayertreeview.c * app/widgets/gimptoolbox-dnd.c: pass a GimpProgress to all file related functions. Embed the progress in the file dialog where possible. * app/core/gimpdrawable-blend.[ch] * app/core/gimpdrawable-transform.[ch] * app/core/gimpimage-convert.[ch] * app/core/gimpimage-flip.[ch] * app/core/gimpimage-resize.[ch] * app/core/gimpimage-rotate.[ch] * app/core/gimpimage-scale.[ch] * app/core/gimpitem-linked.[ch] * app/core/gimpitem.[ch] * app/core/gimpchannel.c * app/core/gimpdrawable.c * app/core/gimplayer.c * app/core/gimpselection.c * app/vectors/gimpvectors.c: replaced callback/data by GimpProgress. * app/tools/gimpblendtool.c * app/tools/gimptransformtool.c * app/gui/convert-dialog.c * app/actions/documents-commands.c * app/actions/file-commands.c * app/actions/image-commands.c * app/actions/layers-commands.c * app/actions/plug-in-commands.c * app/actions/vectors-commands.c * tools/pdbgen/pdb/convert.pdb * tools/pdbgen/pdb/edit.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb: changed callers accordingly. * app/pdb/*_cmds.c: regenerated.
2004-08-11 02:47:21 +08:00
GimpProgress *progress)
{
GimpVectors *vectors = GIMP_VECTORS (item);
Get rid of the "current_context" which was in fact just a bunch of global 2004-04-15 Michael Natterer <mitch@gimp.org> Get rid of the "current_context" which was in fact just a bunch of global variables. Instead, pass the needed context all the way from the GUI and the PDB to the core. This is a prerequisite for macro recording and generally helps separating the various subsystems from each other. Work in progress... * app/core/gimp.[ch]: removed member "current_context" and gimp_[get|set]_current_context(). * app/core/gimp-edit.[ch] * app/core/gimpdrawable-blend.[ch] * app/core/gimpdrawable-bucket-fill.[ch] * app/core/gimpdrawable-offset.[ch] * app/core/gimpdrawable-transform.[ch] * app/core/gimpimage-crop.[ch] * app/core/gimpimage-flip.[ch] * app/core/gimpimage-merge.[ch] * app/core/gimpimage-resize.[ch] * app/core/gimpimage-rotate.[ch] * app/core/gimpimage.[ch] * app/core/gimpimagefile.[ch] * app/core/gimpitem-linked.[ch] * app/core/gimpitem.[ch] * app/core/gimplayer.[ch] * app/core/gimpselection.[ch] * app/core/gimptemplate.[ch] * app/file/file-open.[ch] * app/file/file-save.[ch] * app/pdb/procedural_db.[ch] * app/text/gimptext-compat.[ch] * app/text/gimptextlayer-transform.[ch] * app/gui/brush-select.[ch] * app/gui/font-select.[ch] * app/gui/gradient-select.[ch] * app/gui/palette-select.[ch] * app/gui/pattern-select.[ch]: added tons of "GimpContext *context" parameters and use the passed context instead of gimp_get_current_context(). * app/app_procs.c * app/batch.c * app/core/gimpchannel.c * app/core/gimpdrawable.c * app/paint/gimperaser.c * app/paint/gimppaintbrush.c * app/plug-in/plug-in-message.c * app/plug-in/plug-ins.c * app/text/gimptextlayer.c * app/tools/gimpblendtool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpcroptool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpfliptool.c * app/tools/gimpinktool.c * app/tools/gimptransformtool.c * app/vectors/gimpvectors.c * app/gui/convert-dialog.c * app/gui/drawable-commands.c * app/gui/edit-commands.c * app/gui/file-commands.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/image-commands.c * app/gui/layers-commands.c * app/gui/offset-dialog.c * app/gui/select-commands.c * app/gui/vectors-commands.c * app/widgets/gimpdnd.c * app/widgets/gimpdocumentview.c * app/widgets/gimphelp.c * app/widgets/gimpthumbbox.c: pass gimp_get_user_context() or GIMP_CONTEXT(tool_options) or whatever is the right context to the changed core functions. * tools/pdbgen/app.pl: pass "GimpContext *context" to all generated PDB invokers. * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/edit.pdb * tools/pdbgen/pdb/font_select.pdb * tools/pdbgen/pdb/gradient_select.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/paint_tools.pdb * tools/pdbgen/pdb/palette.pdb * tools/pdbgen/pdb/palette_select.pdb * tools/pdbgen/pdb/palettes.pdb * tools/pdbgen/pdb/paths.pdb * tools/pdbgen/pdb/pattern_select.pdb * tools/pdbgen/pdb/patterns.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/text_tool.pdb * tools/pdbgen/pdb/transform_tools.pdb: pass the new context parameter to the changed core functions. * app/pdb/*_cmds.c: regenerated.
2004-04-15 07:37:34 +08:00
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);
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; 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);
}
app/actions/channels-commands.c app/actions/colormap-actions.c 2007-12-25 Michael Natterer <mitch@gimp.org> * app/actions/channels-commands.c * app/actions/colormap-actions.c * app/actions/colormap-commands.c * app/actions/image-commands.c * app/core/gimp-edit.c * app/core/gimpdrawable-preview.c * app/core/gimpimage-colorhash.c * app/core/gimpimage-colormap.c * app/core/gimpimage-convert.c * app/core/gimpimage-crop.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-flip.c * app/core/gimpimage-guides.c * app/core/gimpimage-merge.c * app/core/gimpimage-preview.c * app/core/gimpimage-quick-mask.c * app/core/gimpimage-resize.c * app/core/gimpimage-rotate.c * app/core/gimpimage-sample-points.c * app/core/gimpimage-scale.c * app/core/gimpimage-snap.c * app/core/gimpimage.c * app/core/gimpimagefile.c * app/core/gimpimageundo.c * app/core/gimpitem-preview.c * app/core/gimpitem.c * app/core/gimplayer.c * app/core/gimppalette-import.c * app/core/gimpprojection-construct.c * app/core/gimpprojection.c * app/core/gimpselection.c * app/core/gimpundo.c * app/dialogs/layer-options-dialog.c * app/dialogs/print-size-dialog.c * app/display/gimpdisplay.c * app/display/gimpdisplayshell-draw.c * app/display/gimpdisplayshell-scale.c * app/display/gimpdisplayshell-scroll.c * app/display/gimpdisplayshell-title.c * app/display/gimpdisplayshell-transform.c * app/display/gimpdisplayshell.c * app/display/gimpstatusbar.c * app/file/file-open.c * app/paint/gimppaintoptions.c * app/tools/gimpaligntool.c * app/tools/gimpcolortool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpiscissorstool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimpperspectiveclonetool.c * app/tools/gimprectangleselecttool.c * app/tools/gimprectangletool.c * app/tools/gimprotatetool.c * app/vectors/gimpvectors-export.c * app/vectors/gimpvectors-import.c * app/vectors/gimpvectors.c * app/widgets/gimpimagepropview.c * app/widgets/gimpnavigationview.c * app/widgets/gimpselectioneditor.c * app/widgets/gimpviewrendererdrawable.c * app/widgets/gimpviewrendererimage.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/image.pdb: use accessors for many image properties. * app/pdb/guides_cmds.c * app/pdb/image_cmds.c: regenerated. svn path=/trunk/; revision=24432
2007-12-26 00:21:40 +08:00
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);
}
static void
gimp_vectors_resize (GimpItem *item,
GimpContext *context,
GimpFillType fill_type,
gint new_width,
gint new_height,
gint offset_x,
gint offset_y)
{
GimpVectors *vectors = GIMP_VECTORS (item);
Get rid of the "current_context" which was in fact just a bunch of global 2004-04-15 Michael Natterer <mitch@gimp.org> Get rid of the "current_context" which was in fact just a bunch of global variables. Instead, pass the needed context all the way from the GUI and the PDB to the core. This is a prerequisite for macro recording and generally helps separating the various subsystems from each other. Work in progress... * app/core/gimp.[ch]: removed member "current_context" and gimp_[get|set]_current_context(). * app/core/gimp-edit.[ch] * app/core/gimpdrawable-blend.[ch] * app/core/gimpdrawable-bucket-fill.[ch] * app/core/gimpdrawable-offset.[ch] * app/core/gimpdrawable-transform.[ch] * app/core/gimpimage-crop.[ch] * app/core/gimpimage-flip.[ch] * app/core/gimpimage-merge.[ch] * app/core/gimpimage-resize.[ch] * app/core/gimpimage-rotate.[ch] * app/core/gimpimage.[ch] * app/core/gimpimagefile.[ch] * app/core/gimpitem-linked.[ch] * app/core/gimpitem.[ch] * app/core/gimplayer.[ch] * app/core/gimpselection.[ch] * app/core/gimptemplate.[ch] * app/file/file-open.[ch] * app/file/file-save.[ch] * app/pdb/procedural_db.[ch] * app/text/gimptext-compat.[ch] * app/text/gimptextlayer-transform.[ch] * app/gui/brush-select.[ch] * app/gui/font-select.[ch] * app/gui/gradient-select.[ch] * app/gui/palette-select.[ch] * app/gui/pattern-select.[ch]: added tons of "GimpContext *context" parameters and use the passed context instead of gimp_get_current_context(). * app/app_procs.c * app/batch.c * app/core/gimpchannel.c * app/core/gimpdrawable.c * app/paint/gimperaser.c * app/paint/gimppaintbrush.c * app/plug-in/plug-in-message.c * app/plug-in/plug-ins.c * app/text/gimptextlayer.c * app/tools/gimpblendtool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpcroptool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpfliptool.c * app/tools/gimpinktool.c * app/tools/gimptransformtool.c * app/vectors/gimpvectors.c * app/gui/convert-dialog.c * app/gui/drawable-commands.c * app/gui/edit-commands.c * app/gui/file-commands.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/image-commands.c * app/gui/layers-commands.c * app/gui/offset-dialog.c * app/gui/select-commands.c * app/gui/vectors-commands.c * app/widgets/gimpdnd.c * app/widgets/gimpdocumentview.c * app/widgets/gimphelp.c * app/widgets/gimpthumbbox.c: pass gimp_get_user_context() or GIMP_CONTEXT(tool_options) or whatever is the right context to the changed core functions. * tools/pdbgen/app.pl: pass "GimpContext *context" to all generated PDB invokers. * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/edit.pdb * tools/pdbgen/pdb/font_select.pdb * tools/pdbgen/pdb/gradient_select.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/paint_tools.pdb * tools/pdbgen/pdb/palette.pdb * tools/pdbgen/pdb/palette_select.pdb * tools/pdbgen/pdb/palettes.pdb * tools/pdbgen/pdb/paths.pdb * tools/pdbgen/pdb/pattern_select.pdb * tools/pdbgen/pdb/patterns.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/text_tool.pdb * tools/pdbgen/pdb/transform_tools.pdb: pass the new context parameter to the changed core functions. * app/pdb/*_cmds.c: regenerated.
2004-04-15 07:37:34 +08:00
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);
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; 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, fill_type,
app/actions/channels-commands.c app/actions/colormap-actions.c 2007-12-25 Michael Natterer <mitch@gimp.org> * app/actions/channels-commands.c * app/actions/colormap-actions.c * app/actions/colormap-commands.c * app/actions/image-commands.c * app/core/gimp-edit.c * app/core/gimpdrawable-preview.c * app/core/gimpimage-colorhash.c * app/core/gimpimage-colormap.c * app/core/gimpimage-convert.c * app/core/gimpimage-crop.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-flip.c * app/core/gimpimage-guides.c * app/core/gimpimage-merge.c * app/core/gimpimage-preview.c * app/core/gimpimage-quick-mask.c * app/core/gimpimage-resize.c * app/core/gimpimage-rotate.c * app/core/gimpimage-sample-points.c * app/core/gimpimage-scale.c * app/core/gimpimage-snap.c * app/core/gimpimage.c * app/core/gimpimagefile.c * app/core/gimpimageundo.c * app/core/gimpitem-preview.c * app/core/gimpitem.c * app/core/gimplayer.c * app/core/gimppalette-import.c * app/core/gimpprojection-construct.c * app/core/gimpprojection.c * app/core/gimpselection.c * app/core/gimpundo.c * app/dialogs/layer-options-dialog.c * app/dialogs/print-size-dialog.c * app/display/gimpdisplay.c * app/display/gimpdisplayshell-draw.c * app/display/gimpdisplayshell-scale.c * app/display/gimpdisplayshell-scroll.c * app/display/gimpdisplayshell-title.c * app/display/gimpdisplayshell-transform.c * app/display/gimpdisplayshell.c * app/display/gimpstatusbar.c * app/file/file-open.c * app/paint/gimppaintoptions.c * app/tools/gimpaligntool.c * app/tools/gimpcolortool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpiscissorstool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimpperspectiveclonetool.c * app/tools/gimprectangleselecttool.c * app/tools/gimprectangletool.c * app/tools/gimprotatetool.c * app/vectors/gimpvectors-export.c * app/vectors/gimpvectors-import.c * app/vectors/gimpvectors.c * app/widgets/gimpimagepropview.c * app/widgets/gimpnavigationview.c * app/widgets/gimpselectioneditor.c * app/widgets/gimpviewrendererdrawable.c * app/widgets/gimpviewrendererimage.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/image.pdb: use accessors for many image properties. * app/pdb/guides_cmds.c * app/pdb/image_cmds.c: regenerated. svn path=/trunk/; revision=24432
2007-12-26 00:21:40 +08:00
gimp_image_get_width (image),
gimp_image_get_height (image),
0, 0);
gimp_vectors_thaw (vectors);
}
static void
gimp_vectors_flip (GimpItem *item,
Get rid of the "current_context" which was in fact just a bunch of global 2004-04-15 Michael Natterer <mitch@gimp.org> Get rid of the "current_context" which was in fact just a bunch of global variables. Instead, pass the needed context all the way from the GUI and the PDB to the core. This is a prerequisite for macro recording and generally helps separating the various subsystems from each other. Work in progress... * app/core/gimp.[ch]: removed member "current_context" and gimp_[get|set]_current_context(). * app/core/gimp-edit.[ch] * app/core/gimpdrawable-blend.[ch] * app/core/gimpdrawable-bucket-fill.[ch] * app/core/gimpdrawable-offset.[ch] * app/core/gimpdrawable-transform.[ch] * app/core/gimpimage-crop.[ch] * app/core/gimpimage-flip.[ch] * app/core/gimpimage-merge.[ch] * app/core/gimpimage-resize.[ch] * app/core/gimpimage-rotate.[ch] * app/core/gimpimage.[ch] * app/core/gimpimagefile.[ch] * app/core/gimpitem-linked.[ch] * app/core/gimpitem.[ch] * app/core/gimplayer.[ch] * app/core/gimpselection.[ch] * app/core/gimptemplate.[ch] * app/file/file-open.[ch] * app/file/file-save.[ch] * app/pdb/procedural_db.[ch] * app/text/gimptext-compat.[ch] * app/text/gimptextlayer-transform.[ch] * app/gui/brush-select.[ch] * app/gui/font-select.[ch] * app/gui/gradient-select.[ch] * app/gui/palette-select.[ch] * app/gui/pattern-select.[ch]: added tons of "GimpContext *context" parameters and use the passed context instead of gimp_get_current_context(). * app/app_procs.c * app/batch.c * app/core/gimpchannel.c * app/core/gimpdrawable.c * app/paint/gimperaser.c * app/paint/gimppaintbrush.c * app/plug-in/plug-in-message.c * app/plug-in/plug-ins.c * app/text/gimptextlayer.c * app/tools/gimpblendtool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpcroptool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpfliptool.c * app/tools/gimpinktool.c * app/tools/gimptransformtool.c * app/vectors/gimpvectors.c * app/gui/convert-dialog.c * app/gui/drawable-commands.c * app/gui/edit-commands.c * app/gui/file-commands.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/image-commands.c * app/gui/layers-commands.c * app/gui/offset-dialog.c * app/gui/select-commands.c * app/gui/vectors-commands.c * app/widgets/gimpdnd.c * app/widgets/gimpdocumentview.c * app/widgets/gimphelp.c * app/widgets/gimpthumbbox.c: pass gimp_get_user_context() or GIMP_CONTEXT(tool_options) or whatever is the right context to the changed core functions. * tools/pdbgen/app.pl: pass "GimpContext *context" to all generated PDB invokers. * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/edit.pdb * tools/pdbgen/pdb/font_select.pdb * tools/pdbgen/pdb/gradient_select.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/paint_tools.pdb * tools/pdbgen/pdb/palette.pdb * tools/pdbgen/pdb/palette_select.pdb * tools/pdbgen/pdb/palettes.pdb * tools/pdbgen/pdb/paths.pdb * tools/pdbgen/pdb/pattern_select.pdb * tools/pdbgen/pdb/patterns.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/text_tool.pdb * tools/pdbgen/pdb/transform_tools.pdb: pass the new context parameter to the changed core functions. * app/pdb/*_cmds.c: regenerated.
2004-04-15 07:37:34 +08:00
GimpContext *context,
GimpOrientationType flip_type,
gdouble axis,
gboolean clip_result)
{
GimpVectors *vectors = GIMP_VECTORS (item);
GList *list;
GimpMatrix3 matrix;
gimp_matrix3_identity (&matrix);
gimp_transform_matrix_flip (&matrix, flip_type, axis);
gimp_vectors_freeze (vectors);
gimp_image_undo_push_vectors_mod (gimp_item_get_image (item),
_("Flip Path"),
vectors);
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; list; list = g_list_next (list))
{
GimpStroke *stroke = list->data;
gimp_stroke_transform (stroke, &matrix);
}
gimp_vectors_thaw (vectors);
}
static void
gimp_vectors_rotate (GimpItem *item,
Get rid of the "current_context" which was in fact just a bunch of global 2004-04-15 Michael Natterer <mitch@gimp.org> Get rid of the "current_context" which was in fact just a bunch of global variables. Instead, pass the needed context all the way from the GUI and the PDB to the core. This is a prerequisite for macro recording and generally helps separating the various subsystems from each other. Work in progress... * app/core/gimp.[ch]: removed member "current_context" and gimp_[get|set]_current_context(). * app/core/gimp-edit.[ch] * app/core/gimpdrawable-blend.[ch] * app/core/gimpdrawable-bucket-fill.[ch] * app/core/gimpdrawable-offset.[ch] * app/core/gimpdrawable-transform.[ch] * app/core/gimpimage-crop.[ch] * app/core/gimpimage-flip.[ch] * app/core/gimpimage-merge.[ch] * app/core/gimpimage-resize.[ch] * app/core/gimpimage-rotate.[ch] * app/core/gimpimage.[ch] * app/core/gimpimagefile.[ch] * app/core/gimpitem-linked.[ch] * app/core/gimpitem.[ch] * app/core/gimplayer.[ch] * app/core/gimpselection.[ch] * app/core/gimptemplate.[ch] * app/file/file-open.[ch] * app/file/file-save.[ch] * app/pdb/procedural_db.[ch] * app/text/gimptext-compat.[ch] * app/text/gimptextlayer-transform.[ch] * app/gui/brush-select.[ch] * app/gui/font-select.[ch] * app/gui/gradient-select.[ch] * app/gui/palette-select.[ch] * app/gui/pattern-select.[ch]: added tons of "GimpContext *context" parameters and use the passed context instead of gimp_get_current_context(). * app/app_procs.c * app/batch.c * app/core/gimpchannel.c * app/core/gimpdrawable.c * app/paint/gimperaser.c * app/paint/gimppaintbrush.c * app/plug-in/plug-in-message.c * app/plug-in/plug-ins.c * app/text/gimptextlayer.c * app/tools/gimpblendtool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpcroptool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpfliptool.c * app/tools/gimpinktool.c * app/tools/gimptransformtool.c * app/vectors/gimpvectors.c * app/gui/convert-dialog.c * app/gui/drawable-commands.c * app/gui/edit-commands.c * app/gui/file-commands.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/image-commands.c * app/gui/layers-commands.c * app/gui/offset-dialog.c * app/gui/select-commands.c * app/gui/vectors-commands.c * app/widgets/gimpdnd.c * app/widgets/gimpdocumentview.c * app/widgets/gimphelp.c * app/widgets/gimpthumbbox.c: pass gimp_get_user_context() or GIMP_CONTEXT(tool_options) or whatever is the right context to the changed core functions. * tools/pdbgen/app.pl: pass "GimpContext *context" to all generated PDB invokers. * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/edit.pdb * tools/pdbgen/pdb/font_select.pdb * tools/pdbgen/pdb/gradient_select.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/paint_tools.pdb * tools/pdbgen/pdb/palette.pdb * tools/pdbgen/pdb/palette_select.pdb * tools/pdbgen/pdb/palettes.pdb * tools/pdbgen/pdb/paths.pdb * tools/pdbgen/pdb/pattern_select.pdb * tools/pdbgen/pdb/patterns.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/text_tool.pdb * tools/pdbgen/pdb/transform_tools.pdb: pass the new context parameter to the changed core functions. * app/pdb/*_cmds.c: regenerated.
2004-04-15 07:37:34 +08:00
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);
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; list; list = g_list_next (list))
{
GimpStroke *stroke = list->data;
gimp_stroke_transform (stroke, &matrix);
}
gimp_vectors_thaw (vectors);
}
static void
gimp_vectors_transform (GimpItem *item,
Get rid of the "current_context" which was in fact just a bunch of global 2004-04-15 Michael Natterer <mitch@gimp.org> Get rid of the "current_context" which was in fact just a bunch of global variables. Instead, pass the needed context all the way from the GUI and the PDB to the core. This is a prerequisite for macro recording and generally helps separating the various subsystems from each other. Work in progress... * app/core/gimp.[ch]: removed member "current_context" and gimp_[get|set]_current_context(). * app/core/gimp-edit.[ch] * app/core/gimpdrawable-blend.[ch] * app/core/gimpdrawable-bucket-fill.[ch] * app/core/gimpdrawable-offset.[ch] * app/core/gimpdrawable-transform.[ch] * app/core/gimpimage-crop.[ch] * app/core/gimpimage-flip.[ch] * app/core/gimpimage-merge.[ch] * app/core/gimpimage-resize.[ch] * app/core/gimpimage-rotate.[ch] * app/core/gimpimage.[ch] * app/core/gimpimagefile.[ch] * app/core/gimpitem-linked.[ch] * app/core/gimpitem.[ch] * app/core/gimplayer.[ch] * app/core/gimpselection.[ch] * app/core/gimptemplate.[ch] * app/file/file-open.[ch] * app/file/file-save.[ch] * app/pdb/procedural_db.[ch] * app/text/gimptext-compat.[ch] * app/text/gimptextlayer-transform.[ch] * app/gui/brush-select.[ch] * app/gui/font-select.[ch] * app/gui/gradient-select.[ch] * app/gui/palette-select.[ch] * app/gui/pattern-select.[ch]: added tons of "GimpContext *context" parameters and use the passed context instead of gimp_get_current_context(). * app/app_procs.c * app/batch.c * app/core/gimpchannel.c * app/core/gimpdrawable.c * app/paint/gimperaser.c * app/paint/gimppaintbrush.c * app/plug-in/plug-in-message.c * app/plug-in/plug-ins.c * app/text/gimptextlayer.c * app/tools/gimpblendtool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpcroptool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpfliptool.c * app/tools/gimpinktool.c * app/tools/gimptransformtool.c * app/vectors/gimpvectors.c * app/gui/convert-dialog.c * app/gui/drawable-commands.c * app/gui/edit-commands.c * app/gui/file-commands.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/image-commands.c * app/gui/layers-commands.c * app/gui/offset-dialog.c * app/gui/select-commands.c * app/gui/vectors-commands.c * app/widgets/gimpdnd.c * app/widgets/gimpdocumentview.c * app/widgets/gimphelp.c * app/widgets/gimpthumbbox.c: pass gimp_get_user_context() or GIMP_CONTEXT(tool_options) or whatever is the right context to the changed core functions. * tools/pdbgen/app.pl: pass "GimpContext *context" to all generated PDB invokers. * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/edit.pdb * tools/pdbgen/pdb/font_select.pdb * tools/pdbgen/pdb/gradient_select.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/paint_tools.pdb * tools/pdbgen/pdb/palette.pdb * tools/pdbgen/pdb/palette_select.pdb * tools/pdbgen/pdb/palettes.pdb * tools/pdbgen/pdb/paths.pdb * tools/pdbgen/pdb/pattern_select.pdb * tools/pdbgen/pdb/patterns.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/text_tool.pdb * tools/pdbgen/pdb/transform_tools.pdb: pass the new context parameter to the changed core functions. * app/pdb/*_cmds.c: regenerated.
2004-04-15 07:37:34 +08:00
GimpContext *context,
const GimpMatrix3 *matrix,
GimpTransformDirection direction,
GimpInterpolationType interpolation_type,
GimpTransformResize clip_result,
Redid the whole internal progress stuff: don't pass around 2004-08-10 Michael Natterer <mitch@gimp.org> Redid the whole internal progress stuff: don't pass around progress_callback and progress_data; instead, provide a pointer to a GimpProgressInterface which can be implemented by a variety of backends. Addresses (but not yet fixes) bugs #6010, #97266 and #135185. * app/display/Makefile.am * app/display/gimpprogress.[ch]: removed the old progress hack. * app/core/Makefile.am * app/core/core-types.h * app/core/gimpprogress.[ch]: implement GimpProgressInterface. * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpprogressdialog.[ch]: the standalone progress dialog as widget implementing GimpProgressInterface. * app/display/gimpdisplay.c * app/display/gimpstatusbar.[ch] * app/widgets/gimpfiledialog.[ch] * app/widgets/gimpthumbbox.[ch]: added GimpProgressInterface implementation to these classes. * app/core/gimp-gui.[ch] * app/gui/gui-vtable.c: replaced the old progress vtable entries by two new to create and destroy a GimpProgressDialog in case no other progress is available. * app/pdb/procedural_db.[ch] * app/plug-in/plug-in-run.[ch] * tools/pdbgen/app.pl: pass a GimpProgress to all PDB wrappers and all plug-ins. * app/plug-in/plug-in.[ch] * app/plug-in/plug-ins.c * app/plug-in/plug-in-message.c * app/plug-in/plug-in-progress.c: handle the case there the plug-in was crated with a progress as well as the case where it wasn't. * app/app_procs.c * app/batch.c * app/xcf/xcf.c * app/file/file-open.[ch] * app/file/file-save.[ch] * app/widgets/gimphelp.c * app/widgets/gimpbrushselect.c * app/widgets/gimpfontselect.c * app/widgets/gimpgradientselect.c * app/widgets/gimppaletteselect.c * app/widgets/gimppatternselect.c: changed accordingly. * app/core/gimpimagefile.[ch] * app/display/gimpdisplayshell-dnd.c * app/gui/file-open-dialog.c * app/gui/file-open-location-dialog.c * app/gui/file-save-dialog.c * app/widgets/gimplayertreeview.c * app/widgets/gimptoolbox-dnd.c: pass a GimpProgress to all file related functions. Embed the progress in the file dialog where possible. * app/core/gimpdrawable-blend.[ch] * app/core/gimpdrawable-transform.[ch] * app/core/gimpimage-convert.[ch] * app/core/gimpimage-flip.[ch] * app/core/gimpimage-resize.[ch] * app/core/gimpimage-rotate.[ch] * app/core/gimpimage-scale.[ch] * app/core/gimpitem-linked.[ch] * app/core/gimpitem.[ch] * app/core/gimpchannel.c * app/core/gimpdrawable.c * app/core/gimplayer.c * app/core/gimpselection.c * app/vectors/gimpvectors.c: replaced callback/data by GimpProgress. * app/tools/gimpblendtool.c * app/tools/gimptransformtool.c * app/gui/convert-dialog.c * app/actions/documents-commands.c * app/actions/file-commands.c * app/actions/image-commands.c * app/actions/layers-commands.c * app/actions/plug-in-commands.c * app/actions/vectors-commands.c * tools/pdbgen/pdb/convert.pdb * tools/pdbgen/pdb/edit.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb: changed callers accordingly. * app/pdb/*_cmds.c: regenerated.
2004-08-11 02:47:21 +08:00
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);
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; list; list = g_list_next (list))
{
GimpStroke *stroke = list->data;
gimp_stroke_transform (stroke, &local_matrix);
}
gimp_vectors_thaw (vectors);
}
static gboolean
gimp_vectors_fill (GimpItem *item,
GimpDrawable *drawable,
GimpFillOptions *fill_options,
gboolean push_undo,
GimpProgress *progress,
GError **error)
{
GimpVectors *vectors = GIMP_VECTORS (item);
if (g_queue_is_empty (vectors->strokes))
{
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
_("Not enough points to fill"));
return FALSE;
}
return gimp_drawable_fill_vectors (drawable, fill_options,
vectors, push_undo, error);
}
added new virtual function GimpItem::stroke(). 2003-09-01 Michael Natterer <mitch@gimp.org> * app/core/gimpitem.[ch]: added new virtual function GimpItem::stroke(). * app/core/gimpchannel.c * app/vectors/gimpvectors.c: implement GimpItem::stroke(). * app/core/gimpimage-mask.[ch] (gimp_image_mask_stroke): changed signature to match gimp_item_stroke() (the selection mask *really* should be a GimpChannel subclass). Removed global variable "gboolean gimp_image_mask_stroking"... * app/core/gimpimage.[ch]: ...and added "gboolean mask_stroking" to the GimpImage struct. * app/gui/vectors-commands.[ch]: removed vectors_stroke_vectors(). * app/widgets/widgets-types.h: removed GimpStrokeItemFunc typedef. * app/widgets/gimpvectorstreeview.[ch]: removed "stroke_item_func" member and use gimp_item_stroke() instead. * app/gui/dialogs-constructors.c (dialogs_vectors_list_view_new) * app/gui/edit-commands.c (edit_stroke_cmd_callback) * app/gui/vectors-commands. (vectors_stroke_cmd_callback) * app/widgets/gimpselectioneditor.c (gimp_selection_editor_stroke_clicked) * tools/pdbgen/pdb/edit.pdb (gimp_edit_stroke): changed accordingly. * app/pdb/edit_cmds.c: regenerated. Note that there is no GUI for "stroke channel", although it would be utterly cool to have one, since currently slelection stroking cannot be masked by a selection (because we stroke the selection). Anyway, if anyone has an idea how to trigger "stroke channel" with another drawable active (the one to stroke to), please let me know...
2003-09-02 01:56:44 +08:00
static gboolean
gimp_vectors_stroke (GimpItem *item,
GimpDrawable *drawable,
GimpStrokeOptions *stroke_options,
gboolean push_undo,
GimpProgress *progress,
GError **error)
added new virtual function GimpItem::stroke(). 2003-09-01 Michael Natterer <mitch@gimp.org> * app/core/gimpitem.[ch]: added new virtual function GimpItem::stroke(). * app/core/gimpchannel.c * app/vectors/gimpvectors.c: implement GimpItem::stroke(). * app/core/gimpimage-mask.[ch] (gimp_image_mask_stroke): changed signature to match gimp_item_stroke() (the selection mask *really* should be a GimpChannel subclass). Removed global variable "gboolean gimp_image_mask_stroking"... * app/core/gimpimage.[ch]: ...and added "gboolean mask_stroking" to the GimpImage struct. * app/gui/vectors-commands.[ch]: removed vectors_stroke_vectors(). * app/widgets/widgets-types.h: removed GimpStrokeItemFunc typedef. * app/widgets/gimpvectorstreeview.[ch]: removed "stroke_item_func" member and use gimp_item_stroke() instead. * app/gui/dialogs-constructors.c (dialogs_vectors_list_view_new) * app/gui/edit-commands.c (edit_stroke_cmd_callback) * app/gui/vectors-commands. (vectors_stroke_cmd_callback) * app/widgets/gimpselectioneditor.c (gimp_selection_editor_stroke_clicked) * tools/pdbgen/pdb/edit.pdb (gimp_edit_stroke): changed accordingly. * app/pdb/edit_cmds.c: regenerated. Note that there is no GUI for "stroke channel", although it would be utterly cool to have one, since currently slelection stroking cannot be masked by a selection (because we stroke the selection). Anyway, if anyone has an idea how to trigger "stroke channel" with another drawable active (the one to stroke to), please let me know...
2003-09-02 01:56:44 +08:00
{
GimpVectors *vectors = GIMP_VECTORS (item);
gboolean retval = FALSE;
added new virtual function GimpItem::stroke(). 2003-09-01 Michael Natterer <mitch@gimp.org> * app/core/gimpitem.[ch]: added new virtual function GimpItem::stroke(). * app/core/gimpchannel.c * app/vectors/gimpvectors.c: implement GimpItem::stroke(). * app/core/gimpimage-mask.[ch] (gimp_image_mask_stroke): changed signature to match gimp_item_stroke() (the selection mask *really* should be a GimpChannel subclass). Removed global variable "gboolean gimp_image_mask_stroking"... * app/core/gimpimage.[ch]: ...and added "gboolean mask_stroking" to the GimpImage struct. * app/gui/vectors-commands.[ch]: removed vectors_stroke_vectors(). * app/widgets/widgets-types.h: removed GimpStrokeItemFunc typedef. * app/widgets/gimpvectorstreeview.[ch]: removed "stroke_item_func" member and use gimp_item_stroke() instead. * app/gui/dialogs-constructors.c (dialogs_vectors_list_view_new) * app/gui/edit-commands.c (edit_stroke_cmd_callback) * app/gui/vectors-commands. (vectors_stroke_cmd_callback) * app/widgets/gimpselectioneditor.c (gimp_selection_editor_stroke_clicked) * tools/pdbgen/pdb/edit.pdb (gimp_edit_stroke): changed accordingly. * app/pdb/edit_cmds.c: regenerated. Note that there is no GUI for "stroke channel", although it would be utterly cool to have one, since currently slelection stroking cannot be masked by a selection (because we stroke the selection). Anyway, if anyone has an idea how to trigger "stroke channel" with another drawable active (the one to stroke to), please let me know...
2003-09-02 01:56:44 +08:00
2016-01-25 13:21:27 +08:00
if (g_queue_is_empty (vectors->strokes))
{
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
_("Not enough points to stroke"));
return FALSE;
}
added new virtual function GimpItem::stroke(). 2003-09-01 Michael Natterer <mitch@gimp.org> * app/core/gimpitem.[ch]: added new virtual function GimpItem::stroke(). * app/core/gimpchannel.c * app/vectors/gimpvectors.c: implement GimpItem::stroke(). * app/core/gimpimage-mask.[ch] (gimp_image_mask_stroke): changed signature to match gimp_item_stroke() (the selection mask *really* should be a GimpChannel subclass). Removed global variable "gboolean gimp_image_mask_stroking"... * app/core/gimpimage.[ch]: ...and added "gboolean mask_stroking" to the GimpImage struct. * app/gui/vectors-commands.[ch]: removed vectors_stroke_vectors(). * app/widgets/widgets-types.h: removed GimpStrokeItemFunc typedef. * app/widgets/gimpvectorstreeview.[ch]: removed "stroke_item_func" member and use gimp_item_stroke() instead. * app/gui/dialogs-constructors.c (dialogs_vectors_list_view_new) * app/gui/edit-commands.c (edit_stroke_cmd_callback) * app/gui/vectors-commands. (vectors_stroke_cmd_callback) * app/widgets/gimpselectioneditor.c (gimp_selection_editor_stroke_clicked) * tools/pdbgen/pdb/edit.pdb (gimp_edit_stroke): changed accordingly. * app/pdb/edit_cmds.c: regenerated. Note that there is no GUI for "stroke channel", although it would be utterly cool to have one, since currently slelection stroking cannot be masked by a selection (because we stroke the selection). Anyway, if anyone has an idea how to trigger "stroke channel" with another drawable active (the one to stroke to), please let me know...
2003-09-02 01:56:44 +08:00
switch (gimp_stroke_options_get_method (stroke_options))
{
case GIMP_STROKE_LINE:
retval = gimp_drawable_stroke_vectors (drawable, stroke_options,
vectors, push_undo, error);
break;
case GIMP_STROKE_PAINT_METHOD:
{
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);
}
added new virtual function GimpItem::stroke(). 2003-09-01 Michael Natterer <mitch@gimp.org> * app/core/gimpitem.[ch]: added new virtual function GimpItem::stroke(). * app/core/gimpchannel.c * app/vectors/gimpvectors.c: implement GimpItem::stroke(). * app/core/gimpimage-mask.[ch] (gimp_image_mask_stroke): changed signature to match gimp_item_stroke() (the selection mask *really* should be a GimpChannel subclass). Removed global variable "gboolean gimp_image_mask_stroking"... * app/core/gimpimage.[ch]: ...and added "gboolean mask_stroking" to the GimpImage struct. * app/gui/vectors-commands.[ch]: removed vectors_stroke_vectors(). * app/widgets/widgets-types.h: removed GimpStrokeItemFunc typedef. * app/widgets/gimpvectorstreeview.[ch]: removed "stroke_item_func" member and use gimp_item_stroke() instead. * app/gui/dialogs-constructors.c (dialogs_vectors_list_view_new) * app/gui/edit-commands.c (edit_stroke_cmd_callback) * app/gui/vectors-commands. (vectors_stroke_cmd_callback) * app/widgets/gimpselectioneditor.c (gimp_selection_editor_stroke_clicked) * tools/pdbgen/pdb/edit.pdb (gimp_edit_stroke): changed accordingly. * app/pdb/edit_cmds.c: regenerated. Note that there is no GUI for "stroke channel", although it would be utterly cool to have one, since currently slelection stroking cannot be masked by a selection (because we stroke the selection). Anyway, if anyone has an idea how to trigger "stroke channel" with another drawable active (the one to stroke to), please let me know...
2003-09-02 01:56:44 +08:00
return retval;
}
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_real_freeze (GimpVectors *vectors)
{
/* release cached bezier representation */
if (vectors->bezier_desc)
{
gimp_bezier_desc_free (vectors->bezier_desc);
vectors->bezier_desc = NULL;
}
/* invalidate bounds */
vectors->bounds_valid = FALSE;
}
static void
gimp_vectors_real_thaw (GimpVectors *vectors)
{
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (vectors));
}
/* public functions */
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;
}
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)));
}
void
gimp_vectors_freeze (GimpVectors *vectors)
{
g_return_if_fail (GIMP_IS_VECTORS (vectors));
vectors->freeze_count++;
if (vectors->freeze_count == 1)
g_signal_emit (vectors, gimp_vectors_signals[FREEZE], 0);
}
void
gimp_vectors_thaw (GimpVectors *vectors)
{
g_return_if_fail (GIMP_IS_VECTORS (vectors));
g_return_if_fail (vectors->freeze_count > 0);
vectors->freeze_count--;
if (vectors->freeze_count == 0)
g_signal_emit (vectors, gimp_vectors_signals[THAW], 0);
}
void
gimp_vectors_copy_strokes (GimpVectors *src_vectors,
GimpVectors *dest_vectors)
{
g_return_if_fail (GIMP_IS_VECTORS (src_vectors));
g_return_if_fail (GIMP_IS_VECTORS (dest_vectors));
gimp_vectors_freeze (dest_vectors);
2016-01-25 13:21:27 +08:00
g_queue_free_full (dest_vectors->strokes, (GDestroyNotify) g_object_unref);
dest_vectors->strokes = g_queue_new ();
g_hash_table_remove_all (dest_vectors->stroke_to_list);
dest_vectors->last_stroke_ID = 0;
gimp_vectors_add_strokes (src_vectors, dest_vectors);
gimp_vectors_thaw (dest_vectors);
}
void
gimp_vectors_add_strokes (GimpVectors *src_vectors,
GimpVectors *dest_vectors)
{
GList *stroke;
g_return_if_fail (GIMP_IS_VECTORS (src_vectors));
g_return_if_fail (GIMP_IS_VECTORS (dest_vectors));
gimp_vectors_freeze (dest_vectors);
2016-01-25 17:59:46 +08:00
for (stroke = src_vectors->strokes->head;
stroke != NULL;
stroke = g_list_next (stroke))
{
GimpStroke *newstroke = gimp_stroke_duplicate (stroke->data);
2016-01-25 17:59:46 +08:00
g_queue_push_tail (dest_vectors->strokes, newstroke);
/* Also add to {stroke: GList node} map */
2016-01-25 17:59:46 +08:00
g_hash_table_insert (dest_vectors->stroke_to_list,
newstroke,
g_queue_peek_tail_link (dest_vectors->strokes));
dest_vectors->last_stroke_ID++;
gimp_stroke_set_ID (newstroke,
dest_vectors->last_stroke_ID);
}
gimp_vectors_thaw (dest_vectors);
}
void
gimp_vectors_stroke_add (GimpVectors *vectors,
GimpStroke *stroke)
{
g_return_if_fail (GIMP_IS_VECTORS (vectors));
g_return_if_fail (GIMP_IS_STROKE (stroke));
gimp_vectors_freeze (vectors);
GIMP_VECTORS_GET_CLASS (vectors)->stroke_add (vectors, stroke);
gimp_vectors_thaw (vectors);
}
static void
gimp_vectors_real_stroke_add (GimpVectors *vectors,
GimpStroke *stroke)
{
/*
* Don't prepend into vector->strokes. See ChangeLog 2003-05-21
* --Mitch
*/
g_queue_push_tail (vectors->strokes, g_object_ref (stroke));
/* Also add to {stroke: GList node} map */
2016-01-25 13:21:27 +08:00
g_hash_table_insert (vectors->stroke_to_list,
stroke,
g_queue_peek_tail_link (vectors->strokes));
vectors->last_stroke_ID++;
gimp_stroke_set_ID (stroke, vectors->last_stroke_ID);
}
void
gimp_vectors_stroke_remove (GimpVectors *vectors,
GimpStroke *stroke)
{
g_return_if_fail (GIMP_IS_VECTORS (vectors));
g_return_if_fail (GIMP_IS_STROKE (stroke));
gimp_vectors_freeze (vectors);
GIMP_VECTORS_GET_CLASS (vectors)->stroke_remove (vectors, stroke);
gimp_vectors_thaw (vectors);
}
static void
gimp_vectors_real_stroke_remove (GimpVectors *vectors,
GimpStroke *stroke)
{
GList *list = g_hash_table_lookup (vectors->stroke_to_list, stroke);
if (list)
{
g_queue_delete_link (vectors->strokes, list);
g_hash_table_remove (vectors->stroke_to_list, stroke);
g_object_unref (stroke);
}
}
gint
gimp_vectors_get_n_strokes (GimpVectors *vectors)
{
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), 0);
2016-01-25 13:21:27 +08:00
return g_queue_get_length (vectors->strokes);
}
GimpStroke *
gimp_vectors_stroke_get (GimpVectors *vectors,
const GimpCoords *coord)
{
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL);
return GIMP_VECTORS_GET_CLASS (vectors)->stroke_get (vectors, coord);
}
static GimpStroke *
gimp_vectors_real_stroke_get (GimpVectors *vectors,
const GimpCoords *coord)
{
GimpStroke *minstroke = NULL;
gdouble mindist = G_MAXDOUBLE;
GList *list;
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; list; list = g_list_next (list))
{
GimpStroke *stroke = list->data;
GimpAnchor *anchor = gimp_stroke_anchor_get (stroke, coord);
if (anchor)
{
gdouble dx = coord->x - anchor->position.x;
gdouble dy = coord->y - anchor->position.y;
if (mindist > dx * dx + dy * dy)
{
mindist = dx * dx + dy * dy;
minstroke = stroke;
}
}
}
return minstroke;
}
GimpStroke *
gimp_vectors_stroke_get_by_ID (GimpVectors *vectors,
gint id)
{
GList *list;
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL);
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; list; list = g_list_next (list))
{
if (gimp_stroke_get_ID (list->data) == id)
return list->data;
}
return NULL;
}
GimpStroke *
gimp_vectors_stroke_get_next (GimpVectors *vectors,
GimpStroke *prev)
{
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL);
return GIMP_VECTORS_GET_CLASS (vectors)->stroke_get_next (vectors, prev);
}
static GimpStroke *
gimp_vectors_real_stroke_get_next (GimpVectors *vectors,
GimpStroke *prev)
{
if (! prev)
{
return g_queue_peek_head (vectors->strokes);
}
else
{
GList *stroke = g_hash_table_lookup (vectors->stroke_to_list, prev);
g_return_val_if_fail (stroke != NULL, NULL);
return stroke->next ? stroke->next->data : NULL;
}
}
gdouble
gimp_vectors_stroke_get_length (GimpVectors *vectors,
GimpStroke *stroke)
{
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), 0.0);
g_return_val_if_fail (GIMP_IS_STROKE (stroke), 0.0);
return GIMP_VECTORS_GET_CLASS (vectors)->stroke_get_length (vectors, stroke);
}
static gdouble
gimp_vectors_real_stroke_get_length (GimpVectors *vectors,
GimpStroke *stroke)
{
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), 0.0);
g_return_val_if_fail (GIMP_IS_STROKE (stroke), 0.0);
2013-06-16 04:57:10 +08:00
return gimp_stroke_get_length (stroke, vectors->precision);
}
GimpAnchor *
gimp_vectors_anchor_get (GimpVectors *vectors,
const GimpCoords *coord,
GimpStroke **ret_stroke)
{
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL);
return GIMP_VECTORS_GET_CLASS (vectors)->anchor_get (vectors, coord,
ret_stroke);
}
static GimpAnchor *
gimp_vectors_real_anchor_get (GimpVectors *vectors,
const GimpCoords *coord,
GimpStroke **ret_stroke)
{
GimpAnchor *minanchor = NULL;
gdouble mindist = -1;
GList *list;
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; list; list = g_list_next (list))
{
GimpStroke *stroke = list->data;
GimpAnchor *anchor = gimp_stroke_anchor_get (stroke, coord);
if (anchor)
{
gdouble dx = coord->x - anchor->position.x;
gdouble dy = coord->y - anchor->position.y;
if (mindist > dx * dx + dy * dy || mindist < 0)
{
mindist = dx * dx + dy * dy;
minanchor = anchor;
if (ret_stroke)
*ret_stroke = stroke;
}
}
}
return minanchor;
}
void
gimp_vectors_anchor_delete (GimpVectors *vectors,
GimpAnchor *anchor)
{
g_return_if_fail (GIMP_IS_VECTORS (vectors));
g_return_if_fail (anchor != NULL);
GIMP_VECTORS_GET_CLASS (vectors)->anchor_delete (vectors, anchor);
}
static void
gimp_vectors_real_anchor_delete (GimpVectors *vectors,
GimpAnchor *anchor)
{
}
void
gimp_vectors_anchor_select (GimpVectors *vectors,
GimpStroke *target_stroke,
GimpAnchor *anchor,
gboolean selected,
gboolean exclusive)
{
GList *list;
2016-01-25 13:21:27 +08:00
for (list = vectors->strokes->head; list; list = g_list_next (list))
{
GimpStroke *stroke = list->data;
gimp_stroke_anchor_select (stroke,
stroke == target_stroke ? anchor : NULL,
selected, exclusive);
}
}
gdouble
gimp_vectors_get_length (GimpVectors *vectors,
const GimpAnchor *start)
{
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), 0.0);
return GIMP_VECTORS_GET_CLASS (vectors)->get_length (vectors, start);
}
static gdouble
gimp_vectors_real_get_length (GimpVectors *vectors,
const GimpAnchor *start)
{
g_printerr ("gimp_vectors_get_length: default implementation\n");
return 0;
}
gdouble
gimp_vectors_get_distance (GimpVectors *vectors,
const GimpCoords *coord)
{
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), 0.0);
return GIMP_VECTORS_GET_CLASS (vectors)->get_distance (vectors, coord);
}
static gdouble
gimp_vectors_real_get_distance (GimpVectors *vectors,
const GimpCoords *coord)
{
g_printerr ("gimp_vectors_get_distance: default implementation\n");
return 0;
}
gint
gimp_vectors_interpolate (GimpVectors *vectors,
GimpStroke *stroke,
gdouble precision,
gint max_points,
GimpCoords *ret_coords)
{
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), 0);
return GIMP_VECTORS_GET_CLASS (vectors)->interpolate (vectors, stroke,
precision, max_points,
ret_coords);
}
static gint
gimp_vectors_real_interpolate (GimpVectors *vectors,
GimpStroke *stroke,
gdouble precision,
gint max_points,
GimpCoords *ret_coords)
{
g_printerr ("gimp_vectors_interpolate: default implementation\n");
return 0;
}
const GimpBezierDesc *
gimp_vectors_get_bezier (GimpVectors *vectors)
{
g_return_val_if_fail (GIMP_IS_VECTORS (vectors), NULL);
if (! vectors->bezier_desc)
{
vectors->bezier_desc = gimp_vectors_make_bezier (vectors);
}
return vectors->bezier_desc;
}
static GimpBezierDesc *
gimp_vectors_make_bezier (GimpVectors *vectors)
{
return GIMP_VECTORS_GET_CLASS (vectors)->make_bezier (vectors);
}
static GimpBezierDesc *
gimp_vectors_real_make_bezier (GimpVectors *vectors)
{
GimpStroke *stroke;
GArray *cmd_array;
GimpBezierDesc *ret_bezdesc = NULL;
cmd_array = g_array_new (FALSE, FALSE, sizeof (cairo_path_data_t));
for (stroke = gimp_vectors_stroke_get_next (vectors, NULL);
stroke;
stroke = gimp_vectors_stroke_get_next (vectors, stroke))
{
GimpBezierDesc *bezdesc = gimp_stroke_make_bezier (stroke);
2010-09-12 05:00:48 +08:00
if (bezdesc)
{
cmd_array = g_array_append_vals (cmd_array, bezdesc->data,
bezdesc->num_data);
gimp_bezier_desc_free (bezdesc);
}
}
if (cmd_array->len > 0)
ret_bezdesc = gimp_bezier_desc_new ((cairo_path_data_t *) cmd_array->data,
cmd_array->len);
2012-02-07 21:06:12 +08:00
g_array_free (cmd_array, FALSE);
return ret_bezdesc;
}