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:
Michael Natterer
2015-11-13 18:51:32 +01:00
parent fd13b9a1f7
commit c6b6031f31
10 changed files with 198 additions and 55 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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"

View File

@ -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" />