app: add "orientation" property to GimpToolCompass + improvements
Add an "orientation" property to GimpToolCompass, which can be one
of "auto", "horizontal", or "vertical", and which controls the
orientation of the line against which the angle is measured, when
not in 3-point mode (previously, the line would always be
horizontal.) When "orientation" is "auto", the orientation is
automatically set to either horizontal or vertical, such that the
measured angle is <= 45 deg.
Keep the line horizontal, or vertical, in display-space, rather
than in image-space, so that the compass works correctly even when
the canvas is rotated and/or flipped.
Fix the compass's behavior when the image's horizontal and vertical
resolutions are different, both with and without dot-for-dot.
Add "pixel-angle" and "unit-angle" read-only properties, which
return the measured angle either with or without taking the image's
resolution into account, respectively. These properties will be
used by the measure tool in the next commit, instead of having it
implement its own angle calculation.
(cherry picked from commit d2f33cf1be
)
This commit is contained in:
@ -455,6 +455,37 @@ gimp_vector_mode_get_type (void)
|
||||
return type;
|
||||
}
|
||||
|
||||
GType
|
||||
gimp_compass_orientation_get_type (void)
|
||||
{
|
||||
static const GEnumValue values[] =
|
||||
{
|
||||
{ GIMP_COMPASS_ORIENTATION_AUTO, "GIMP_COMPASS_ORIENTATION_AUTO", "auto" },
|
||||
{ GIMP_COMPASS_ORIENTATION_HORIZONTAL, "GIMP_COMPASS_ORIENTATION_HORIZONTAL", "horizontal" },
|
||||
{ GIMP_COMPASS_ORIENTATION_VERTICAL, "GIMP_COMPASS_ORIENTATION_VERTICAL", "vertical" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const GimpEnumDesc descs[] =
|
||||
{
|
||||
{ GIMP_COMPASS_ORIENTATION_AUTO, NC_("compass-orientation", "Auto"), NULL },
|
||||
{ GIMP_COMPASS_ORIENTATION_HORIZONTAL, NC_("compass-orientation", "Horizontal"), NULL },
|
||||
{ GIMP_COMPASS_ORIENTATION_VERTICAL, NC_("compass-orientation", "Vertical"), NULL },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (! type))
|
||||
{
|
||||
type = g_enum_register_static ("GimpCompassOrientation", values);
|
||||
gimp_type_set_translation_context (type, "compass-orientation");
|
||||
gimp_enum_set_value_descriptions (type, descs);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
GType
|
||||
gimp_zoom_focus_get_type (void)
|
||||
{
|
||||
|
@ -197,6 +197,18 @@ typedef enum
|
||||
} GimpVectorMode;
|
||||
|
||||
|
||||
#define GIMP_TYPE_COMPASS_ORIENTATION (gimp_compass_orientation_get_type ())
|
||||
|
||||
GType gimp_compass_orientation_get_type (void) G_GNUC_CONST;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GIMP_COMPASS_ORIENTATION_AUTO, /*< desc="Auto" >*/
|
||||
GIMP_COMPASS_ORIENTATION_HORIZONTAL, /*< desc="Horizontal" >*/
|
||||
GIMP_COMPASS_ORIENTATION_VERTICAL /*< desc="Vertical" >*/
|
||||
} GimpCompassOrientation;
|
||||
|
||||
|
||||
#define GIMP_TYPE_ZOOM_FOCUS (gimp_zoom_focus_get_type ())
|
||||
|
||||
GType gimp_zoom_focus_get_type (void) G_GNUC_CONST;
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "gimpdisplay.h"
|
||||
#include "gimpdisplayshell.h"
|
||||
#include "gimpdisplayshell-appearance.h"
|
||||
#include "gimpdisplayshell-transform.h"
|
||||
#include "gimpdisplayshell-utils.h"
|
||||
#include "gimptoolcompass.h"
|
||||
|
||||
@ -49,6 +50,8 @@
|
||||
|
||||
|
||||
#define ARC_RADIUS 30
|
||||
#define EPSILON 1e-6
|
||||
|
||||
|
||||
/* possible measure functions */
|
||||
typedef enum
|
||||
@ -64,13 +67,16 @@ typedef enum
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_ORIENTATION,
|
||||
PROP_N_POINTS,
|
||||
PROP_X1,
|
||||
PROP_Y1,
|
||||
PROP_X2,
|
||||
PROP_Y2,
|
||||
PROP_X3,
|
||||
PROP_Y3
|
||||
PROP_Y3,
|
||||
PROP_PIXEL_ANGLE,
|
||||
PROP_UNIT_ANGLE
|
||||
};
|
||||
|
||||
enum
|
||||
@ -81,12 +87,16 @@ enum
|
||||
|
||||
struct _GimpToolCompassPrivate
|
||||
{
|
||||
GimpCompassOrientation orientation;
|
||||
gint n_points;
|
||||
gint x[3];
|
||||
gint y[3];
|
||||
|
||||
gdouble angle1;
|
||||
gdouble angle2;
|
||||
GimpVector2 radius1;
|
||||
GimpVector2 radius2;
|
||||
gdouble display_angle;
|
||||
gdouble pixel_angle;
|
||||
gdouble unit_angle;
|
||||
|
||||
CompassFunction function;
|
||||
gdouble mouse_x;
|
||||
@ -97,8 +107,8 @@ struct _GimpToolCompassPrivate
|
||||
|
||||
GimpCanvasItem *line1;
|
||||
GimpCanvasItem *line2;
|
||||
GimpCanvasItem *angle;
|
||||
GimpCanvasItem *angle_line;
|
||||
GimpCanvasItem *arc;
|
||||
GimpCanvasItem *arc_line;
|
||||
GimpCanvasItem *handles[3];
|
||||
};
|
||||
|
||||
@ -153,6 +163,9 @@ static gboolean gimp_tool_compass_get_cursor (GimpToolWidget *widget
|
||||
static gint gimp_tool_compass_get_point (GimpToolCompass *compass,
|
||||
const GimpCoords *coords);
|
||||
static void gimp_tool_compass_update_hilight (GimpToolCompass *compass);
|
||||
static void gimp_tool_compass_update_angle (GimpToolCompass *compass,
|
||||
GimpCompassOrientation orientation,
|
||||
gboolean flip);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GimpToolCompass, gimp_tool_compass, GIMP_TYPE_TOOL_WIDGET)
|
||||
@ -195,6 +208,13 @@ gimp_tool_compass_class_init (GimpToolCompassClass *klass)
|
||||
G_TYPE_BOOLEAN,
|
||||
G_TYPE_BOOLEAN);
|
||||
|
||||
g_object_class_install_property (object_class, PROP_ORIENTATION,
|
||||
g_param_spec_enum ("orientation", NULL, NULL,
|
||||
GIMP_TYPE_COMPASS_ORIENTATION,
|
||||
GIMP_COMPASS_ORIENTATION_AUTO,
|
||||
GIMP_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_N_POINTS,
|
||||
g_param_spec_int ("n-points", NULL, NULL,
|
||||
1, 3, 1,
|
||||
@ -243,6 +263,16 @@ gimp_tool_compass_class_init (GimpToolCompassClass *klass)
|
||||
GIMP_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_PIXEL_ANGLE,
|
||||
g_param_spec_double ("pixel-angle", NULL, NULL,
|
||||
-G_PI, G_PI, 0.0,
|
||||
GIMP_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_UNIT_ANGLE,
|
||||
g_param_spec_double ("unit-angle", NULL, NULL,
|
||||
-G_PI, G_PI, 0.0,
|
||||
GIMP_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GimpToolCompassPrivate));
|
||||
}
|
||||
|
||||
@ -256,72 +286,6 @@ gimp_tool_compass_init (GimpToolCompass *compass)
|
||||
compass->private->point = -1;
|
||||
}
|
||||
|
||||
static gdouble
|
||||
gimp_tool_compass_get_angle (gint dx,
|
||||
gint dy,
|
||||
gdouble xres,
|
||||
gdouble yres)
|
||||
{
|
||||
gdouble angle;
|
||||
|
||||
if (dx)
|
||||
angle = gimp_rad_to_deg (atan (((gdouble) (dy) / yres) /
|
||||
((gdouble) (dx) / xres)));
|
||||
else if (dy)
|
||||
angle = dy > 0 ? 270.0 : 90.0;
|
||||
else
|
||||
angle = 180.0;
|
||||
|
||||
if (dx > 0)
|
||||
{
|
||||
if (dy > 0)
|
||||
angle = 360.0 - angle;
|
||||
else
|
||||
angle = -angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = 180.0 - angle;
|
||||
}
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_tool_compass_update_angles (GimpToolCompass *compass)
|
||||
{
|
||||
GimpToolWidget *widget = GIMP_TOOL_WIDGET (compass);
|
||||
GimpToolCompassPrivate *private = compass->private;
|
||||
GimpDisplayShell *shell = gimp_tool_widget_get_shell (widget);
|
||||
GimpImage *image = gimp_display_get_image (shell->display);
|
||||
gint ax, ay;
|
||||
gint bx, by;
|
||||
gdouble xres;
|
||||
gdouble yres;
|
||||
|
||||
ax = private->x[1] - private->x[0];
|
||||
ay = private->y[1] - private->y[0];
|
||||
|
||||
if (private->n_points == 3)
|
||||
{
|
||||
bx = private->x[2] - private->x[0];
|
||||
by = private->y[2] - private->y[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
bx = 0;
|
||||
by = 0;
|
||||
}
|
||||
|
||||
gimp_image_get_resolution (image, &xres, &yres);
|
||||
|
||||
if (private->n_points != 3)
|
||||
bx = ax > 0 ? 1 : -1;
|
||||
|
||||
private->angle1 = gimp_tool_compass_get_angle (ax, ay, xres, yres);
|
||||
private->angle2 = gimp_tool_compass_get_angle (bx, by, xres, yres);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_tool_compass_constructed (GObject *object)
|
||||
{
|
||||
@ -349,7 +313,7 @@ gimp_tool_compass_constructed (GObject *object)
|
||||
private->x[2],
|
||||
private->y[2]);
|
||||
|
||||
private->angle = gimp_tool_widget_add_handle (widget,
|
||||
private->arc = gimp_tool_widget_add_handle (widget,
|
||||
GIMP_HANDLE_CIRCLE,
|
||||
private->x[0],
|
||||
private->y[0],
|
||||
@ -357,7 +321,7 @@ gimp_tool_compass_constructed (GObject *object)
|
||||
ARC_RADIUS * 2 + 1,
|
||||
GIMP_HANDLE_ANCHOR_CENTER);
|
||||
|
||||
private->angle_line = gimp_tool_widget_add_line (widget,
|
||||
private->arc_line = gimp_tool_widget_add_line (widget,
|
||||
private->x[0],
|
||||
private->y[0],
|
||||
private->x[0] + 10,
|
||||
@ -413,6 +377,9 @@ gimp_tool_compass_set_property (GObject *object,
|
||||
case PROP_Y3:
|
||||
private->y[2] = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_ORIENTATION:
|
||||
private->orientation = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
@ -452,6 +419,15 @@ gimp_tool_compass_get_property (GObject *object,
|
||||
case PROP_Y3:
|
||||
g_value_set_int (value, private->y[2]);
|
||||
break;
|
||||
case PROP_ORIENTATION:
|
||||
g_value_set_enum (value, private->orientation);
|
||||
break;
|
||||
case PROP_PIXEL_ANGLE:
|
||||
g_value_set_double (value, private->pixel_angle);
|
||||
break;
|
||||
case PROP_UNIT_ANGLE:
|
||||
g_value_set_double (value, private->unit_angle);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
@ -468,10 +444,13 @@ gimp_tool_compass_changed (GimpToolWidget *widget)
|
||||
gdouble angle1;
|
||||
gdouble angle2;
|
||||
gint draw_arc = 0;
|
||||
gdouble target;
|
||||
gdouble arc_radius;
|
||||
gdouble arc_line_length;
|
||||
|
||||
gimp_tool_compass_update_angles (compass);
|
||||
gimp_tool_compass_update_angle (compass, private->orientation, FALSE);
|
||||
|
||||
angle1 = -atan2 (private->radius1.y * shell->scale_y,
|
||||
private->radius1.x * shell->scale_x);
|
||||
angle2 = -private->display_angle;
|
||||
|
||||
gimp_canvas_line_set (private->line1,
|
||||
private->x[0],
|
||||
@ -505,36 +484,26 @@ gimp_tool_compass_changed (GimpToolWidget *widget)
|
||||
draw_arc++;
|
||||
}
|
||||
|
||||
angle1 = private->angle2 / 180.0 * G_PI;
|
||||
angle2 = (private->angle1 - private->angle2) / 180.0 * G_PI;
|
||||
|
||||
if (angle2 > G_PI)
|
||||
angle2 -= 2.0 * G_PI;
|
||||
|
||||
if (angle2 < -G_PI)
|
||||
angle2 += 2.0 * G_PI;
|
||||
|
||||
gimp_canvas_handle_set_position (private->angle,
|
||||
gimp_canvas_handle_set_position (private->arc,
|
||||
private->x[0], private->y[0]);
|
||||
gimp_canvas_handle_set_angles (private->angle, angle1, angle2);
|
||||
gimp_canvas_item_set_visible (private->angle,
|
||||
gimp_canvas_handle_set_angles (private->arc, angle1, angle2);
|
||||
gimp_canvas_item_set_visible (private->arc,
|
||||
private->n_points > 1 &&
|
||||
draw_arc == private->n_points - 1 &&
|
||||
angle2 != 0.0);
|
||||
fabs (angle2) > EPSILON);
|
||||
|
||||
target = FUNSCALEX (shell, (GIMP_CANVAS_HANDLE_SIZE_CROSS >> 1));
|
||||
arc_radius = FUNSCALEX (shell, ARC_RADIUS);
|
||||
arc_line_length = (ARC_RADIUS + (GIMP_CANVAS_HANDLE_SIZE_CROSS >> 1)) /
|
||||
hypot (private->radius2.x * shell->scale_x,
|
||||
private->radius2.y * shell->scale_y);
|
||||
|
||||
gimp_canvas_line_set (private->angle_line,
|
||||
gimp_canvas_line_set (private->arc_line,
|
||||
private->x[0],
|
||||
private->y[0],
|
||||
private->x[0] + (private->x[1] > private->x[0] ?
|
||||
(arc_radius + target) :
|
||||
-(arc_radius + target)),
|
||||
private->y[0]);
|
||||
gimp_canvas_item_set_visible (private->angle_line,
|
||||
private->x[0] + private->radius2.x * arc_line_length,
|
||||
private->y[0] + private->radius2.y * arc_line_length);
|
||||
gimp_canvas_item_set_visible (private->arc_line,
|
||||
private->n_points == 2 &&
|
||||
angle2 != 0.0);
|
||||
fabs (angle2) > EPSILON);
|
||||
|
||||
gimp_canvas_handle_set_position (private->handles[0],
|
||||
private->x[0], private->y[0]);
|
||||
@ -1051,11 +1020,99 @@ gimp_tool_compass_update_hilight (GimpToolCompass *compass)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_tool_compass_update_angle (GimpToolCompass *compass,
|
||||
GimpCompassOrientation orientation,
|
||||
gboolean flip)
|
||||
{
|
||||
GimpToolWidget *widget = GIMP_TOOL_WIDGET (compass);
|
||||
GimpToolCompassPrivate *private = compass->private;
|
||||
GimpDisplayShell *shell = gimp_tool_widget_get_shell (widget);
|
||||
GimpImage *image = gimp_display_get_image (shell->display);
|
||||
GimpVector2 radius1;
|
||||
GimpVector2 radius2;
|
||||
gdouble xres;
|
||||
gdouble yres;
|
||||
|
||||
gimp_image_get_resolution (image, &xres, &yres);
|
||||
|
||||
private->radius1.x = private->x[1] - private->x[0];
|
||||
private->radius1.y = private->y[1] - private->y[0];
|
||||
|
||||
if (private->n_points == 3)
|
||||
{
|
||||
private->radius2.x = private->x[2] - private->x[0];
|
||||
private->radius2.y = private->y[2] - private->y[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
gdouble angle = -shell->rotate_angle * G_PI / 180.0;
|
||||
|
||||
if (orientation == GIMP_COMPASS_ORIENTATION_VERTICAL)
|
||||
angle -= G_PI / 2.0;
|
||||
|
||||
if (flip)
|
||||
angle += G_PI;
|
||||
|
||||
if (shell->flip_horizontally)
|
||||
angle = G_PI - angle;
|
||||
if (shell->flip_vertically)
|
||||
angle = -angle;
|
||||
|
||||
private->radius2.x = cos (angle);
|
||||
private->radius2.y = sin (angle);
|
||||
|
||||
if (! shell->dot_for_dot)
|
||||
{
|
||||
private->radius2.x *= xres;
|
||||
private->radius2.y *= yres;
|
||||
|
||||
gimp_vector2_normalize (&private->radius2);
|
||||
}
|
||||
}
|
||||
|
||||
radius1 = private->radius1;
|
||||
radius2 = private->radius2;
|
||||
|
||||
private->pixel_angle = atan2 (gimp_vector2_cross_product (&radius1, &radius2).x,
|
||||
gimp_vector2_inner_product (&radius1, &radius2));
|
||||
|
||||
radius1.x /= xres;
|
||||
radius1.y /= yres;
|
||||
|
||||
radius2.x /= xres;
|
||||
radius2.y /= yres;
|
||||
|
||||
private->unit_angle = atan2 (gimp_vector2_cross_product (&radius1, &radius2).x,
|
||||
gimp_vector2_inner_product (&radius1, &radius2));
|
||||
|
||||
if (shell->dot_for_dot)
|
||||
private->display_angle = private->pixel_angle;
|
||||
else
|
||||
private->display_angle = private->unit_angle;
|
||||
|
||||
if (private->n_points == 2)
|
||||
{
|
||||
if (! flip && fabs (private->display_angle) > G_PI / 2.0 + EPSILON)
|
||||
{
|
||||
gimp_tool_compass_update_angle (compass, orientation, TRUE);
|
||||
}
|
||||
else if (orientation == GIMP_COMPASS_ORIENTATION_AUTO &&
|
||||
fabs (private->display_angle) > G_PI / 4.0 + EPSILON)
|
||||
{
|
||||
gimp_tool_compass_update_angle (compass,
|
||||
GIMP_COMPASS_ORIENTATION_VERTICAL,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
GimpToolWidget *
|
||||
gimp_tool_compass_new (GimpDisplayShell *shell,
|
||||
GimpCompassOrientation orientation,
|
||||
gint n_points,
|
||||
gint x1,
|
||||
gint y1,
|
||||
@ -1068,6 +1125,7 @@ gimp_tool_compass_new (GimpDisplayShell *shell,
|
||||
|
||||
return g_object_new (GIMP_TYPE_TOOL_COMPASS,
|
||||
"shell", shell,
|
||||
"orientation", orientation,
|
||||
"n-points", n_points,
|
||||
"x1", x1,
|
||||
"y1", y1,
|
||||
|
@ -59,6 +59,7 @@ struct _GimpToolCompassClass
|
||||
GType gimp_tool_compass_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GimpToolWidget * gimp_tool_compass_new (GimpDisplayShell *shell,
|
||||
GimpCompassOrientation orinetation,
|
||||
gint n_points,
|
||||
gint x1,
|
||||
gint y1,
|
||||
|
@ -436,6 +436,7 @@ gimp_measure_tool_start (GimpMeasureTool *measure,
|
||||
measure->y[2] = 0;
|
||||
|
||||
measure->widget = gimp_tool_compass_new (shell,
|
||||
GIMP_COMPASS_ORIENTATION_AUTO,
|
||||
measure->n_points,
|
||||
measure->x[0],
|
||||
measure->y[0],
|
||||
|
Reference in New Issue
Block a user