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 "display-types.h"
27
28 #include "core/gimp-utils.h"
29 #include "core/gimpimage.h"
30 #include "core/gimpunit.h"
31
32 #include "gimpdisplay.h"
33 #include "gimpdisplayshell.h"
34 #include "gimpdisplayshell-utils.h"
35
36 #include "gimp-intl.h"
37
38 void
gimp_display_shell_get_constrained_line_params(GimpDisplayShell * shell,gdouble * offset_angle,gdouble * xres,gdouble * yres)39 gimp_display_shell_get_constrained_line_params (GimpDisplayShell *shell,
40 gdouble *offset_angle,
41 gdouble *xres,
42 gdouble *yres)
43 {
44 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
45 g_return_if_fail (offset_angle != NULL);
46 g_return_if_fail (xres != NULL);
47 g_return_if_fail (yres != NULL);
48
49 if (shell->flip_horizontally ^ shell->flip_vertically)
50 *offset_angle = +shell->rotate_angle;
51 else
52 *offset_angle = -shell->rotate_angle;
53
54 *xres = 1.0;
55 *yres = 1.0;
56
57 if (! shell->dot_for_dot)
58 {
59 GimpImage *image = gimp_display_get_image (shell->display);
60
61 if (image)
62 gimp_image_get_resolution (image, xres, yres);
63 }
64 }
65
66 void
gimp_display_shell_constrain_line(GimpDisplayShell * shell,gdouble start_x,gdouble start_y,gdouble * end_x,gdouble * end_y,gint n_snap_lines)67 gimp_display_shell_constrain_line (GimpDisplayShell *shell,
68 gdouble start_x,
69 gdouble start_y,
70 gdouble *end_x,
71 gdouble *end_y,
72 gint n_snap_lines)
73 {
74 gdouble offset_angle;
75 gdouble xres, yres;
76
77 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
78 g_return_if_fail (end_x != NULL);
79 g_return_if_fail (end_y != NULL);
80
81 gimp_display_shell_get_constrained_line_params (shell,
82 &offset_angle,
83 &xres, &yres);
84
85 gimp_constrain_line (start_x, start_y,
86 end_x, end_y,
87 n_snap_lines,
88 offset_angle,
89 xres, yres);
90 }
91
92 gdouble
gimp_display_shell_constrain_angle(GimpDisplayShell * shell,gdouble angle,gint n_snap_lines)93 gimp_display_shell_constrain_angle (GimpDisplayShell *shell,
94 gdouble angle,
95 gint n_snap_lines)
96 {
97 gdouble x, y;
98
99 g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), 0.0);
100
101 x = cos (angle);
102 y = sin (angle);
103
104 gimp_display_shell_constrain_line (shell,
105 0.0, 0.0,
106 &x, &y,
107 n_snap_lines);
108
109 return atan2 (y, x);
110 }
111
112 /**
113 * gimp_display_shell_get_line_status:
114 * @status: initial status text.
115 * @separator: separator text between the line information and @status.
116 * @shell: #GimpDisplayShell this status text will be displayed for.
117 * @x1: abscissa of first point.
118 * @y1: ordinate of first point.
119 * @x2: abscissa of second point.
120 * @y2: ordinate of second point.
121 *
122 * Utility function to prepend the status message with a distance and
123 * angle value. Obviously this is only to be used for tools when it
124 * makes sense, and in particular when there is a concept of line. For
125 * instance when shift-clicking a painting tool or in the blend tool,
126 * etc.
127 * This utility prevents code duplication but also ensures a common
128 * display for every tool where such a status is needed. It will take
129 * into account the shell unit settings and will use the ideal digit
130 * precision according to current image resolution.
131 *
132 * Return value: a newly allocated string containing the enhanced status.
133 **/
134 gchar *
gimp_display_shell_get_line_status(GimpDisplayShell * shell,const gchar * status,const gchar * separator,gdouble x1,gdouble y1,gdouble x2,gdouble y2)135 gimp_display_shell_get_line_status (GimpDisplayShell *shell,
136 const gchar *status,
137 const gchar *separator,
138 gdouble x1,
139 gdouble y1,
140 gdouble x2,
141 gdouble y2)
142 {
143 GimpImage *image;
144 gchar *enhanced_status;
145 gdouble xres;
146 gdouble yres;
147 gdouble dx, dy, pixel_dist;
148 gdouble angle;
149
150 image = gimp_display_get_image (shell->display);
151 if (! image)
152 {
153 /* This makes no sense to add line information when no image is
154 * attached to the display. */
155 return g_strdup (status);
156 }
157
158 if (shell->unit == GIMP_UNIT_PIXEL)
159 xres = yres = 1.0;
160 else
161 gimp_image_get_resolution (image, &xres, &yres);
162
163 dx = x2 - x1;
164 dy = y2 - y1;
165 pixel_dist = sqrt (SQR (dx) + SQR (dy));
166
167 if (dx)
168 {
169 angle = gimp_rad_to_deg (atan ((dy/yres) / (dx/xres)));
170 if (dx > 0)
171 {
172 if (dy > 0)
173 angle = 360.0 - angle;
174 else if (dy < 0)
175 angle = -angle;
176 }
177 else
178 {
179 angle = 180.0 - angle;
180 }
181 }
182 else if (dy)
183 {
184 angle = dy > 0 ? 270.0 : 90.0;
185 }
186 else
187 {
188 angle = 0.0;
189 }
190
191 if (shell->unit == GIMP_UNIT_PIXEL)
192 {
193 enhanced_status = g_strdup_printf ("%.1f %s, %.2f\302\260%s%s",
194 pixel_dist, _("pixels"), angle,
195 separator, status);
196 }
197 else
198 {
199 gdouble inch_dist;
200 gdouble unit_dist;
201 gint digits = 0;
202
203 /* The distance in unit. */
204 inch_dist = sqrt (SQR (dx / xres) + SQR (dy / yres));
205 unit_dist = gimp_unit_get_factor (shell->unit) * inch_dist;
206
207 /* The ideal digit precision for unit in current resolution. */
208 if (inch_dist)
209 digits = gimp_unit_get_scaled_digits (shell->unit,
210 pixel_dist / inch_dist);
211
212 enhanced_status = g_strdup_printf ("%.*f %s, %.2f\302\260%s%s",
213 digits, unit_dist,
214 gimp_unit_get_symbol (shell->unit),
215 angle, separator, status);
216
217 }
218
219 return enhanced_status;
220 }
221