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 <stdlib.h>
21 #include <string.h>
22 
23 #include <gdk-pixbuf/gdk-pixbuf.h>
24 #include <gegl.h>
25 
26 #include "libgimpbase/gimpbase.h"
27 
28 #include "paint-types.h"
29 
30 #include "gegl/gimp-gegl-apply-operation.h"
31 #include "gegl/gimp-gegl-loops.h"
32 
33 #include "core/gimp.h"
34 #include "core/gimpdrawable.h"
35 #include "core/gimpdynamics.h"
36 #include "core/gimperror.h"
37 #include "core/gimpimage.h"
38 #include "core/gimppattern.h"
39 #include "core/gimppickable.h"
40 #include "core/gimpsymmetry.h"
41 
42 #include "gimpclone.h"
43 #include "gimpcloneoptions.h"
44 
45 #include "gimp-intl.h"
46 
47 
48 static gboolean   gimp_clone_start      (GimpPaintCore     *paint_core,
49                                          GimpDrawable      *drawable,
50                                          GimpPaintOptions  *paint_options,
51                                          const GimpCoords  *coords,
52                                          GError           **error);
53 
54 static void       gimp_clone_motion     (GimpSourceCore    *source_core,
55                                          GimpDrawable      *drawable,
56                                          GimpPaintOptions  *paint_options,
57                                          const GimpCoords  *coords,
58                                          GeglNode          *op,
59                                          gdouble            opacity,
60                                          GimpPickable      *src_pickable,
61                                          GeglBuffer        *src_buffer,
62                                          GeglRectangle     *src_rect,
63                                          gint               src_offset_x,
64                                          gint               src_offset_y,
65                                          GeglBuffer        *paint_buffer,
66                                          gint               paint_buffer_x,
67                                          gint               paint_buffer_y,
68                                          gint               paint_area_offset_x,
69                                          gint               paint_area_offset_y,
70                                          gint               paint_area_width,
71                                          gint               paint_area_height);
72 
73 static gboolean   gimp_clone_use_source (GimpSourceCore    *source_core,
74                                          GimpSourceOptions *options);
75 
76 
G_DEFINE_TYPE(GimpClone,gimp_clone,GIMP_TYPE_SOURCE_CORE)77 G_DEFINE_TYPE (GimpClone, gimp_clone, GIMP_TYPE_SOURCE_CORE)
78 
79 #define parent_class gimp_clone_parent_class
80 
81 
82 void
83 gimp_clone_register (Gimp                      *gimp,
84                      GimpPaintRegisterCallback  callback)
85 {
86   (* callback) (gimp,
87                 GIMP_TYPE_CLONE,
88                 GIMP_TYPE_CLONE_OPTIONS,
89                 "gimp-clone",
90                 _("Clone"),
91                 "gimp-tool-clone");
92 }
93 
94 static void
gimp_clone_class_init(GimpCloneClass * klass)95 gimp_clone_class_init (GimpCloneClass *klass)
96 {
97   GimpPaintCoreClass  *paint_core_class  = GIMP_PAINT_CORE_CLASS (klass);
98   GimpSourceCoreClass *source_core_class = GIMP_SOURCE_CORE_CLASS (klass);
99 
100   paint_core_class->start       = gimp_clone_start;
101 
102   source_core_class->use_source = gimp_clone_use_source;
103   source_core_class->motion     = gimp_clone_motion;
104 }
105 
106 static void
gimp_clone_init(GimpClone * clone)107 gimp_clone_init (GimpClone *clone)
108 {
109 }
110 
111 static gboolean
gimp_clone_start(GimpPaintCore * paint_core,GimpDrawable * drawable,GimpPaintOptions * paint_options,const GimpCoords * coords,GError ** error)112 gimp_clone_start (GimpPaintCore     *paint_core,
113                   GimpDrawable      *drawable,
114                   GimpPaintOptions  *paint_options,
115                   const GimpCoords  *coords,
116                   GError           **error)
117 {
118   GimpCloneOptions *options = GIMP_CLONE_OPTIONS (paint_options);
119 
120   if (! GIMP_PAINT_CORE_CLASS (parent_class)->start (paint_core, drawable,
121                                                      paint_options, coords,
122                                                      error))
123     {
124       return FALSE;
125     }
126 
127   if (options->clone_type == GIMP_CLONE_PATTERN)
128     {
129       if (! gimp_context_get_pattern (GIMP_CONTEXT (options)))
130         {
131           g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
132                                _("No patterns available for use with this tool."));
133           return FALSE;
134         }
135     }
136 
137   return TRUE;
138 }
139 
140 static void
gimp_clone_motion(GimpSourceCore * source_core,GimpDrawable * drawable,GimpPaintOptions * paint_options,const GimpCoords * coords,GeglNode * op,gdouble opacity,GimpPickable * src_pickable,GeglBuffer * src_buffer,GeglRectangle * src_rect,gint src_offset_x,gint src_offset_y,GeglBuffer * paint_buffer,gint paint_buffer_x,gint paint_buffer_y,gint paint_area_offset_x,gint paint_area_offset_y,gint paint_area_width,gint paint_area_height)141 gimp_clone_motion (GimpSourceCore   *source_core,
142                    GimpDrawable     *drawable,
143                    GimpPaintOptions *paint_options,
144                    const GimpCoords *coords,
145                    GeglNode         *op,
146                    gdouble           opacity,
147                    GimpPickable     *src_pickable,
148                    GeglBuffer       *src_buffer,
149                    GeglRectangle    *src_rect,
150                    gint              src_offset_x,
151                    gint              src_offset_y,
152                    GeglBuffer       *paint_buffer,
153                    gint              paint_buffer_x,
154                    gint              paint_buffer_y,
155                    gint              paint_area_offset_x,
156                    gint              paint_area_offset_y,
157                    gint              paint_area_width,
158                    gint              paint_area_height)
159 {
160   GimpPaintCore     *paint_core     = GIMP_PAINT_CORE (source_core);
161   GimpBrushCore     *brush_core     = GIMP_BRUSH_CORE (source_core);
162   GimpCloneOptions  *options        = GIMP_CLONE_OPTIONS (paint_options);
163   GimpSourceOptions *source_options = GIMP_SOURCE_OPTIONS (paint_options);
164   GimpContext       *context        = GIMP_CONTEXT (paint_options);
165   GimpDynamics      *dynamics       = brush_core->dynamics;
166   GimpImage         *image          = gimp_item_get_image (GIMP_ITEM (drawable));
167   gdouble            fade_point;
168   gdouble            force;
169 
170   if (gimp_source_core_use_source (source_core, source_options))
171     {
172       if (! op)
173         {
174           gimp_gegl_buffer_copy (src_buffer,
175                                  GEGL_RECTANGLE (src_rect->x,
176                                                  src_rect->y,
177                                                  paint_area_width,
178                                                  paint_area_height),
179                                  GEGL_ABYSS_NONE,
180                                  paint_buffer,
181                                  GEGL_RECTANGLE (paint_area_offset_x,
182                                                  paint_area_offset_y,
183                                                  0, 0));
184         }
185       else
186         {
187           gimp_gegl_apply_operation (src_buffer, NULL, NULL, op,
188                                      paint_buffer,
189                                      GEGL_RECTANGLE (paint_area_offset_x,
190                                                      paint_area_offset_y,
191                                                      paint_area_width,
192                                                      paint_area_height),
193                                      FALSE);
194         }
195     }
196   else if (options->clone_type == GIMP_CLONE_PATTERN)
197     {
198       GimpPattern *pattern    = gimp_context_get_pattern (context);
199       GeglBuffer  *src_buffer = gimp_pattern_create_buffer (pattern);
200 
201       src_offset_x += gegl_buffer_get_width (src_buffer) / 2;
202       src_offset_y += gegl_buffer_get_height (src_buffer) / 2;
203 
204       gegl_buffer_set_pattern (paint_buffer,
205                                GEGL_RECTANGLE (paint_area_offset_x,
206                                                paint_area_offset_y,
207                                                paint_area_width,
208                                                paint_area_height),
209                                src_buffer,
210                                - paint_buffer_x - src_offset_x,
211                                - paint_buffer_y - src_offset_y);
212 
213       g_object_unref (src_buffer);
214     }
215   else
216     {
217       g_return_if_reached ();
218     }
219 
220   fade_point = gimp_paint_options_get_fade (paint_options, image,
221                                             paint_core->pixel_dist);
222 
223   if (gimp_dynamics_is_output_enabled (dynamics, GIMP_DYNAMICS_OUTPUT_FORCE))
224     force = gimp_dynamics_get_linear_value (dynamics,
225                                             GIMP_DYNAMICS_OUTPUT_FORCE,
226                                             coords,
227                                             paint_options,
228                                             fade_point);
229   else
230     force = paint_options->brush_force;
231 
232   gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable,
233                                 coords,
234                                 MIN (opacity, GIMP_OPACITY_OPAQUE),
235                                 gimp_context_get_opacity (context),
236                                 gimp_context_get_paint_mode (context),
237                                 gimp_paint_options_get_brush_mode (paint_options),
238                                 force,
239 
240                                 /* In fixed mode, paint incremental so the
241                                  * individual brushes are properly applied
242                                  * on top of each other.
243                                  * Otherwise the stuff we paint is seamless
244                                  * and we don't need intermediate masking.
245                                  */
246                                 source_options->align_mode ==
247                                 GIMP_SOURCE_ALIGN_FIXED ?
248                                 GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT);
249 }
250 
251 static gboolean
gimp_clone_use_source(GimpSourceCore * source_core,GimpSourceOptions * options)252 gimp_clone_use_source (GimpSourceCore    *source_core,
253                        GimpSourceOptions *options)
254 {
255   return GIMP_CLONE_OPTIONS (options)->clone_type == GIMP_CLONE_IMAGE;
256 }
257