/**
 * 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);
}
Esempio n. 2
0
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);
    }
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
/**
 * 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));
        }
    }
}