1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <string.h>
21
22 #include <gegl.h>
23 #include <gtk/gtk.h>
24
25 #include "libgimpmath/gimpmath.h"
26
27 #include "tools-types.h"
28
29 #include "core/gimpimage.h"
30 #include "core/gimppickable.h"
31
32 #include "display/gimpcanvas.h"
33 #include "display/gimpcanvasarc.h"
34 #include "display/gimpcanvasboundary.h"
35 #include "display/gimpcanvasgroup.h"
36 #include "display/gimpcanvasguide.h"
37 #include "display/gimpcanvashandle.h"
38 #include "display/gimpcanvasitem-utils.h"
39 #include "display/gimpcanvasline.h"
40 #include "display/gimpcanvaspen.h"
41 #include "display/gimpcanvaspolygon.h"
42 #include "display/gimpcanvasrectangle.h"
43 #include "display/gimpcanvassamplepoint.h"
44 #include "display/gimpcanvastextcursor.h"
45 #include "display/gimpcanvastransformpreview.h"
46 #include "display/gimpdisplay.h"
47 #include "display/gimpdisplayshell.h"
48 #include "display/gimpdisplayshell-items.h"
49 #include "display/gimpdisplayshell-transform.h"
50 #include "display/gimptoolwidget.h"
51
52 #include "gimpdrawtool.h"
53 #include "gimptoolcontrol.h"
54
55
56 #define USE_TIMEOUT
57 #define DRAW_FPS 120
58 #define DRAW_TIMEOUT (1000 /* milliseconds */ / (2 * DRAW_FPS))
59 #define MINIMUM_DRAW_INTERVAL (G_TIME_SPAN_SECOND / DRAW_FPS)
60
61
62 static void gimp_draw_tool_dispose (GObject *object);
63
64 static gboolean gimp_draw_tool_has_display (GimpTool *tool,
65 GimpDisplay *display);
66 static GimpDisplay * gimp_draw_tool_has_image (GimpTool *tool,
67 GimpImage *image);
68 static void gimp_draw_tool_control (GimpTool *tool,
69 GimpToolAction action,
70 GimpDisplay *display);
71 static gboolean gimp_draw_tool_key_press (GimpTool *tool,
72 GdkEventKey *kevent,
73 GimpDisplay *display);
74 static gboolean gimp_draw_tool_key_release (GimpTool *tool,
75 GdkEventKey *kevent,
76 GimpDisplay *display);
77 static void gimp_draw_tool_modifier_key (GimpTool *tool,
78 GdkModifierType key,
79 gboolean press,
80 GdkModifierType state,
81 GimpDisplay *display);
82 static void gimp_draw_tool_active_modifier_key
83 (GimpTool *tool,
84 GdkModifierType key,
85 gboolean press,
86 GdkModifierType state,
87 GimpDisplay *display);
88 static void gimp_draw_tool_oper_update (GimpTool *tool,
89 const GimpCoords *coords,
90 GdkModifierType state,
91 gboolean proximity,
92 GimpDisplay *display);
93 static void gimp_draw_tool_cursor_update (GimpTool *tool,
94 const GimpCoords *coords,
95 GdkModifierType state,
96 GimpDisplay *display);
97
98 static void gimp_draw_tool_widget_status (GimpToolWidget *widget,
99 const gchar *status,
100 GimpTool *tool);
101 static void gimp_draw_tool_widget_status_coords
102 (GimpToolWidget *widget,
103 const gchar *title,
104 gdouble x,
105 const gchar *separator,
106 gdouble y,
107 const gchar *help,
108 GimpTool *tool);
109 static void gimp_draw_tool_widget_message
110 (GimpToolWidget *widget,
111 const gchar *message,
112 GimpTool *tool);
113 static void gimp_draw_tool_widget_snap_offsets
114 (GimpToolWidget *widget,
115 gint offset_x,
116 gint offset_y,
117 gint width,
118 gint height,
119 GimpTool *tool);
120
121 static void gimp_draw_tool_draw (GimpDrawTool *draw_tool);
122 static void gimp_draw_tool_undraw (GimpDrawTool *draw_tool);
123 static void gimp_draw_tool_real_draw (GimpDrawTool *draw_tool);
124
125
G_DEFINE_TYPE(GimpDrawTool,gimp_draw_tool,GIMP_TYPE_TOOL)126 G_DEFINE_TYPE (GimpDrawTool, gimp_draw_tool, GIMP_TYPE_TOOL)
127
128 #define parent_class gimp_draw_tool_parent_class
129
130
131 static void
132 gimp_draw_tool_class_init (GimpDrawToolClass *klass)
133 {
134 GObjectClass *object_class = G_OBJECT_CLASS (klass);
135 GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
136
137 object_class->dispose = gimp_draw_tool_dispose;
138
139 tool_class->has_display = gimp_draw_tool_has_display;
140 tool_class->has_image = gimp_draw_tool_has_image;
141 tool_class->control = gimp_draw_tool_control;
142 tool_class->key_press = gimp_draw_tool_key_press;
143 tool_class->key_release = gimp_draw_tool_key_release;
144 tool_class->modifier_key = gimp_draw_tool_modifier_key;
145 tool_class->active_modifier_key = gimp_draw_tool_active_modifier_key;
146 tool_class->oper_update = gimp_draw_tool_oper_update;
147 tool_class->cursor_update = gimp_draw_tool_cursor_update;
148
149 klass->draw = gimp_draw_tool_real_draw;
150 }
151
152 static void
gimp_draw_tool_init(GimpDrawTool * draw_tool)153 gimp_draw_tool_init (GimpDrawTool *draw_tool)
154 {
155 draw_tool->display = NULL;
156 draw_tool->paused_count = 0;
157 draw_tool->preview = NULL;
158 draw_tool->item = NULL;
159 }
160
161 static void
gimp_draw_tool_dispose(GObject * object)162 gimp_draw_tool_dispose (GObject *object)
163 {
164 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (object);
165
166 if (draw_tool->draw_timeout)
167 {
168 g_source_remove (draw_tool->draw_timeout);
169 draw_tool->draw_timeout = 0;
170 }
171
172 gimp_draw_tool_set_widget (draw_tool, NULL);
173 gimp_draw_tool_set_default_status (draw_tool, NULL);
174
175 G_OBJECT_CLASS (parent_class)->dispose (object);
176 }
177
178 static gboolean
gimp_draw_tool_has_display(GimpTool * tool,GimpDisplay * display)179 gimp_draw_tool_has_display (GimpTool *tool,
180 GimpDisplay *display)
181 {
182 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
183
184 return (display == draw_tool->display ||
185 GIMP_TOOL_CLASS (parent_class)->has_display (tool, display));
186 }
187
188 static GimpDisplay *
gimp_draw_tool_has_image(GimpTool * tool,GimpImage * image)189 gimp_draw_tool_has_image (GimpTool *tool,
190 GimpImage *image)
191 {
192 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
193 GimpDisplay *display;
194
195 display = GIMP_TOOL_CLASS (parent_class)->has_image (tool, image);
196
197 if (! display && draw_tool->display)
198 {
199 if (image && gimp_display_get_image (draw_tool->display) == image)
200 display = draw_tool->display;
201
202 /* NULL image means any display */
203 if (! image)
204 display = draw_tool->display;
205 }
206
207 return display;
208 }
209
210 static void
gimp_draw_tool_control(GimpTool * tool,GimpToolAction action,GimpDisplay * display)211 gimp_draw_tool_control (GimpTool *tool,
212 GimpToolAction action,
213 GimpDisplay *display)
214 {
215 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
216
217 switch (action)
218 {
219 case GIMP_TOOL_ACTION_PAUSE:
220 case GIMP_TOOL_ACTION_RESUME:
221 break;
222
223 case GIMP_TOOL_ACTION_HALT:
224 if (gimp_draw_tool_is_active (draw_tool))
225 gimp_draw_tool_stop (draw_tool);
226 gimp_draw_tool_set_widget (draw_tool, NULL);
227 break;
228
229 case GIMP_TOOL_ACTION_COMMIT:
230 break;
231 }
232
233 GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
234 }
235
236 static gboolean
gimp_draw_tool_key_press(GimpTool * tool,GdkEventKey * kevent,GimpDisplay * display)237 gimp_draw_tool_key_press (GimpTool *tool,
238 GdkEventKey *kevent,
239 GimpDisplay *display)
240 {
241 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
242
243 if (draw_tool->widget && display == draw_tool->display)
244 {
245 return gimp_tool_widget_key_press (draw_tool->widget, kevent);
246 }
247
248 return GIMP_TOOL_CLASS (parent_class)->key_press (tool, kevent, display);
249 }
250
251 static gboolean
gimp_draw_tool_key_release(GimpTool * tool,GdkEventKey * kevent,GimpDisplay * display)252 gimp_draw_tool_key_release (GimpTool *tool,
253 GdkEventKey *kevent,
254 GimpDisplay *display)
255 {
256 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
257
258 if (draw_tool->widget && display == draw_tool->display)
259 {
260 return gimp_tool_widget_key_release (draw_tool->widget, kevent);
261 }
262
263 return GIMP_TOOL_CLASS (parent_class)->key_release (tool, kevent, display);
264 }
265
266 static void
gimp_draw_tool_modifier_key(GimpTool * tool,GdkModifierType key,gboolean press,GdkModifierType state,GimpDisplay * display)267 gimp_draw_tool_modifier_key (GimpTool *tool,
268 GdkModifierType key,
269 gboolean press,
270 GdkModifierType state,
271 GimpDisplay *display)
272 {
273 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
274
275 if (draw_tool->widget && display == draw_tool->display)
276 {
277 gimp_tool_widget_hover_modifier (draw_tool->widget, key, press, state);
278 }
279
280 GIMP_TOOL_CLASS (parent_class)->modifier_key (tool, key, press, state,
281 display);
282 }
283
284 static void
gimp_draw_tool_active_modifier_key(GimpTool * tool,GdkModifierType key,gboolean press,GdkModifierType state,GimpDisplay * display)285 gimp_draw_tool_active_modifier_key (GimpTool *tool,
286 GdkModifierType key,
287 gboolean press,
288 GdkModifierType state,
289 GimpDisplay *display)
290 {
291 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
292
293 if (draw_tool->widget && display == draw_tool->display)
294 {
295 gimp_tool_widget_motion_modifier (draw_tool->widget, key, press, state);
296 }
297
298 GIMP_TOOL_CLASS (parent_class)->active_modifier_key (tool, key, press, state,
299 display);
300 }
301
302 static void
gimp_draw_tool_oper_update(GimpTool * tool,const GimpCoords * coords,GdkModifierType state,gboolean proximity,GimpDisplay * display)303 gimp_draw_tool_oper_update (GimpTool *tool,
304 const GimpCoords *coords,
305 GdkModifierType state,
306 gboolean proximity,
307 GimpDisplay *display)
308 {
309 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
310
311 if (draw_tool->widget && display == draw_tool->display)
312 {
313 gimp_tool_widget_hover (draw_tool->widget, coords, state, proximity);
314 }
315 else if (proximity && draw_tool->default_status)
316 {
317 gimp_tool_replace_status (tool, display, "%s", draw_tool->default_status);
318 }
319 else if (! proximity)
320 {
321 gimp_tool_pop_status (tool, display);
322 }
323 else
324 {
325 GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state,
326 proximity, display);
327 }
328 }
329
330 static void
gimp_draw_tool_cursor_update(GimpTool * tool,const GimpCoords * coords,GdkModifierType state,GimpDisplay * display)331 gimp_draw_tool_cursor_update (GimpTool *tool,
332 const GimpCoords *coords,
333 GdkModifierType state,
334 GimpDisplay *display)
335 {
336 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
337
338 if (draw_tool->widget && display == draw_tool->display)
339 {
340 GimpCursorType cursor;
341 GimpToolCursorType tool_cursor;
342 GimpCursorModifier modifier;
343
344 cursor = gimp_tool_control_get_cursor (tool->control);
345 tool_cursor = gimp_tool_control_get_tool_cursor (tool->control);
346 modifier = gimp_tool_control_get_cursor_modifier (tool->control);
347
348 if (gimp_tool_widget_get_cursor (draw_tool->widget, coords, state,
349 &cursor, &tool_cursor, &modifier))
350 {
351 gimp_tool_set_cursor (tool, display,
352 cursor, tool_cursor, modifier);
353 return;
354 }
355 }
356
357 GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state,
358 display);
359 }
360
361 static void
gimp_draw_tool_widget_status(GimpToolWidget * widget,const gchar * status,GimpTool * tool)362 gimp_draw_tool_widget_status (GimpToolWidget *widget,
363 const gchar *status,
364 GimpTool *tool)
365 {
366 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
367
368 if (gimp_draw_tool_is_active (draw_tool))
369 {
370 if (status)
371 gimp_tool_replace_status (tool, draw_tool->display, "%s", status);
372 else
373 gimp_tool_pop_status (tool, draw_tool->display);
374 }
375 }
376
377 static void
gimp_draw_tool_widget_status_coords(GimpToolWidget * widget,const gchar * title,gdouble x,const gchar * separator,gdouble y,const gchar * help,GimpTool * tool)378 gimp_draw_tool_widget_status_coords (GimpToolWidget *widget,
379 const gchar *title,
380 gdouble x,
381 const gchar *separator,
382 gdouble y,
383 const gchar *help,
384 GimpTool *tool)
385 {
386 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
387
388 if (gimp_draw_tool_is_active (draw_tool))
389 {
390 gimp_tool_pop_status (tool, draw_tool->display);
391 gimp_tool_push_status_coords (tool, draw_tool->display,
392 gimp_tool_control_get_precision (
393 tool->control),
394 title, x, separator, y, help);
395 }
396 }
397
398 static void
gimp_draw_tool_widget_message(GimpToolWidget * widget,const gchar * message,GimpTool * tool)399 gimp_draw_tool_widget_message (GimpToolWidget *widget,
400 const gchar *message,
401 GimpTool *tool)
402 {
403 GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool);
404
405 if (gimp_draw_tool_is_active (draw_tool))
406 gimp_tool_message_literal (tool, draw_tool->display, message);
407 }
408
409 static void
gimp_draw_tool_widget_snap_offsets(GimpToolWidget * widget,gint offset_x,gint offset_y,gint width,gint height,GimpTool * tool)410 gimp_draw_tool_widget_snap_offsets (GimpToolWidget *widget,
411 gint offset_x,
412 gint offset_y,
413 gint width,
414 gint height,
415 GimpTool *tool)
416 {
417 gimp_tool_control_set_snap_offsets (tool->control,
418 offset_x, offset_y,
419 width, height);
420 }
421
422 #ifdef USE_TIMEOUT
423 static gboolean
gimp_draw_tool_draw_timeout(GimpDrawTool * draw_tool)424 gimp_draw_tool_draw_timeout (GimpDrawTool *draw_tool)
425 {
426 guint64 now = g_get_monotonic_time ();
427
428 /* keep the timeout running if the last drawing just happened */
429 if ((now - draw_tool->last_draw_time) <= MINIMUM_DRAW_INTERVAL)
430 return TRUE;
431
432 draw_tool->draw_timeout = 0;
433
434 gimp_draw_tool_draw (draw_tool);
435
436 return FALSE;
437 }
438 #endif
439
440 static void
gimp_draw_tool_draw(GimpDrawTool * draw_tool)441 gimp_draw_tool_draw (GimpDrawTool *draw_tool)
442 {
443 guint64 now = g_get_monotonic_time ();
444
445 if (draw_tool->display &&
446 draw_tool->paused_count == 0 &&
447 (! draw_tool->draw_timeout ||
448 (now - draw_tool->last_draw_time) > MINIMUM_DRAW_INTERVAL))
449 {
450 GimpDisplayShell *shell = gimp_display_get_shell (draw_tool->display);
451
452 if (draw_tool->draw_timeout)
453 {
454 g_source_remove (draw_tool->draw_timeout);
455 draw_tool->draw_timeout = 0;
456 }
457
458 gimp_draw_tool_undraw (draw_tool);
459
460 GIMP_DRAW_TOOL_GET_CLASS (draw_tool)->draw (draw_tool);
461
462 if (draw_tool->group_stack)
463 {
464 g_warning ("%s: draw_tool->group_stack not empty after calling "
465 "GimpDrawTool::draw() of %s",
466 G_STRFUNC,
467 g_type_name (G_TYPE_FROM_INSTANCE (draw_tool)));
468
469 while (draw_tool->group_stack)
470 gimp_draw_tool_pop_group (draw_tool);
471 }
472
473 if (draw_tool->preview)
474 gimp_display_shell_add_preview_item (shell, draw_tool->preview);
475
476 if (draw_tool->item)
477 gimp_display_shell_add_tool_item (shell, draw_tool->item);
478
479 #if 0
480 gimp_display_shell_flush (shell, TRUE);
481 #endif
482
483 draw_tool->last_draw_time = g_get_monotonic_time ();
484
485 #if 0
486 g_printerr ("drawing tool stuff took %f seconds\n",
487 (draw_tool->last_draw_time - now) / 1000000.0);
488 #endif
489 }
490 }
491
492 static void
gimp_draw_tool_undraw(GimpDrawTool * draw_tool)493 gimp_draw_tool_undraw (GimpDrawTool *draw_tool)
494 {
495 if (draw_tool->display)
496 {
497 GimpDisplayShell *shell = gimp_display_get_shell (draw_tool->display);
498
499 if (draw_tool->preview)
500 {
501 gimp_display_shell_remove_preview_item (shell, draw_tool->preview);
502 g_clear_object (&draw_tool->preview);
503 }
504
505 if (draw_tool->item)
506 {
507 gimp_display_shell_remove_tool_item (shell, draw_tool->item);
508 g_clear_object (&draw_tool->item);
509 }
510 }
511 }
512
513 static void
gimp_draw_tool_real_draw(GimpDrawTool * draw_tool)514 gimp_draw_tool_real_draw (GimpDrawTool *draw_tool)
515 {
516 if (draw_tool->widget)
517 {
518 GimpCanvasItem *item = gimp_tool_widget_get_item (draw_tool->widget);
519
520 gimp_draw_tool_add_item (draw_tool, item);
521 }
522 }
523
524 void
gimp_draw_tool_start(GimpDrawTool * draw_tool,GimpDisplay * display)525 gimp_draw_tool_start (GimpDrawTool *draw_tool,
526 GimpDisplay *display)
527 {
528 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
529 g_return_if_fail (GIMP_IS_DISPLAY (display));
530 g_return_if_fail (gimp_draw_tool_is_active (draw_tool) == FALSE);
531
532 draw_tool->display = display;
533
534 gimp_draw_tool_draw (draw_tool);
535 }
536
537 void
gimp_draw_tool_stop(GimpDrawTool * draw_tool)538 gimp_draw_tool_stop (GimpDrawTool *draw_tool)
539 {
540 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
541 g_return_if_fail (gimp_draw_tool_is_active (draw_tool) == TRUE);
542
543 gimp_draw_tool_undraw (draw_tool);
544
545 if (draw_tool->draw_timeout)
546 {
547 g_source_remove (draw_tool->draw_timeout);
548 draw_tool->draw_timeout = 0;
549 }
550
551 draw_tool->last_draw_time = 0;
552
553 draw_tool->display = NULL;
554 }
555
556 gboolean
gimp_draw_tool_is_active(GimpDrawTool * draw_tool)557 gimp_draw_tool_is_active (GimpDrawTool *draw_tool)
558 {
559 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), FALSE);
560
561 return draw_tool->display != NULL;
562 }
563
564 void
gimp_draw_tool_pause(GimpDrawTool * draw_tool)565 gimp_draw_tool_pause (GimpDrawTool *draw_tool)
566 {
567 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
568
569 draw_tool->paused_count++;
570
571 if (draw_tool->draw_timeout)
572 {
573 g_source_remove (draw_tool->draw_timeout);
574 draw_tool->draw_timeout = 0;
575 }
576 }
577
578 void
gimp_draw_tool_resume(GimpDrawTool * draw_tool)579 gimp_draw_tool_resume (GimpDrawTool *draw_tool)
580 {
581 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
582 g_return_if_fail (draw_tool->paused_count > 0);
583
584 draw_tool->paused_count--;
585
586 if (draw_tool->paused_count == 0)
587 {
588 #ifdef USE_TIMEOUT
589 /* Don't install the timeout if the draw tool isn't active, so
590 * suspend()/resume() can always be called, and have no side
591 * effect on an inactive tool. See bug #687851.
592 */
593 if (gimp_draw_tool_is_active (draw_tool) && ! draw_tool->draw_timeout)
594 {
595 draw_tool->draw_timeout =
596 gdk_threads_add_timeout_full (G_PRIORITY_HIGH_IDLE,
597 DRAW_TIMEOUT,
598 (GSourceFunc) gimp_draw_tool_draw_timeout,
599 draw_tool, NULL);
600 }
601 #endif
602
603 /* call draw() anyway, it will do nothing if the timeout is
604 * running, but will additionally check the drawing times to
605 * ensure the minimum framerate
606 */
607 gimp_draw_tool_draw (draw_tool);
608 }
609 }
610
611 /**
612 * gimp_draw_tool_calc_distance:
613 * @draw_tool: a #GimpDrawTool
614 * @display: a #GimpDisplay
615 * @x1: start point X in image coordinates
616 * @y1: start point Y in image coordinates
617 * @x2: end point X in image coordinates
618 * @y2: end point Y in image coordinates
619 *
620 * If you just need to compare distances, consider to use
621 * gimp_draw_tool_calc_distance_square() instead.
622 *
623 * Returns: the distance between the given points in display coordinates
624 **/
625 gdouble
gimp_draw_tool_calc_distance(GimpDrawTool * draw_tool,GimpDisplay * display,gdouble x1,gdouble y1,gdouble x2,gdouble y2)626 gimp_draw_tool_calc_distance (GimpDrawTool *draw_tool,
627 GimpDisplay *display,
628 gdouble x1,
629 gdouble y1,
630 gdouble x2,
631 gdouble y2)
632 {
633 return sqrt (gimp_draw_tool_calc_distance_square (draw_tool, display,
634 x1, y1, x2, y2));
635 }
636
637 /**
638 * gimp_draw_tool_calc_distance_square:
639 * @draw_tool: a #GimpDrawTool
640 * @display: a #GimpDisplay
641 * @x1: start point X in image coordinates
642 * @y1: start point Y in image coordinates
643 * @x2: end point X in image coordinates
644 * @y2: end point Y in image coordinates
645 *
646 * This function is more effective than gimp_draw_tool_calc_distance()
647 * as it doesn't perform a sqrt(). Use this if you just need to compare
648 * distances.
649 *
650 * Returns: the square of the distance between the given points in
651 * display coordinates
652 **/
653 gdouble
gimp_draw_tool_calc_distance_square(GimpDrawTool * draw_tool,GimpDisplay * display,gdouble x1,gdouble y1,gdouble x2,gdouble y2)654 gimp_draw_tool_calc_distance_square (GimpDrawTool *draw_tool,
655 GimpDisplay *display,
656 gdouble x1,
657 gdouble y1,
658 gdouble x2,
659 gdouble y2)
660 {
661 GimpDisplayShell *shell;
662 gdouble tx1, ty1;
663 gdouble tx2, ty2;
664
665 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), 0.0);
666 g_return_val_if_fail (GIMP_IS_DISPLAY (display), 0.0);
667
668 shell = gimp_display_get_shell (display);
669
670 gimp_display_shell_transform_xy_f (shell, x1, y1, &tx1, &ty1);
671 gimp_display_shell_transform_xy_f (shell, x2, y2, &tx2, &ty2);
672
673 return SQR (tx2 - tx1) + SQR (ty2 - ty1);
674 }
675
676 void
gimp_draw_tool_set_widget(GimpDrawTool * draw_tool,GimpToolWidget * widget)677 gimp_draw_tool_set_widget (GimpDrawTool *draw_tool,
678 GimpToolWidget *widget)
679 {
680 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
681 g_return_if_fail (widget == NULL || GIMP_IS_TOOL_WIDGET (widget));
682
683 if (widget == draw_tool->widget)
684 return;
685
686 if (draw_tool->widget)
687 {
688 gimp_tool_widget_set_focus (draw_tool->widget, FALSE);
689
690 g_signal_handlers_disconnect_by_func (draw_tool->widget,
691 gimp_draw_tool_widget_status,
692 draw_tool);
693 g_signal_handlers_disconnect_by_func (draw_tool->widget,
694 gimp_draw_tool_widget_status_coords,
695 draw_tool);
696 g_signal_handlers_disconnect_by_func (draw_tool->widget,
697 gimp_draw_tool_widget_message,
698 draw_tool);
699 g_signal_handlers_disconnect_by_func (draw_tool->widget,
700 gimp_draw_tool_widget_snap_offsets,
701 draw_tool);
702
703 if (gimp_draw_tool_is_active (draw_tool))
704 {
705 GimpCanvasItem *item = gimp_tool_widget_get_item (draw_tool->widget);
706
707 gimp_draw_tool_remove_item (draw_tool, item);
708 }
709
710 g_object_unref (draw_tool->widget);
711 }
712
713 draw_tool->widget = widget;
714
715 if (draw_tool->widget)
716 {
717 g_object_ref (draw_tool->widget);
718
719 if (gimp_draw_tool_is_active (draw_tool))
720 {
721 GimpCanvasItem *item = gimp_tool_widget_get_item (draw_tool->widget);
722
723 gimp_draw_tool_add_item (draw_tool, item);
724 }
725
726 g_signal_connect (draw_tool->widget, "status",
727 G_CALLBACK (gimp_draw_tool_widget_status),
728 draw_tool);
729 g_signal_connect (draw_tool->widget, "status-coords",
730 G_CALLBACK (gimp_draw_tool_widget_status_coords),
731 draw_tool);
732 g_signal_connect (draw_tool->widget, "message",
733 G_CALLBACK (gimp_draw_tool_widget_message),
734 draw_tool);
735 g_signal_connect (draw_tool->widget, "snap-offsets",
736 G_CALLBACK (gimp_draw_tool_widget_snap_offsets),
737 draw_tool);
738
739 gimp_tool_widget_set_focus (draw_tool->widget, TRUE);
740 }
741 }
742
743 void
gimp_draw_tool_set_default_status(GimpDrawTool * draw_tool,const gchar * status)744 gimp_draw_tool_set_default_status (GimpDrawTool *draw_tool,
745 const gchar *status)
746 {
747 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
748
749 if (draw_tool->default_status)
750 g_free (draw_tool->default_status);
751
752 draw_tool->default_status = g_strdup (status);
753 }
754
755 void
gimp_draw_tool_add_preview(GimpDrawTool * draw_tool,GimpCanvasItem * item)756 gimp_draw_tool_add_preview (GimpDrawTool *draw_tool,
757 GimpCanvasItem *item)
758 {
759 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
760 g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
761
762 if (! draw_tool->preview)
763 draw_tool->preview =
764 gimp_canvas_group_new (gimp_display_get_shell (draw_tool->display));
765
766 gimp_canvas_group_add_item (GIMP_CANVAS_GROUP (draw_tool->preview), item);
767 }
768
769 void
gimp_draw_tool_remove_preview(GimpDrawTool * draw_tool,GimpCanvasItem * item)770 gimp_draw_tool_remove_preview (GimpDrawTool *draw_tool,
771 GimpCanvasItem *item)
772 {
773 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
774 g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
775 g_return_if_fail (draw_tool->preview != NULL);
776
777 gimp_canvas_group_remove_item (GIMP_CANVAS_GROUP (draw_tool->preview), item);
778 }
779
780 void
gimp_draw_tool_add_item(GimpDrawTool * draw_tool,GimpCanvasItem * item)781 gimp_draw_tool_add_item (GimpDrawTool *draw_tool,
782 GimpCanvasItem *item)
783 {
784 GimpCanvasGroup *group;
785
786 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
787 g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
788
789 if (! draw_tool->item)
790 draw_tool->item =
791 gimp_canvas_group_new (gimp_display_get_shell (draw_tool->display));
792
793 group = GIMP_CANVAS_GROUP (draw_tool->item);
794
795 if (draw_tool->group_stack)
796 group = draw_tool->group_stack->data;
797
798 gimp_canvas_group_add_item (group, item);
799 }
800
801 void
gimp_draw_tool_remove_item(GimpDrawTool * draw_tool,GimpCanvasItem * item)802 gimp_draw_tool_remove_item (GimpDrawTool *draw_tool,
803 GimpCanvasItem *item)
804 {
805 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
806 g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
807 g_return_if_fail (draw_tool->item != NULL);
808
809 gimp_canvas_group_remove_item (GIMP_CANVAS_GROUP (draw_tool->item), item);
810 }
811
812 GimpCanvasGroup *
gimp_draw_tool_add_stroke_group(GimpDrawTool * draw_tool)813 gimp_draw_tool_add_stroke_group (GimpDrawTool *draw_tool)
814 {
815 GimpCanvasItem *item;
816
817 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
818
819 item = gimp_canvas_group_new (gimp_display_get_shell (draw_tool->display));
820 gimp_canvas_group_set_group_stroking (GIMP_CANVAS_GROUP (item), TRUE);
821
822 gimp_draw_tool_add_item (draw_tool, item);
823 g_object_unref (item);
824
825 return GIMP_CANVAS_GROUP (item);
826 }
827
828 GimpCanvasGroup *
gimp_draw_tool_add_fill_group(GimpDrawTool * draw_tool)829 gimp_draw_tool_add_fill_group (GimpDrawTool *draw_tool)
830 {
831 GimpCanvasItem *item;
832
833 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
834
835 item = gimp_canvas_group_new (gimp_display_get_shell (draw_tool->display));
836 gimp_canvas_group_set_group_filling (GIMP_CANVAS_GROUP (item), TRUE);
837
838 gimp_draw_tool_add_item (draw_tool, item);
839 g_object_unref (item);
840
841 return GIMP_CANVAS_GROUP (item);
842 }
843
844 void
gimp_draw_tool_push_group(GimpDrawTool * draw_tool,GimpCanvasGroup * group)845 gimp_draw_tool_push_group (GimpDrawTool *draw_tool,
846 GimpCanvasGroup *group)
847 {
848 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
849 g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
850
851 draw_tool->group_stack = g_list_prepend (draw_tool->group_stack, group);
852 }
853
854 void
gimp_draw_tool_pop_group(GimpDrawTool * draw_tool)855 gimp_draw_tool_pop_group (GimpDrawTool *draw_tool)
856 {
857 g_return_if_fail (GIMP_IS_DRAW_TOOL (draw_tool));
858 g_return_if_fail (draw_tool->group_stack != NULL);
859
860 draw_tool->group_stack = g_list_remove (draw_tool->group_stack,
861 draw_tool->group_stack->data);
862 }
863
864 /**
865 * gimp_draw_tool_add_line:
866 * @draw_tool: the #GimpDrawTool
867 * @x1: start point X in image coordinates
868 * @y1: start point Y in image coordinates
869 * @x2: end point X in image coordinates
870 * @y2: end point Y in image coordinates
871 *
872 * This function takes image space coordinates and transforms them to
873 * screen window coordinates, then draws a line between the resulting
874 * coordindates.
875 **/
876 GimpCanvasItem *
gimp_draw_tool_add_line(GimpDrawTool * draw_tool,gdouble x1,gdouble y1,gdouble x2,gdouble y2)877 gimp_draw_tool_add_line (GimpDrawTool *draw_tool,
878 gdouble x1,
879 gdouble y1,
880 gdouble x2,
881 gdouble y2)
882 {
883 GimpCanvasItem *item;
884
885 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
886
887 item = gimp_canvas_line_new (gimp_display_get_shell (draw_tool->display),
888 x1, y1, x2, y2);
889
890 gimp_draw_tool_add_item (draw_tool, item);
891 g_object_unref (item);
892
893 return item;
894 }
895
896 /**
897 * gimp_draw_tool_add_guide:
898 * @draw_tool: the #GimpDrawTool
899 * @orientation: the orientation of the guide line
900 * @position: the position of the guide line in image coordinates
901 *
902 * This function draws a guide line across the canvas.
903 **/
904 GimpCanvasItem *
gimp_draw_tool_add_guide(GimpDrawTool * draw_tool,GimpOrientationType orientation,gint position,GimpGuideStyle style)905 gimp_draw_tool_add_guide (GimpDrawTool *draw_tool,
906 GimpOrientationType orientation,
907 gint position,
908 GimpGuideStyle style)
909 {
910 GimpCanvasItem *item;
911
912 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
913
914 item = gimp_canvas_guide_new (gimp_display_get_shell (draw_tool->display),
915 orientation, position,
916 style);
917
918 gimp_draw_tool_add_item (draw_tool, item);
919 g_object_unref (item);
920
921 return item;
922 }
923
924 /**
925 * gimp_draw_tool_add_crosshair:
926 * @draw_tool: the #GimpDrawTool
927 * @position_x: the position of the vertical guide line in image coordinates
928 * @position_y: the position of the horizontal guide line in image coordinates
929 *
930 * This function draws two crossing guide lines across the canvas.
931 **/
932 GimpCanvasItem *
gimp_draw_tool_add_crosshair(GimpDrawTool * draw_tool,gint position_x,gint position_y)933 gimp_draw_tool_add_crosshair (GimpDrawTool *draw_tool,
934 gint position_x,
935 gint position_y)
936 {
937 GimpCanvasGroup *group;
938
939 group = gimp_draw_tool_add_stroke_group (draw_tool);
940
941 gimp_draw_tool_push_group (draw_tool, group);
942 gimp_draw_tool_add_guide (draw_tool,
943 GIMP_ORIENTATION_VERTICAL, position_x,
944 GIMP_GUIDE_STYLE_NONE);
945 gimp_draw_tool_add_guide (draw_tool,
946 GIMP_ORIENTATION_HORIZONTAL, position_y,
947 GIMP_GUIDE_STYLE_NONE);
948 gimp_draw_tool_pop_group (draw_tool);
949
950 return GIMP_CANVAS_ITEM (group);
951 }
952
953 /**
954 * gimp_draw_tool_add_sample_point:
955 * @draw_tool: the #GimpDrawTool
956 * @x: X position of the sample point
957 * @y: Y position of the sample point
958 * @index: Index of the sample point
959 *
960 * This function draws a sample point
961 **/
962 GimpCanvasItem *
gimp_draw_tool_add_sample_point(GimpDrawTool * draw_tool,gint x,gint y,gint index)963 gimp_draw_tool_add_sample_point (GimpDrawTool *draw_tool,
964 gint x,
965 gint y,
966 gint index)
967 {
968 GimpCanvasItem *item;
969
970 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
971
972 item = gimp_canvas_sample_point_new (gimp_display_get_shell (draw_tool->display),
973 x, y, index, TRUE);
974
975 gimp_draw_tool_add_item (draw_tool, item);
976 g_object_unref (item);
977
978 return item;
979 }
980
981 /**
982 * gimp_draw_tool_add_rectangle:
983 * @draw_tool: the #GimpDrawTool
984 * @filled: whether to fill the rectangle
985 * @x: horizontal image coordinate
986 * @y: vertical image coordinate
987 * @width: width in image coordinates
988 * @height: height in image coordinates
989 *
990 * This function takes image space coordinates and transforms them to
991 * screen window coordinates, then draws the resulting rectangle.
992 **/
993 GimpCanvasItem *
gimp_draw_tool_add_rectangle(GimpDrawTool * draw_tool,gboolean filled,gdouble x,gdouble y,gdouble width,gdouble height)994 gimp_draw_tool_add_rectangle (GimpDrawTool *draw_tool,
995 gboolean filled,
996 gdouble x,
997 gdouble y,
998 gdouble width,
999 gdouble height)
1000 {
1001 GimpCanvasItem *item;
1002
1003 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
1004
1005 item = gimp_canvas_rectangle_new (gimp_display_get_shell (draw_tool->display),
1006 x, y, width, height, filled);
1007
1008 gimp_draw_tool_add_item (draw_tool, item);
1009 g_object_unref (item);
1010
1011 return item;
1012 }
1013
1014 GimpCanvasItem *
gimp_draw_tool_add_arc(GimpDrawTool * draw_tool,gboolean filled,gdouble x,gdouble y,gdouble width,gdouble height,gdouble start_angle,gdouble slice_angle)1015 gimp_draw_tool_add_arc (GimpDrawTool *draw_tool,
1016 gboolean filled,
1017 gdouble x,
1018 gdouble y,
1019 gdouble width,
1020 gdouble height,
1021 gdouble start_angle,
1022 gdouble slice_angle)
1023 {
1024 GimpCanvasItem *item;
1025
1026 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
1027
1028 item = gimp_canvas_arc_new (gimp_display_get_shell (draw_tool->display),
1029 x + width / 2.0,
1030 y + height / 2.0,
1031 width / 2.0,
1032 height / 2.0,
1033 start_angle,
1034 slice_angle,
1035 filled);
1036
1037 gimp_draw_tool_add_item (draw_tool, item);
1038 g_object_unref (item);
1039
1040 return item;
1041 }
1042
1043 GimpCanvasItem *
gimp_draw_tool_add_handle(GimpDrawTool * draw_tool,GimpHandleType type,gdouble x,gdouble y,gint width,gint height,GimpHandleAnchor anchor)1044 gimp_draw_tool_add_handle (GimpDrawTool *draw_tool,
1045 GimpHandleType type,
1046 gdouble x,
1047 gdouble y,
1048 gint width,
1049 gint height,
1050 GimpHandleAnchor anchor)
1051 {
1052 GimpCanvasItem *item;
1053
1054 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
1055
1056 item = gimp_canvas_handle_new (gimp_display_get_shell (draw_tool->display),
1057 type, anchor, x, y, width, height);
1058
1059 gimp_draw_tool_add_item (draw_tool, item);
1060 g_object_unref (item);
1061
1062 return item;
1063 }
1064
1065 GimpCanvasItem *
gimp_draw_tool_add_lines(GimpDrawTool * draw_tool,const GimpVector2 * points,gint n_points,GimpMatrix3 * transform,gboolean filled)1066 gimp_draw_tool_add_lines (GimpDrawTool *draw_tool,
1067 const GimpVector2 *points,
1068 gint n_points,
1069 GimpMatrix3 *transform,
1070 gboolean filled)
1071 {
1072 GimpCanvasItem *item;
1073
1074 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
1075
1076 if (points == NULL || n_points < 2)
1077 return NULL;
1078
1079 item = gimp_canvas_polygon_new (gimp_display_get_shell (draw_tool->display),
1080 points, n_points, transform, filled);
1081
1082 gimp_draw_tool_add_item (draw_tool, item);
1083 g_object_unref (item);
1084
1085 return item;
1086 }
1087
1088 GimpCanvasItem *
gimp_draw_tool_add_strokes(GimpDrawTool * draw_tool,const GimpCoords * points,gint n_points,GimpMatrix3 * transform,gboolean filled)1089 gimp_draw_tool_add_strokes (GimpDrawTool *draw_tool,
1090 const GimpCoords *points,
1091 gint n_points,
1092 GimpMatrix3 *transform,
1093 gboolean filled)
1094 {
1095 GimpCanvasItem *item;
1096
1097 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
1098
1099 if (points == NULL || n_points < 2)
1100 return NULL;
1101
1102 item = gimp_canvas_polygon_new_from_coords (gimp_display_get_shell (draw_tool->display),
1103 points, n_points, transform, filled);
1104
1105 gimp_draw_tool_add_item (draw_tool, item);
1106 g_object_unref (item);
1107
1108 return item;
1109 }
1110
1111 GimpCanvasItem *
gimp_draw_tool_add_pen(GimpDrawTool * draw_tool,const GimpVector2 * points,gint n_points,GimpContext * context,GimpActiveColor color,gint width)1112 gimp_draw_tool_add_pen (GimpDrawTool *draw_tool,
1113 const GimpVector2 *points,
1114 gint n_points,
1115 GimpContext *context,
1116 GimpActiveColor color,
1117 gint width)
1118 {
1119 GimpCanvasItem *item;
1120
1121 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
1122
1123 if (points == NULL || n_points < 2)
1124 return NULL;
1125
1126 item = gimp_canvas_pen_new (gimp_display_get_shell (draw_tool->display),
1127 points, n_points, context, color, width);
1128
1129 gimp_draw_tool_add_item (draw_tool, item);
1130 g_object_unref (item);
1131
1132 return item;
1133 }
1134
1135 /**
1136 * gimp_draw_tool_add_boundary:
1137 * @draw_tool: a #GimpDrawTool
1138 * @bound_segs: the sorted brush outline
1139 * @n_bound_segs: the number of segments in @bound_segs
1140 * @matrix: transform matrix for the boundary
1141 * @offset_x: x offset
1142 * @offset_y: y offset
1143 *
1144 * Draw the boundary of the brush that @draw_tool uses. The boundary
1145 * should be sorted with sort_boundary(), and @n_bound_segs should
1146 * include the sentinel segments inserted by sort_boundary() that
1147 * indicate the end of connected segment sequences (groups) .
1148 */
1149 GimpCanvasItem *
gimp_draw_tool_add_boundary(GimpDrawTool * draw_tool,const GimpBoundSeg * bound_segs,gint n_bound_segs,GimpMatrix3 * transform,gdouble offset_x,gdouble offset_y)1150 gimp_draw_tool_add_boundary (GimpDrawTool *draw_tool,
1151 const GimpBoundSeg *bound_segs,
1152 gint n_bound_segs,
1153 GimpMatrix3 *transform,
1154 gdouble offset_x,
1155 gdouble offset_y)
1156 {
1157 GimpCanvasItem *item;
1158
1159 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
1160 g_return_val_if_fail (n_bound_segs > 0, NULL);
1161 g_return_val_if_fail (bound_segs != NULL, NULL);
1162
1163 item = gimp_canvas_boundary_new (gimp_display_get_shell (draw_tool->display),
1164 bound_segs, n_bound_segs,
1165 transform,
1166 offset_x, offset_y);
1167
1168 gimp_draw_tool_add_item (draw_tool, item);
1169 g_object_unref (item);
1170
1171 return item;
1172 }
1173
1174 GimpCanvasItem *
gimp_draw_tool_add_text_cursor(GimpDrawTool * draw_tool,PangoRectangle * cursor,gboolean overwrite,GimpTextDirection direction)1175 gimp_draw_tool_add_text_cursor (GimpDrawTool *draw_tool,
1176 PangoRectangle *cursor,
1177 gboolean overwrite,
1178 GimpTextDirection direction)
1179 {
1180 GimpCanvasItem *item;
1181
1182 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
1183
1184 item = gimp_canvas_text_cursor_new (gimp_display_get_shell (draw_tool->display),
1185 cursor, overwrite, direction);
1186
1187 gimp_draw_tool_add_item (draw_tool, item);
1188 g_object_unref (item);
1189
1190 return item;
1191 }
1192
1193 GimpCanvasItem *
gimp_draw_tool_add_transform_preview(GimpDrawTool * draw_tool,GimpPickable * pickable,const GimpMatrix3 * transform,gdouble x1,gdouble y1,gdouble x2,gdouble y2)1194 gimp_draw_tool_add_transform_preview (GimpDrawTool *draw_tool,
1195 GimpPickable *pickable,
1196 const GimpMatrix3 *transform,
1197 gdouble x1,
1198 gdouble y1,
1199 gdouble x2,
1200 gdouble y2)
1201 {
1202 GimpCanvasItem *item;
1203
1204 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), NULL);
1205 g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL);
1206 g_return_val_if_fail (transform != NULL, NULL);
1207
1208 item = gimp_canvas_transform_preview_new (gimp_display_get_shell (draw_tool->display),
1209 pickable, transform,
1210 x1, y1, x2, y2);
1211
1212 gimp_draw_tool_add_preview (draw_tool, item);
1213 g_object_unref (item);
1214
1215 return item;
1216 }
1217
1218 gboolean
gimp_draw_tool_on_handle(GimpDrawTool * draw_tool,GimpDisplay * display,gdouble x,gdouble y,GimpHandleType type,gdouble handle_x,gdouble handle_y,gint width,gint height,GimpHandleAnchor anchor)1219 gimp_draw_tool_on_handle (GimpDrawTool *draw_tool,
1220 GimpDisplay *display,
1221 gdouble x,
1222 gdouble y,
1223 GimpHandleType type,
1224 gdouble handle_x,
1225 gdouble handle_y,
1226 gint width,
1227 gint height,
1228 GimpHandleAnchor anchor)
1229 {
1230 GimpDisplayShell *shell;
1231 gdouble tx, ty;
1232 gdouble handle_tx, handle_ty;
1233
1234 g_return_val_if_fail (GIMP_IS_DRAW_TOOL (draw_tool), FALSE);
1235 g_return_val_if_fail (GIMP_IS_DISPLAY (display), FALSE);
1236
1237 shell = gimp_display_get_shell (display);
1238
1239 gimp_display_shell_zoom_xy_f (shell,
1240 x, y,
1241 &tx, &ty);
1242 gimp_display_shell_zoom_xy_f (shell,
1243 handle_x, handle_y,
1244 &handle_tx, &handle_ty);
1245
1246 switch (type)
1247 {
1248 case GIMP_HANDLE_SQUARE:
1249 case GIMP_HANDLE_FILLED_SQUARE:
1250 case GIMP_HANDLE_CROSS:
1251 case GIMP_HANDLE_CROSSHAIR:
1252 gimp_canvas_item_shift_to_north_west (anchor,
1253 handle_tx, handle_ty,
1254 width, height,
1255 &handle_tx, &handle_ty);
1256
1257 return (tx == CLAMP (tx, handle_tx, handle_tx + width) &&
1258 ty == CLAMP (ty, handle_ty, handle_ty + height));
1259
1260 case GIMP_HANDLE_CIRCLE:
1261 case GIMP_HANDLE_FILLED_CIRCLE:
1262 gimp_canvas_item_shift_to_center (anchor,
1263 handle_tx, handle_ty,
1264 width, height,
1265 &handle_tx, &handle_ty);
1266
1267 /* FIXME */
1268 if (width != height)
1269 width = (width + height) / 2;
1270
1271 width /= 2;
1272
1273 return ((SQR (handle_tx - tx) + SQR (handle_ty - ty)) < SQR (width));
1274
1275 default:
1276 g_warning ("%s: invalid handle type %d", G_STRFUNC, type);
1277 break;
1278 }
1279
1280 return FALSE;
1281 }
1282