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 <string.h>
21
22 #include <gdk-pixbuf/gdk-pixbuf.h>
23 #include <gegl.h>
24
25 #include "libgimpmath/gimpmath.h"
26
27 #include "paint-types.h"
28
29 #include "operations/layer-modes/gimp-layer-modes.h"
30
31 #include "gegl/gimp-babl.h"
32 #include "gegl/gimp-gegl-loops.h"
33
34 #include "core/gimpbrush-header.h"
35 #include "core/gimpbrushgenerated.h"
36 #include "core/gimpdrawable.h"
37 #include "core/gimpdynamics.h"
38 #include "core/gimpdynamicsoutput.h"
39 #include "core/gimperror.h"
40 #include "core/gimpimage.h"
41 #include "core/gimpmarshal.h"
42 #include "core/gimpsymmetry.h"
43 #include "core/gimptempbuf.h"
44
45 #include "gimpbrushcore.h"
46 #include "gimpbrushcore-loops.h"
47 #include "gimpbrushcore-kernels.h"
48
49 #include "gimppaintoptions.h"
50
51 #include "gimp-intl.h"
52
53
54 #define EPSILON 0.00001
55
56 enum
57 {
58 SET_BRUSH,
59 SET_DYNAMICS,
60 LAST_SIGNAL
61 };
62
63
64 /* local function prototypes */
65
66 static void gimp_brush_core_finalize (GObject *object);
67
68 static gboolean gimp_brush_core_start (GimpPaintCore *core,
69 GimpDrawable *drawable,
70 GimpPaintOptions *paint_options,
71 const GimpCoords *coords,
72 GError **error);
73 static gboolean gimp_brush_core_pre_paint (GimpPaintCore *core,
74 GimpDrawable *drawable,
75 GimpPaintOptions *paint_options,
76 GimpPaintState paint_state,
77 guint32 time);
78 static void gimp_brush_core_post_paint (GimpPaintCore *core,
79 GimpDrawable *drawable,
80 GimpPaintOptions *paint_options,
81 GimpPaintState paint_state,
82 guint32 time);
83 static void gimp_brush_core_interpolate (GimpPaintCore *core,
84 GimpDrawable *drawable,
85 GimpPaintOptions *paint_options,
86 guint32 time);
87
88 static GeglBuffer * gimp_brush_core_get_paint_buffer(GimpPaintCore *paint_core,
89 GimpDrawable *drawable,
90 GimpPaintOptions *paint_options,
91 GimpLayerMode paint_mode,
92 const GimpCoords *coords,
93 gint *paint_buffer_x,
94 gint *paint_buffer_y,
95 gint *paint_width,
96 gint *paint_height);
97
98 static void gimp_brush_core_real_set_brush (GimpBrushCore *core,
99 GimpBrush *brush);
100 static void gimp_brush_core_real_set_dynamics (GimpBrushCore *core,
101 GimpDynamics *dynamics);
102
103 static gdouble gimp_brush_core_get_angle (GimpBrushCore *core);
104 static gboolean gimp_brush_core_get_reflect (GimpBrushCore *core);
105
106 static const GimpTempBuf *
107 gimp_brush_core_transform_mask (GimpBrushCore *core,
108 GimpBrush *brush);
109
110 static void gimp_brush_core_invalidate_cache (GimpBrush *brush,
111 GimpBrushCore *core);
112
113
114 G_DEFINE_TYPE (GimpBrushCore, gimp_brush_core, GIMP_TYPE_PAINT_CORE)
115
116 #define parent_class gimp_brush_core_parent_class
117
118 static guint core_signals[LAST_SIGNAL] = { 0, };
119
120
121 static void
gimp_brush_core_class_init(GimpBrushCoreClass * klass)122 gimp_brush_core_class_init (GimpBrushCoreClass *klass)
123 {
124 GObjectClass *object_class = G_OBJECT_CLASS (klass);
125 GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass);
126
127 core_signals[SET_BRUSH] =
128 g_signal_new ("set-brush",
129 G_TYPE_FROM_CLASS (klass),
130 G_SIGNAL_RUN_LAST,
131 G_STRUCT_OFFSET (GimpBrushCoreClass, set_brush),
132 NULL, NULL,
133 gimp_marshal_VOID__OBJECT,
134 G_TYPE_NONE, 1,
135 GIMP_TYPE_BRUSH);
136
137 core_signals[SET_DYNAMICS] =
138 g_signal_new ("set-dynamics",
139 G_TYPE_FROM_CLASS (klass),
140 G_SIGNAL_RUN_LAST,
141 G_STRUCT_OFFSET (GimpBrushCoreClass, set_dynamics),
142 NULL, NULL,
143 gimp_marshal_VOID__OBJECT,
144 G_TYPE_NONE, 1,
145 GIMP_TYPE_DYNAMICS);
146
147 object_class->finalize = gimp_brush_core_finalize;
148
149 paint_core_class->start = gimp_brush_core_start;
150 paint_core_class->pre_paint = gimp_brush_core_pre_paint;
151 paint_core_class->post_paint = gimp_brush_core_post_paint;
152 paint_core_class->interpolate = gimp_brush_core_interpolate;
153 paint_core_class->get_paint_buffer = gimp_brush_core_get_paint_buffer;
154
155 klass->handles_changing_brush = FALSE;
156 klass->handles_transforming_brush = TRUE;
157 klass->handles_dynamic_transforming_brush = TRUE;
158
159 klass->set_brush = gimp_brush_core_real_set_brush;
160 klass->set_dynamics = gimp_brush_core_real_set_dynamics;
161 }
162
163 static void
gimp_brush_core_init(GimpBrushCore * core)164 gimp_brush_core_init (GimpBrushCore *core)
165 {
166 gint i, j;
167
168 core->main_brush = NULL;
169 core->brush = NULL;
170 core->dynamics = NULL;
171 core->spacing = 1.0;
172 core->scale = 1.0;
173 core->angle = 0.0;
174 core->reflect = FALSE;
175 core->hardness = 1.0;
176 core->aspect_ratio = 0.0;
177
178 core->symmetry_angle = 0.0;
179 core->symmetry_reflect = FALSE;
180
181 core->pressure_brush = NULL;
182
183 core->last_solid_brush_mask = NULL;
184 core->solid_cache_invalid = FALSE;
185
186 core->transform_brush = NULL;
187 core->transform_pixmap = NULL;
188
189 core->last_subsample_brush_mask = NULL;
190 core->subsample_cache_invalid = FALSE;
191
192 core->rand = g_rand_new ();
193
194 for (i = 0; i < BRUSH_CORE_SOLID_SUBSAMPLE; i++)
195 {
196 for (j = 0; j < BRUSH_CORE_SOLID_SUBSAMPLE; j++)
197 {
198 core->solid_brushes[i][j] = NULL;
199 }
200 }
201
202 for (i = 0; i < BRUSH_CORE_JITTER_LUTSIZE - 1; ++i)
203 {
204 core->jitter_lut_y[i] = cos (gimp_deg_to_rad (i * 360 /
205 BRUSH_CORE_JITTER_LUTSIZE));
206 core->jitter_lut_x[i] = sin (gimp_deg_to_rad (i * 360 /
207 BRUSH_CORE_JITTER_LUTSIZE));
208 }
209
210 gimp_assert (BRUSH_CORE_SUBSAMPLE == KERNEL_SUBSAMPLE);
211
212 for (i = 0; i < KERNEL_SUBSAMPLE + 1; i++)
213 {
214 for (j = 0; j < KERNEL_SUBSAMPLE + 1; j++)
215 {
216 core->subsample_brushes[i][j] = NULL;
217 }
218 }
219 }
220
221 static void
gimp_brush_core_finalize(GObject * object)222 gimp_brush_core_finalize (GObject *object)
223 {
224 GimpBrushCore *core = GIMP_BRUSH_CORE (object);
225 gint i, j;
226
227 g_clear_pointer (&core->pressure_brush, gimp_temp_buf_unref);
228
229 for (i = 0; i < BRUSH_CORE_SOLID_SUBSAMPLE; i++)
230 for (j = 0; j < BRUSH_CORE_SOLID_SUBSAMPLE; j++)
231 g_clear_pointer (&core->solid_brushes[i][j], gimp_temp_buf_unref);
232
233 g_clear_pointer (&core->rand, g_rand_free);
234
235 for (i = 0; i < KERNEL_SUBSAMPLE + 1; i++)
236 for (j = 0; j < KERNEL_SUBSAMPLE + 1; j++)
237 g_clear_pointer (&core->subsample_brushes[i][j], gimp_temp_buf_unref);
238
239 if (core->main_brush)
240 {
241 g_signal_handlers_disconnect_by_func (core->main_brush,
242 gimp_brush_core_invalidate_cache,
243 core);
244 gimp_brush_end_use (core->main_brush);
245 g_clear_object (&core->main_brush);
246 }
247
248 g_clear_object (&core->dynamics);
249
250 G_OBJECT_CLASS (parent_class)->finalize (object);
251 }
252
253 static gboolean
gimp_brush_core_pre_paint(GimpPaintCore * paint_core,GimpDrawable * drawable,GimpPaintOptions * paint_options,GimpPaintState paint_state,guint32 time)254 gimp_brush_core_pre_paint (GimpPaintCore *paint_core,
255 GimpDrawable *drawable,
256 GimpPaintOptions *paint_options,
257 GimpPaintState paint_state,
258 guint32 time)
259 {
260 GimpBrushCore *core = GIMP_BRUSH_CORE (paint_core);
261
262 if (paint_state == GIMP_PAINT_STATE_MOTION)
263 {
264 GimpCoords last_coords;
265 GimpCoords current_coords;
266 gdouble scale;
267
268 gimp_paint_core_get_last_coords (paint_core, &last_coords);
269 gimp_paint_core_get_current_coords (paint_core, ¤t_coords);
270
271 /* If we current point == last point, check if the brush
272 * wants to be painted in that case. (Direction dependent
273 * pixmap brush pipes don't, as they don't know which
274 * pixmap to select.)
275 */
276 if (last_coords.x == current_coords.x &&
277 last_coords.y == current_coords.y &&
278 ! gimp_brush_want_null_motion (core->main_brush,
279 &last_coords,
280 ¤t_coords))
281 {
282 return FALSE;
283 }
284 /*No drawing anything if the scale is too small*/
285 if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_transforming_brush)
286 {
287 GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
288 gdouble fade_point;
289
290 if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_dynamic_transforming_brush)
291 {
292 gdouble width;
293 gdouble height;
294
295 fade_point = gimp_paint_options_get_fade (paint_options, image,
296 paint_core->pixel_dist);
297 width = gimp_brush_get_width (core->main_brush);
298 height = gimp_brush_get_height (core->main_brush);
299
300 scale = paint_options->brush_size /
301 MAX (width, height) *
302 gimp_dynamics_get_linear_value (core->dynamics,
303 GIMP_DYNAMICS_OUTPUT_SIZE,
304 ¤t_coords,
305 paint_options,
306 fade_point);
307
308 if (paint_options->brush_lock_to_view &&
309 MAX (current_coords.xscale, current_coords.yscale) > 0)
310 {
311 scale /= MAX (current_coords.xscale, current_coords.yscale);
312
313 /* Cap transform result for brushes or OOM can occur */
314 if ((scale * MAX (width, height)) > GIMP_BRUSH_MAX_SIZE)
315 {
316 scale = GIMP_BRUSH_MAX_SIZE / MAX (width, height);
317 }
318 }
319
320 if (scale < 0.0000001)
321 return FALSE;
322 }
323 }
324
325 if (GIMP_BRUSH_CORE_GET_CLASS (paint_core)->handles_changing_brush)
326 {
327 core->brush = gimp_brush_select_brush (core->main_brush,
328 &last_coords,
329 ¤t_coords);
330 }
331 if ((! GIMP_IS_BRUSH_GENERATED(core->main_brush)) &&
332 (paint_options->brush_hardness != gimp_brush_get_blur_hardness(core->main_brush)))
333 {
334 gimp_brush_flush_blur_caches(core->main_brush);
335 }
336 }
337
338 return TRUE;
339 }
340
341 static void
gimp_brush_core_post_paint(GimpPaintCore * paint_core,GimpDrawable * drawable,GimpPaintOptions * paint_options,GimpPaintState paint_state,guint32 time)342 gimp_brush_core_post_paint (GimpPaintCore *paint_core,
343 GimpDrawable *drawable,
344 GimpPaintOptions *paint_options,
345 GimpPaintState paint_state,
346 guint32 time)
347 {
348 GimpBrushCore *core = GIMP_BRUSH_CORE (paint_core);
349
350 if (paint_state == GIMP_PAINT_STATE_MOTION)
351 {
352 core->brush = core->main_brush;
353 }
354 }
355
356 static gboolean
gimp_brush_core_start(GimpPaintCore * paint_core,GimpDrawable * drawable,GimpPaintOptions * paint_options,const GimpCoords * coords,GError ** error)357 gimp_brush_core_start (GimpPaintCore *paint_core,
358 GimpDrawable *drawable,
359 GimpPaintOptions *paint_options,
360 const GimpCoords *coords,
361 GError **error)
362 {
363 GimpBrushCore *core = GIMP_BRUSH_CORE (paint_core);
364 GimpContext *context = GIMP_CONTEXT (paint_options);
365
366 gimp_brush_core_set_brush (core, gimp_context_get_brush (context));
367
368 gimp_brush_core_set_dynamics (core, gimp_context_get_dynamics (context));
369
370 if (! core->main_brush)
371 {
372 g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
373 _("No brushes available for use with this tool."));
374 return FALSE;
375 }
376
377 if (! core->dynamics)
378 {
379 g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
380 _("No paint dynamics available for use with this tool."));
381 return FALSE;
382 }
383
384 if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_transforming_brush)
385 {
386 gimp_brush_core_eval_transform_dynamics (core,
387 drawable,
388 paint_options,
389 coords);
390
391 gimp_brush_core_eval_transform_symmetry (core, NULL, 0);
392 }
393
394 core->spacing = paint_options->brush_spacing;
395
396 core->brush = core->main_brush;
397
398 core->jitter =
399 gimp_paint_options_get_jitter (paint_options,
400 gimp_item_get_image (GIMP_ITEM (drawable)));
401
402 return TRUE;
403 }
404
405 /**
406 * gimp_avoid_exact_integer
407 * @x: points to a gdouble
408 *
409 * Adjusts *x such that it is not too close to an integer. This is used
410 * for decision algorithms that would be vulnerable to rounding glitches
411 * if exact integers were input.
412 *
413 * Side effects: Changes the value of *x
414 **/
415 static void
gimp_avoid_exact_integer(gdouble * x)416 gimp_avoid_exact_integer (gdouble *x)
417 {
418 const gdouble integral = floor (*x);
419 const gdouble fractional = *x - integral;
420
421 if (fractional < EPSILON)
422 {
423 *x = integral + EPSILON;
424 }
425 else if (fractional > (1 -EPSILON))
426 {
427 *x = integral + (1 - EPSILON);
428 }
429 }
430
431 static void
gimp_brush_core_interpolate(GimpPaintCore * paint_core,GimpDrawable * drawable,GimpPaintOptions * paint_options,guint32 time)432 gimp_brush_core_interpolate (GimpPaintCore *paint_core,
433 GimpDrawable *drawable,
434 GimpPaintOptions *paint_options,
435 guint32 time)
436 {
437 GimpBrushCore *core = GIMP_BRUSH_CORE (paint_core);
438 GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
439 GimpDynamicsOutput *spacing_output;
440 GimpCoords last_coords;
441 GimpCoords current_coords;
442 GimpVector2 delta_vec;
443 gdouble delta_pressure;
444 gdouble delta_xtilt, delta_ytilt;
445 gdouble delta_wheel;
446 gdouble delta_velocity;
447 gdouble temp_direction;
448 GimpVector2 temp_vec;
449 gint n, num_points;
450 gdouble t0, dt, tn;
451 gdouble st_factor, st_offset;
452 gdouble initial;
453 gdouble dist;
454 gdouble total;
455 gdouble pixel_dist;
456 gdouble pixel_initial;
457 gdouble xd, yd;
458 gdouble mag;
459 gdouble dyn_spacing = core->spacing;
460 gdouble fade_point;
461 gboolean use_dyn_spacing;
462
463 g_return_if_fail (GIMP_IS_BRUSH (core->brush));
464
465 gimp_paint_core_get_last_coords (paint_core, &last_coords);
466 gimp_paint_core_get_current_coords (paint_core, ¤t_coords);
467
468 gimp_avoid_exact_integer (&last_coords.x);
469 gimp_avoid_exact_integer (&last_coords.y);
470 gimp_avoid_exact_integer (¤t_coords.x);
471 gimp_avoid_exact_integer (¤t_coords.y);
472
473 delta_vec.x = current_coords.x - last_coords.x;
474 delta_vec.y = current_coords.y - last_coords.y;
475 delta_pressure = current_coords.pressure - last_coords.pressure;
476 delta_xtilt = current_coords.xtilt - last_coords.xtilt;
477 delta_ytilt = current_coords.ytilt - last_coords.ytilt;
478 delta_wheel = current_coords.wheel - last_coords.wheel;
479 delta_velocity = current_coords.velocity - last_coords.velocity;
480 temp_direction = current_coords.direction;
481
482 /* return if there has been no motion */
483 if (! delta_vec.x &&
484 ! delta_vec.y &&
485 ! delta_pressure &&
486 ! delta_xtilt &&
487 ! delta_ytilt &&
488 ! delta_wheel &&
489 ! delta_velocity)
490 return;
491
492 pixel_dist = gimp_vector2_length (&delta_vec);
493 pixel_initial = paint_core->pixel_dist;
494
495 /* Zero sized brushes are unfit for interpolate, so we just let
496 * paint core fail on its own
497 */
498 if (core->scale == 0.0)
499 {
500 gimp_paint_core_set_last_coords (paint_core, ¤t_coords);
501
502 gimp_paint_core_paint (paint_core, drawable, paint_options,
503 GIMP_PAINT_STATE_MOTION, time);
504
505 paint_core->pixel_dist = pixel_initial + pixel_dist; /* Don't forget to update pixel distance*/
506
507 return;
508 }
509
510 /* Handle dynamic spacing */
511 spacing_output = gimp_dynamics_get_output (core->dynamics,
512 GIMP_DYNAMICS_OUTPUT_SPACING);
513
514 fade_point = gimp_paint_options_get_fade (paint_options, image,
515 paint_core->pixel_dist);
516
517 use_dyn_spacing = gimp_dynamics_output_is_enabled (spacing_output);
518
519 if (use_dyn_spacing)
520 {
521 dyn_spacing = gimp_dynamics_output_get_linear_value (spacing_output,
522 ¤t_coords,
523 paint_options,
524 fade_point);
525
526 /* Dynamic spacing assumes that the value set in core is the min
527 * value and the max is full 200% spacing. This approach differs
528 * from the usual factor from user input approach because making
529 * spacing smaller than the nominal value is unlikely and
530 * spacing has a hard defined max.
531 */
532 dyn_spacing = (core->spacing +
533 ((2.0 - core->spacing) * (1.0 - dyn_spacing)));
534
535 /* Limiting spacing to minimum 1% */
536 dyn_spacing = MAX (core->spacing, dyn_spacing);
537 }
538
539 /* calculate the distance traveled in the coordinate space of the brush */
540 temp_vec = gimp_brush_get_x_axis (core->brush);
541 gimp_vector2_mul (&temp_vec, core->scale);
542 gimp_vector2_rotate (&temp_vec, core->angle * G_PI * 2);
543
544 mag = gimp_vector2_length (&temp_vec);
545 xd = gimp_vector2_inner_product (&delta_vec, &temp_vec) / (mag * mag);
546
547 temp_vec = gimp_brush_get_y_axis (core->brush);
548 gimp_vector2_mul (&temp_vec, core->scale);
549 gimp_vector2_rotate (&temp_vec, core->angle * G_PI * 2);
550
551 mag = gimp_vector2_length (&temp_vec);
552 yd = gimp_vector2_inner_product (&delta_vec, &temp_vec) / (mag * mag);
553
554 dist = 0.5 * sqrt (xd * xd + yd * yd);
555 total = dist + paint_core->distance;
556 initial = paint_core->distance;
557
558
559 if (delta_vec.x * delta_vec.x > delta_vec.y * delta_vec.y)
560 {
561 st_factor = delta_vec.x;
562 st_offset = last_coords.x - 0.5;
563 }
564 else
565 {
566 st_factor = delta_vec.y;
567 st_offset = last_coords.y - 0.5;
568 }
569
570 if (use_dyn_spacing)
571 {
572 gint s0;
573
574 num_points = dist / dyn_spacing;
575
576 s0 = (gint) floor (st_offset + 0.5);
577 t0 = (s0 - st_offset) / st_factor;
578 dt = dyn_spacing / dist;
579
580 if (num_points == 0)
581 return;
582 }
583 else if (fabs (st_factor) > dist / core->spacing)
584 {
585 /* The stripe principle leads to brush positions that are spaced
586 * *closer* than the official brush spacing. Use the official
587 * spacing instead. This is the common case when the brush spacing
588 * is large.
589 * The net effect is then to put a lower bound on the spacing, but
590 * one that varies with the slope of the line. This is suppose to
591 * make thin lines (say, with a 1x1 brush) prettier while leaving
592 * lines with larger brush spacing as they used to look in 1.2.x.
593 */
594
595 dt = core->spacing / dist;
596 n = (gint) (initial / core->spacing + 1.0 + EPSILON);
597 t0 = (n * core->spacing - initial) / dist;
598 num_points = 1 + (gint) floor ((1 + EPSILON - t0) / dt);
599
600 /* if we arnt going to paint anything this time and the brush
601 * has only moved on one axis return without updating the brush
602 * position, distance etc. so that we can more accurately space
603 * brush strokes when curves are supplied to us in single pixel
604 * chunks.
605 */
606
607 if (num_points == 0 && (delta_vec.x == 0 || delta_vec.y == 0))
608 return;
609 }
610 else if (fabs (st_factor) < EPSILON)
611 {
612 /* Hm, we've hardly moved at all. Don't draw anything, but reset the
613 * old coordinates and hope we've gone longer the next time...
614 */
615 current_coords.x = last_coords.x;
616 current_coords.y = last_coords.y;
617
618 gimp_paint_core_set_current_coords (paint_core, ¤t_coords);
619
620 /* ... but go along with the current pressure, tilt and wheel */
621 return;
622 }
623 else
624 {
625 gint direction = st_factor > 0 ? 1 : -1;
626 gint x, y;
627 gint s0, sn;
628
629 /* Choose the first and last stripe to paint.
630 * FIRST PRIORITY is to avoid gaps painting with a 1x1 aliasing
631 * brush when a horizontalish line segment follows a verticalish
632 * one or vice versa - no matter what the angle between the two
633 * lines is. This will also limit the local thinning that a 1x1
634 * subsampled brush may suffer in the same situation.
635 * SECOND PRIORITY is to avoid making free-hand drawings
636 * unpleasantly fat by plotting redundant points.
637 * These are achieved by the following rules, but it is a little
638 * tricky to see just why. Do not change this algorithm unless you
639 * are sure you know what you're doing!
640 */
641
642 /* Basic case: round the beginning and ending point to nearest
643 * stripe center.
644 */
645 s0 = (gint) floor (st_offset + 0.5);
646 sn = (gint) floor (st_offset + st_factor + 0.5);
647
648 t0 = (s0 - st_offset) / st_factor;
649 tn = (sn - st_offset) / st_factor;
650
651 x = (gint) floor (last_coords.x + t0 * delta_vec.x);
652 y = (gint) floor (last_coords.y + t0 * delta_vec.y);
653
654 if (t0 < 0.0 && !( x == (gint) floor (last_coords.x) &&
655 y == (gint) floor (last_coords.y) ))
656 {
657 /* Exception A: If the first stripe's brush position is
658 * EXTRApolated into a different pixel square than the
659 * ideal starting point, don't plot it.
660 */
661 s0 += direction;
662 }
663 else if (x == (gint) floor (paint_core->last_paint.x) &&
664 y == (gint) floor (paint_core->last_paint.y))
665 {
666 /* Exception B: If first stripe's brush position is within the
667 * same pixel square as the last plot of the previous line,
668 * don't plot it either.
669 */
670 s0 += direction;
671 }
672
673 x = (gint) floor (last_coords.x + tn * delta_vec.x);
674 y = (gint) floor (last_coords.y + tn * delta_vec.y);
675
676 if (tn > 1.0 && !( x == (gint) floor (current_coords.x) &&
677 y == (gint) floor (current_coords.y)))
678 {
679 /* Exception C: If the last stripe's brush position is
680 * EXTRApolated into a different pixel square than the
681 * ideal ending point, don't plot it.
682 */
683 sn -= direction;
684 }
685
686 t0 = (s0 - st_offset) / st_factor;
687 tn = (sn - st_offset) / st_factor;
688 dt = direction * 1.0 / st_factor;
689 num_points = 1 + direction * (sn - s0);
690
691 if (num_points >= 1)
692 {
693 /* Hack the reported total distance such that it looks to the
694 * next line as if the the last pixel plotted were at an integer
695 * multiple of the brush spacing. This helps prevent artifacts
696 * for connected lines when the brush spacing is such that some
697 * slopes will use the stripe regime and other slopes will use
698 * the nominal brush spacing.
699 */
700
701 if (tn < 1)
702 total = initial + tn * dist;
703
704 total = core->spacing * (gint) (total / core->spacing + 0.5);
705 total += (1.0 - tn) * dist;
706 }
707 }
708
709 for (n = 0; n < num_points; n++)
710 {
711 gdouble t = t0 + n * dt;
712 gdouble p = (gdouble) n / num_points;
713
714 current_coords.x = last_coords.x + t * delta_vec.x;
715 current_coords.y = last_coords.y + t * delta_vec.y;
716 current_coords.pressure = last_coords.pressure + p * delta_pressure;
717 current_coords.xtilt = last_coords.xtilt + p * delta_xtilt;
718 current_coords.ytilt = last_coords.ytilt + p * delta_ytilt;
719 current_coords.wheel = last_coords.wheel + p * delta_wheel;
720 current_coords.velocity = last_coords.velocity + p * delta_velocity;
721 current_coords.direction = temp_direction;
722 current_coords.xscale = last_coords.xscale;
723 current_coords.yscale = last_coords.yscale;
724 current_coords.angle = last_coords.angle;
725 current_coords.reflect = last_coords.reflect;
726
727 if (core->jitter > 0.0)
728 {
729 GimpVector2 x_axis;
730 GimpVector2 y_axis;
731 gdouble dyn_jitter;
732 gdouble jitter_dist;
733 gint32 jitter_angle;
734
735 x_axis = gimp_brush_get_x_axis (core->brush);
736 y_axis = gimp_brush_get_y_axis (core->brush);
737
738 dyn_jitter = (core->jitter *
739 gimp_dynamics_get_linear_value (core->dynamics,
740 GIMP_DYNAMICS_OUTPUT_JITTER,
741 ¤t_coords,
742 paint_options,
743 fade_point));
744
745 jitter_dist = g_rand_double_range (core->rand, 0, dyn_jitter);
746 jitter_angle = g_rand_int_range (core->rand,
747 0, BRUSH_CORE_JITTER_LUTSIZE);
748
749 current_coords.x +=
750 (x_axis.x + y_axis.x) *
751 jitter_dist * core->jitter_lut_x[jitter_angle] * core->scale;
752
753 current_coords.y +=
754 (y_axis.y + x_axis.y) *
755 jitter_dist * core->jitter_lut_y[jitter_angle] * core->scale;
756 }
757
758 gimp_paint_core_set_current_coords (paint_core, ¤t_coords);
759
760 paint_core->distance = initial + t * dist;
761 paint_core->pixel_dist = pixel_initial + t * pixel_dist;
762
763 gimp_paint_core_paint (paint_core, drawable, paint_options,
764 GIMP_PAINT_STATE_MOTION, time);
765 }
766
767 current_coords.x = last_coords.x + delta_vec.x;
768 current_coords.y = last_coords.y + delta_vec.y;
769 current_coords.pressure = last_coords.pressure + delta_pressure;
770 current_coords.xtilt = last_coords.xtilt + delta_xtilt;
771 current_coords.ytilt = last_coords.ytilt + delta_ytilt;
772 current_coords.wheel = last_coords.wheel + delta_wheel;
773 current_coords.velocity = last_coords.velocity + delta_velocity;
774 current_coords.xscale = last_coords.xscale;
775 current_coords.yscale = last_coords.yscale;
776 current_coords.angle = last_coords.angle;
777 current_coords.reflect = last_coords.reflect;
778
779 gimp_paint_core_set_current_coords (paint_core, ¤t_coords);
780 gimp_paint_core_set_last_coords (paint_core, ¤t_coords);
781
782 paint_core->distance = total;
783 paint_core->pixel_dist = pixel_initial + pixel_dist;
784 }
785
786 static GeglBuffer *
gimp_brush_core_get_paint_buffer(GimpPaintCore * paint_core,GimpDrawable * drawable,GimpPaintOptions * paint_options,GimpLayerMode paint_mode,const GimpCoords * coords,gint * paint_buffer_x,gint * paint_buffer_y,gint * paint_width,gint * paint_height)787 gimp_brush_core_get_paint_buffer (GimpPaintCore *paint_core,
788 GimpDrawable *drawable,
789 GimpPaintOptions *paint_options,
790 GimpLayerMode paint_mode,
791 const GimpCoords *coords,
792 gint *paint_buffer_x,
793 gint *paint_buffer_y,
794 gint *paint_width,
795 gint *paint_height)
796 {
797 GimpBrushCore *core = GIMP_BRUSH_CORE (paint_core);
798 gint x, y;
799 gint x1, y1, x2, y2;
800 gint drawable_width, drawable_height;
801 gint brush_width, brush_height;
802
803 gimp_brush_transform_size (core->brush,
804 core->scale, core->aspect_ratio,
805 gimp_brush_core_get_angle (core),
806 gimp_brush_core_get_reflect (core),
807 &brush_width, &brush_height);
808
809 if (paint_width)
810 *paint_width = brush_width;
811 if (paint_height)
812 *paint_height = brush_height;
813
814 /* adjust the x and y coordinates to the upper left corner of the brush */
815 x = (gint) floor (coords->x) - (brush_width / 2);
816 y = (gint) floor (coords->y) - (brush_height / 2);
817
818 drawable_width = gimp_item_get_width (GIMP_ITEM (drawable));
819 drawable_height = gimp_item_get_height (GIMP_ITEM (drawable));
820
821 x1 = CLAMP (x - 1, 0, drawable_width);
822 y1 = CLAMP (y - 1, 0, drawable_height);
823 x2 = CLAMP (x + brush_width + 1, 0, drawable_width);
824 y2 = CLAMP (y + brush_height + 1, 0, drawable_height);
825
826 /* configure the canvas buffer */
827 if ((x2 - x1) && (y2 - y1))
828 {
829 GimpTempBuf *temp_buf;
830 const Babl *format;
831 GimpLayerCompositeMode composite_mode;
832
833 composite_mode = gimp_layer_mode_get_paint_composite_mode (paint_mode);
834
835 format = gimp_layer_mode_get_format (paint_mode,
836 GIMP_LAYER_COLOR_SPACE_AUTO,
837 GIMP_LAYER_COLOR_SPACE_AUTO,
838 composite_mode,
839 gimp_drawable_get_format (drawable));
840
841 if (paint_core->paint_buffer &&
842 gegl_buffer_get_width (paint_core->paint_buffer) == (x2 - x1) &&
843 gegl_buffer_get_height (paint_core->paint_buffer) == (y2 - y1) &&
844 gegl_buffer_get_format (paint_core->paint_buffer) == format)
845 {
846 *paint_buffer_x = x1;
847 *paint_buffer_y = y1;
848
849 return paint_core->paint_buffer;
850 }
851
852 g_clear_object (&paint_core->paint_buffer);
853
854 temp_buf = gimp_temp_buf_new ((x2 - x1), (y2 - y1),
855 format);
856
857 *paint_buffer_x = x1;
858 *paint_buffer_y = y1;
859
860 paint_core->paint_buffer = gimp_temp_buf_create_buffer (temp_buf);
861
862 gimp_temp_buf_unref (temp_buf);
863
864 return paint_core->paint_buffer;
865 }
866
867 return NULL;
868 }
869
870 static void
gimp_brush_core_real_set_brush(GimpBrushCore * core,GimpBrush * brush)871 gimp_brush_core_real_set_brush (GimpBrushCore *core,
872 GimpBrush *brush)
873 {
874 if (brush == core->main_brush)
875 return;
876
877 if (core->main_brush)
878 {
879 g_signal_handlers_disconnect_by_func (core->main_brush,
880 gimp_brush_core_invalidate_cache,
881 core);
882 gimp_brush_end_use (core->main_brush);
883 }
884
885 g_set_object (&core->main_brush, brush);
886
887 if (core->main_brush)
888 {
889 gimp_brush_begin_use (core->main_brush);
890 g_signal_connect (core->main_brush, "invalidate-preview",
891 G_CALLBACK (gimp_brush_core_invalidate_cache),
892 core);
893 }
894 }
895
896 static void
gimp_brush_core_real_set_dynamics(GimpBrushCore * core,GimpDynamics * dynamics)897 gimp_brush_core_real_set_dynamics (GimpBrushCore *core,
898 GimpDynamics *dynamics)
899 {
900 g_set_object (&core->dynamics, dynamics);
901 }
902
903 void
gimp_brush_core_set_brush(GimpBrushCore * core,GimpBrush * brush)904 gimp_brush_core_set_brush (GimpBrushCore *core,
905 GimpBrush *brush)
906 {
907 g_return_if_fail (GIMP_IS_BRUSH_CORE (core));
908 g_return_if_fail (brush == NULL || GIMP_IS_BRUSH (brush));
909
910 if (brush != core->main_brush)
911 g_signal_emit (core, core_signals[SET_BRUSH], 0, brush);
912 }
913
914 void
gimp_brush_core_set_dynamics(GimpBrushCore * core,GimpDynamics * dynamics)915 gimp_brush_core_set_dynamics (GimpBrushCore *core,
916 GimpDynamics *dynamics)
917 {
918 g_return_if_fail (GIMP_IS_BRUSH_CORE (core));
919 g_return_if_fail (dynamics == NULL || GIMP_IS_DYNAMICS (dynamics));
920
921 if (dynamics != core->dynamics)
922 g_signal_emit (core, core_signals[SET_DYNAMICS], 0, dynamics);
923 }
924
925 void
gimp_brush_core_paste_canvas(GimpBrushCore * core,GimpDrawable * drawable,const GimpCoords * coords,gdouble brush_opacity,gdouble image_opacity,GimpLayerMode paint_mode,GimpBrushApplicationMode brush_hardness,gdouble dynamic_force,GimpPaintApplicationMode mode)926 gimp_brush_core_paste_canvas (GimpBrushCore *core,
927 GimpDrawable *drawable,
928 const GimpCoords *coords,
929 gdouble brush_opacity,
930 gdouble image_opacity,
931 GimpLayerMode paint_mode,
932 GimpBrushApplicationMode brush_hardness,
933 gdouble dynamic_force,
934 GimpPaintApplicationMode mode)
935 {
936 const GimpTempBuf *brush_mask;
937
938 brush_mask = gimp_brush_core_get_brush_mask (core, coords,
939 brush_hardness,
940 dynamic_force);
941
942 if (brush_mask)
943 {
944 GimpPaintCore *paint_core = GIMP_PAINT_CORE (core);
945 gint x;
946 gint y;
947 gint off_x;
948 gint off_y;
949
950 x = (gint) floor (coords->x) - (gimp_temp_buf_get_width (brush_mask) >> 1);
951 y = (gint) floor (coords->y) - (gimp_temp_buf_get_height (brush_mask) >> 1);
952
953 off_x = (x < 0) ? -x : 0;
954 off_y = (y < 0) ? -y : 0;
955
956 gimp_paint_core_paste (paint_core, brush_mask,
957 off_x, off_y,
958 drawable,
959 brush_opacity,
960 image_opacity,
961 paint_mode,
962 mode);
963 }
964 }
965
966 /* Similar to gimp_brush_core_paste_canvas, but replaces the alpha channel
967 * rather than using it to composite (i.e. transparent over opaque
968 * becomes transparent rather than opauqe.
969 */
970 void
gimp_brush_core_replace_canvas(GimpBrushCore * core,GimpDrawable * drawable,const GimpCoords * coords,gdouble brush_opacity,gdouble image_opacity,GimpBrushApplicationMode brush_hardness,gdouble dynamic_force,GimpPaintApplicationMode mode)971 gimp_brush_core_replace_canvas (GimpBrushCore *core,
972 GimpDrawable *drawable,
973 const GimpCoords *coords,
974 gdouble brush_opacity,
975 gdouble image_opacity,
976 GimpBrushApplicationMode brush_hardness,
977 gdouble dynamic_force,
978 GimpPaintApplicationMode mode)
979 {
980 const GimpTempBuf *brush_mask;
981
982 brush_mask = gimp_brush_core_get_brush_mask (core, coords,
983 brush_hardness,
984 dynamic_force);
985
986 if (brush_mask)
987 {
988 GimpPaintCore *paint_core = GIMP_PAINT_CORE (core);
989 gint x;
990 gint y;
991 gint off_x;
992 gint off_y;
993
994 x = (gint) floor (coords->x) - (gimp_temp_buf_get_width (brush_mask) >> 1);
995 y = (gint) floor (coords->y) - (gimp_temp_buf_get_height (brush_mask) >> 1);
996
997 off_x = (x < 0) ? -x : 0;
998 off_y = (y < 0) ? -y : 0;
999
1000 gimp_paint_core_replace (paint_core, brush_mask,
1001 off_x, off_y,
1002 drawable,
1003 brush_opacity,
1004 image_opacity,
1005 mode);
1006 }
1007 }
1008
1009
1010 static void
gimp_brush_core_invalidate_cache(GimpBrush * brush,GimpBrushCore * core)1011 gimp_brush_core_invalidate_cache (GimpBrush *brush,
1012 GimpBrushCore *core)
1013 {
1014 /* Make sure we don't cache data for a brush that has changed */
1015
1016 core->subsample_cache_invalid = TRUE;
1017 core->solid_cache_invalid = TRUE;
1018
1019 /* Notify of the brush change */
1020
1021 g_signal_emit (core, core_signals[SET_BRUSH], 0, brush);
1022 }
1023
1024
1025 /************************************************************
1026 * LOCAL FUNCTION DEFINITIONS *
1027 ************************************************************/
1028
1029 static gdouble
gimp_brush_core_get_angle(GimpBrushCore * core)1030 gimp_brush_core_get_angle (GimpBrushCore *core)
1031 {
1032 gdouble angle = core->angle;
1033
1034 if (core->reflect)
1035 angle -= core->symmetry_angle;
1036 else
1037 angle += core->symmetry_angle;
1038
1039 angle = fmod (angle, 1.0);
1040
1041 if (angle < 0.0)
1042 angle += 1.0;
1043
1044 return angle;
1045 }
1046
1047 static gboolean
gimp_brush_core_get_reflect(GimpBrushCore * core)1048 gimp_brush_core_get_reflect (GimpBrushCore *core)
1049 {
1050 return core->reflect ^ core->symmetry_reflect;
1051 }
1052
1053 static const GimpTempBuf *
gimp_brush_core_transform_mask(GimpBrushCore * core,GimpBrush * brush)1054 gimp_brush_core_transform_mask (GimpBrushCore *core,
1055 GimpBrush *brush)
1056 {
1057 const GimpTempBuf *mask;
1058
1059 if (core->scale <= 0.0)
1060 return NULL;
1061
1062 mask = gimp_brush_transform_mask (brush,
1063 core->scale,
1064 core->aspect_ratio,
1065 gimp_brush_core_get_angle (core),
1066 gimp_brush_core_get_reflect (core),
1067 core->hardness);
1068
1069 if (mask == core->transform_brush)
1070 return mask;
1071
1072 core->transform_brush = mask;
1073 core->subsample_cache_invalid = TRUE;
1074 core->solid_cache_invalid = TRUE;
1075
1076 return core->transform_brush;
1077 }
1078
1079 const GimpTempBuf *
gimp_brush_core_get_brush_mask(GimpBrushCore * core,const GimpCoords * coords,GimpBrushApplicationMode brush_hardness,gdouble dynamic_force)1080 gimp_brush_core_get_brush_mask (GimpBrushCore *core,
1081 const GimpCoords *coords,
1082 GimpBrushApplicationMode brush_hardness,
1083 gdouble dynamic_force)
1084 {
1085 const GimpTempBuf *mask;
1086
1087 if (dynamic_force <= 0.0)
1088 return NULL;
1089
1090 mask = gimp_brush_core_transform_mask (core, core->brush);
1091
1092 if (! mask)
1093 return NULL;
1094
1095 switch (brush_hardness)
1096 {
1097 case GIMP_BRUSH_SOFT:
1098 return gimp_brush_core_subsample_mask (core, mask,
1099 coords->x,
1100 coords->y);
1101 break;
1102
1103 case GIMP_BRUSH_HARD:
1104 return gimp_brush_core_solidify_mask (core, mask,
1105 coords->x,
1106 coords->y);
1107 break;
1108
1109 case GIMP_BRUSH_PRESSURE:
1110 return gimp_brush_core_pressurize_mask (core, mask,
1111 coords->x,
1112 coords->y,
1113 dynamic_force);
1114 break;
1115 }
1116
1117 g_return_val_if_reached (NULL);
1118 }
1119
1120 const GimpTempBuf *
gimp_brush_core_get_brush_pixmap(GimpBrushCore * core)1121 gimp_brush_core_get_brush_pixmap (GimpBrushCore *core)
1122 {
1123 const GimpTempBuf *pixmap;
1124
1125 if (core->scale <= 0.0)
1126 return NULL;
1127
1128 pixmap = gimp_brush_transform_pixmap (core->brush,
1129 core->scale,
1130 core->aspect_ratio,
1131 gimp_brush_core_get_angle (core),
1132 gimp_brush_core_get_reflect (core),
1133 core->hardness);
1134
1135 if (pixmap == core->transform_pixmap)
1136 return pixmap;
1137
1138 core->transform_pixmap = pixmap;
1139 core->subsample_cache_invalid = TRUE;
1140
1141 return core->transform_pixmap;
1142 }
1143
1144 void
gimp_brush_core_eval_transform_dynamics(GimpBrushCore * core,GimpDrawable * drawable,GimpPaintOptions * paint_options,const GimpCoords * coords)1145 gimp_brush_core_eval_transform_dynamics (GimpBrushCore *core,
1146 GimpDrawable *drawable,
1147 GimpPaintOptions *paint_options,
1148 const GimpCoords *coords)
1149 {
1150 if (core->main_brush)
1151 {
1152 gdouble max_side;
1153
1154 max_side = MAX (gimp_brush_get_width (core->main_brush),
1155 gimp_brush_get_height (core->main_brush));
1156
1157 core->scale = paint_options->brush_size / max_side;
1158
1159 if (paint_options->brush_lock_to_view &&
1160 MAX (coords->xscale, coords->yscale) > 0)
1161 {
1162 core->scale /= MAX (coords->xscale, coords->yscale);
1163
1164 /* Cap transform result for brushes or OOM can occur */
1165 if ((core->scale * max_side) > GIMP_BRUSH_MAX_SIZE)
1166 {
1167 core->scale = GIMP_BRUSH_MAX_SIZE / max_side;
1168 }
1169 }
1170 }
1171 else
1172 core->scale = -1;
1173
1174 core->aspect_ratio = paint_options->brush_aspect_ratio;
1175 core->angle = paint_options->brush_angle;
1176 core->reflect = FALSE;
1177 core->hardness = paint_options->brush_hardness;
1178
1179 if (paint_options->brush_lock_to_view)
1180 {
1181 core->angle += coords->angle;
1182 core->reflect = coords->reflect;
1183 }
1184
1185 if (! GIMP_IS_DYNAMICS (core->dynamics))
1186 return;
1187
1188 if (GIMP_BRUSH_CORE_GET_CLASS (core)->handles_dynamic_transforming_brush)
1189 {
1190 gdouble fade_point = 1.0;
1191
1192 if (drawable)
1193 {
1194 GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
1195 GimpPaintCore *paint_core = GIMP_PAINT_CORE (core);
1196
1197 fade_point = gimp_paint_options_get_fade (paint_options, image,
1198 paint_core->pixel_dist);
1199 }
1200
1201 core->scale *= gimp_dynamics_get_linear_value (core->dynamics,
1202 GIMP_DYNAMICS_OUTPUT_SIZE,
1203 coords,
1204 paint_options,
1205 fade_point);
1206
1207 core->angle += gimp_dynamics_get_angular_value (core->dynamics,
1208 GIMP_DYNAMICS_OUTPUT_ANGLE,
1209 coords,
1210 paint_options,
1211 fade_point);
1212
1213 core->hardness *= gimp_dynamics_get_linear_value (core->dynamics,
1214 GIMP_DYNAMICS_OUTPUT_HARDNESS,
1215 coords,
1216 paint_options,
1217 fade_point);
1218
1219 if (gimp_dynamics_is_output_enabled (core->dynamics,
1220 GIMP_DYNAMICS_OUTPUT_ASPECT_RATIO))
1221 {
1222 gdouble dyn_aspect;
1223
1224 dyn_aspect = gimp_dynamics_get_aspect_value (core->dynamics,
1225 GIMP_DYNAMICS_OUTPUT_ASPECT_RATIO,
1226 coords,
1227 paint_options,
1228 fade_point);
1229
1230 /* Zero aspect ratio is special cased to half of all ar range,
1231 * to force dynamics to have any effect. Forcing to full results
1232 * in disappearing stamp if applied to maximum.
1233 */
1234 if (core->aspect_ratio == 0.0)
1235 core->aspect_ratio = 10.0 * dyn_aspect;
1236 else
1237 core->aspect_ratio *= dyn_aspect;
1238 }
1239 }
1240 }
1241
1242 void
gimp_brush_core_eval_transform_symmetry(GimpBrushCore * core,GimpSymmetry * symmetry,gint stroke)1243 gimp_brush_core_eval_transform_symmetry (GimpBrushCore *core,
1244 GimpSymmetry *symmetry,
1245 gint stroke)
1246 {
1247 g_return_if_fail (GIMP_IS_BRUSH_CORE (core));
1248 g_return_if_fail (symmetry == NULL || GIMP_IS_SYMMETRY (symmetry));
1249
1250 core->symmetry_angle = 0.0;
1251 core->symmetry_reflect = FALSE;
1252
1253 if (symmetry)
1254 {
1255 gimp_symmetry_get_transform (symmetry,
1256 stroke,
1257 &core->symmetry_angle,
1258 &core->symmetry_reflect);
1259
1260 core->symmetry_angle /= 360.0;
1261 }
1262 }
1263
1264 void
gimp_brush_core_color_area_with_pixmap(GimpBrushCore * core,GimpDrawable * drawable,const GimpCoords * coords,GeglBuffer * area,gint area_x,gint area_y,gboolean apply_mask)1265 gimp_brush_core_color_area_with_pixmap (GimpBrushCore *core,
1266 GimpDrawable *drawable,
1267 const GimpCoords *coords,
1268 GeglBuffer *area,
1269 gint area_x,
1270 gint area_y,
1271 gboolean apply_mask)
1272 {
1273 const GimpTempBuf *pixmap;
1274 GeglBuffer *pixmap_buffer;
1275 const GimpTempBuf *mask;
1276 GeglBuffer *mask_buffer;
1277 gint area_width;
1278 gint area_height;
1279 gint ul_x;
1280 gint ul_y;
1281 gint offset_x;
1282 gint offset_y;
1283
1284 g_return_if_fail (GIMP_IS_BRUSH (core->brush));
1285 g_return_if_fail (gimp_brush_get_pixmap (core->brush) != NULL);
1286
1287 /* scale the brush */
1288 pixmap = gimp_brush_core_get_brush_pixmap (core);
1289
1290 if (! pixmap)
1291 return;
1292
1293 if (apply_mask)
1294 mask = gimp_brush_core_transform_mask (core, core->brush);
1295 else
1296 mask = NULL;
1297
1298 /* Calculate upper left corner of brush as in
1299 * gimp_paint_core_get_paint_area. Ugly to have to do this here, too.
1300 */
1301 ul_x = (gint) floor (coords->x) - (gimp_temp_buf_get_width (pixmap) >> 1);
1302 ul_y = (gint) floor (coords->y) - (gimp_temp_buf_get_height (pixmap) >> 1);
1303
1304 /* Not sure why this is necessary, but empirically the code does
1305 * not work without it for even-sided brushes. See bug #166622.
1306 */
1307 if (gimp_temp_buf_get_width (pixmap) % 2 == 0)
1308 ul_x += ROUND (coords->x) - floor (coords->x);
1309 if (gimp_temp_buf_get_height (pixmap) % 2 == 0)
1310 ul_y += ROUND (coords->y) - floor (coords->y);
1311
1312 offset_x = area_x - ul_x;
1313 offset_y = area_y - ul_y;
1314
1315 area_width = gegl_buffer_get_width (area);
1316 area_height = gegl_buffer_get_height (area);
1317
1318 pixmap_buffer = gimp_temp_buf_create_buffer (pixmap);
1319
1320 gimp_gegl_buffer_copy (pixmap_buffer,
1321 GEGL_RECTANGLE (offset_x, offset_y,
1322 area_width, area_height),
1323 GEGL_ABYSS_NONE,
1324 area,
1325 GEGL_RECTANGLE (0, 0,
1326 area_width, area_height));
1327
1328 g_object_unref (pixmap_buffer);
1329
1330 if (mask)
1331 {
1332 mask_buffer = gimp_temp_buf_create_buffer (mask);
1333
1334 gimp_gegl_apply_mask (mask_buffer,
1335 GEGL_RECTANGLE (offset_x, offset_y,
1336 area_width, area_height),
1337 area,
1338 GEGL_RECTANGLE (0, 0,
1339 area_width, area_height),
1340 1.0);
1341
1342 g_object_unref (mask_buffer);
1343 }
1344 }
1345