[gimp] app: add various handle and vectors hit tests to gimpcanvasitems-utils.[ch]
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add various handle and vectors hit tests to gimpcanvasitems-utils.[ch]
- Date: Wed, 21 Jun 2017 21:29:22 +0000 (UTC)
commit c4d5693903fc9ee6dd5c2224676ca5f5dcf68d6d
Author: Michael Natterer <mitch gimp org>
Date: Wed Jun 21 23:21:26 2017 +0200
app: add various handle and vectors hit tests to gimpcanvasitems-utils.[ch]
1:1 copies of the same functions in gimpdrawtool.[ch].
app/display/gimpcanvasitem-utils.c | 321 ++++++++++++++++++++++++++++++++++++
app/display/gimpcanvasitem-utils.h | 68 ++++++--
2 files changed, 375 insertions(+), 14 deletions(-)
---
diff --git a/app/display/gimpcanvasitem-utils.c b/app/display/gimpcanvasitem-utils.c
index 73dbd54..e72c194 100644
--- a/app/display/gimpcanvasitem-utils.c
+++ b/app/display/gimpcanvasitem-utils.c
@@ -23,10 +23,331 @@
#include <gegl.h>
#include <gtk/gtk.h>
+#include "libgimpmath/gimpmath.h"
+
#include "display-types.h"
+#include "core/gimpimage.h"
+
+#include "vectors/gimpanchor.h"
+#include "vectors/gimpbezierstroke.h"
+#include "vectors/gimpvectors.h"
+
+#include "gimpcanvasitem.h"
#include "gimpcanvasitem-utils.h"
+#include "gimpdisplay.h"
+#include "gimpdisplayshell.h"
+#include "gimpdisplayshell-transform.h"
+
+
+gboolean
+gimp_canvas_item_on_handle (GimpCanvasItem *item,
+ gdouble x,
+ gdouble y,
+ GimpHandleType type,
+ gdouble handle_x,
+ gdouble handle_y,
+ gint width,
+ gint height,
+ GimpHandleAnchor anchor)
+{
+ GimpDisplayShell *shell;
+ gdouble tx, ty;
+ gdouble handle_tx, handle_ty;
+
+ g_return_val_if_fail (GIMP_IS_CANVAS_ITEM (item), FALSE);
+
+ shell = gimp_canvas_item_get_shell (item);
+
+ gimp_display_shell_zoom_xy_f (shell,
+ x, y,
+ &tx, &ty);
+ gimp_display_shell_zoom_xy_f (shell,
+ handle_x, handle_y,
+ &handle_tx, &handle_ty);
+
+ switch (type)
+ {
+ case GIMP_HANDLE_SQUARE:
+ case GIMP_HANDLE_FILLED_SQUARE:
+ case GIMP_HANDLE_CROSS:
+ case GIMP_HANDLE_CROSSHAIR:
+ gimp_canvas_item_shift_to_north_west (anchor,
+ handle_tx, handle_ty,
+ width, height,
+ &handle_tx, &handle_ty);
+
+ return (tx == CLAMP (tx, handle_tx, handle_tx + width) &&
+ ty == CLAMP (ty, handle_ty, handle_ty + height));
+
+ case GIMP_HANDLE_CIRCLE:
+ case GIMP_HANDLE_FILLED_CIRCLE:
+ gimp_canvas_item_shift_to_center (anchor,
+ handle_tx, handle_ty,
+ width, height,
+ &handle_tx, &handle_ty);
+
+ /* FIXME */
+ if (width != height)
+ width = (width + height) / 2;
+
+ width /= 2;
+
+ return ((SQR (handle_tx - tx) + SQR (handle_ty - ty)) < SQR (width));
+
+ default:
+ g_warning ("%s: invalid handle type %d", G_STRFUNC, type);
+ break;
+ }
+ return FALSE;
+}
+
+gboolean
+gimp_canvas_item_on_vectors_handle (GimpCanvasItem *item,
+ GimpVectors *vectors,
+ const GimpCoords *coord,
+ gint width,
+ gint height,
+ GimpAnchorType preferred,
+ gboolean exclusive,
+ GimpAnchor **ret_anchor,
+ GimpStroke **ret_stroke)
+{
+ GimpStroke *stroke = NULL;
+ GimpStroke *pref_stroke = NULL;
+ GimpAnchor *anchor = NULL;
+ GimpAnchor *pref_anchor = NULL;
+ gdouble dx, dy;
+ gdouble pref_mindist = -1;
+ gdouble mindist = -1;
+
+ g_return_val_if_fail (GIMP_IS_CANVAS_ITEM (item), FALSE);
+ g_return_val_if_fail (GIMP_IS_VECTORS (vectors), FALSE);
+ g_return_val_if_fail (coord != NULL, FALSE);
+
+ if (ret_anchor) *ret_anchor = NULL;
+ if (ret_stroke) *ret_stroke = NULL;
+
+ while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke)))
+ {
+ GList *anchor_list;
+ GList *list;
+
+ anchor_list = g_list_concat (gimp_stroke_get_draw_anchors (stroke),
+ gimp_stroke_get_draw_controls (stroke));
+
+ for (list = anchor_list; list; list = g_list_next (list))
+ {
+ dx = coord->x - GIMP_ANCHOR (list->data)->position.x;
+ dy = coord->y - GIMP_ANCHOR (list->data)->position.y;
+
+ if (mindist < 0 || mindist > dx * dx + dy * dy)
+ {
+ mindist = dx * dx + dy * dy;
+ anchor = GIMP_ANCHOR (list->data);
+
+ if (ret_stroke)
+ *ret_stroke = stroke;
+ }
+
+ if ((pref_mindist < 0 || pref_mindist > dx * dx + dy * dy) &&
+ GIMP_ANCHOR (list->data)->type == preferred)
+ {
+ pref_mindist = dx * dx + dy * dy;
+ pref_anchor = GIMP_ANCHOR (list->data);
+ pref_stroke = stroke;
+ }
+ }
+
+ g_list_free (anchor_list);
+ }
+
+ /* If the data passed into ret_anchor is a preferred anchor, return it. */
+ if (ret_anchor && *ret_anchor &&
+ gimp_canvas_item_on_handle (item,
+ coord->x,
+ coord->y,
+ GIMP_HANDLE_CIRCLE,
+ (*ret_anchor)->position.x,
+ (*ret_anchor)->position.y,
+ width, height,
+ GIMP_HANDLE_ANCHOR_CENTER) &&
+ (*ret_anchor)->type == preferred)
+ {
+ if (ret_stroke) *ret_stroke = pref_stroke;
+
+ return TRUE;
+ }
+
+ if (pref_anchor && gimp_canvas_item_on_handle (item,
+ coord->x,
+ coord->y,
+ GIMP_HANDLE_CIRCLE,
+ pref_anchor->position.x,
+ pref_anchor->position.y,
+ width, height,
+ GIMP_HANDLE_ANCHOR_CENTER))
+ {
+ if (ret_anchor) *ret_anchor = pref_anchor;
+ if (ret_stroke) *ret_stroke = pref_stroke;
+
+ return TRUE;
+ }
+ else if (!exclusive && anchor &&
+ gimp_canvas_item_on_handle (item,
+ coord->x,
+ coord->y,
+ GIMP_HANDLE_CIRCLE,
+ anchor->position.x,
+ anchor->position.y,
+ width, height,
+ GIMP_HANDLE_ANCHOR_CENTER))
+ {
+ if (ret_anchor)
+ *ret_anchor = anchor;
+
+ /* *ret_stroke already set correctly. */
+ return TRUE;
+ }
+
+ if (ret_anchor)
+ *ret_anchor = NULL;
+ if (ret_stroke)
+ *ret_stroke = NULL;
+
+ return FALSE;
+}
+
+gboolean
+gimp_canvas_item_on_vectors_curve (GimpCanvasItem *item,
+ GimpVectors *vectors,
+ const GimpCoords *coord,
+ gint width,
+ gint height,
+ GimpCoords *ret_coords,
+ gdouble *ret_pos,
+ GimpAnchor **ret_segment_start,
+ GimpAnchor **ret_segment_end,
+ GimpStroke **ret_stroke)
+{
+ GimpStroke *stroke = NULL;
+ GimpAnchor *segment_start;
+ GimpAnchor *segment_end;
+ GimpCoords min_coords = GIMP_COORDS_DEFAULT_VALUES;
+ GimpCoords cur_coords;
+ gdouble min_dist, cur_dist, cur_pos;
+
+ g_return_val_if_fail (GIMP_IS_CANVAS_ITEM (item), FALSE);
+ g_return_val_if_fail (GIMP_IS_VECTORS (vectors), FALSE);
+ g_return_val_if_fail (coord != NULL, FALSE);
+
+ if (ret_coords) *ret_coords = *coord;
+ if (ret_pos) *ret_pos = -1.0;
+ if (ret_segment_start) *ret_segment_start = NULL;
+ if (ret_segment_end) *ret_segment_end = NULL;
+ if (ret_stroke) *ret_stroke = NULL;
+
+ min_dist = -1.0;
+
+ while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke)))
+ {
+ cur_dist = gimp_stroke_nearest_point_get (stroke, coord, 1.0,
+ &cur_coords,
+ &segment_start,
+ &segment_end,
+ &cur_pos);
+
+ if (cur_dist >= 0 && (min_dist < 0 || cur_dist < min_dist))
+ {
+ min_dist = cur_dist;
+ min_coords = cur_coords;
+
+ if (ret_coords) *ret_coords = cur_coords;
+ if (ret_pos) *ret_pos = cur_pos;
+ if (ret_segment_start) *ret_segment_start = segment_start;
+ if (ret_segment_end) *ret_segment_end = segment_end;
+ if (ret_stroke) *ret_stroke = stroke;
+ }
+ }
+
+ if (min_dist >= 0 &&
+ gimp_canvas_item_on_handle (item,
+ coord->x,
+ coord->y,
+ GIMP_HANDLE_CIRCLE,
+ min_coords.x,
+ min_coords.y,
+ width, height,
+ GIMP_HANDLE_ANCHOR_CENTER))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean
+gimp_canvas_item_on_vectors (GimpCanvasItem *item,
+ const GimpCoords *coords,
+ gint width,
+ gint height,
+ GimpCoords *ret_coords,
+ gdouble *ret_pos,
+ GimpAnchor **ret_segment_start,
+ GimpAnchor **ret_segment_end,
+ GimpStroke **ret_stroke,
+ GimpVectors **ret_vectors)
+{
+ GimpDisplayShell *shell;
+ GimpImage *image;
+ GList *all_vectors;
+ GList *list;
+
+ g_return_val_if_fail (GIMP_IS_CANVAS_ITEM (item), FALSE);
+ g_return_val_if_fail (coords != NULL, FALSE);
+
+ shell = gimp_canvas_item_get_shell (item);
+ image = gimp_display_get_image (shell->display);
+
+ if (ret_coords) *ret_coords = *coords;
+ if (ret_pos) *ret_pos = -1.0;
+ if (ret_segment_start) *ret_segment_start = NULL;
+ if (ret_segment_end) *ret_segment_end = NULL;
+ if (ret_stroke) *ret_stroke = NULL;
+ if (ret_vectors) *ret_vectors = NULL;
+
+ all_vectors = gimp_image_get_vectors_list (image);
+
+ for (list = all_vectors; list; list = g_list_next (list))
+ {
+ GimpVectors *vectors = list->data;
+
+ if (! gimp_item_get_visible (GIMP_ITEM (vectors)))
+ continue;
+
+ if (gimp_canvas_item_on_vectors_curve (item,
+ vectors, coords,
+ width, height,
+ ret_coords,
+ ret_pos,
+ ret_segment_start,
+ ret_segment_end,
+ ret_stroke))
+ {
+ if (ret_vectors)
+ *ret_vectors = vectors;
+
+ g_list_free (all_vectors);
+
+ return TRUE;
+ }
+ }
+
+ g_list_free (all_vectors);
+
+ return FALSE;
+}
void
gimp_canvas_item_shift_to_north_west (GimpHandleAnchor anchor,
diff --git a/app/display/gimpcanvasitem-utils.h b/app/display/gimpcanvasitem-utils.h
index 7271877..bca9b3f 100644
--- a/app/display/gimpcanvasitem-utils.h
+++ b/app/display/gimpcanvasitem-utils.h
@@ -22,20 +22,60 @@
#define __GIMP_CANVAS_ITEM_UTILS_H__
-void gimp_canvas_item_shift_to_north_west (GimpHandleAnchor anchor,
- gdouble x,
- gdouble y,
- gint width,
- gint height,
- gdouble *shifted_x,
- gdouble *shifted_y);
-void gimp_canvas_item_shift_to_center (GimpHandleAnchor anchor,
- gdouble x,
- gdouble y,
- gint width,
- gint height,
- gdouble *shifted_x,
- gdouble *shifted_y);
+gboolean gimp_canvas_item_on_handle (GimpCanvasItem *item,
+ gdouble x,
+ gdouble y,
+ GimpHandleType type,
+ gdouble handle_x,
+ gdouble handle_y,
+ gint width,
+ gint height,
+ GimpHandleAnchor anchor);
+
+gboolean gimp_canvas_item_on_vectors_handle (GimpCanvasItem *item,
+ GimpVectors *vectors,
+ const GimpCoords *coord,
+ gint width,
+ gint height,
+ GimpAnchorType preferred,
+ gboolean exclusive,
+ GimpAnchor **ret_anchor,
+ GimpStroke **ret_stroke);
+gboolean gimp_canvas_item_on_vectors_curve (GimpCanvasItem *item,
+ GimpVectors *vectors,
+ const GimpCoords *coord,
+ gint width,
+ gint height,
+ GimpCoords *ret_coords,
+ gdouble *ret_pos,
+ GimpAnchor **ret_segment_start,
+ GimpAnchor **ret_segment_end,
+ GimpStroke **ret_stroke);
+gboolean gimp_canvas_item_on_vectors (GimpCanvasItem *item,
+ const GimpCoords *coords,
+ gint width,
+ gint height,
+ GimpCoords *ret_coords,
+ gdouble *ret_pos,
+ GimpAnchor **ret_segment_start,
+ GimpAnchor **ret_segment_end,
+ GimpStroke **ret_stroke,
+ GimpVectors **ret_vectors);
+
+void gimp_canvas_item_shift_to_north_west (GimpHandleAnchor anchor,
+ gdouble x,
+ gdouble y,
+ gint width,
+ gint height,
+ gdouble *shifted_x,
+ gdouble *shifted_y);
+void gimp_canvas_item_shift_to_center (GimpHandleAnchor anchor,
+ gdouble x,
+ gdouble y,
+ gint width,
+ gint height,
+ gdouble *shifted_x,
+ gdouble *shifted_y);
#endif /* __GIMP_CANVAS_ITEM_UTILS_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]