1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
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 <gegl.h>
21 #include <gtk/gtk.h>
22 
23 #include "libgimpbase/gimpbase.h"
24 #include "libgimpmath/gimpmath.h"
25 
26 #include "tools-types.h"
27 
28 #include "config/gimpdisplayconfig.h"
29 #include "config/gimpguiconfig.h"
30 
31 #include "core/gimp.h"
32 #include "core/gimp-utils.h"
33 #include "core/gimpdrawable.h"
34 #include "core/gimperror.h"
35 #include "core/gimpimage.h"
36 #include "core/gimplayer.h"
37 #include "core/gimppaintinfo.h"
38 #include "core/gimpprojection.h"
39 #include "core/gimptoolinfo.h"
40 
41 #include "paint/gimppaintcore.h"
42 #include "paint/gimppaintoptions.h"
43 
44 #include "widgets/gimpdevices.h"
45 #include "widgets/gimpwidgets-utils.h"
46 
47 #include "display/gimpdisplay.h"
48 #include "display/gimpdisplayshell.h"
49 #include "display/gimpdisplayshell-selection.h"
50 #include "display/gimpdisplayshell-utils.h"
51 
52 #include "gimpcoloroptions.h"
53 #include "gimppaintoptions-gui.h"
54 #include "gimppainttool.h"
55 #include "gimppainttool-paint.h"
56 #include "gimptoolcontrol.h"
57 #include "gimptools-utils.h"
58 
59 #include "gimp-intl.h"
60 
61 
62 static void   gimp_paint_tool_constructed    (GObject               *object);
63 static void   gimp_paint_tool_finalize       (GObject               *object);
64 
65 static void   gimp_paint_tool_control        (GimpTool              *tool,
66                                               GimpToolAction         action,
67                                               GimpDisplay           *display);
68 static void   gimp_paint_tool_button_press   (GimpTool              *tool,
69                                               const GimpCoords      *coords,
70                                               guint32                time,
71                                               GdkModifierType        state,
72                                               GimpButtonPressType    press_type,
73                                               GimpDisplay           *display);
74 static void   gimp_paint_tool_button_release (GimpTool              *tool,
75                                               const GimpCoords      *coords,
76                                               guint32                time,
77                                               GdkModifierType        state,
78                                               GimpButtonReleaseType  release_type,
79                                               GimpDisplay           *display);
80 static void   gimp_paint_tool_motion         (GimpTool              *tool,
81                                               const GimpCoords      *coords,
82                                               guint32                time,
83                                               GdkModifierType        state,
84                                               GimpDisplay           *display);
85 static void   gimp_paint_tool_modifier_key   (GimpTool              *tool,
86                                               GdkModifierType        key,
87                                               gboolean               press,
88                                               GdkModifierType        state,
89                                               GimpDisplay           *display);
90 static void   gimp_paint_tool_cursor_update  (GimpTool              *tool,
91                                               const GimpCoords      *coords,
92                                               GdkModifierType        state,
93                                               GimpDisplay           *display);
94 static void   gimp_paint_tool_oper_update    (GimpTool              *tool,
95                                               const GimpCoords      *coords,
96                                               GdkModifierType        state,
97                                               gboolean               proximity,
98                                               GimpDisplay           *display);
99 
100 static void   gimp_paint_tool_draw           (GimpDrawTool          *draw_tool);
101 
102 static void
103           gimp_paint_tool_real_paint_prepare (GimpPaintTool         *paint_tool,
104                                               GimpDisplay           *display);
105 
106 static GimpCanvasItem *
107               gimp_paint_tool_get_outline    (GimpPaintTool         *paint_tool,
108                                               GimpDisplay           *display,
109                                               gdouble                x,
110                                               gdouble                y);
111 
112 static gboolean  gimp_paint_tool_check_alpha (GimpPaintTool         *paint_tool,
113                                               GimpDrawable          *drawable,
114                                               GimpDisplay           *display,
115                                               GError               **error);
116 
117 static void   gimp_paint_tool_hard_notify    (GimpPaintOptions      *options,
118                                               const GParamSpec      *pspec,
119                                               GimpPaintTool         *paint_tool);
120 static void   gimp_paint_tool_cursor_notify  (GimpDisplayConfig     *config,
121                                               GParamSpec            *pspec,
122                                               GimpPaintTool         *paint_tool);
123 
124 
G_DEFINE_TYPE(GimpPaintTool,gimp_paint_tool,GIMP_TYPE_COLOR_TOOL)125 G_DEFINE_TYPE (GimpPaintTool, gimp_paint_tool, GIMP_TYPE_COLOR_TOOL)
126 
127 #define parent_class gimp_paint_tool_parent_class
128 
129 
130 static void
131 gimp_paint_tool_class_init (GimpPaintToolClass *klass)
132 {
133   GObjectClass      *object_class    = G_OBJECT_CLASS (klass);
134   GimpToolClass     *tool_class      = GIMP_TOOL_CLASS (klass);
135   GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
136 
137   object_class->constructed  = gimp_paint_tool_constructed;
138   object_class->finalize     = gimp_paint_tool_finalize;
139 
140   tool_class->control        = gimp_paint_tool_control;
141   tool_class->button_press   = gimp_paint_tool_button_press;
142   tool_class->button_release = gimp_paint_tool_button_release;
143   tool_class->motion         = gimp_paint_tool_motion;
144   tool_class->modifier_key   = gimp_paint_tool_modifier_key;
145   tool_class->cursor_update  = gimp_paint_tool_cursor_update;
146   tool_class->oper_update    = gimp_paint_tool_oper_update;
147 
148   draw_tool_class->draw      = gimp_paint_tool_draw;
149 
150   klass->paint_prepare       = gimp_paint_tool_real_paint_prepare;
151 }
152 
153 static void
gimp_paint_tool_init(GimpPaintTool * paint_tool)154 gimp_paint_tool_init (GimpPaintTool *paint_tool)
155 {
156   GimpTool *tool = GIMP_TOOL (paint_tool);
157 
158   gimp_tool_control_set_motion_mode    (tool->control, GIMP_MOTION_MODE_EXACT);
159   gimp_tool_control_set_scroll_lock    (tool->control, TRUE);
160   gimp_tool_control_set_action_opacity (tool->control,
161                                         "context/context-opacity-set");
162 
163   paint_tool->active        = TRUE;
164   paint_tool->pick_colors   = FALSE;
165   paint_tool->draw_line     = FALSE;
166 
167   paint_tool->show_cursor   = TRUE;
168   paint_tool->draw_brush    = TRUE;
169   paint_tool->snap_brush    = FALSE;
170   paint_tool->draw_fallback = FALSE;
171   paint_tool->fallback_size = 0.0;
172   paint_tool->draw_circle   = FALSE;
173   paint_tool->circle_size   = 0.0;
174 
175   paint_tool->status      = _("Click to paint");
176   paint_tool->status_line = _("Click to draw the line");
177   paint_tool->status_ctrl = _("%s to pick a color");
178 
179   paint_tool->core        = NULL;
180 }
181 
182 static void
gimp_paint_tool_constructed(GObject * object)183 gimp_paint_tool_constructed (GObject *object)
184 {
185   GimpTool          *tool       = GIMP_TOOL (object);
186   GimpPaintTool     *paint_tool = GIMP_PAINT_TOOL (object);
187   GimpPaintOptions  *options    = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
188   GimpDisplayConfig *display_config;
189   GimpPaintInfo     *paint_info;
190 
191   G_OBJECT_CLASS (parent_class)->constructed (object);
192 
193   gimp_assert (GIMP_IS_TOOL_INFO (tool->tool_info));
194   gimp_assert (GIMP_IS_PAINT_INFO (tool->tool_info->paint_info));
195 
196   display_config = GIMP_DISPLAY_CONFIG (tool->tool_info->gimp->config);
197 
198   paint_info = tool->tool_info->paint_info;
199 
200   gimp_assert (g_type_is_a (paint_info->paint_type, GIMP_TYPE_PAINT_CORE));
201 
202   paint_tool->core = g_object_new (paint_info->paint_type,
203                                    "undo-desc", paint_info->blurb,
204                                    NULL);
205 
206   g_signal_connect_object (options, "notify::hard",
207                            G_CALLBACK (gimp_paint_tool_hard_notify),
208                            paint_tool, 0);
209 
210   gimp_paint_tool_hard_notify (options, NULL, paint_tool);
211 
212   paint_tool->show_cursor = display_config->show_paint_tool_cursor;
213   paint_tool->draw_brush  = display_config->show_brush_outline;
214   paint_tool->snap_brush  = display_config->snap_brush_outline;
215 
216   g_signal_connect_object (display_config, "notify::show-paint-tool-cursor",
217                            G_CALLBACK (gimp_paint_tool_cursor_notify),
218                            paint_tool, 0);
219   g_signal_connect_object (display_config, "notify::show-brush-outline",
220                            G_CALLBACK (gimp_paint_tool_cursor_notify),
221                            paint_tool, 0);
222   g_signal_connect_object (display_config, "notify::snap-brush-outline",
223                            G_CALLBACK (gimp_paint_tool_cursor_notify),
224                            paint_tool, 0);
225 }
226 
227 static void
gimp_paint_tool_finalize(GObject * object)228 gimp_paint_tool_finalize (GObject *object)
229 {
230   GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (object);
231 
232   if (paint_tool->core)
233     {
234       g_object_unref (paint_tool->core);
235       paint_tool->core = NULL;
236     }
237 
238   G_OBJECT_CLASS (parent_class)->finalize (object);
239 }
240 
241 static void
gimp_paint_tool_control(GimpTool * tool,GimpToolAction action,GimpDisplay * display)242 gimp_paint_tool_control (GimpTool       *tool,
243                          GimpToolAction  action,
244                          GimpDisplay    *display)
245 {
246   GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
247 
248   switch (action)
249     {
250     case GIMP_TOOL_ACTION_PAUSE:
251     case GIMP_TOOL_ACTION_RESUME:
252       break;
253 
254     case GIMP_TOOL_ACTION_HALT:
255       gimp_paint_core_cleanup (paint_tool->core);
256       break;
257 
258     case GIMP_TOOL_ACTION_COMMIT:
259       break;
260     }
261 
262   GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
263 }
264 
265 static void
gimp_paint_tool_button_press(GimpTool * tool,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpButtonPressType press_type,GimpDisplay * display)266 gimp_paint_tool_button_press (GimpTool            *tool,
267                               const GimpCoords    *coords,
268                               guint32              time,
269                               GdkModifierType      state,
270                               GimpButtonPressType  press_type,
271                               GimpDisplay         *display)
272 {
273   GimpDrawTool     *draw_tool  = GIMP_DRAW_TOOL (tool);
274   GimpPaintTool    *paint_tool = GIMP_PAINT_TOOL (tool);
275   GimpPaintOptions *options    = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
276   GimpGuiConfig    *config     = GIMP_GUI_CONFIG (display->gimp->config);
277   GimpDisplayShell *shell      = gimp_display_get_shell (display);
278   GimpImage        *image      = gimp_display_get_image (display);
279   GimpDrawable     *drawable   = gimp_image_get_active_drawable (image);
280   gboolean          constrain;
281   GError           *error = NULL;
282 
283   if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
284     {
285       GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
286                                                     press_type, display);
287       return;
288     }
289 
290   if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
291     {
292       gimp_tool_message_literal (tool, display,
293                                  _("Cannot paint on layer groups."));
294       return;
295     }
296 
297   if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
298     {
299       gimp_tool_message_literal (tool, display,
300                                  _("The active layer's pixels are locked."));
301       gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable));
302       return;
303     }
304 
305   if (! gimp_paint_tool_check_alpha (paint_tool, drawable, display, &error))
306     {
307       GtkWidget *options_gui;
308       GtkWidget *mode_box;
309 
310       gimp_tool_message_literal (tool, display, error->message);
311 
312       options_gui = gimp_tools_get_tool_options_gui (
313                       GIMP_TOOL_OPTIONS (options));
314       mode_box    = gimp_paint_options_gui_get_paint_mode_box (options_gui);
315 
316       if (gtk_widget_is_sensitive (mode_box))
317         gimp_widget_blink (mode_box);
318 
319       g_clear_error (&error);
320 
321       return;
322     }
323 
324   if (! gimp_item_is_visible (GIMP_ITEM (drawable)) &&
325       ! config->edit_non_visible)
326     {
327       gimp_tool_message_literal (tool, display,
328                                  _("The active layer is not visible."));
329       return;
330     }
331 
332   if (gimp_draw_tool_is_active (draw_tool))
333     gimp_draw_tool_stop (draw_tool);
334 
335   if (tool->display            &&
336       tool->display != display &&
337       gimp_display_get_image (tool->display) == image)
338     {
339       /*  if this is a different display, but the same image, HACK around
340        *  in tool internals AFTER stopping the current draw_tool, so
341        *  straight line drawing works across different views of the
342        *  same image.
343        */
344 
345       tool->display = display;
346     }
347 
348   constrain = (state & gimp_get_constrain_behavior_mask ()) != 0;
349 
350   if (! gimp_paint_tool_paint_start (paint_tool,
351                                      display, coords, time, constrain,
352                                      &error))
353     {
354       gimp_tool_message_literal (tool, display, error->message);
355       g_clear_error (&error);
356       return;
357     }
358 
359   tool->display  = display;
360   tool->drawable = drawable;
361 
362   /*  pause the current selection  */
363   gimp_display_shell_selection_pause (shell);
364 
365   gimp_draw_tool_start (draw_tool, display);
366 
367   gimp_tool_control_activate (tool->control);
368 }
369 
370 static void
gimp_paint_tool_button_release(GimpTool * tool,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpButtonReleaseType release_type,GimpDisplay * display)371 gimp_paint_tool_button_release (GimpTool              *tool,
372                                 const GimpCoords      *coords,
373                                 guint32                time,
374                                 GdkModifierType        state,
375                                 GimpButtonReleaseType  release_type,
376                                 GimpDisplay           *display)
377 {
378   GimpPaintTool    *paint_tool = GIMP_PAINT_TOOL (tool);
379   GimpDisplayShell *shell      = gimp_display_get_shell (display);
380   GimpImage        *image      = gimp_display_get_image (display);
381   gboolean          cancel;
382 
383   if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
384     {
385       GIMP_TOOL_CLASS (parent_class)->button_release (tool, coords, time,
386                                                       state, release_type,
387                                                       display);
388       return;
389     }
390 
391   cancel = (release_type == GIMP_BUTTON_RELEASE_CANCEL);
392 
393   gimp_paint_tool_paint_end (paint_tool, time, cancel);
394 
395   gimp_tool_control_halt (tool->control);
396 
397   gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
398 
399   /*  resume the current selection  */
400   gimp_display_shell_selection_resume (shell);
401 
402   gimp_image_flush (image);
403 
404   gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
405 }
406 
407 static void
gimp_paint_tool_motion(GimpTool * tool,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpDisplay * display)408 gimp_paint_tool_motion (GimpTool         *tool,
409                         const GimpCoords *coords,
410                         guint32           time,
411                         GdkModifierType   state,
412                         GimpDisplay      *display)
413 {
414   GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
415 
416   GIMP_TOOL_CLASS (parent_class)->motion (tool, coords, time, state, display);
417 
418   if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
419     return;
420 
421   if (! paint_tool->snap_brush)
422     gimp_draw_tool_pause  (GIMP_DRAW_TOOL (tool));
423 
424   gimp_paint_tool_paint_motion (paint_tool, coords, time);
425 
426   if (! paint_tool->snap_brush)
427     gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
428 }
429 
430 static void
gimp_paint_tool_modifier_key(GimpTool * tool,GdkModifierType key,gboolean press,GdkModifierType state,GimpDisplay * display)431 gimp_paint_tool_modifier_key (GimpTool        *tool,
432                               GdkModifierType  key,
433                               gboolean         press,
434                               GdkModifierType  state,
435                               GimpDisplay     *display)
436 {
437   GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (tool);
438   GimpDrawTool  *draw_tool  = GIMP_DRAW_TOOL (tool);
439 
440   if (paint_tool->pick_colors && ! paint_tool->draw_line)
441     {
442       if ((state & gimp_get_all_modifiers_mask ()) ==
443           gimp_get_constrain_behavior_mask ())
444         {
445           if (! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
446             {
447               GimpToolInfo *info = gimp_get_tool_info (display->gimp,
448                                                        "gimp-color-picker-tool");
449 
450               if (GIMP_IS_TOOL_INFO (info))
451                 {
452                   if (gimp_draw_tool_is_active (draw_tool))
453                     gimp_draw_tool_stop (draw_tool);
454 
455                   gimp_color_tool_enable (GIMP_COLOR_TOOL (tool),
456                                           GIMP_COLOR_OPTIONS (info->tool_options));
457 
458                   switch (GIMP_COLOR_TOOL (tool)->pick_target)
459                     {
460                     case GIMP_COLOR_PICK_TARGET_FOREGROUND:
461                       gimp_tool_push_status (tool, display,
462                                              _("Click in any image to pick the "
463                                                "foreground color"));
464                       break;
465 
466                     case GIMP_COLOR_PICK_TARGET_BACKGROUND:
467                       gimp_tool_push_status (tool, display,
468                                              _("Click in any image to pick the "
469                                                "background color"));
470                       break;
471 
472                     default:
473                       break;
474                     }
475                 }
476             }
477         }
478       else
479         {
480           if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
481             {
482               gimp_tool_pop_status (tool, display);
483               gimp_color_tool_disable (GIMP_COLOR_TOOL (tool));
484             }
485         }
486     }
487 }
488 
489 static void
gimp_paint_tool_cursor_update(GimpTool * tool,const GimpCoords * coords,GdkModifierType state,GimpDisplay * display)490 gimp_paint_tool_cursor_update (GimpTool         *tool,
491                                const GimpCoords *coords,
492                                GdkModifierType   state,
493                                GimpDisplay      *display)
494 {
495   GimpPaintTool      *paint_tool = GIMP_PAINT_TOOL (tool);
496   GimpGuiConfig      *config     = GIMP_GUI_CONFIG (display->gimp->config);
497   GimpCursorModifier  modifier;
498   GimpCursorModifier  toggle_modifier;
499   GimpCursorModifier  old_modifier;
500   GimpCursorModifier  old_toggle_modifier;
501 
502   modifier        = tool->control->cursor_modifier;
503   toggle_modifier = tool->control->toggle_cursor_modifier;
504 
505   old_modifier        = modifier;
506   old_toggle_modifier = toggle_modifier;
507 
508   if (! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
509     {
510       GimpImage    *image    = gimp_display_get_image (display);
511       GimpDrawable *drawable = gimp_image_get_active_drawable (image);
512 
513       if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable))               ||
514           gimp_item_is_content_locked (GIMP_ITEM (drawable))                  ||
515           ! gimp_paint_tool_check_alpha (paint_tool, drawable, display, NULL) ||
516           ! (gimp_item_is_visible (GIMP_ITEM (drawable)) ||
517              config->edit_non_visible))
518         {
519           modifier        = GIMP_CURSOR_MODIFIER_BAD;
520           toggle_modifier = GIMP_CURSOR_MODIFIER_BAD;
521         }
522 
523       if (! paint_tool->show_cursor &&
524           modifier != GIMP_CURSOR_MODIFIER_BAD)
525         {
526           gimp_tool_set_cursor (tool, display,
527                                 GIMP_CURSOR_NONE,
528                                 GIMP_TOOL_CURSOR_NONE,
529                                 GIMP_CURSOR_MODIFIER_NONE);
530           return;
531         }
532 
533       gimp_tool_control_set_cursor_modifier        (tool->control,
534                                                     modifier);
535       gimp_tool_control_set_toggle_cursor_modifier (tool->control,
536                                                     toggle_modifier);
537     }
538 
539   GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state,
540                                                  display);
541 
542   /*  reset old stuff here so we are not interfering with the modifiers
543    *  set by our subclasses
544    */
545   gimp_tool_control_set_cursor_modifier        (tool->control,
546                                                 old_modifier);
547   gimp_tool_control_set_toggle_cursor_modifier (tool->control,
548                                                 old_toggle_modifier);
549 }
550 
551 static void
gimp_paint_tool_oper_update(GimpTool * tool,const GimpCoords * coords,GdkModifierType state,gboolean proximity,GimpDisplay * display)552 gimp_paint_tool_oper_update (GimpTool         *tool,
553                              const GimpCoords *coords,
554                              GdkModifierType   state,
555                              gboolean          proximity,
556                              GimpDisplay      *display)
557 {
558   GimpPaintTool    *paint_tool    = GIMP_PAINT_TOOL (tool);
559   GimpDrawTool     *draw_tool     = GIMP_DRAW_TOOL (tool);
560   GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
561   GimpPaintCore    *core          = paint_tool->core;
562   GimpDisplayShell *shell         = gimp_display_get_shell (display);
563   GimpImage        *image         = gimp_display_get_image (display);
564   GimpDrawable     *drawable      = gimp_image_get_active_drawable (image);
565 
566   if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
567     {
568       GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state,
569                                                    proximity, display);
570       return;
571     }
572 
573   gimp_draw_tool_pause (draw_tool);
574 
575   if (gimp_draw_tool_is_active (draw_tool) &&
576       draw_tool->display != display)
577     gimp_draw_tool_stop (draw_tool);
578 
579   gimp_tool_pop_status (tool, display);
580 
581   if (tool->display            &&
582       tool->display != display &&
583       gimp_display_get_image (tool->display) == image)
584     {
585       /*  if this is a different display, but the same image, HACK around
586        *  in tool internals AFTER stopping the current draw_tool, so
587        *  straight line drawing works across different views of the
588        *  same image.
589        */
590 
591       tool->display = display;
592     }
593 
594   if (drawable && proximity)
595     {
596       gchar    *status;
597       gboolean  constrain_mask = gimp_get_constrain_behavior_mask ();
598       gint      off_x, off_y;
599 
600       core->cur_coords = *coords;
601 
602       gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
603 
604       core->cur_coords.x -= off_x;
605       core->cur_coords.y -= off_y;
606 
607       if (display == tool->display && (state & GIMP_PAINT_TOOL_LINE_MASK))
608         {
609           /*  If shift is down and this is not the first paint stroke,
610            *  draw a line.
611            */
612           gchar   *status_help;
613           gdouble  offset_angle;
614           gdouble  xres, yres;
615 
616           gimp_display_shell_get_constrained_line_params (shell,
617                                                           &offset_angle,
618                                                           &xres, &yres);
619 
620           gimp_paint_core_round_line (core, paint_options,
621                                       (state & constrain_mask) != 0,
622                                       offset_angle, xres, yres);
623 
624           status_help = gimp_suggest_modifiers (paint_tool->status_line,
625                                                 constrain_mask & ~state,
626                                                 NULL,
627                                                 _("%s for constrained angles"),
628                                                 NULL);
629 
630           status = gimp_display_shell_get_line_status (shell, status_help,
631                                                        ". ",
632                                                        core->last_coords.x,
633                                                        core->last_coords.y,
634                                                        core->cur_coords.x,
635                                                        core->cur_coords.y);
636           g_free (status_help);
637           paint_tool->draw_line = TRUE;
638         }
639       else
640         {
641           GdkModifierType  modifiers = 0;
642 
643           /* HACK: A paint tool may set status_ctrl to NULL to indicate that
644            * it ignores the Ctrl modifier (temporarily or permanently), so
645            * it should not be suggested.  This is different from how
646            * gimp_suggest_modifiers() would interpret this parameter.
647            */
648           if (paint_tool->status_ctrl != NULL)
649             modifiers |= constrain_mask;
650 
651           /* suggest drawing lines only after the first point is set
652            */
653           if (display == tool->display)
654             modifiers |= GIMP_PAINT_TOOL_LINE_MASK;
655 
656           status = gimp_suggest_modifiers (paint_tool->status,
657                                            modifiers & ~state,
658                                            _("%s for a straight line"),
659                                            paint_tool->status_ctrl,
660                                            NULL);
661           paint_tool->draw_line = FALSE;
662         }
663       gimp_tool_push_status (tool, display, "%s", status);
664       g_free (status);
665 
666       paint_tool->cursor_x = core->cur_coords.x;
667       paint_tool->cursor_y = core->cur_coords.y;
668 
669       if (! gimp_draw_tool_is_active (draw_tool))
670         gimp_draw_tool_start (draw_tool, display);
671     }
672   else if (gimp_draw_tool_is_active (draw_tool))
673     {
674       gimp_draw_tool_stop (draw_tool);
675     }
676 
677   GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
678                                                display);
679 
680   gimp_draw_tool_resume (draw_tool);
681 }
682 
683 static void
gimp_paint_tool_draw(GimpDrawTool * draw_tool)684 gimp_paint_tool_draw (GimpDrawTool *draw_tool)
685 {
686   GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (draw_tool);
687 
688 
689   if (paint_tool->active &&
690       ! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (draw_tool)))
691     {
692       GimpPaintCore  *core       = paint_tool->core;
693       GimpImage      *image      = gimp_display_get_image (draw_tool->display);
694       GimpDrawable   *drawable   = gimp_image_get_active_drawable (image);
695       GimpCanvasItem *outline    = NULL;
696       gboolean        line_drawn = FALSE;
697       gdouble         cur_x, cur_y;
698       gint            off_x, off_y;
699 
700       gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
701 
702       if (gimp_paint_tool_paint_is_active (paint_tool) &&
703           paint_tool->snap_brush)
704         {
705           cur_x = paint_tool->paint_x + off_x;
706           cur_y = paint_tool->paint_y + off_y;
707         }
708       else
709         {
710           cur_x = paint_tool->cursor_x + off_x;
711           cur_y = paint_tool->cursor_y + off_y;
712 
713           if (paint_tool->draw_line &&
714               ! gimp_tool_control_is_active (GIMP_TOOL (draw_tool)->control))
715             {
716               GimpCanvasGroup *group;
717               gdouble          last_x, last_y;
718 
719               last_x = core->last_coords.x + off_x;
720               last_y = core->last_coords.y + off_y;
721 
722               group = gimp_draw_tool_add_stroke_group (draw_tool);
723               gimp_draw_tool_push_group (draw_tool, group);
724 
725               gimp_draw_tool_add_handle (draw_tool,
726                                          GIMP_HANDLE_CIRCLE,
727                                          last_x, last_y,
728                                          GIMP_TOOL_HANDLE_SIZE_CIRCLE,
729                                          GIMP_TOOL_HANDLE_SIZE_CIRCLE,
730                                          GIMP_HANDLE_ANCHOR_CENTER);
731 
732               gimp_draw_tool_add_line (draw_tool,
733                                        last_x, last_y,
734                                        cur_x, cur_y);
735 
736               gimp_draw_tool_add_handle (draw_tool,
737                                          GIMP_HANDLE_CIRCLE,
738                                          cur_x, cur_y,
739                                          GIMP_TOOL_HANDLE_SIZE_CIRCLE,
740                                          GIMP_TOOL_HANDLE_SIZE_CIRCLE,
741                                          GIMP_HANDLE_ANCHOR_CENTER);
742 
743               gimp_draw_tool_pop_group (draw_tool);
744 
745               line_drawn = TRUE;
746             }
747         }
748 
749       gimp_paint_tool_set_draw_fallback (paint_tool, FALSE, 0.0);
750 
751       if (paint_tool->draw_brush)
752         outline = gimp_paint_tool_get_outline (paint_tool,
753                                                draw_tool->display,
754                                                cur_x, cur_y);
755 
756       if (outline)
757         {
758           gimp_draw_tool_add_item (draw_tool, outline);
759           g_object_unref (outline);
760         }
761       else if (paint_tool->draw_fallback)
762         {
763           /* Lets make a sensible fallback cursor
764            *
765            * Sensible cursor is
766            *  * crossed to indicate draw point
767            *  * reactive to options alterations
768            *  * not a full circle that would be in the way
769            */
770           gint size = (gint) paint_tool->fallback_size;
771 
772 #define TICKMARK_ANGLE 48
773 #define ROTATION_ANGLE G_PI / 4
774 
775           /* marks for indicating full size */
776           gimp_draw_tool_add_arc (draw_tool,
777                                   FALSE,
778                                   cur_x - (size / 2.0),
779                                   cur_y - (size / 2.0),
780                                   size, size,
781                                   ROTATION_ANGLE - (2.0 * G_PI) / (TICKMARK_ANGLE * 2),
782                                   (2.0 * G_PI) / TICKMARK_ANGLE);
783 
784           gimp_draw_tool_add_arc (draw_tool,
785                                   FALSE,
786                                   cur_x - (size / 2.0),
787                                   cur_y - (size / 2.0),
788                                   size, size,
789                                   ROTATION_ANGLE + G_PI / 2 - (2.0 * G_PI) / (TICKMARK_ANGLE * 2),
790                                   (2.0 * G_PI) / TICKMARK_ANGLE);
791 
792           gimp_draw_tool_add_arc (draw_tool,
793                                   FALSE,
794                                   cur_x - (size / 2.0),
795                                   cur_y - (size / 2.0),
796                                   size, size,
797                                   ROTATION_ANGLE + G_PI - (2.0 * G_PI) / (TICKMARK_ANGLE * 2),
798                                   (2.0 * G_PI) / TICKMARK_ANGLE);
799 
800           gimp_draw_tool_add_arc (draw_tool,
801                                   FALSE,
802                                   cur_x - (size / 2.0),
803                                   cur_y - (size / 2.0),
804                                   size, size,
805                                   ROTATION_ANGLE + 3 * G_PI / 2 - (2.0 * G_PI) / (TICKMARK_ANGLE * 2),
806                                   (2.0 * G_PI) / TICKMARK_ANGLE);
807         }
808       else if (paint_tool->draw_circle)
809         {
810           gint size = (gint) paint_tool->circle_size;
811 
812           /* draw an indicatory circle */
813           gimp_draw_tool_add_arc (draw_tool,
814                                   FALSE,
815                                   cur_x - (size / 2.0),
816                                   cur_y - (size / 2.0),
817                                   size, size,
818                                   0.0, (2.0 * G_PI));
819         }
820 
821       if (! outline                 &&
822           ! line_drawn              &&
823           ! paint_tool->show_cursor &&
824           ! paint_tool->draw_circle)
825         {
826           /*  don't leave the user without any indication and draw
827            *  a fallback crosshair
828            */
829           gimp_draw_tool_add_handle (draw_tool,
830                                      GIMP_HANDLE_CROSSHAIR,
831                                      cur_x, cur_y,
832                                      GIMP_TOOL_HANDLE_SIZE_CROSSHAIR,
833                                      GIMP_TOOL_HANDLE_SIZE_CROSSHAIR,
834                                      GIMP_HANDLE_ANCHOR_CENTER);
835         }
836     }
837 
838   GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
839 }
840 
841 static void
gimp_paint_tool_real_paint_prepare(GimpPaintTool * paint_tool,GimpDisplay * display)842 gimp_paint_tool_real_paint_prepare (GimpPaintTool *paint_tool,
843                                     GimpDisplay   *display)
844 {
845   GimpDisplayShell *shell = gimp_display_get_shell (display);
846 
847   gimp_paint_core_set_show_all (paint_tool->core, shell->show_all);
848 }
849 
850 static GimpCanvasItem *
gimp_paint_tool_get_outline(GimpPaintTool * paint_tool,GimpDisplay * display,gdouble x,gdouble y)851 gimp_paint_tool_get_outline (GimpPaintTool *paint_tool,
852                              GimpDisplay   *display,
853                              gdouble        x,
854                              gdouble        y)
855 {
856   if (GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->get_outline)
857     return GIMP_PAINT_TOOL_GET_CLASS (paint_tool)->get_outline (paint_tool,
858                                                                 display, x, y);
859 
860   return NULL;
861 }
862 
863 static gboolean
gimp_paint_tool_check_alpha(GimpPaintTool * paint_tool,GimpDrawable * drawable,GimpDisplay * display,GError ** error)864 gimp_paint_tool_check_alpha (GimpPaintTool  *paint_tool,
865                              GimpDrawable   *drawable,
866                              GimpDisplay    *display,
867                              GError        **error)
868 {
869   GimpPaintToolClass *klass = GIMP_PAINT_TOOL_GET_CLASS (paint_tool);
870 
871   if (klass->is_alpha_only && klass->is_alpha_only (paint_tool, drawable))
872     {
873       if (! gimp_drawable_has_alpha (drawable))
874         {
875           g_set_error_literal (
876             error, GIMP_ERROR, GIMP_FAILED,
877             _("The active layer does not have an alpha channel."));
878 
879           return FALSE;
880         }
881 
882         if (GIMP_IS_LAYER (drawable) &&
883             gimp_layer_get_lock_alpha (GIMP_LAYER (drawable)))
884         {
885           g_set_error_literal (
886             error, GIMP_ERROR, GIMP_FAILED,
887             _("The active layer's alpha channel is locked."));
888 
889           if (error)
890             gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable));
891 
892           return FALSE;
893         }
894     }
895 
896   return TRUE;
897 }
898 
899 static void
gimp_paint_tool_hard_notify(GimpPaintOptions * options,const GParamSpec * pspec,GimpPaintTool * paint_tool)900 gimp_paint_tool_hard_notify (GimpPaintOptions *options,
901                              const GParamSpec *pspec,
902                              GimpPaintTool    *paint_tool)
903 {
904   if (paint_tool->active)
905     {
906       GimpTool *tool = GIMP_TOOL (paint_tool);
907 
908       gimp_tool_control_set_precision (tool->control,
909                                        options->hard ?
910                                        GIMP_CURSOR_PRECISION_PIXEL_CENTER :
911                                        GIMP_CURSOR_PRECISION_SUBPIXEL);
912     }
913 }
914 
915 static void
gimp_paint_tool_cursor_notify(GimpDisplayConfig * config,GParamSpec * pspec,GimpPaintTool * paint_tool)916 gimp_paint_tool_cursor_notify (GimpDisplayConfig *config,
917                                GParamSpec        *pspec,
918                                GimpPaintTool     *paint_tool)
919 {
920   gimp_draw_tool_pause (GIMP_DRAW_TOOL (paint_tool));
921 
922   paint_tool->show_cursor = config->show_paint_tool_cursor;
923   paint_tool->draw_brush  = config->show_brush_outline;
924   paint_tool->snap_brush  = config->snap_brush_outline;
925 
926   gimp_draw_tool_resume (GIMP_DRAW_TOOL (paint_tool));
927 }
928 
929 void
gimp_paint_tool_set_active(GimpPaintTool * tool,gboolean active)930 gimp_paint_tool_set_active (GimpPaintTool *tool,
931                             gboolean       active)
932 {
933   g_return_if_fail (GIMP_IS_PAINT_TOOL (tool));
934 
935   if (active != tool->active)
936     {
937       GimpPaintOptions *options = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
938 
939       gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
940 
941       tool->active = active;
942 
943       if (active)
944         gimp_paint_tool_hard_notify (options, NULL, tool);
945 
946       gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
947     }
948 }
949 
950 /**
951  * gimp_paint_tool_enable_color_picker:
952  * @tool:   a #GimpPaintTool
953  * @target: the #GimpColorPickTarget to set
954  *
955  * This is a convenience function used from the init method of paint
956  * tools that want the color picking functionality. The @mode that is
957  * set here is used to decide what cursor modifier to draw and if the
958  * picked color goes to the foreground or background color.
959  **/
960 void
gimp_paint_tool_enable_color_picker(GimpPaintTool * tool,GimpColorPickTarget target)961 gimp_paint_tool_enable_color_picker (GimpPaintTool       *tool,
962                                      GimpColorPickTarget  target)
963 {
964   g_return_if_fail (GIMP_IS_PAINT_TOOL (tool));
965 
966   tool->pick_colors = TRUE;
967 
968   GIMP_COLOR_TOOL (tool)->pick_target = target;
969 }
970 
971 void
gimp_paint_tool_set_draw_fallback(GimpPaintTool * tool,gboolean draw_fallback,gint fallback_size)972 gimp_paint_tool_set_draw_fallback (GimpPaintTool *tool,
973                                    gboolean       draw_fallback,
974                                    gint           fallback_size)
975 {
976   g_return_if_fail (GIMP_IS_PAINT_TOOL (tool));
977 
978   tool->draw_fallback = draw_fallback;
979   tool->fallback_size = fallback_size;
980 }
981 
982 void
gimp_paint_tool_set_draw_circle(GimpPaintTool * tool,gboolean draw_circle,gint circle_size)983 gimp_paint_tool_set_draw_circle (GimpPaintTool *tool,
984                                  gboolean       draw_circle,
985                                  gint           circle_size)
986 {
987   g_return_if_fail (GIMP_IS_PAINT_TOOL (tool));
988 
989   tool->draw_circle = draw_circle;
990   tool->circle_size = circle_size;
991 }
992