Bug 758049 - Please add canvas flipping
Enable flipping in the canvas rotate transform matrix, and add some menu items to control it. Rename the "Rotate" menu to "Flip & Rotate".
This commit is contained in:
@ -68,7 +68,7 @@ static const GimpActionEntry view_actions[] =
|
||||
{
|
||||
{ "view-menu", NULL, NC_("view-action", "_View") },
|
||||
{ "view-zoom-menu", NULL, NC_("view-action", "_Zoom") },
|
||||
{ "view-rotate-menu", NULL, NC_("view-action", "_Rotate") },
|
||||
{ "view-rotate-menu", NULL, NC_("view-action", "_Flip & Rotate") },
|
||||
{ "view-padding-color-menu", NULL, NC_("view-action", "_Padding Color") },
|
||||
{ "view-move-to-screen-menu", GIMP_STOCK_MOVE_TO_SCREEN,
|
||||
NC_("view-action", "Move to Screen"), NULL, NULL, NULL,
|
||||
@ -394,6 +394,21 @@ static const GimpRadioActionEntry view_zoom_explicit_actions[] =
|
||||
GIMP_HELP_VIEW_ZOOM_OTHER }
|
||||
};
|
||||
|
||||
static const GimpToggleActionEntry view_flip_actions[] =
|
||||
{
|
||||
{ "view-flip-horizontally", GIMP_STOCK_FLIP_HORIZONTAL,
|
||||
NC_("view-action", "Flip Horizontally"), NULL, NULL,
|
||||
G_CALLBACK (view_flip_horizontally_cmd_callback),
|
||||
FALSE,
|
||||
GIMP_HELP_VIEW_FLIP },
|
||||
|
||||
{ "view-flip-vertically", GIMP_STOCK_FLIP_VERTICAL,
|
||||
NC_("view-action", "Flip Vertically"), NULL, NULL,
|
||||
G_CALLBACK (view_flip_vertically_cmd_callback),
|
||||
FALSE,
|
||||
GIMP_HELP_VIEW_FLIP }
|
||||
};
|
||||
|
||||
static const GimpEnumActionEntry view_rotate_absolute_actions[] =
|
||||
{
|
||||
{ "view-rotate-set-absolute", NULL,
|
||||
@ -402,8 +417,9 @@ static const GimpEnumActionEntry view_rotate_absolute_actions[] =
|
||||
NULL },
|
||||
|
||||
{ "view-rotate-reset", GIMP_STOCK_RESET,
|
||||
NC_("view-action", "_Reset to 0°"), "exclam",
|
||||
NC_("view-action", "Reset the angle of rotation to 0°"),
|
||||
NC_("view-action", "_Reset Flip & Rotate"), "exclam",
|
||||
NC_("view-action",
|
||||
"Reset flipping to unflipped and the angle of rotation to 0°"),
|
||||
GIMP_ACTION_SELECT_SET_TO_DEFAULT, FALSE,
|
||||
GIMP_HELP_VIEW_ROTATE_RESET },
|
||||
};
|
||||
@ -577,6 +593,10 @@ view_actions_setup (GimpActionGroup *group)
|
||||
10000,
|
||||
G_CALLBACK (view_zoom_explicit_cmd_callback));
|
||||
|
||||
gimp_action_group_add_toggle_actions (group, "view-action",
|
||||
view_flip_actions,
|
||||
G_N_ELEMENTS (view_flip_actions));
|
||||
|
||||
gimp_action_group_add_enum_actions (group, "view-action",
|
||||
view_rotate_absolute_actions,
|
||||
G_N_ELEMENTS (view_rotate_absolute_actions),
|
||||
@ -633,13 +653,15 @@ void
|
||||
view_actions_update (GimpActionGroup *group,
|
||||
gpointer data)
|
||||
{
|
||||
GimpDisplay *display = action_data_get_display (data);
|
||||
GimpImage *image = NULL;
|
||||
GimpDisplayShell *shell = NULL;
|
||||
GimpDisplayOptions *options = NULL;
|
||||
gchar *label = NULL;
|
||||
gboolean fullscreen = FALSE;
|
||||
gboolean revert_enabled = FALSE; /* able to revert zoom? */
|
||||
GimpDisplay *display = action_data_get_display (data);
|
||||
GimpImage *image = NULL;
|
||||
GimpDisplayShell *shell = NULL;
|
||||
GimpDisplayOptions *options = NULL;
|
||||
gchar *label = NULL;
|
||||
gboolean fullscreen = FALSE;
|
||||
gboolean revert_enabled = FALSE; /* able to revert zoom? */
|
||||
gboolean flip_horizontally = FALSE;
|
||||
gboolean flip_vertically = FALSE;
|
||||
|
||||
if (display)
|
||||
{
|
||||
@ -657,6 +679,9 @@ view_actions_update (GimpActionGroup *group,
|
||||
shell->no_image_options);
|
||||
|
||||
revert_enabled = gimp_display_shell_scale_can_revert (shell);
|
||||
|
||||
flip_horizontally = shell->flip_horizontally;
|
||||
flip_vertically = shell->flip_vertically;
|
||||
}
|
||||
|
||||
#define SET_ACTIVE(action,condition) \
|
||||
@ -686,44 +711,50 @@ view_actions_update (GimpActionGroup *group,
|
||||
_("Re_vert Zoom"));
|
||||
}
|
||||
|
||||
SET_SENSITIVE ("view-zoom", image);
|
||||
SET_SENSITIVE ("view-zoom-minimum", image);
|
||||
SET_SENSITIVE ("view-zoom-maximum", image);
|
||||
SET_SENSITIVE ("view-zoom-in", image);
|
||||
SET_SENSITIVE ("view-zoom-in-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-in-skip", image);
|
||||
SET_SENSITIVE ("view-zoom-out", image);
|
||||
SET_SENSITIVE ("view-zoom-out-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-out-skip", image);
|
||||
SET_SENSITIVE ("view-zoom", image);
|
||||
SET_SENSITIVE ("view-zoom-minimum", image);
|
||||
SET_SENSITIVE ("view-zoom-maximum", image);
|
||||
SET_SENSITIVE ("view-zoom-in", image);
|
||||
SET_SENSITIVE ("view-zoom-in-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-in-skip", image);
|
||||
SET_SENSITIVE ("view-zoom-out", image);
|
||||
SET_SENSITIVE ("view-zoom-out-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-out-skip", image);
|
||||
|
||||
SET_SENSITIVE ("view-zoom-fit-in", image);
|
||||
SET_SENSITIVE ("view-zoom-fill", image);
|
||||
SET_SENSITIVE ("view-zoom-selection", image);
|
||||
SET_SENSITIVE ("view-zoom-revert", image);
|
||||
SET_SENSITIVE ("view-zoom-fit-in", image);
|
||||
SET_SENSITIVE ("view-zoom-fill", image);
|
||||
SET_SENSITIVE ("view-zoom-selection", image);
|
||||
SET_SENSITIVE ("view-zoom-revert", image);
|
||||
|
||||
SET_SENSITIVE ("view-zoom-16-1", image);
|
||||
SET_SENSITIVE ("view-zoom-16-1-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-8-1", image);
|
||||
SET_SENSITIVE ("view-zoom-8-1-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-4-1", image);
|
||||
SET_SENSITIVE ("view-zoom-4-1-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-2-1", image);
|
||||
SET_SENSITIVE ("view-zoom-2-1-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-1-1", image);
|
||||
SET_SENSITIVE ("view-zoom-1-1-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-1-2", image);
|
||||
SET_SENSITIVE ("view-zoom-1-4", image);
|
||||
SET_SENSITIVE ("view-zoom-1-8", image);
|
||||
SET_SENSITIVE ("view-zoom-1-16", image);
|
||||
SET_SENSITIVE ("view-zoom-other", image);
|
||||
SET_SENSITIVE ("view-zoom-16-1", image);
|
||||
SET_SENSITIVE ("view-zoom-16-1-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-8-1", image);
|
||||
SET_SENSITIVE ("view-zoom-8-1-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-4-1", image);
|
||||
SET_SENSITIVE ("view-zoom-4-1-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-2-1", image);
|
||||
SET_SENSITIVE ("view-zoom-2-1-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-1-1", image);
|
||||
SET_SENSITIVE ("view-zoom-1-1-accel", image);
|
||||
SET_SENSITIVE ("view-zoom-1-2", image);
|
||||
SET_SENSITIVE ("view-zoom-1-4", image);
|
||||
SET_SENSITIVE ("view-zoom-1-8", image);
|
||||
SET_SENSITIVE ("view-zoom-1-16", image);
|
||||
SET_SENSITIVE ("view-zoom-other", image);
|
||||
|
||||
SET_SENSITIVE ("view-rotate-reset", image);
|
||||
SET_SENSITIVE ("view-rotate-15", image);
|
||||
SET_SENSITIVE ("view-rotate-345", image);
|
||||
SET_SENSITIVE ("view-rotate-90", image);
|
||||
SET_SENSITIVE ("view-rotate-180", image);
|
||||
SET_SENSITIVE ("view-rotate-270", image);
|
||||
SET_SENSITIVE ("view-rotate-other", image);
|
||||
SET_SENSITIVE ("view-flip-horizontally", image);
|
||||
SET_ACTIVE ("view-flip-horizontally", flip_horizontally);
|
||||
|
||||
SET_SENSITIVE ("view-flip-vertically", image);
|
||||
SET_ACTIVE ("view-flip-vertically", flip_vertically);
|
||||
|
||||
SET_SENSITIVE ("view-rotate-reset", image);
|
||||
SET_SENSITIVE ("view-rotate-15", image);
|
||||
SET_SENSITIVE ("view-rotate-345", image);
|
||||
SET_SENSITIVE ("view-rotate-90", image);
|
||||
SET_SENSITIVE ("view-rotate-180", image);
|
||||
SET_SENSITIVE ("view-rotate-270", image);
|
||||
SET_SENSITIVE ("view-rotate-other", image);
|
||||
|
||||
if (image)
|
||||
{
|
||||
@ -866,9 +897,32 @@ static void
|
||||
view_actions_set_rotate (GimpActionGroup *group,
|
||||
GimpDisplayShell *shell)
|
||||
{
|
||||
gchar *label;
|
||||
const gchar *flip;
|
||||
gchar *label;
|
||||
|
||||
label = g_strdup_printf (_("_Rotate (%d°)"), (gint) shell->rotate_angle);
|
||||
if (shell->flip_horizontally &&
|
||||
shell->flip_vertically)
|
||||
{
|
||||
/* please preserve the trailing space */
|
||||
flip = _("(H+V) ");
|
||||
}
|
||||
else if (shell->flip_horizontally)
|
||||
{
|
||||
/* please preserve the trailing space */
|
||||
flip = _("(H) ");
|
||||
}
|
||||
else if (shell->flip_vertically)
|
||||
{
|
||||
/* please preserve the trailing space */
|
||||
flip = _("(V) ");
|
||||
}
|
||||
else
|
||||
{
|
||||
flip = "";
|
||||
}
|
||||
|
||||
label = g_strdup_printf (_("_Flip %s& Rotate (%d°)"),
|
||||
flip, (gint) shell->rotate_angle);
|
||||
gimp_action_group_set_action_label (group, "view-rotate-menu", label);
|
||||
g_free (label);
|
||||
}
|
||||
|
@ -305,6 +305,44 @@ view_dot_for_dot_cmd_callback (GtkAction *action,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
view_flip_horizontally_cmd_callback (GtkAction *action,
|
||||
gpointer data)
|
||||
{
|
||||
GimpDisplay *display;
|
||||
GimpDisplayShell *shell;
|
||||
gboolean active;
|
||||
return_if_no_display (display, data);
|
||||
|
||||
shell = gimp_display_get_shell (display);
|
||||
|
||||
active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
|
||||
|
||||
if (active != shell->flip_horizontally)
|
||||
{
|
||||
gimp_display_shell_flip (shell, active, shell->flip_vertically);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
view_flip_vertically_cmd_callback (GtkAction *action,
|
||||
gpointer data)
|
||||
{
|
||||
GimpDisplay *display;
|
||||
GimpDisplayShell *shell;
|
||||
gboolean active;
|
||||
return_if_no_display (display, data);
|
||||
|
||||
shell = gimp_display_get_shell (display);
|
||||
|
||||
active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
|
||||
|
||||
if (active != shell->flip_vertically)
|
||||
{
|
||||
gimp_display_shell_flip (shell, shell->flip_horizontally, active);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
view_rotate_absolute_cmd_callback (GtkAction *action,
|
||||
gint value,
|
||||
@ -324,6 +362,9 @@ view_rotate_absolute_cmd_callback (GtkAction *action,
|
||||
TRUE);
|
||||
|
||||
gimp_display_shell_rotate_to (shell, angle);
|
||||
|
||||
if (value == GIMP_ACTION_SELECT_SET_TO_DEFAULT)
|
||||
gimp_display_shell_flip (shell, FALSE, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -50,6 +50,11 @@ void view_scroll_vertical_cmd_callback (GtkAction *action,
|
||||
gint value,
|
||||
gpointer data);
|
||||
|
||||
void view_flip_horizontally_cmd_callback (GtkAction *action,
|
||||
gpointer data);
|
||||
void view_flip_vertically_cmd_callback (GtkAction *action,
|
||||
gpointer data);
|
||||
|
||||
void view_rotate_absolute_cmd_callback (GtkAction *action,
|
||||
gint value,
|
||||
gpointer data);
|
||||
|
@ -33,6 +33,24 @@
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
gimp_display_shell_flip (GimpDisplayShell *shell,
|
||||
gboolean flip_horizontally,
|
||||
gboolean flip_vertically)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||||
|
||||
if (flip_horizontally != shell->flip_horizontally ||
|
||||
flip_vertically != shell->flip_vertically)
|
||||
{
|
||||
shell->flip_horizontally = flip_horizontally ? TRUE : FALSE;
|
||||
shell->flip_vertically = flip_vertically ? TRUE : FALSE;
|
||||
|
||||
gimp_display_shell_rotated (shell);
|
||||
gimp_display_shell_expose_full (shell);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gimp_display_shell_rotate (GimpDisplayShell *shell,
|
||||
gdouble delta)
|
||||
@ -119,7 +137,10 @@ gimp_display_shell_rotate_update_transform (GimpDisplayShell *shell)
|
||||
g_free (shell->rotate_transform);
|
||||
g_free (shell->rotate_untransform);
|
||||
|
||||
if (shell->rotate_angle != 0.0 && gimp_display_get_image (shell->display))
|
||||
if ((shell->rotate_angle != 0.0 ||
|
||||
shell->flip_horizontally ||
|
||||
shell->flip_vertically) &&
|
||||
gimp_display_get_image (shell->display))
|
||||
{
|
||||
gint image_width, image_height;
|
||||
gdouble cx, cy;
|
||||
@ -134,8 +155,17 @@ gimp_display_shell_rotate_update_transform (GimpDisplayShell *shell)
|
||||
cy = -shell->offset_y + image_height / 2;
|
||||
|
||||
cairo_matrix_init_translate (shell->rotate_transform, cx, cy);
|
||||
cairo_matrix_rotate (shell->rotate_transform,
|
||||
shell->rotate_angle / 180.0 * G_PI);
|
||||
|
||||
if (shell->rotate_angle != 0.0)
|
||||
cairo_matrix_rotate (shell->rotate_transform,
|
||||
shell->rotate_angle / 180.0 * G_PI);
|
||||
|
||||
if (shell->flip_horizontally)
|
||||
cairo_matrix_scale (shell->rotate_transform, -1.0, 1.0);
|
||||
|
||||
if (shell->flip_vertically)
|
||||
cairo_matrix_scale (shell->rotate_transform, 1.0, -1.0);
|
||||
|
||||
cairo_matrix_translate (shell->rotate_transform, -cx, -cy);
|
||||
|
||||
*shell->rotate_untransform = *shell->rotate_transform;
|
||||
|
@ -19,6 +19,10 @@
|
||||
#define __GIMP_DISPLAY_SHELL_ROTATE_H__
|
||||
|
||||
|
||||
void gimp_display_shell_flip (GimpDisplayShell *shell,
|
||||
gboolean flip_horizontally,
|
||||
gboolean flip_vertically);
|
||||
|
||||
void gimp_display_shell_rotate (GimpDisplayShell *shell,
|
||||
gdouble delta);
|
||||
void gimp_display_shell_rotate_to (GimpDisplayShell *shell,
|
||||
|
@ -61,8 +61,8 @@ void gimp_display_shell_zoom_segments (const GimpDisplayShell *shell,
|
||||
gdouble offset_y);
|
||||
|
||||
|
||||
/* rotate: functions to transform from unrotated but zoomed display
|
||||
* space to rotated display space and back
|
||||
/* rotate: functions to transform from unrotated and unflipped but
|
||||
* zoomed display space to rotated and filpped display space and back
|
||||
*/
|
||||
|
||||
void gimp_display_shell_rotate_coords (const GimpDisplayShell *shell,
|
||||
@ -114,8 +114,9 @@ void gimp_display_shell_unrotate_bounds (GimpDisplayShell *shell,
|
||||
gdouble *ny2);
|
||||
|
||||
|
||||
/* transform: functions to transform from image space to rotated display
|
||||
* space and back, taking into account scroll offset, scale, and rotation
|
||||
/* transform: functions to transform from image space to rotated
|
||||
* display space and back, taking into account scroll offset, scale,
|
||||
* rotation and flipping
|
||||
*/
|
||||
|
||||
void gimp_display_shell_transform_coords (const GimpDisplayShell *shell,
|
||||
|
@ -1472,7 +1472,9 @@ gimp_display_shell_empty (GimpDisplayShell *shell)
|
||||
|
||||
gimp_statusbar_empty (GIMP_STATUSBAR (shell->statusbar));
|
||||
|
||||
shell->rotate_angle = 0.0;
|
||||
shell->flip_horizontally = FALSE;
|
||||
shell->flip_vertically = FALSE;
|
||||
shell->rotate_angle = 0.0;
|
||||
gimp_display_shell_rotate_update_transform (shell);
|
||||
|
||||
gimp_display_shell_expose_full (shell);
|
||||
|
@ -67,6 +67,8 @@ struct _GimpDisplayShell
|
||||
gdouble scale_x; /* horizontal scale factor */
|
||||
gdouble scale_y; /* vertical scale factor */
|
||||
|
||||
gboolean flip_horizontally;
|
||||
gboolean flip_vertically;
|
||||
gdouble rotate_angle;
|
||||
cairo_matrix_t *rotate_transform;
|
||||
cairo_matrix_t *rotate_untransform;
|
||||
|
@ -88,6 +88,7 @@
|
||||
#define GIMP_HELP_VIEW_ZOOM_FILL "gimp-view-zoom-fill"
|
||||
#define GIMP_HELP_VIEW_ZOOM_SELECTION "gimp-view-zoom-selection"
|
||||
#define GIMP_HELP_VIEW_ZOOM_OTHER "gimp-view-zoom-other"
|
||||
#define GIMP_HELP_VIEW_FLIP "gimp-view-flip"
|
||||
#define GIMP_HELP_VIEW_ROTATE_RESET "gimp-view-rotate-reset"
|
||||
#define GIMP_HELP_VIEW_ROTATE_15 "gimp-view-rotate-15"
|
||||
#define GIMP_HELP_VIEW_ROTATE_90 "gimp-view-rotate-90"
|
||||
|
@ -277,6 +277,9 @@
|
||||
<menu action="view-rotate-menu" name="Rotate">
|
||||
<menuitem action="view-rotate-reset" />
|
||||
<separator />
|
||||
<menuitem action="view-flip-horizontally" />
|
||||
<menuitem action="view-flip-vertically" />
|
||||
<separator />
|
||||
<menuitem action="view-rotate-15" />
|
||||
<menuitem action="view-rotate-345" />
|
||||
<menuitem action="view-rotate-90" />
|
||||
|
Reference in New Issue
Block a user