/** * gimp_display_shell_scale_fill: * @shell: the #GimpDisplayShell * * Sets the scale such that the entire display area is precisely * filled by the image. **/ void gimp_display_shell_scale_fill (GimpDisplayShell *shell) { GimpImage *image; gint image_width; gint image_height; gdouble xres; gdouble yres; gdouble zoom_factor; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); image = gimp_display_get_image (shell->display); image_width = gimp_image_get_width (image); image_height = gimp_image_get_height (image); gimp_image_get_resolution (image, &xres, &yres); if (! shell->dot_for_dot) { image_width = ROUND (image_width * shell->monitor_xres / xres); image_height = ROUND (image_height * shell->monitor_yres / yres); } zoom_factor = MAX ((gdouble) shell->disp_width / (gdouble) image_width, (gdouble) shell->disp_height / (gdouble) image_height); gimp_display_shell_scale (shell, GIMP_ZOOM_TO, zoom_factor, GIMP_ZOOM_FOCUS_BEST_GUESS); gimp_display_shell_scroll_center_image (shell, TRUE, TRUE); }
static void gimp_display_shell_size_changed_detailed_handler (GimpImage *image, gint previous_origin_x, gint previous_origin_y, gint previous_width, gint previous_height, GimpDisplayShell *shell) { if (shell->display->config->resize_windows_on_resize) { GimpImageWindow *window = gimp_display_shell_get_window (shell); if (window && gimp_image_window_get_active_shell (window) == shell) { /* If the window is resized just center the image in it when it * has change size */ gimp_image_window_shrink_wrap (window, FALSE); } } else { GimpImage *image = gimp_display_get_image (shell->display); gint new_width = gimp_image_get_width (image); gint new_height = gimp_image_get_height (image); gint scaled_previous_origin_x = SCALEX (shell, previous_origin_x); gint scaled_previous_origin_y = SCALEY (shell, previous_origin_y); gboolean horizontally; gboolean vertically; horizontally = (SCALEX (shell, previous_width) > shell->disp_width && SCALEX (shell, new_width) <= shell->disp_width); vertically = (SCALEY (shell, previous_height) > shell->disp_height && SCALEY (shell, new_height) <= shell->disp_height); gimp_display_shell_scroll_set_offset (shell, shell->offset_x + scaled_previous_origin_x, shell->offset_y + scaled_previous_origin_y); gimp_display_shell_scroll_center_image (shell, horizontally, vertically); /* The above calls might not lead to a call to * gimp_display_shell_scroll_clamp_and_update() in all cases we * need it to be called, so simply call it explicitly here at * the end */ gimp_display_shell_scroll_clamp_and_update (shell); gimp_display_shell_expose_full (shell); } }
static void gimp_display_shell_scroll_center_image_callback (GtkWidget *canvas, GtkAllocation *allocation, CenterImageData *data) { g_signal_handlers_disconnect_by_func (canvas, gimp_display_shell_scroll_center_image_callback, data); gimp_display_shell_scroll_center_image (data->shell, data->horizontally, data->vertically); g_slice_free (CenterImageData, data); }
/** * gimp_display_shell_scale_fit_or_fill: * @shell: the #GimpDisplayShell * @fill: whether to scale the image to fill the viewport, * or fit inside the viewport * * A common implementation for gimp_display_shell_scale_{fit_in,fill}(). **/ static void gimp_display_shell_scale_fit_or_fill (GimpDisplayShell *shell, gboolean fill) { GimpImage *image; gdouble image_x; gdouble image_y; gdouble image_width; gdouble image_height; gdouble current_scale; gdouble zoom_factor; image = gimp_display_get_image (shell->display); gimp_display_shell_transform_bounds (shell, 0, 0, gimp_image_get_width (image), gimp_image_get_height (image), &image_x, &image_y, &image_width, &image_height); image_width -= image_x; image_height -= image_y; current_scale = gimp_zoom_model_get_factor (shell->zoom); if (fill) { zoom_factor = MAX (shell->disp_width / image_width, shell->disp_height / image_height); } else { zoom_factor = MIN (shell->disp_width / image_width, shell->disp_height / image_height); } gimp_display_shell_scale (shell, GIMP_ZOOM_TO, zoom_factor * current_scale, GIMP_ZOOM_FOCUS_BEST_GUESS); gimp_display_shell_scroll_center_image (shell, TRUE, TRUE); }
static void gimp_display_shell_size_changed_detailed_handler (GimpImage *image, gint previous_origin_x, gint previous_origin_y, gint previous_width, gint previous_height, GimpDisplayShell *shell) { GimpDisplayConfig *config = shell->display->config; gboolean resize_window; /* Resize windows only in multi-window mode */ resize_window = (config->resize_windows_on_resize && ! GIMP_GUI_CONFIG (config)->single_window_mode); if (resize_window) { GimpImageWindow *window = gimp_display_shell_get_window (shell); if (window && gimp_image_window_get_active_shell (window) == shell) { /* If the window is resized just center the image in it when it * has change size */ gimp_image_window_shrink_wrap (window, FALSE); } } else { GimpImage *image = gimp_display_get_image (shell->display); gint new_width = gimp_image_get_width (image); gint new_height = gimp_image_get_height (image); gint scaled_previous_origin_x; gint scaled_previous_origin_y; gboolean horizontally; gboolean vertically; scaled_previous_origin_x = SCALEX (shell, previous_origin_x); scaled_previous_origin_y = SCALEY (shell, previous_origin_y); horizontally = (SCALEX (shell, previous_width) > shell->disp_width && SCALEX (shell, new_width) <= shell->disp_width); vertically = (SCALEY (shell, previous_height) > shell->disp_height && SCALEY (shell, new_height) <= shell->disp_height); gimp_display_shell_scroll_set_offset (shell, shell->offset_x + scaled_previous_origin_x, shell->offset_y + scaled_previous_origin_y); gimp_display_shell_scroll_center_image (shell, horizontally, vertically); /* The above calls might not lead to a call to * gimp_display_shell_scroll_clamp_and_update() and * gimp_display_shell_expose_full() in all cases because when * scaling the old and new scroll offset might be the same. * * We need them to be called in all cases, so simply call them * explicitly here at the end */ gimp_display_shell_scroll_clamp_and_update (shell); gimp_display_shell_expose_full (shell); } }
void gimp_display_shell_canvas_size_allocate (GtkWidget *widget, GtkAllocation *allocation, GimpDisplayShell *shell) { /* are we in destruction? */ if (! shell->display || ! gimp_display_get_shell (shell->display)) return; if ((shell->disp_width != allocation->width) || (shell->disp_height != allocation->height)) { if (shell->zoom_on_resize && shell->disp_width > 64 && shell->disp_height > 64 && allocation->width > 64 && allocation->height > 64) { gdouble scale = gimp_zoom_model_get_factor (shell->zoom); gint offset_x; gint offset_y; /* FIXME: The code is a bit of a mess */ /* multiply the zoom_factor with the ratio of the new and * old canvas diagonals */ scale *= (sqrt (SQR (allocation->width) + SQR (allocation->height)) / sqrt (SQR (shell->disp_width) + SQR (shell->disp_height))); offset_x = UNSCALEX (shell, shell->offset_x); offset_y = UNSCALEX (shell, shell->offset_y); gimp_zoom_model_zoom (shell->zoom, GIMP_ZOOM_TO, scale); shell->offset_x = SCALEX (shell, offset_x); shell->offset_y = SCALEY (shell, offset_y); } shell->disp_width = allocation->width; shell->disp_height = allocation->height; /* When we size-allocate due to resize of the top level window, * we want some additional logic. Don't apply it on * zoom_on_resize though. */ if (shell->size_allocate_from_configure_event && ! shell->zoom_on_resize) { gboolean center_horizontally; gboolean center_vertically; gint target_offset_x; gint target_offset_y; gint sw; gint sh; gimp_display_shell_scale_get_image_size (shell, &sw, &sh); center_horizontally = sw <= shell->disp_width; center_vertically = sh <= shell->disp_height; gimp_display_shell_scroll_center_image (shell, center_horizontally, center_vertically); /* This is basically the best we can do before we get an * API for storing the image offset at the start of an * image window resize using the mouse */ target_offset_x = shell->offset_x; target_offset_y = shell->offset_y; if (! center_horizontally) { target_offset_x = MAX (shell->offset_x, 0); } if (! center_vertically) { target_offset_y = MAX (shell->offset_y, 0); } gimp_display_shell_scroll_set_offset (shell, target_offset_x, target_offset_y); } gimp_display_shell_scroll_clamp_and_update (shell); gimp_display_shell_scaled (shell); /* Reset */ shell->size_allocate_from_configure_event = FALSE; } }
/** * gimp_display_shell_scale: * @shell: the #GimpDisplayShell * @zoom_type: whether to zoom in, our or to a specific scale * @scale: ignored unless @zoom_type == %GIMP_ZOOM_TO * * This function figures out the context of the zoom and behaves * appropriatley thereafter. * **/ void gimp_display_shell_scale (GimpDisplayShell *shell, GimpZoomType zoom_type, gdouble new_scale, GimpZoomFocus zoom_focus) { gdouble current_scale; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); g_return_if_fail (shell->canvas != NULL); current_scale = gimp_zoom_model_get_factor (shell->zoom); if (zoom_type != GIMP_ZOOM_TO) new_scale = gimp_zoom_model_zoom_step (zoom_type, current_scale); if (! SCALE_EQUALS (new_scale, current_scale)) { GimpDisplayConfig *config = shell->display->config; gboolean resize_window; /* Resize windows only in multi-window mode */ resize_window = (config->resize_windows_on_zoom && ! GIMP_GUI_CONFIG (config)->single_window_mode); if (resize_window) { /* If the window is resized on zoom, simply do the zoom and * get things rolling */ gimp_zoom_model_zoom (shell->zoom, GIMP_ZOOM_TO, new_scale); gimp_display_shell_scale_resize (shell, TRUE, FALSE); } else { gboolean starts_fitting_horiz; gboolean starts_fitting_vert; gboolean zoom_focus_almost_centered_horiz; gboolean zoom_focus_almost_centered_vert; gboolean image_center_almost_centered_horiz; gboolean image_center_almost_centered_vert; gdouble x, y; gint image_center_x; gint image_center_y; gimp_display_shell_scale_get_zoom_focus (shell, new_scale, current_scale, &x, &y, zoom_focus); gimp_display_shell_scale_get_image_center_viewport (shell, &image_center_x, &image_center_y); gimp_display_shell_scale_to (shell, new_scale, x, y); /* If an image axis started to fit due to zooming out or if * the focus point is as good as in the center, center on * that axis */ gimp_display_shell_scale_image_starts_to_fit (shell, new_scale, current_scale, &starts_fitting_horiz, &starts_fitting_vert); gimp_display_shell_scale_viewport_coord_almost_centered (shell, x, y, &zoom_focus_almost_centered_horiz, &zoom_focus_almost_centered_vert); gimp_display_shell_scale_viewport_coord_almost_centered (shell, image_center_x, image_center_y, &image_center_almost_centered_horiz, &image_center_almost_centered_vert); gimp_display_shell_scroll_center_image (shell, starts_fitting_horiz || (zoom_focus_almost_centered_horiz && image_center_almost_centered_horiz), starts_fitting_vert || (zoom_focus_almost_centered_vert && image_center_almost_centered_vert)); } } }
/** * gimp_display_shell_scale: * @shell: the #GimpDisplayShell * @zoom_type: whether to zoom in, our or to a specific scale * @scale: ignored unless @zoom_type == %GIMP_ZOOM_TO * * This function figures out the context of the zoom and behaves * appropriatley thereafter. * **/ void gimp_display_shell_scale (GimpDisplayShell *shell, GimpZoomType zoom_type, gdouble new_scale, GimpZoomFocus zoom_focus) { gint x, y; gdouble current_scale; gdouble real_new_scale; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); g_return_if_fail (shell->canvas != NULL); current_scale = gimp_zoom_model_get_factor (shell->zoom); if (zoom_type != GIMP_ZOOM_TO) { real_new_scale = gimp_zoom_model_zoom_step (zoom_type, current_scale); } else { real_new_scale = new_scale; } if (! SCALE_EQUALS (real_new_scale, current_scale)) { if (shell->display->config->resize_windows_on_zoom) { GimpImageWindow *window = gimp_display_shell_get_window (shell); /* If the window is resized on zoom, simply do the zoom and * get things rolling */ gimp_zoom_model_zoom (shell->zoom, GIMP_ZOOM_TO, real_new_scale); gimp_display_shell_scaled (shell); if (window && gimp_image_window_get_active_shell (window) == shell) { gimp_image_window_shrink_wrap (window, FALSE); } } else { gboolean starts_fitting_horiz; gboolean starts_fitting_vert; gboolean zoom_focus_almost_centered_horiz; gboolean zoom_focus_almost_centered_vert; gboolean image_center_almost_centered_horiz; gboolean image_center_almost_centered_vert; gint image_center_x; gint image_center_y; gimp_display_shell_scale_get_zoom_focus (shell, real_new_scale, current_scale, &x, &y, zoom_focus); gimp_display_shell_scale_get_image_center_viewport (shell, &image_center_x, &image_center_y); gimp_display_shell_scale_to (shell, real_new_scale, x, y); /* If an image axis started to fit due to zooming out or if * the focus point is as good as in the center, center on * that axis */ gimp_display_shell_scale_image_starts_to_fit (shell, real_new_scale, current_scale, &starts_fitting_horiz, &starts_fitting_vert); gimp_display_shell_scale_viewport_coord_almost_centered (shell, x, y, &zoom_focus_almost_centered_horiz, &zoom_focus_almost_centered_vert); gimp_display_shell_scale_viewport_coord_almost_centered (shell, image_center_x, image_center_y, &image_center_almost_centered_horiz, &image_center_almost_centered_vert); gimp_display_shell_scroll_center_image (shell, starts_fitting_horiz || (zoom_focus_almost_centered_horiz && image_center_almost_centered_horiz), starts_fitting_vert || (zoom_focus_almost_centered_vert && image_center_almost_centered_vert)); } } }