[gimp] app, menus: add "show all" mode to GimpDisplayShell; "View -> Show All" toggle
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app, menus: add "show all" mode to GimpDisplayShell; "View -> Show All" toggle
- Date: Wed, 4 Sep 2019 18:00:28 +0000 (UTC)
commit 86dc451bce69b33b29c7cf46a02864cc75fc8fcf
Author: Ell <ell_se yahoo com>
Date: Wed Sep 4 15:50:29 2019 +0300
app, menus: add "show all" mode to GimpDisplayShell; "View -> Show All" toggle
Add a "show all" mode to GimpDisplayShell, controlled through a
corresponding "View -> Show All" menu item. When enabled, the
entire image content is displayed, instead of cropping the image
to the canvas size. More generally, the display behaves as if the
canvas were infinite. The following commits improve the overall
behavior in this mode.
Add a prefernces option to control the default "show all" state.
app/actions/view-actions.c | 13 +++-
app/actions/view-commands.c | 30 +++++++++
app/actions/view-commands.h | 4 ++
app/config/gimpdisplayconfig.c | 14 ++++
app/config/gimpdisplayconfig.h | 1 +
app/config/gimprc-blurbs.h | 3 +
app/dialogs/preferences-dialog.c | 6 +-
app/display/gimpdisplay-handlers.c | 40 ++++++++---
app/display/gimpdisplay.c | 76 ++++++++++++++++-----
app/display/gimpdisplay.h | 3 +
app/display/gimpdisplayshell-callbacks.c | 66 +++++++++++++-----
app/display/gimpdisplayshell-handlers.c | 14 ++++
app/display/gimpdisplayshell-render.c | 17 +++--
app/display/gimpdisplayshell-scale.c | 112 +++++++++++++++++++++++++++++++
app/display/gimpdisplayshell-scale.h | 12 ++++
app/display/gimpdisplayshell.c | 103 +++++++++++++++++++++++++++-
app/display/gimpdisplayshell.h | 9 +++
app/widgets/gimphelp-ids.h | 1 +
menus/image-menu.xml.in | 1 +
19 files changed, 476 insertions(+), 49 deletions(-)
---
diff --git a/app/actions/view-actions.c b/app/actions/view-actions.c
index 4d577a4a1a..852e2df542 100644
--- a/app/actions/view-actions.c
+++ b/app/actions/view-actions.c
@@ -172,6 +172,14 @@ static const GimpActionEntry view_actions[] =
static const GimpToggleActionEntry view_toggle_actions[] =
{
+
+ { "view-show-all", NULL,
+ NC_("view-action", "Show _All"), NULL,
+ NC_("view-action", "Show full image content"),
+ view_show_all_cmd_callback,
+ FALSE,
+ GIMP_HELP_VIEW_SHOW_ALL },
+
{ "view-dot-for-dot", NULL,
NC_("view-action", "_Dot for Dot"), NULL,
NC_("view-action", "A pixel on the screen represents an image pixel"),
@@ -251,7 +259,7 @@ static const GimpToggleActionEntry view_toggle_actions[] =
GIMP_HELP_VIEW_SHOW_SAMPLE_POINTS },
{ "view-snap-to-guides", NULL,
- NC_("view-action", "Sn_ap to Guides"), NULL,
+ NC_("view-action", "Snap to Gu_ides"), NULL,
NC_("view-action", "Tool operations snap to guides"),
view_snap_to_guides_cmd_callback,
TRUE,
@@ -899,6 +907,9 @@ view_actions_update (GimpActionGroup *group,
SET_SENSITIVE ("view-new", image);
SET_SENSITIVE ("view-close", image);
+ SET_SENSITIVE ("view-show-all", image);
+ SET_ACTIVE ("view-show-all", display && shell->show_all);
+
SET_SENSITIVE ("view-dot-for-dot", image);
SET_ACTIVE ("view-dot-for-dot", display && shell->dot_for_dot);
diff --git a/app/actions/view-commands.c b/app/actions/view-commands.c
index 3e17f3276f..71026c527d 100644
--- a/app/actions/view-commands.c
+++ b/app/actions/view-commands.c
@@ -309,6 +309,36 @@ view_zoom_other_cmd_callback (GimpAction *action,
}
}
+void
+view_show_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpDisplayShell *shell;
+ gboolean active;
+ return_if_no_display (display, data);
+
+ shell = gimp_display_get_shell (display);
+
+ active = g_variant_get_boolean (value);
+
+ if (active != shell->show_all)
+ {
+ GimpImageWindow *window = gimp_display_shell_get_window (shell);
+
+ gimp_display_shell_set_show_all (shell, active);
+
+ if (window)
+ SET_ACTIVE (gimp_image_window_get_ui_manager (window),
+ "view-show-all", shell->show_all);
+
+ if (IS_ACTIVE_DISPLAY (display))
+ SET_ACTIVE (shell->popup_manager, "view-show-all",
+ shell->show_all);
+ }
+}
+
void
view_dot_for_dot_cmd_callback (GimpAction *action,
GVariant *value,
diff --git a/app/actions/view-commands.h b/app/actions/view-commands.h
index 72afae9b2c..c28a24ef2e 100644
--- a/app/actions/view-commands.h
+++ b/app/actions/view-commands.h
@@ -53,6 +53,10 @@ void view_zoom_explicit_cmd_callback (GimpAction *action,
void view_zoom_other_cmd_callback (GimpAction *action,
gpointer data);
+void view_show_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data);
+
void view_dot_for_dot_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
diff --git a/app/config/gimpdisplayconfig.c b/app/config/gimpdisplayconfig.c
index 1e285ca518..3c55522020 100644
--- a/app/config/gimpdisplayconfig.c
+++ b/app/config/gimpdisplayconfig.c
@@ -51,6 +51,7 @@ enum
PROP_MARCHING_ANTS_SPEED,
PROP_RESIZE_WINDOWS_ON_ZOOM,
PROP_RESIZE_WINDOWS_ON_RESIZE,
+ PROP_DEFAULT_SHOW_ALL,
PROP_DEFAULT_DOT_FOR_DOT,
PROP_INITIAL_ZOOM_TO_FIT,
PROP_CURSOR_MODE,
@@ -158,6 +159,13 @@ gimp_display_config_class_init (GimpDisplayConfigClass *klass)
FALSE,
GIMP_PARAM_STATIC_STRINGS);
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_DEFAULT_SHOW_ALL,
+ "default-show-all",
+ "Default show-all",
+ DEFAULT_SHOW_ALL_BLURB,
+ FALSE,
+ GIMP_PARAM_STATIC_STRINGS);
+
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_DEFAULT_DOT_FOR_DOT,
"default-dot-for-dot",
"Default dot-for-dot",
@@ -401,6 +409,9 @@ gimp_display_config_set_property (GObject *object,
case PROP_RESIZE_WINDOWS_ON_RESIZE:
display_config->resize_windows_on_resize = g_value_get_boolean (value);
break;
+ case PROP_DEFAULT_SHOW_ALL:
+ display_config->default_show_all = g_value_get_boolean (value);
+ break;
case PROP_DEFAULT_DOT_FOR_DOT:
display_config->default_dot_for_dot = g_value_get_boolean (value);
break;
@@ -507,6 +518,9 @@ gimp_display_config_get_property (GObject *object,
case PROP_RESIZE_WINDOWS_ON_RESIZE:
g_value_set_boolean (value, display_config->resize_windows_on_resize);
break;
+ case PROP_DEFAULT_SHOW_ALL:
+ g_value_set_boolean (value, display_config->default_show_all);
+ break;
case PROP_DEFAULT_DOT_FOR_DOT:
g_value_set_boolean (value, display_config->default_dot_for_dot);
break;
diff --git a/app/config/gimpdisplayconfig.h b/app/config/gimpdisplayconfig.h
index 2c6c05b0dd..3fe2050047 100644
--- a/app/config/gimpdisplayconfig.h
+++ b/app/config/gimpdisplayconfig.h
@@ -47,6 +47,7 @@ struct _GimpDisplayConfig
gint marching_ants_speed;
gboolean resize_windows_on_zoom;
gboolean resize_windows_on_resize;
+ gboolean default_show_all;
gboolean default_dot_for_dot;
gboolean initial_zoom_to_fit;
GimpCursorMode cursor_mode;
diff --git a/app/config/gimprc-blurbs.h b/app/config/gimprc-blurbs.h
index 9b64a19fdb..e710fd6021 100644
--- a/app/config/gimprc-blurbs.h
+++ b/app/config/gimprc-blurbs.h
@@ -67,6 +67,9 @@ _("Context-dependent mouse pointers are helpful. They are enabled by " \
"Specify a default tool preset. The tool preset is searched for in the " \
"specified tool prests path."
+#define DEFAULT_SHOW_ALL_BLURB \
+_("Show full image content by default.")
+
#define DEFAULT_DOT_FOR_DOT_BLURB \
_("When enabled, this will ensure that each pixel of an image gets " \
"mapped to a pixel on the screen.")
diff --git a/app/dialogs/preferences-dialog.c b/app/dialogs/preferences-dialog.c
index 71a2a72b39..af827c335b 100644
--- a/app/dialogs/preferences-dialog.c
+++ b/app/dialogs/preferences-dialog.c
@@ -2817,6 +2817,10 @@ prefs_dialog_new (Gimp *gimp,
/* General */
vbox2 = prefs_frame_new (_("General"), GTK_CONTAINER (vbox), FALSE);
+ prefs_check_button_add (object, "default-show-all",
+ _("Use \"Show _all\" by default"),
+ GTK_BOX (vbox2));
+
prefs_check_button_add (object, "default-dot-for-dot",
_("Use \"_Dot for dot\" by default"),
GTK_BOX (vbox2));
@@ -2824,7 +2828,7 @@ prefs_dialog_new (Gimp *gimp,
grid = prefs_grid_new (GTK_CONTAINER (vbox2));
prefs_spin_button_add (object, "marching-ants-speed", 1.0, 10.0, 0,
- _("Marching _ants speed:"),
+ _("Marching ants s_peed:"),
GTK_GRID (grid), 0, size_group);
/* Zoom & Resize Behavior */
diff --git a/app/display/gimpdisplay-handlers.c b/app/display/gimpdisplay-handlers.c
index a255d8c667..94cb863ad7 100644
--- a/app/display/gimpdisplay-handlers.c
+++ b/app/display/gimpdisplay-handlers.c
@@ -30,16 +30,21 @@
/* local function prototypes */
-static void gimp_display_update_handler (GimpProjection *projection,
- gboolean now,
- gint x,
- gint y,
- gint w,
- gint h,
- GimpDisplay *display);
-static void gimp_display_flush_handler (GimpImage *image,
- gboolean invalidate_preview,
- GimpDisplay *display);
+static void gimp_display_update_handler (GimpProjection *projection,
+ gboolean now,
+ gint x,
+ gint y,
+ gint w,
+ gint h,
+ GimpDisplay *display);
+
+static void gimp_display_bounds_changed_handler (GimpImage *image,
+ gint old_x,
+ gint old_y,
+ GimpDisplay *display);
+static void gimp_display_flush_handler (GimpImage *image,
+ gboolean invalidate_preview,
+ GimpDisplay *display);
/* public functions */
@@ -59,6 +64,9 @@ gimp_display_connect (GimpDisplay *display)
G_CALLBACK (gimp_display_update_handler),
display);
+ g_signal_connect (image, "bounds-changed",
+ G_CALLBACK (gimp_display_bounds_changed_handler),
+ display);
g_signal_connect (image, "flush",
G_CALLBACK (gimp_display_flush_handler),
display);
@@ -78,6 +86,9 @@ gimp_display_disconnect (GimpDisplay *display)
g_signal_handlers_disconnect_by_func (image,
gimp_display_flush_handler,
display);
+ g_signal_handlers_disconnect_by_func (image,
+ gimp_display_bounds_changed_handler,
+ display);
g_signal_handlers_disconnect_by_func (gimp_image_get_projection (image),
gimp_display_update_handler,
@@ -99,6 +110,15 @@ gimp_display_update_handler (GimpProjection *projection,
gimp_display_update_area (display, now, x, y, w, h);
}
+static void
+gimp_display_bounds_changed_handler (GimpImage *image,
+ gint old_x,
+ gint old_y,
+ GimpDisplay *display)
+{
+ gimp_display_update_bounding_box (display);
+}
+
static void
gimp_display_flush_handler (GimpImage *image,
gboolean invalidate_preview,
diff --git a/app/display/gimpdisplay.c b/app/display/gimpdisplay.c
index 905cdc7142..8f076edab1 100644
--- a/app/display/gimpdisplay.c
+++ b/app/display/gimpdisplay.c
@@ -70,6 +70,8 @@ struct _GimpDisplayImplPrivate
gint instance; /* the instance # of this display as
* taken from the image at creation */
+ GeglRectangle bounding_box;
+
GtkWidget *shell;
cairo_region_t *update_region;
};
@@ -385,6 +387,8 @@ gimp_display_new (Gimp *gimp,
shell = gimp_display_get_shell (display);
+ gimp_display_update_bounding_box (display);
+
gimp_image_window_add_shell (window, shell);
gimp_display_shell_present (shell);
@@ -579,6 +583,8 @@ gimp_display_set_image (GimpDisplay *display,
if (old_image)
g_object_unref (old_image);
+ gimp_display_update_bounding_box (display);
+
if (shell)
{
if (image)
@@ -653,6 +659,48 @@ gimp_display_fill (GimpDisplay *display,
image, unit, scale);
}
+void
+gimp_display_update_bounding_box (GimpDisplay *display)
+{
+ GimpDisplayImplPrivate *private;
+ GimpDisplayShell *shell;
+ GeglRectangle bounding_box = {};
+
+ g_return_if_fail (GIMP_IS_DISPLAY (display));
+
+ private = GIMP_DISPLAY_IMPL (display)->priv;
+ shell = gimp_display_get_shell (display);
+
+ if (shell)
+ {
+ bounding_box = gimp_display_shell_get_bounding_box (shell);
+
+ if (! gegl_rectangle_equal (&bounding_box, &private->bounding_box))
+ {
+ GeglRectangle diff_rects[4];
+ gint n_diff_rects;
+ gint i;
+
+ n_diff_rects = gegl_rectangle_subtract (diff_rects,
+ &private->bounding_box,
+ &bounding_box);
+
+ for (i = 0; i < n_diff_rects; i++)
+ {
+ gimp_display_paint_area (display,
+ diff_rects[i].x, diff_rects[i].y,
+ diff_rects[i].width, diff_rects[i].height);
+ }
+
+ private->bounding_box = bounding_box;
+ }
+ }
+ else
+ {
+ private->bounding_box = bounding_box;
+ }
+}
+
void
gimp_display_update_area (GimpDisplay *display,
gboolean now,
@@ -748,27 +796,25 @@ gimp_display_paint_area (GimpDisplay *display,
gint w,
gint h)
{
- GimpDisplayImplPrivate *private = GIMP_DISPLAY_IMPL (display)->priv;
- GimpDisplayShell *shell = gimp_display_get_shell (display);
- gint image_width = gimp_image_get_width (private->image);
- gint image_height = gimp_image_get_height (private->image);
+ GimpDisplayImplPrivate *private = GIMP_DISPLAY_IMPL (display)->priv;
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+ GeglRectangle rect;
gint x1, y1, x2, y2;
gdouble x1_f, y1_f, x2_f, y2_f;
- /* Bounds check */
- x1 = CLAMP (x, 0, image_width);
- y1 = CLAMP (y, 0, image_height);
- x2 = CLAMP (x + w, 0, image_width);
- y2 = CLAMP (y + h, 0, image_height);
-
- x = x1;
- y = y1;
- w = (x2 - x1);
- h = (y2 - y1);
+ if (! gegl_rectangle_intersect (&rect,
+ &private->bounding_box,
+ GEGL_RECTANGLE (x, y, w, h)))
+ {
+ return;
+ }
/* display the area */
gimp_display_shell_transform_bounds (shell,
- x, y, x + w, y + h,
+ rect.x,
+ rect.y,
+ rect.x + rect.width,
+ rect.y + rect.height,
&x1_f, &y1_f, &x2_f, &y2_f);
/* make sure to expose a superset of the transformed sub-pixel expose
diff --git a/app/display/gimpdisplay.h b/app/display/gimpdisplay.h
index 6fbb5154fa..b928fdbf2b 100644
--- a/app/display/gimpdisplay.h
+++ b/app/display/gimpdisplay.h
@@ -77,6 +77,9 @@ void gimp_display_fill (GimpDisplay *display,
GimpUnit unit,
gdouble scale);
+void gimp_display_update_bounding_box
+ (GimpDisplay *display);
+
void gimp_display_update_area (GimpDisplay *display,
gboolean now,
gint x,
diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c
index 31a5ae00c5..3662c180e8 100644
--- a/app/display/gimpdisplayshell-callbacks.c
+++ b/app/display/gimpdisplayshell-callbacks.c
@@ -44,6 +44,7 @@
#include "gimpdisplayshell-scrollbars.h"
#include "gimpdisplayshell-selection.h"
#include "gimpdisplayshell-title.h"
+#include "gimpdisplayshell-transform.h"
#include "gimpimagewindow.h"
#include "gimpnavigationeditor.h"
@@ -468,14 +469,18 @@ gimp_display_shell_canvas_draw_image (GimpDisplayShell *shell,
cairo_t *cr)
{
cairo_rectangle_list_t *clip_rectangles;
- cairo_rectangle_int_t image_rect;
+ GeglRectangle image_rect;
+ GeglRectangle rotated_image_rect;
cairo_matrix_t matrix;
+ gdouble x1, y1;
+ gdouble x2, y2;
- image_rect.x = - shell->offset_x;
- image_rect.y = - shell->offset_y;
- gimp_display_shell_scale_get_image_size (shell,
- &image_rect.width,
- &image_rect.height);
+ gimp_display_shell_scale_get_image_unrotated_bounding_box (
+ shell,
+ &image_rect.x,
+ &image_rect.y,
+ &image_rect.width,
+ &image_rect.height);
/* first, draw the background
*/
@@ -494,6 +499,13 @@ gimp_display_shell_canvas_draw_image (GimpDisplayShell *shell,
if (shell->rotate_transform)
cairo_transform (cr, shell->rotate_transform);
+ if (shell->show_all)
+ {
+ cairo_save (cr);
+ gimp_display_shell_draw_checkerboard (shell, cr);
+ cairo_restore (cr);
+ }
+
cairo_rectangle (cr,
image_rect.x,
image_rect.y,
@@ -501,13 +513,28 @@ gimp_display_shell_canvas_draw_image (GimpDisplayShell *shell,
image_rect.height);
cairo_clip (cr);
+ gimp_display_shell_rotate_bounds (shell,
+ image_rect.x,
+ image_rect.y,
+ image_rect.x + image_rect.width,
+ image_rect.y + image_rect.height,
+ &x1, &y1, &x2, &y2);
+
+ rotated_image_rect.x = floor (x1);
+ rotated_image_rect.y = floor (y1);
+ rotated_image_rect.width = ceil (x2) - rotated_image_rect.x;
+ rotated_image_rect.height = ceil (y2) - rotated_image_rect.y;
+
if (gdk_cairo_get_clip_rectangle (cr, NULL))
{
gint i;
- cairo_save (cr);
- gimp_display_shell_draw_checkerboard (shell, cr);
- cairo_restore (cr);
+ if (! shell->show_all)
+ {
+ cairo_save (cr);
+ gimp_display_shell_draw_checkerboard (shell, cr);
+ cairo_restore (cr);
+ }
if (shell->show_image)
{
@@ -515,13 +542,20 @@ gimp_display_shell_canvas_draw_image (GimpDisplayShell *shell,
for (i = 0; i < clip_rectangles->num_rectangles; i++)
{
- cairo_rectangle_t rect = clip_rectangles->rectangles[i];
-
- gimp_display_shell_draw_image (shell, cr,
- floor (rect.x),
- floor (rect.y),
- ceil (rect.width),
- ceil (rect.height));
+ cairo_rectangle_t clip_rect = clip_rectangles->rectangles[i];
+ GeglRectangle rect;
+
+ rect.x = floor (clip_rect.x);
+ rect.y = floor (clip_rect.y);
+ rect.width = ceil (clip_rect.x + clip_rect.width) - rect.x;
+ rect.height = ceil (clip_rect.y + clip_rect.height) - rect.y;
+
+ if (gegl_rectangle_intersect (&rect, &rect, &rotated_image_rect))
+ {
+ gimp_display_shell_draw_image (shell, cr,
+ rect.x, rect.y,
+ rect.width, rect.height);
+ }
}
}
}
diff --git a/app/display/gimpdisplayshell-handlers.c b/app/display/gimpdisplayshell-handlers.c
index d3bac52f1c..efb82fb8fd 100644
--- a/app/display/gimpdisplayshell-handlers.c
+++ b/app/display/gimpdisplayshell-handlers.c
@@ -387,6 +387,13 @@ gimp_display_shell_connect (GimpDisplayShell *shell)
gimp_canvas_layer_boundary_set_layer (GIMP_CANVAS_LAYER_BOUNDARY (shell->layer_boundary),
gimp_image_get_active_layer (image));
+
+ if (shell->show_all)
+ {
+ gimp_image_inc_show_all_count (image);
+
+ gimp_image_flush (image);
+ }
}
void
@@ -550,6 +557,13 @@ gimp_display_shell_disconnect (GimpDisplayShell *shell)
g_signal_handlers_disconnect_by_func (image,
gimp_display_shell_clean_dirty_handler,
shell);
+
+ if (shell->show_all)
+ {
+ gimp_image_dec_show_all_count (image);
+
+ gimp_image_flush (image);
+ }
}
diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c
index 61631cef80..f49a8206ef 100644
--- a/app/display/gimpdisplayshell-render.c
+++ b/app/display/gimpdisplayshell-render.c
@@ -143,6 +143,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
gint y;
gint width;
gint height;
+ GeglAbyssPolicy abyss_policy;
gint filter = GEGL_BUFFER_FILTER_AUTO;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
@@ -166,13 +167,19 @@ gimp_display_shell_render (GimpDisplayShell *shell,
display_config = shell->display->config;
+ if (shell->show_all)
+ abyss_policy = GEGL_ABYSS_NONE;
+ else
+ abyss_policy = GEGL_ABYSS_CLAMP;
+
if (display_config->zoom_quality != GIMP_ZOOM_QUALITY_HIGH)
{
filter = GEGL_BUFFER_FILTER_NEAREST;
}
image = gimp_display_get_image (shell->display);
- buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (image));
+ buffer = gimp_pickable_get_buffer (
+ gimp_display_shell_get_pickable (shell));
#ifdef USE_NODE_BLIT
node = gimp_projectable_get_graph (GIMP_PROJECTABLE (image));
@@ -265,7 +272,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
GEGL_RECTANGLE (x, y, width, height), scale,
gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
shell->profile_data, shell->profile_stride,
- GEGL_ABYSS_CLAMP | filter);
+ abyss_policy | filter);
#else
gegl_node_blit (node,
scale, GEGL_RECTANGLE (x, y, width, height),
@@ -283,7 +290,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
GEGL_RECTANGLE (x, y, width, height), scale,
shell->filter_format,
shell->filter_data, shell->filter_stride,
- GEGL_ABYSS_CLAMP | filter);
+ abyss_policy | filter);
#else
gegl_node_blit (node,
scale, GEGL_RECTANGLE (x, y, width, height),
@@ -396,7 +403,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
GEGL_RECTANGLE (0, 0, width, height), 1.0,
babl_format ("cairo-ARGB32"),
cairo_data, cairo_stride,
- GEGL_ABYSS_CLAMP);
+ GEGL_ABYSS_NONE);
}
}
else
@@ -409,7 +416,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
GEGL_RECTANGLE (x, y, width, height), scale,
babl_format ("cairo-ARGB32"),
cairo_data, cairo_stride,
- GEGL_ABYSS_CLAMP | filter);
+ abyss_policy | filter);
#else
gegl_node_blit (node,
scale, GEGL_RECTANGLE (x, y, width, height),
diff --git a/app/display/gimpdisplayshell-scale.c b/app/display/gimpdisplayshell-scale.c
index 440c304639..a6c40f9f07 100644
--- a/app/display/gimpdisplayshell-scale.c
+++ b/app/display/gimpdisplayshell-scale.c
@@ -275,6 +275,118 @@ gimp_display_shell_scale_get_image_bounds (GimpDisplayShell *shell,
if (h) *h = y2 - y1;
}
+/**
+ * gimp_display_shell_scale_get_image_bounding_box:
+ * @shell:
+ * @x:
+ * @y:
+ * @w:
+ * @h:
+ *
+ * Gets the screen-space boudning box of the image content, after it has
+ * been transformed (i.e., scaled, rotated, and scrolled).
+ **/
+void
+gimp_display_shell_scale_get_image_bounding_box (GimpDisplayShell *shell,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h)
+{
+ GeglRectangle bounding_box;
+ gdouble x1, y1;
+ gdouble x2, y2;
+
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+ bounding_box = gimp_display_shell_get_bounding_box (shell);
+
+ gimp_display_shell_transform_bounds (shell,
+ bounding_box.x,
+ bounding_box.y,
+ bounding_box.x + bounding_box.width,
+ bounding_box.y + bounding_box.height,
+ &x1, &y1,
+ &x2, &y2);
+
+ if (! shell->show_all)
+ {
+ x1 = ceil (x1);
+ y1 = ceil (y1);
+ x2 = floor (x2);
+ y2 = floor (y2);
+ }
+ else
+ {
+ x1 = floor (x1);
+ y1 = floor (y1);
+ x2 = ceil (x2);
+ y2 = ceil (y2);
+ }
+
+ if (x) *x = x1 + shell->offset_x;
+ if (y) *y = y1 + shell->offset_y;
+ if (w) *w = x2 - x1;
+ if (h) *h = y2 - y1;
+}
+
+/**
+ * gimp_display_shell_scale_get_image_unrotated_bounding_box:
+ * @shell:
+ * @x:
+ * @y:
+ * @w:
+ * @h:
+ *
+ * Gets the screen-space boudning box of the image content, after it has
+ * been scaled and scrolled, but before it has been rotated.
+ **/
+void
+gimp_display_shell_scale_get_image_unrotated_bounding_box (GimpDisplayShell *shell,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h)
+{
+ GeglRectangle bounding_box;
+ gdouble x1, y1;
+ gdouble x2, y2;
+
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+ bounding_box = gimp_display_shell_get_bounding_box (shell);
+
+ x1 = bounding_box.x * shell->scale_x -
+ shell->offset_x;
+ y1 = bounding_box.y * shell->scale_y -
+ shell->offset_y;
+
+ x2 = (bounding_box.x + bounding_box.width) * shell->scale_x -
+ shell->offset_x;
+ y2 = (bounding_box.y + bounding_box.height) * shell->scale_y -
+ shell->offset_y;
+
+ if (! shell->show_all)
+ {
+ x1 = ceil (x1);
+ y1 = ceil (y1);
+ x2 = floor (x2);
+ y2 = floor (y2);
+ }
+ else
+ {
+ x1 = floor (x1);
+ y1 = floor (y1);
+ x2 = ceil (x2);
+ y2 = ceil (y2);
+ }
+
+ if (x) *x = x1;
+ if (y) *y = y1;
+ if (w) *w = x2 - x1;
+ if (h) *h = y2 - y1;
+}
+
/**
* gimp_display_shell_scale_image_is_within_viewport:
* @shell:
diff --git a/app/display/gimpdisplayshell-scale.h b/app/display/gimpdisplayshell-scale.h
index 8489a1545a..7f38eb0264 100644
--- a/app/display/gimpdisplayshell-scale.h
+++ b/app/display/gimpdisplayshell-scale.h
@@ -34,6 +34,18 @@ void gimp_display_shell_scale_get_image_bounds (GimpDisplayShell *shell,
gint *y,
gint *w,
gint *h);
+void gimp_display_shell_scale_get_image_bounding_box
+ (GimpDisplayShell *shell,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h);
+void gimp_display_shell_scale_get_image_unrotated_bounding_box
+ (GimpDisplayShell *shell,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h);
gboolean gimp_display_shell_scale_image_is_within_viewport
(GimpDisplayShell *shell,
gboolean *horizontally,
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index c580fe9537..54c78488a1 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -45,6 +45,8 @@
#include "core/gimpimage-grid.h"
#include "core/gimpimage-guides.h"
#include "core/gimpimage-snap.h"
+#include "core/gimppickable.h"
+#include "core/gimpprojectable.h"
#include "core/gimpprojection.h"
#include "core/gimpmarshal.h"
#include "core/gimptemplate.h"
@@ -99,7 +101,8 @@ enum
PROP_UNIT,
PROP_TITLE,
PROP_STATUS,
- PROP_ICON
+ PROP_ICON,
+ PROP_SHOW_ALL
};
enum
@@ -289,6 +292,12 @@ gimp_display_shell_class_init (GimpDisplayShellClass *klass)
GDK_TYPE_PIXBUF,
GIMP_PARAM_READWRITE));
+ g_object_class_install_property (object_class, PROP_SHOW_ALL,
+ g_param_spec_boolean ("show-all",
+ NULL, NULL,
+ FALSE,
+ GIMP_PARAM_READWRITE));
+
gtk_widget_class_set_css_name (widget_class, "GimpDisplayShell");
}
@@ -316,6 +325,8 @@ gimp_display_shell_init (GimpDisplayShell *shell)
shell->show_image = TRUE;
+ shell->show_all = FALSE;
+
gimp_display_shell_items_init (shell);
shell->icon_size = 128;
@@ -714,6 +725,8 @@ gimp_display_shell_constructed (GObject *object)
/* make sure the information is up-to-date */
gimp_display_shell_scale_update (shell);
+
+ gimp_display_shell_set_show_all (shell, config->default_show_all);
}
static void
@@ -836,6 +849,9 @@ gimp_display_shell_set_property (GObject *object,
g_object_unref (shell->icon);
shell->icon = g_value_dup_object (value);
break;
+ case PROP_SHOW_ALL:
+ gimp_display_shell_set_show_all (shell, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -874,6 +890,9 @@ gimp_display_shell_get_property (GObject *object,
case PROP_ICON:
g_value_set_object (value, shell->icon);
break;
+ case PROP_SHOW_ALL:
+ g_value_set_boolean (value, shell->show_all);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -1441,6 +1460,8 @@ gimp_display_shell_fill (GimpDisplayShell *shell,
config = shell->display->config;
window = gimp_display_shell_get_window (shell);
+ shell->show_image = TRUE;
+
shell->dot_for_dot = config->default_dot_for_dot;
gimp_display_shell_set_unit (shell, unit);
@@ -1475,6 +1496,8 @@ gimp_display_shell_fill (GimpDisplayShell *shell,
g_idle_add_full (GIMP_PRIORITY_DISPLAY_SHELL_FILL_IDLE,
(GSourceFunc) gimp_display_shell_fill_idle, shell,
NULL);
+
+ gimp_display_shell_set_show_all (shell, config->default_show_all);
}
void
@@ -1741,6 +1764,84 @@ gimp_display_shell_set_show_image (GimpDisplayShell *shell,
}
}
+void
+gimp_display_shell_set_show_all (GimpDisplayShell *shell,
+ gboolean show_all)
+{
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+ if (show_all != shell->show_all)
+ {
+ GimpImage *image = gimp_display_get_image (shell->display);
+
+ shell->show_all = show_all;
+
+ if (image)
+ {
+ if (show_all)
+ gimp_image_inc_show_all_count (image);
+ else
+ gimp_image_dec_show_all_count (image);
+
+ gimp_image_flush (image);
+ }
+
+ gimp_display_update_bounding_box (shell->display);
+
+ gimp_display_shell_expose_full (shell);
+
+ g_object_notify (G_OBJECT (shell), "show-all");
+ }
+}
+
+
+GimpPickable *
+gimp_display_shell_get_pickable (GimpDisplayShell *shell)
+{
+ GimpImage *image;
+
+ g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
+
+ image = gimp_display_get_image (shell->display);
+
+ if (image)
+ {
+ if (! shell->show_all)
+ return GIMP_PICKABLE (image);
+ else
+ return GIMP_PICKABLE (gimp_image_get_projection (image));
+ }
+
+ return NULL;
+}
+
+GeglRectangle
+gimp_display_shell_get_bounding_box (GimpDisplayShell *shell)
+{
+ GeglRectangle bounding_box = {};
+ GimpImage *image;
+
+ g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), bounding_box);
+
+ image = gimp_display_get_image (shell->display);
+
+ if (image)
+ {
+ if (! shell->show_all)
+ {
+ bounding_box.width = gimp_image_get_width (image);
+ bounding_box.height = gimp_image_get_height (image);
+ }
+ else
+ {
+ bounding_box = gimp_projectable_get_bounding_box (
+ GIMP_PROJECTABLE (image));
+ }
+ }
+
+ return bounding_box;
+}
+
void
gimp_display_shell_flush (GimpDisplayShell *shell)
{
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index 3afbe3d164..fb4261eaf7 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -92,6 +92,8 @@ struct _GimpDisplayShell
gboolean show_image; /* whether to show the image */
+ gboolean show_all; /* show the entire image */
+
Selection *selection; /* Selection (marching ants) */
GList *children;
@@ -308,6 +310,13 @@ void gimp_display_shell_set_show_image
(GimpDisplayShell *shell,
gboolean show_image);
+void gimp_display_shell_set_show_all (GimpDisplayShell *shell,
+ gboolean show_all);
+
+GimpPickable * gimp_display_shell_get_pickable (GimpDisplayShell *shell);
+GeglRectangle gimp_display_shell_get_bounding_box
+ (GimpDisplayShell *shell);
+
void gimp_display_shell_flush (GimpDisplayShell *shell);
void gimp_display_shell_pause (GimpDisplayShell *shell);
diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h
index c8da9c1739..720d47dc0f 100644
--- a/app/widgets/gimphelp-ids.h
+++ b/app/widgets/gimphelp-ids.h
@@ -83,6 +83,7 @@
#define GIMP_HELP_SELECTION_TO_PATH "gimp-selection-to-path"
#define GIMP_HELP_VIEW_NEW "gimp-view-new"
+#define GIMP_HELP_VIEW_SHOW_ALL "gimp-view-show-all"
#define GIMP_HELP_VIEW_DOT_FOR_DOT "gimp-view-dot-for-dot"
#define GIMP_HELP_VIEW_SCROLL_CENTER "gimp-view-scroll-center"
#define GIMP_HELP_VIEW_ZOOM_REVERT "gimp-view-zoom-revert"
diff --git a/menus/image-menu.xml.in b/menus/image-menu.xml.in
index 6b8b6de956..35291ff120 100644
--- a/menus/image-menu.xml.in
+++ b/menus/image-menu.xml.in
@@ -261,6 +261,7 @@
<menu action="view-menu" name="View">
<menuitem action="view-new" />
+ <menuitem action="view-show-all" />
<menuitem action="view-dot-for-dot" />
<menu action="view-zoom-menu" name="Zoom">
<menuitem action="view-zoom-revert" />
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]