1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpsymmetry-mirror.c
5 * Copyright (C) 2015 Jehan <jehan@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include <cairo.h>
26 #include <gegl.h>
27 #include <gdk-pixbuf/gdk-pixbuf.h>
28
29 #include "libgimpconfig/gimpconfig.h"
30
31 #include "core-types.h"
32
33 #include "gimp.h"
34 #include "gimp-cairo.h"
35 #include "gimpbrush.h"
36 #include "gimpguide.h"
37 #include "gimpimage.h"
38 #include "gimpimage-guides.h"
39 #include "gimpimage-symmetry.h"
40 #include "gimpitem.h"
41 #include "gimpsymmetry-mirror.h"
42
43 #include "gimp-intl.h"
44
45
46 enum
47 {
48 PROP_0,
49 PROP_HORIZONTAL_SYMMETRY,
50 PROP_VERTICAL_SYMMETRY,
51 PROP_POINT_SYMMETRY,
52 PROP_DISABLE_TRANSFORMATION,
53 PROP_MIRROR_POSITION_X,
54 PROP_MIRROR_POSITION_Y
55 };
56
57
58 /* Local function prototypes */
59
60 static void gimp_mirror_constructed (GObject *object);
61 static void gimp_mirror_finalize (GObject *object);
62 static void gimp_mirror_set_property (GObject *object,
63 guint property_id,
64 const GValue *value,
65 GParamSpec *pspec);
66 static void gimp_mirror_get_property (GObject *object,
67 guint property_id,
68 GValue *value,
69 GParamSpec *pspec);
70
71 static void gimp_mirror_update_strokes (GimpSymmetry *mirror,
72 GimpDrawable *drawable,
73 GimpCoords *origin);
74 static void gimp_mirror_get_transform (GimpSymmetry *mirror,
75 gint stroke,
76 gdouble *angle,
77 gboolean *reflect);
78 static void gimp_mirror_reset (GimpMirror *mirror);
79 static void gimp_mirror_add_guide (GimpMirror *mirror,
80 GimpOrientationType orientation);
81 static void gimp_mirror_remove_guide (GimpMirror *mirror,
82 GimpOrientationType orientation);
83 static void gimp_mirror_guide_removed_cb (GObject *object,
84 GimpMirror *mirror);
85 static void gimp_mirror_guide_position_cb (GObject *object,
86 GParamSpec *pspec,
87 GimpMirror *mirror);
88 static void gimp_mirror_active_changed (GimpSymmetry *sym);
89 static void gimp_mirror_set_horizontal_symmetry (GimpMirror *mirror,
90 gboolean active);
91 static void gimp_mirror_set_vertical_symmetry (GimpMirror *mirror,
92 gboolean active);
93 static void gimp_mirror_set_point_symmetry (GimpMirror *mirror,
94 gboolean active);
95
96 static void gimp_mirror_image_size_changed_cb (GimpImage *image,
97 gint previous_origin_x,
98 gint previous_origin_y,
99 gint previous_width,
100 gint previous_height,
101 GimpSymmetry *sym);
102
G_DEFINE_TYPE(GimpMirror,gimp_mirror,GIMP_TYPE_SYMMETRY)103 G_DEFINE_TYPE (GimpMirror, gimp_mirror, GIMP_TYPE_SYMMETRY)
104
105 #define parent_class gimp_mirror_parent_class
106
107
108 static void
109 gimp_mirror_class_init (GimpMirrorClass *klass)
110 {
111 GObjectClass *object_class = G_OBJECT_CLASS (klass);
112 GimpSymmetryClass *symmetry_class = GIMP_SYMMETRY_CLASS (klass);
113 GParamSpec *pspec;
114
115 object_class->constructed = gimp_mirror_constructed;
116 object_class->finalize = gimp_mirror_finalize;
117 object_class->set_property = gimp_mirror_set_property;
118 object_class->get_property = gimp_mirror_get_property;
119
120 symmetry_class->label = _("Mirror");
121 symmetry_class->update_strokes = gimp_mirror_update_strokes;
122 symmetry_class->get_transform = gimp_mirror_get_transform;
123 symmetry_class->active_changed = gimp_mirror_active_changed;
124
125 GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_HORIZONTAL_SYMMETRY,
126 "horizontal-symmetry",
127 _("Horizontal Symmetry"),
128 _("Reflect the initial stroke across a horizontal axis"),
129 FALSE,
130 GIMP_PARAM_STATIC_STRINGS |
131 GIMP_SYMMETRY_PARAM_GUI);
132
133 GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_VERTICAL_SYMMETRY,
134 "vertical-symmetry",
135 _("Vertical Symmetry"),
136 _("Reflect the initial stroke across a vertical axis"),
137 FALSE,
138 GIMP_PARAM_STATIC_STRINGS |
139 GIMP_SYMMETRY_PARAM_GUI);
140
141 GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_POINT_SYMMETRY,
142 "point-symmetry",
143 _("Central Symmetry"),
144 _("Invert the initial stroke through a point"),
145 FALSE,
146 GIMP_PARAM_STATIC_STRINGS |
147 GIMP_SYMMETRY_PARAM_GUI);
148
149 GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_DISABLE_TRANSFORMATION,
150 "disable-transformation",
151 _("Disable brush transform"),
152 _("Disable brush reflection"),
153 FALSE,
154 GIMP_PARAM_STATIC_STRINGS |
155 GIMP_SYMMETRY_PARAM_GUI);
156
157 GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_MIRROR_POSITION_X,
158 "mirror-position-x",
159 _("Vertical axis position"),
160 NULL,
161 0.0, G_MAXDOUBLE, 0.0,
162 GIMP_PARAM_STATIC_STRINGS |
163 GIMP_SYMMETRY_PARAM_GUI);
164
165 pspec = g_object_class_find_property (object_class, "mirror-position-x");
166 gegl_param_spec_set_property_key (pspec, "unit", "pixel-coordinate");
167 gegl_param_spec_set_property_key (pspec, "axis", "x");
168
169 GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_MIRROR_POSITION_Y,
170 "mirror-position-y",
171 _("Horizontal axis position"),
172 NULL,
173 0.0, G_MAXDOUBLE, 0.0,
174 GIMP_PARAM_STATIC_STRINGS |
175 GIMP_SYMMETRY_PARAM_GUI);
176
177 pspec = g_object_class_find_property (object_class, "mirror-position-y");
178 gegl_param_spec_set_property_key (pspec, "unit", "pixel-coordinate");
179 gegl_param_spec_set_property_key (pspec, "axis", "y");
180 }
181
182 static void
gimp_mirror_init(GimpMirror * mirror)183 gimp_mirror_init (GimpMirror *mirror)
184 {
185 }
186
187 static void
gimp_mirror_constructed(GObject * object)188 gimp_mirror_constructed (GObject *object)
189 {
190 GimpSymmetry *sym = GIMP_SYMMETRY (object);
191
192 g_signal_connect_object (sym->image, "size-changed-detailed",
193 G_CALLBACK (gimp_mirror_image_size_changed_cb),
194 sym, 0);
195 }
196
197 static void
gimp_mirror_finalize(GObject * object)198 gimp_mirror_finalize (GObject *object)
199 {
200 GimpMirror *mirror = GIMP_MIRROR (object);
201
202 g_clear_object (&mirror->horizontal_guide);
203 g_clear_object (&mirror->vertical_guide);
204
205 G_OBJECT_CLASS (parent_class)->finalize (object);
206 }
207
208 static void
gimp_mirror_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)209 gimp_mirror_set_property (GObject *object,
210 guint property_id,
211 const GValue *value,
212 GParamSpec *pspec)
213 {
214 GimpMirror *mirror = GIMP_MIRROR (object);
215 GimpImage *image = GIMP_SYMMETRY (mirror)->image;
216
217 switch (property_id)
218 {
219 case PROP_HORIZONTAL_SYMMETRY:
220 gimp_mirror_set_horizontal_symmetry (mirror,
221 g_value_get_boolean (value));
222 break;
223
224 case PROP_VERTICAL_SYMMETRY:
225 gimp_mirror_set_vertical_symmetry (mirror,
226 g_value_get_boolean (value));
227 break;
228
229 case PROP_POINT_SYMMETRY:
230 gimp_mirror_set_point_symmetry (mirror,
231 g_value_get_boolean (value));
232 break;
233
234 case PROP_DISABLE_TRANSFORMATION:
235 mirror->disable_transformation = g_value_get_boolean (value);
236 break;
237
238 case PROP_MIRROR_POSITION_X:
239 if (g_value_get_double (value) >= 0.0 &&
240 g_value_get_double (value) < (gdouble) gimp_image_get_width (image))
241 {
242 mirror->mirror_position_x = g_value_get_double (value);
243
244 if (mirror->vertical_guide)
245 {
246 g_signal_handlers_block_by_func (mirror->vertical_guide,
247 gimp_mirror_guide_position_cb,
248 mirror);
249 gimp_image_move_guide (image, mirror->vertical_guide,
250 mirror->mirror_position_x,
251 FALSE);
252 g_signal_handlers_unblock_by_func (mirror->vertical_guide,
253 gimp_mirror_guide_position_cb,
254 mirror);
255 }
256 }
257 break;
258
259 case PROP_MIRROR_POSITION_Y:
260 if (g_value_get_double (value) >= 0.0 &&
261 g_value_get_double (value) < (gdouble) gimp_image_get_height (image))
262 {
263 mirror->mirror_position_y = g_value_get_double (value);
264
265 if (mirror->horizontal_guide)
266 {
267 g_signal_handlers_block_by_func (mirror->horizontal_guide,
268 gimp_mirror_guide_position_cb,
269 mirror);
270 gimp_image_move_guide (image, mirror->horizontal_guide,
271 mirror->mirror_position_y,
272 FALSE);
273 g_signal_handlers_unblock_by_func (mirror->horizontal_guide,
274 gimp_mirror_guide_position_cb,
275 mirror);
276 }
277 }
278 break;
279
280 default:
281 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
282 break;
283 }
284 }
285
286 static void
gimp_mirror_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)287 gimp_mirror_get_property (GObject *object,
288 guint property_id,
289 GValue *value,
290 GParamSpec *pspec)
291 {
292 GimpMirror *mirror = GIMP_MIRROR (object);
293
294 switch (property_id)
295 {
296 case PROP_HORIZONTAL_SYMMETRY:
297 g_value_set_boolean (value, mirror->horizontal_mirror);
298 break;
299 case PROP_VERTICAL_SYMMETRY:
300 g_value_set_boolean (value, mirror->vertical_mirror);
301 break;
302 case PROP_POINT_SYMMETRY:
303 g_value_set_boolean (value, mirror->point_symmetry);
304 break;
305 case PROP_DISABLE_TRANSFORMATION:
306 g_value_set_boolean (value, mirror->disable_transformation);
307 break;
308 case PROP_MIRROR_POSITION_X:
309 g_value_set_double (value, mirror->mirror_position_x);
310 break;
311 case PROP_MIRROR_POSITION_Y:
312 g_value_set_double (value, mirror->mirror_position_y);
313 break;
314 default:
315 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
316 break;
317 }
318 }
319
320 static void
gimp_mirror_update_strokes(GimpSymmetry * sym,GimpDrawable * drawable,GimpCoords * origin)321 gimp_mirror_update_strokes (GimpSymmetry *sym,
322 GimpDrawable *drawable,
323 GimpCoords *origin)
324 {
325 GimpMirror *mirror = GIMP_MIRROR (sym);
326 GList *strokes = NULL;
327 GimpCoords *coords;
328 gdouble mirror_position_x, mirror_position_y;
329 gint offset_x, offset_y;
330
331 gimp_item_get_offset (GIMP_ITEM (drawable), &offset_x, &offset_y);
332
333 mirror_position_x = mirror->mirror_position_x - offset_x;
334 mirror_position_y = mirror->mirror_position_y - offset_y;
335
336 g_list_free_full (sym->strokes, g_free);
337 strokes = g_list_prepend (strokes,
338 g_memdup (origin, sizeof (GimpCoords)));
339
340 if (mirror->horizontal_mirror)
341 {
342 coords = g_memdup (origin, sizeof (GimpCoords));
343 coords->y = 2.0 * mirror_position_y - origin->y;
344 strokes = g_list_prepend (strokes, coords);
345 }
346
347 if (mirror->vertical_mirror)
348 {
349 coords = g_memdup (origin, sizeof (GimpCoords));
350 coords->x = 2.0 * mirror_position_x - origin->x;
351 strokes = g_list_prepend (strokes, coords);
352 }
353
354 if (mirror->point_symmetry)
355 {
356 coords = g_memdup (origin, sizeof (GimpCoords));
357 coords->x = 2.0 * mirror_position_x - origin->x;
358 coords->y = 2.0 * mirror_position_y - origin->y;
359 strokes = g_list_prepend (strokes, coords);
360 }
361
362 sym->strokes = g_list_reverse (strokes);
363
364 g_signal_emit_by_name (sym, "strokes-updated", sym->image);
365 }
366
367 static void
gimp_mirror_get_transform(GimpSymmetry * sym,gint stroke,gdouble * angle,gboolean * reflect)368 gimp_mirror_get_transform (GimpSymmetry *sym,
369 gint stroke,
370 gdouble *angle,
371 gboolean *reflect)
372 {
373 GimpMirror *mirror = GIMP_MIRROR (sym);
374
375 if (mirror->disable_transformation)
376 return;
377
378 if (! mirror->horizontal_mirror && stroke >= 1)
379 stroke++;
380
381 if (! mirror->vertical_mirror && stroke >= 2)
382 stroke++;
383
384 switch (stroke)
385 {
386 /* original */
387 case 0:
388 break;
389
390 /* horizontal */
391 case 1:
392 *angle = 180.0;
393 *reflect = TRUE;
394 break;
395
396 /* vertical */
397 case 2:
398 *reflect = TRUE;
399 break;
400
401 /* central */
402 case 3:
403 *angle = 180.0;
404 break;
405
406 default:
407 g_return_if_reached ();
408 }
409 }
410
411 static void
gimp_mirror_reset(GimpMirror * mirror)412 gimp_mirror_reset (GimpMirror *mirror)
413 {
414 GimpSymmetry *sym = GIMP_SYMMETRY (mirror);
415
416 if (sym->origin)
417 {
418 gimp_symmetry_set_origin (sym, sym->drawable,
419 sym->origin);
420 }
421 }
422
423 static void
gimp_mirror_add_guide(GimpMirror * mirror,GimpOrientationType orientation)424 gimp_mirror_add_guide (GimpMirror *mirror,
425 GimpOrientationType orientation)
426 {
427 GimpSymmetry *sym = GIMP_SYMMETRY (mirror);
428 GimpImage *image;
429 Gimp *gimp;
430 GimpGuide *guide;
431 gdouble position;
432
433 image = sym->image;
434 gimp = image->gimp;
435
436 guide = gimp_guide_custom_new (orientation,
437 gimp->next_guide_ID++,
438 GIMP_GUIDE_STYLE_MIRROR);
439
440 if (orientation == GIMP_ORIENTATION_HORIZONTAL)
441 {
442 /* Mirror guide position at first activation is at canvas middle. */
443 if (mirror->mirror_position_y < 1.0)
444 position = gimp_image_get_height (image) / 2.0;
445 else
446 position = mirror->mirror_position_y;
447
448 g_object_set (mirror,
449 "mirror-position-y", position,
450 NULL);
451
452 mirror->horizontal_guide = guide;
453 }
454 else
455 {
456 /* Mirror guide position at first activation is at canvas middle. */
457 if (mirror->mirror_position_x < 1.0)
458 position = gimp_image_get_width (image) / 2.0;
459 else
460 position = mirror->mirror_position_x;
461
462 g_object_set (mirror,
463 "mirror-position-x", position,
464 NULL);
465
466 mirror->vertical_guide = guide;
467 }
468
469 g_signal_connect (guide, "removed",
470 G_CALLBACK (gimp_mirror_guide_removed_cb),
471 mirror);
472
473 gimp_image_add_guide (image, guide, (gint) position);
474
475 g_signal_connect (guide, "notify::position",
476 G_CALLBACK (gimp_mirror_guide_position_cb),
477 mirror);
478 }
479
480 static void
gimp_mirror_remove_guide(GimpMirror * mirror,GimpOrientationType orientation)481 gimp_mirror_remove_guide (GimpMirror *mirror,
482 GimpOrientationType orientation)
483 {
484 GimpSymmetry *sym = GIMP_SYMMETRY (mirror);
485 GimpImage *image;
486 GimpGuide *guide;
487
488 image = sym->image;
489 guide = (orientation == GIMP_ORIENTATION_HORIZONTAL) ?
490 mirror->horizontal_guide : mirror->vertical_guide;
491
492 /* The guide may have already been removed, for instance from GUI. */
493 if (guide)
494 {
495 g_signal_handlers_disconnect_by_func (G_OBJECT (guide),
496 gimp_mirror_guide_removed_cb,
497 mirror);
498 g_signal_handlers_disconnect_by_func (G_OBJECT (guide),
499 gimp_mirror_guide_position_cb,
500 mirror);
501
502 gimp_image_remove_guide (image, guide, FALSE);
503 g_object_unref (guide);
504
505 if (orientation == GIMP_ORIENTATION_HORIZONTAL)
506 mirror->horizontal_guide = NULL;
507 else
508 mirror->vertical_guide = NULL;
509 }
510 }
511
512 static void
gimp_mirror_guide_removed_cb(GObject * object,GimpMirror * mirror)513 gimp_mirror_guide_removed_cb (GObject *object,
514 GimpMirror *mirror)
515 {
516 GimpSymmetry *symmetry = GIMP_SYMMETRY (mirror);
517
518 g_signal_handlers_disconnect_by_func (object,
519 gimp_mirror_guide_removed_cb,
520 mirror);
521 g_signal_handlers_disconnect_by_func (object,
522 gimp_mirror_guide_position_cb,
523 mirror);
524
525 if (GIMP_GUIDE (object) == mirror->horizontal_guide)
526 {
527 g_object_unref (mirror->horizontal_guide);
528 mirror->horizontal_guide = NULL;
529
530 g_object_set (mirror,
531 "horizontal-symmetry", FALSE,
532 NULL);
533 g_object_set (mirror,
534 "point-symmetry", FALSE,
535 NULL);
536 g_object_set (mirror,
537 "mirror-position-y", 0.0,
538 NULL);
539
540 if (mirror->vertical_guide &&
541 ! mirror->vertical_mirror)
542 {
543 g_signal_handlers_disconnect_by_func (G_OBJECT (mirror->vertical_guide),
544 gimp_mirror_guide_removed_cb,
545 mirror);
546 g_signal_handlers_disconnect_by_func (G_OBJECT (mirror->vertical_guide),
547 gimp_mirror_guide_position_cb,
548 mirror);
549
550 gimp_image_remove_guide (symmetry->image,
551 mirror->vertical_guide,
552 FALSE);
553 g_clear_object (&mirror->vertical_guide);
554 }
555 }
556 else if (GIMP_GUIDE (object) == mirror->vertical_guide)
557 {
558 g_object_unref (mirror->vertical_guide);
559 mirror->vertical_guide = NULL;
560
561 g_object_set (mirror,
562 "vertical-symmetry", FALSE,
563 NULL);
564 g_object_set (mirror,
565 "point-symmetry", FALSE,
566 NULL);
567 g_object_set (mirror,
568 "mirror-position-x", 0.0,
569 NULL);
570
571 if (mirror->horizontal_guide &&
572 ! mirror->horizontal_mirror)
573 {
574 g_signal_handlers_disconnect_by_func (G_OBJECT (mirror->horizontal_guide),
575 gimp_mirror_guide_removed_cb,
576 mirror);
577 g_signal_handlers_disconnect_by_func (G_OBJECT (mirror->horizontal_guide),
578 gimp_mirror_guide_position_cb,
579 mirror);
580
581 gimp_image_remove_guide (symmetry->image,
582 mirror->horizontal_guide,
583 FALSE);
584 g_clear_object (&mirror->horizontal_guide);
585 }
586 }
587
588 if (mirror->horizontal_guide == NULL &&
589 mirror->vertical_guide == NULL)
590 {
591 gimp_image_symmetry_remove (symmetry->image,
592 GIMP_SYMMETRY (mirror));
593 }
594 else
595 {
596 gimp_mirror_reset (mirror);
597 g_signal_emit_by_name (mirror, "gui-param-changed",
598 GIMP_SYMMETRY (mirror)->image);
599 }
600 }
601
602 static void
gimp_mirror_guide_position_cb(GObject * object,GParamSpec * pspec,GimpMirror * mirror)603 gimp_mirror_guide_position_cb (GObject *object,
604 GParamSpec *pspec,
605 GimpMirror *mirror)
606 {
607 GimpGuide *guide = GIMP_GUIDE (object);
608
609 if (guide == mirror->horizontal_guide)
610 {
611 g_object_set (mirror,
612 "mirror-position-y", (gdouble) gimp_guide_get_position (guide),
613 NULL);
614 }
615 else if (guide == mirror->vertical_guide)
616 {
617 g_object_set (mirror,
618 "mirror-position-x", (gdouble) gimp_guide_get_position (guide),
619 NULL);
620 }
621 }
622
623 static void
gimp_mirror_active_changed(GimpSymmetry * sym)624 gimp_mirror_active_changed (GimpSymmetry *sym)
625 {
626 GimpMirror *mirror = GIMP_MIRROR (sym);
627
628 if (sym->active)
629 {
630 if ((mirror->horizontal_mirror || mirror->point_symmetry) &&
631 ! mirror->horizontal_guide)
632 gimp_mirror_add_guide (mirror, GIMP_ORIENTATION_HORIZONTAL);
633
634 if ((mirror->vertical_mirror || mirror->point_symmetry) &&
635 ! mirror->vertical_guide)
636 gimp_mirror_add_guide (mirror, GIMP_ORIENTATION_VERTICAL);
637 }
638 else
639 {
640 if (mirror->horizontal_guide)
641 gimp_mirror_remove_guide (mirror, GIMP_ORIENTATION_HORIZONTAL);
642
643 if (mirror->vertical_guide)
644 gimp_mirror_remove_guide (mirror, GIMP_ORIENTATION_VERTICAL);
645 }
646 }
647
648 static void
gimp_mirror_set_horizontal_symmetry(GimpMirror * mirror,gboolean active)649 gimp_mirror_set_horizontal_symmetry (GimpMirror *mirror,
650 gboolean active)
651 {
652 if (active == mirror->horizontal_mirror)
653 return;
654
655 mirror->horizontal_mirror = active;
656
657 if (active)
658 {
659 if (! mirror->horizontal_guide)
660 gimp_mirror_add_guide (mirror, GIMP_ORIENTATION_HORIZONTAL);
661 }
662 else if (! mirror->point_symmetry)
663 {
664 gimp_mirror_remove_guide (mirror, GIMP_ORIENTATION_HORIZONTAL);
665 }
666
667 gimp_mirror_reset (mirror);
668 }
669
670 static void
gimp_mirror_set_vertical_symmetry(GimpMirror * mirror,gboolean active)671 gimp_mirror_set_vertical_symmetry (GimpMirror *mirror,
672 gboolean active)
673 {
674 if (active == mirror->vertical_mirror)
675 return;
676
677 mirror->vertical_mirror = active;
678
679 if (active)
680 {
681 if (! mirror->vertical_guide)
682 gimp_mirror_add_guide (mirror, GIMP_ORIENTATION_VERTICAL);
683 }
684 else if (! mirror->point_symmetry)
685 {
686 gimp_mirror_remove_guide (mirror, GIMP_ORIENTATION_VERTICAL);
687 }
688
689 gimp_mirror_reset (mirror);
690 }
691
692 static void
gimp_mirror_set_point_symmetry(GimpMirror * mirror,gboolean active)693 gimp_mirror_set_point_symmetry (GimpMirror *mirror,
694 gboolean active)
695 {
696 if (active == mirror->point_symmetry)
697 return;
698
699 mirror->point_symmetry = active;
700
701 if (active)
702 {
703 /* Show the horizontal guide unless already shown */
704 if (! mirror->horizontal_guide)
705 gimp_mirror_add_guide (mirror, GIMP_ORIENTATION_HORIZONTAL);
706
707 /* Show the vertical guide unless already shown */
708 if (! mirror->vertical_guide)
709 gimp_mirror_add_guide (mirror, GIMP_ORIENTATION_VERTICAL);
710 }
711 else
712 {
713 /* Remove the horizontal guide unless needed by horizontal mirror */
714 if (! mirror->horizontal_mirror)
715 gimp_mirror_remove_guide (mirror, GIMP_ORIENTATION_HORIZONTAL);
716
717 /* Remove the vertical guide unless needed by vertical mirror */
718 if (! mirror->vertical_mirror)
719 gimp_mirror_remove_guide (mirror, GIMP_ORIENTATION_VERTICAL);
720 }
721
722 gimp_mirror_reset (mirror);
723 }
724
725 static void
gimp_mirror_image_size_changed_cb(GimpImage * image,gint previous_origin_x,gint previous_origin_y,gint previous_width,gint previous_height,GimpSymmetry * sym)726 gimp_mirror_image_size_changed_cb (GimpImage *image,
727 gint previous_origin_x,
728 gint previous_origin_y,
729 gint previous_width,
730 gint previous_height,
731 GimpSymmetry *sym)
732 {
733 if (previous_width != gimp_image_get_width (image) ||
734 previous_height != gimp_image_get_height (image))
735 {
736 g_signal_emit_by_name (sym, "gui-param-changed", sym->image);
737 }
738 }
739