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 <cairo.h>
21 #include <gegl.h>
22 #include <gdk-pixbuf/gdk-pixbuf.h>
23 
24 #include "libgimpcolor/gimpcolor.h"
25 
26 #include "core-types.h"
27 
28 #include "gimp.h"
29 #include "gimpchannel.h"
30 #include "gimpimage.h"
31 #include "gimpimage-private.h"
32 #include "gimpimage-quick-mask.h"
33 #include "gimpimage-undo.h"
34 #include "gimpimage-undo-push.h"
35 #include "gimplayer.h"
36 #include "gimplayer-floating-selection.h"
37 
38 #include "gimp-intl.h"
39 
40 
41 #define CHANNEL_WAS_ACTIVE (0x2)
42 
43 
44 /*  public functions  */
45 
46 void
gimp_image_set_quick_mask_state(GimpImage * image,gboolean active)47 gimp_image_set_quick_mask_state (GimpImage *image,
48                                  gboolean   active)
49 {
50   GimpImagePrivate *private;
51   GimpChannel      *selection;
52   GimpChannel      *mask;
53   gboolean          channel_was_active;
54 
55   g_return_if_fail (GIMP_IS_IMAGE (image));
56 
57   if (active == gimp_image_get_quick_mask_state (image))
58     return;
59 
60   private = GIMP_IMAGE_GET_PRIVATE (image);
61 
62   /*  Keep track of the state so that we can make the right drawable
63    *  active again when deactiviting quick mask (see bug #134371).
64    */
65   if (private->quick_mask_state)
66     channel_was_active = (private->quick_mask_state & CHANNEL_WAS_ACTIVE) != 0;
67   else
68     channel_was_active = gimp_image_get_active_channel (image) != NULL;
69 
70   /*  Set private->quick_mask_state early so we can return early when
71    *  being called recursively.
72    */
73   private->quick_mask_state = (active
74                                ? TRUE | (channel_was_active ?
75                                          CHANNEL_WAS_ACTIVE : 0)
76                                : FALSE);
77 
78   selection = gimp_image_get_mask (image);
79   mask      = gimp_image_get_quick_mask (image);
80 
81   if (active)
82     {
83       if (! mask)
84         {
85           GimpLayer *floating_sel;
86 
87           gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_QUICK_MASK,
88                                        C_("undo-type", "Enable Quick Mask"));
89 
90           floating_sel = gimp_image_get_floating_selection (image);
91 
92           if (floating_sel)
93             floating_sel_to_layer (floating_sel, NULL);
94 
95           mask = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (selection),
96                                                     GIMP_TYPE_CHANNEL));
97 
98           if (! gimp_channel_is_empty (selection))
99             gimp_channel_clear (selection, NULL, TRUE);
100 
101           gimp_channel_set_color (mask, &private->quick_mask_color, FALSE);
102           gimp_item_rename (GIMP_ITEM (mask), GIMP_IMAGE_QUICK_MASK_NAME,
103                             NULL);
104 
105           if (private->quick_mask_inverted)
106             gimp_channel_invert (mask, FALSE);
107 
108           gimp_image_add_channel (image, mask, NULL, 0, TRUE);
109 
110           gimp_image_undo_group_end (image);
111         }
112     }
113   else
114     {
115       if (mask)
116         {
117           GimpLayer *floating_sel = gimp_image_get_floating_selection (image);
118 
119           gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_QUICK_MASK,
120                                        C_("undo-type", "Disable Quick Mask"));
121 
122           if (private->quick_mask_inverted)
123             gimp_channel_invert (mask, TRUE);
124 
125           if (floating_sel &&
126               gimp_layer_get_floating_sel_drawable (floating_sel) == GIMP_DRAWABLE (mask))
127             floating_sel_anchor (floating_sel);
128 
129           gimp_item_to_selection (GIMP_ITEM (mask),
130                                   GIMP_CHANNEL_OP_REPLACE,
131                                   TRUE, FALSE, 0.0, 0.0);
132           gimp_image_remove_channel (image, mask, TRUE, NULL);
133 
134           if (! channel_was_active)
135             gimp_image_unset_active_channel (image);
136 
137           gimp_image_undo_group_end (image);
138         }
139     }
140 
141   gimp_image_quick_mask_changed (image);
142 }
143 
144 gboolean
gimp_image_get_quick_mask_state(GimpImage * image)145 gimp_image_get_quick_mask_state (GimpImage *image)
146 {
147   g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
148 
149   return GIMP_IMAGE_GET_PRIVATE (image)->quick_mask_state;
150 }
151 
152 void
gimp_image_set_quick_mask_color(GimpImage * image,const GimpRGB * color)153 gimp_image_set_quick_mask_color (GimpImage     *image,
154                                  const GimpRGB *color)
155 {
156   GimpChannel *quick_mask;
157 
158   g_return_if_fail (GIMP_IS_IMAGE (image));
159   g_return_if_fail (color != NULL);
160 
161   GIMP_IMAGE_GET_PRIVATE (image)->quick_mask_color = *color;
162 
163   quick_mask = gimp_image_get_quick_mask (image);
164   if (quick_mask)
165     gimp_channel_set_color (quick_mask, color, TRUE);
166 }
167 
168 void
gimp_image_get_quick_mask_color(GimpImage * image,GimpRGB * color)169 gimp_image_get_quick_mask_color (GimpImage *image,
170                                  GimpRGB   *color)
171 {
172   g_return_if_fail (GIMP_IS_IMAGE (image));
173   g_return_if_fail (color != NULL);
174 
175   *color = GIMP_IMAGE_GET_PRIVATE (image)->quick_mask_color;
176 }
177 
178 GimpChannel *
gimp_image_get_quick_mask(GimpImage * image)179 gimp_image_get_quick_mask (GimpImage *image)
180 {
181   g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
182 
183   return gimp_image_get_channel_by_name (image, GIMP_IMAGE_QUICK_MASK_NAME);
184 }
185 
186 void
gimp_image_quick_mask_invert(GimpImage * image)187 gimp_image_quick_mask_invert (GimpImage *image)
188 {
189   GimpImagePrivate *private;
190 
191   g_return_if_fail (GIMP_IS_IMAGE (image));
192 
193   private = GIMP_IMAGE_GET_PRIVATE (image);
194 
195   if (private->quick_mask_state)
196     {
197       GimpChannel *quick_mask = gimp_image_get_quick_mask (image);
198 
199       if (quick_mask)
200         gimp_channel_invert (quick_mask, TRUE);
201     }
202 
203   private->quick_mask_inverted = ! private->quick_mask_inverted;
204 }
205 
206 gboolean
gimp_image_get_quick_mask_inverted(GimpImage * image)207 gimp_image_get_quick_mask_inverted (GimpImage *image)
208 {
209   g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
210 
211   return GIMP_IMAGE_GET_PRIVATE (image)->quick_mask_inverted;
212 }
213