mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-22 12:32:37 +00:00
d162376d47
2001-11-01 Michael Natterer <mitch@gimp.org> * app/display/Makefile.am * app/display/gimpdisplay-callbacks.[ch] * app/display/gimpdisplay-render.[ch] * app/display/gimpdisplay-scale.[ch] * app/display/gimpdisplay-scroll.[ch]: removed and added as gimpdisplayshell-foo.[ch] because they are all methods of the shell. * app/display/gimpdisplay.[ch] * app/display/gimpdisplayshell.[ch]: moved the "offset" and "size" variables from GimpDisplay to GimpDisplayShell. GimpDisplay should know nothing about screen coordinates. The gdisplay_[un]transform_foo() methods are still part of GimpDisplay but will be moved to GimpDisplayShell as soon as the tools' vitrual functions speak in image coordinates instead of GdkEvents. * app/display/gimpdisplayshell-callbacks.[ch]: prefixed all functions with gimp_display_shell_*. Moved some stuff to a "realize" callback File still has to be renamed. * app/display/gimpdisplay-foreach.[ch]: removed gdisplays_shrink_wrap(). * app/gui/menus.c * app/gui/view-commands.[ch] * app/display/gimpdisplayshell-scale.[ch]: implemented "Zoom to Fit Window" function (#57670). * app/nav_window.c * app/display/gimpdisplay-handlers.c * app/display/gimpdisplayshell-render.[ch] * app/display/gimpdisplayshell-scale.[ch] * app/display/gimpdisplayshell-scroll.[ch] * app/gui/colormap-dialog.c * app/gui/gui.c * app/gui/preferences-dialog.c * app/tools/gimpmagnifytool.c * app/tools/gimpmovetool.c * app/widgets/gimppreview.c: changed according to variable and filename changes. * app/tools/tool_manager.c: tool_manager_select_tool(): send the active tool a "HALT" command before selecting the new one. Fixes stale tool dialogs which were there because some other hack was removed (This is IMHO the right place to shut down the active tool). * app/tools/gimpcroptool.c: don't shrink wrap after cropping but let gimprc.allow_resize_windows decide. * app/tools/gimpselectiontool.c: gimage_mask_value() takes image, not screen coordinates. A good example of how braindead it is to pass GdkEvents to tools :-) Fixes incorrect cursor and oper update of the selection tools. * app/tools/gimptransformtool.c * app/undo.c: removed (#if 0 for now) some strange code which did manual exposing of GimpDisplayShell areas. This was definitely a hack and should not be there given the image emits correct "update" signals.
791 lines
20 KiB
C
791 lines
20 KiB
C
/* The GIMP -- an image manipulation program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "display-types.h"
|
|
#include "gui/gui-types.h" /* FIXME */
|
|
|
|
#include "core/gimp.h"
|
|
#include "core/gimpcontext.h"
|
|
#include "core/gimpdrawable.h"
|
|
#include "core/gimpimage.h"
|
|
|
|
#include "tools/gimptool.h"
|
|
#include "tools/tool_manager.h"
|
|
|
|
#include "gui/info-window.h"
|
|
|
|
#include "gimpdisplay.h"
|
|
#include "gimpdisplay-area.h"
|
|
#include "gimpdisplay-handlers.h"
|
|
#include "gimpdisplay-selection.h"
|
|
#include "gimpdisplayshell.h"
|
|
#include "gximage.h"
|
|
|
|
#include "gimprc.h"
|
|
#include "nav_window.h"
|
|
#include "plug_in.h"
|
|
#include "qmask.h"
|
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
static void gimp_display_class_init (GimpDisplayClass *klass);
|
|
static void gimp_display_init (GimpDisplay *gdisp);
|
|
|
|
static void gimp_display_finalize (GObject *object);
|
|
|
|
static void gimp_display_flush_whenever (GimpDisplay *gdisp,
|
|
gboolean now);
|
|
static void gimp_display_paint_area (GimpDisplay *gdisp,
|
|
gint x,
|
|
gint y,
|
|
gint w,
|
|
gint h);
|
|
|
|
|
|
static GimpObjectClass *parent_class = NULL;
|
|
|
|
GSList *display_list = NULL;
|
|
static gint display_num = 1;
|
|
|
|
|
|
GType
|
|
gimp_display_get_type (void)
|
|
{
|
|
static GType display_type = 0;
|
|
|
|
if (! display_type)
|
|
{
|
|
static const GTypeInfo display_info =
|
|
{
|
|
sizeof (GimpDisplayClass),
|
|
(GBaseInitFunc) NULL,
|
|
(GBaseFinalizeFunc) NULL,
|
|
(GClassInitFunc) gimp_display_class_init,
|
|
NULL, /* class_finalize */
|
|
NULL, /* class_data */
|
|
sizeof (GimpDisplay),
|
|
0, /* n_preallocs */
|
|
(GInstanceInitFunc) gimp_display_init,
|
|
};
|
|
|
|
display_type = g_type_register_static (GIMP_TYPE_OBJECT,
|
|
"GimpDisplay",
|
|
&display_info, 0);
|
|
}
|
|
|
|
return display_type;
|
|
}
|
|
|
|
static void
|
|
gimp_display_class_init (GimpDisplayClass *klass)
|
|
{
|
|
GObjectClass *object_class;
|
|
|
|
object_class = G_OBJECT_CLASS (klass);
|
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
|
|
|
object_class->finalize = gimp_display_finalize;
|
|
}
|
|
|
|
static void
|
|
gimp_display_init (GimpDisplay *gdisp)
|
|
{
|
|
gdisp->ID = display_num++;
|
|
|
|
gdisp->gimage = NULL;
|
|
gdisp->instance = 0;
|
|
|
|
gdisp->shell = NULL;
|
|
|
|
gdisp->scale = 0;
|
|
gdisp->dot_for_dot = gimprc.default_dot_for_dot;
|
|
gdisp->draw_guides = TRUE;
|
|
gdisp->snap_to_guides = TRUE;
|
|
|
|
gdisp->select = NULL;
|
|
|
|
gdisp->update_areas = NULL;
|
|
|
|
gdisp->idle_render.idleid = -1;
|
|
gdisp->idle_render.update_areas = NULL;
|
|
gdisp->idle_render.active = FALSE;
|
|
}
|
|
|
|
static void
|
|
gimp_display_finalize (GObject *object)
|
|
{
|
|
GimpDisplay *gdisp;
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY (object));
|
|
|
|
gdisp = GIMP_DISPLAY (object);
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
GimpDisplay *
|
|
gdisplay_new (GimpImage *gimage,
|
|
guint scale)
|
|
{
|
|
GimpDisplay *gdisp;
|
|
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
|
|
|
|
/* If there isn't an interface, never create a gdisplay */
|
|
if (gimage->gimp->no_interface)
|
|
return NULL;
|
|
|
|
/*
|
|
* Set all GimpDisplay parameters...
|
|
*/
|
|
gdisp = g_object_new (GIMP_TYPE_DISPLAY, NULL);
|
|
|
|
/* add the new display to the list so that it isn't lost */
|
|
display_list = g_slist_append (display_list, gdisp);
|
|
|
|
gimp_display_connect (gdisp, gimage);
|
|
|
|
gdisp->scale = scale;
|
|
|
|
/* create the shell for the image */
|
|
gdisp->shell = gimp_display_shell_new (gdisp);
|
|
|
|
return gdisp;
|
|
}
|
|
|
|
void
|
|
gdisplay_delete (GimpDisplay *gdisp)
|
|
{
|
|
GimpTool *active_tool;
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY (gdisp));
|
|
|
|
/* remove the display from the list */
|
|
display_list = g_slist_remove (display_list, gdisp);
|
|
|
|
/* stop any active tool */
|
|
tool_manager_control_active (gdisp->gimage->gimp, HALT, gdisp);
|
|
|
|
active_tool = tool_manager_get_active (gdisp->gimage->gimp);
|
|
|
|
/* clear out the pointer to this gdisp from the active tool */
|
|
if (active_tool && active_tool->gdisp == gdisp)
|
|
{
|
|
active_tool->drawable = NULL;
|
|
active_tool->gdisp = NULL;
|
|
}
|
|
|
|
if (gdisp->select)
|
|
{
|
|
selection_free (gdisp->select);
|
|
gdisp->select = NULL;
|
|
}
|
|
|
|
/* If this gdisplay was idlerendering at the time when it was deleted,
|
|
deactivate the idlerendering thread before deletion! */
|
|
if (gdisp->idle_render.active)
|
|
{
|
|
g_source_remove (gdisp->idle_render.idleid);
|
|
gdisp->idle_render.active = FALSE;
|
|
}
|
|
|
|
/* free the update area lists */
|
|
gimp_display_area_list_free (gdisp->update_areas);
|
|
gimp_display_area_list_free (gdisp->idle_render.update_areas);
|
|
|
|
if (gdisp->shell)
|
|
{
|
|
gtk_widget_destroy (gdisp->shell);
|
|
gdisp->shell = NULL;
|
|
}
|
|
|
|
/* free the gimage */
|
|
gimp_display_disconnect (gdisp);
|
|
|
|
g_object_unref (G_OBJECT (gdisp));
|
|
}
|
|
|
|
GimpDisplay *
|
|
gdisplay_get_by_ID (Gimp *gimp,
|
|
gint ID)
|
|
{
|
|
GimpDisplay *gdisp;
|
|
GSList *list;
|
|
|
|
/* Traverse the list of displays, returning the one that matches the ID
|
|
* If no display in the list is a match, return NULL.
|
|
*/
|
|
for (list = display_list; list; list = g_slist_next (list))
|
|
{
|
|
gdisp = (GimpDisplay *) list->data;
|
|
|
|
if (gdisp->ID == ID)
|
|
return gdisp;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
gdisplay_reconnect (GimpDisplay *gdisp,
|
|
GimpImage *gimage)
|
|
{
|
|
g_return_if_fail (GIMP_IS_DISPLAY (gdisp));
|
|
g_return_if_fail (GIMP_IS_IMAGE (gimage));
|
|
|
|
if (gdisp->idle_render.active)
|
|
{
|
|
g_source_remove (gdisp->idle_render.idleid);
|
|
gdisp->idle_render.idleid = 0;
|
|
gdisp->idle_render.active = FALSE;
|
|
}
|
|
|
|
gimp_display_disconnect (gdisp);
|
|
|
|
gimp_display_connect (gdisp, gimage);
|
|
|
|
gdisplay_add_update_area (gdisp,
|
|
0, 0,
|
|
gdisp->gimage->width,
|
|
gdisp->gimage->height);
|
|
|
|
gimp_display_shell_resize_cursor_label (GIMP_DISPLAY_SHELL (gdisp->shell));
|
|
gimp_display_shell_shrink_wrap (GIMP_DISPLAY_SHELL (gdisp->shell));
|
|
}
|
|
|
|
static gint
|
|
idle_render_next_area (GimpDisplay *gdisp)
|
|
{
|
|
GimpArea *ga;
|
|
GSList *list;
|
|
|
|
list = gdisp->idle_render.update_areas;
|
|
|
|
if (list == NULL)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
ga = (GimpArea *) list->data;
|
|
|
|
gdisp->idle_render.update_areas =
|
|
g_slist_remove (gdisp->idle_render.update_areas, ga);
|
|
|
|
gdisp->idle_render.x = gdisp->idle_render.basex = ga->x1;
|
|
gdisp->idle_render.y = gdisp->idle_render.basey = ga->y1;
|
|
gdisp->idle_render.width = ga->x2 - ga->x1;
|
|
gdisp->idle_render.height = ga->y2 - ga->y1;
|
|
|
|
g_free (ga);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Unless specified otherwise, display re-rendering is organised by
|
|
* IdleRender, which amalgamates areas to be re-rendered and breaks
|
|
* them into bite-sized chunks which are chewed on in a low- priority
|
|
* idle thread. This greatly improves responsiveness for many GIMP
|
|
* operations. -- Adam
|
|
*/
|
|
static gint
|
|
idlerender_callback (gpointer data)
|
|
{
|
|
const gint CHUNK_WIDTH = 256;
|
|
const gint CHUNK_HEIGHT = 128;
|
|
gint workx, worky, workw, workh;
|
|
GimpDisplay *gdisp = data;
|
|
|
|
workw = CHUNK_WIDTH;
|
|
workh = CHUNK_HEIGHT;
|
|
workx = gdisp->idle_render.x;
|
|
worky = gdisp->idle_render.y;
|
|
|
|
if (workx + workw > gdisp->idle_render.basex + gdisp->idle_render.width)
|
|
{
|
|
workw = gdisp->idle_render.basex + gdisp->idle_render.width - workx;
|
|
}
|
|
|
|
if (worky+workh > gdisp->idle_render.basey+gdisp->idle_render.height)
|
|
{
|
|
workh = gdisp->idle_render.basey + gdisp->idle_render.height - worky;
|
|
}
|
|
|
|
gimp_display_paint_area (gdisp, workx, worky, workw, workh);
|
|
|
|
gimp_display_shell_flush (GIMP_DISPLAY_SHELL (gdisp->shell));
|
|
|
|
gdisp->idle_render.x += CHUNK_WIDTH;
|
|
if (gdisp->idle_render.x >=
|
|
gdisp->idle_render.basex + gdisp->idle_render.width)
|
|
{
|
|
gdisp->idle_render.x = gdisp->idle_render.basex;
|
|
gdisp->idle_render.y += CHUNK_HEIGHT;
|
|
if (gdisp->idle_render.y >=
|
|
gdisp->idle_render.basey + gdisp->idle_render.height)
|
|
{
|
|
if (idle_render_next_area(gdisp) != 0)
|
|
{
|
|
/* FINISHED */
|
|
gdisp->idle_render.active = FALSE;
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Still work to do. */
|
|
return 1;
|
|
}
|
|
|
|
static void
|
|
gimp_display_idlerender_init (GimpDisplay *gdisp)
|
|
{
|
|
GSList *list;
|
|
GimpArea *ga, *new_ga;
|
|
|
|
/* We need to merge the IdleRender's and the GimpDisplay's update_areas list
|
|
* to keep track of which of the updates have been flushed and hence need
|
|
* to be drawn.
|
|
*/
|
|
list = gdisp->update_areas;
|
|
|
|
while (list)
|
|
{
|
|
ga = (GimpArea *) list->data;
|
|
new_ga = g_malloc (sizeof(GimpArea));
|
|
memcpy (new_ga, ga, sizeof(GimpArea));
|
|
|
|
gdisp->idle_render.update_areas =
|
|
gimp_display_area_list_process (gdisp->idle_render.update_areas, new_ga);
|
|
|
|
list = g_slist_next (list);
|
|
}
|
|
|
|
/* If an idlerender was already running, merge the remainder of its
|
|
unrendered area with the update_areas list, and make it start work
|
|
on the next unrendered area in the list. */
|
|
if (gdisp->idle_render.active)
|
|
{
|
|
new_ga = g_malloc (sizeof (GimpArea));
|
|
new_ga->x1 = gdisp->idle_render.basex;
|
|
new_ga->y1 = gdisp->idle_render.y;
|
|
new_ga->x2 = gdisp->idle_render.basex + gdisp->idle_render.width;
|
|
new_ga->y2 = gdisp->idle_render.y +
|
|
(gdisp->idle_render.height -
|
|
(gdisp->idle_render.y - gdisp->idle_render.basey)
|
|
);
|
|
|
|
gdisp->idle_render.update_areas =
|
|
gimp_display_area_list_process (gdisp->idle_render.update_areas, new_ga);
|
|
|
|
idle_render_next_area (gdisp);
|
|
}
|
|
else
|
|
{
|
|
if (gdisp->idle_render.update_areas == NULL)
|
|
{
|
|
g_warning ("Wanted to start idlerender thread with no update_areas. (+memleak)");
|
|
return;
|
|
}
|
|
|
|
idle_render_next_area (gdisp);
|
|
|
|
gdisp->idle_render.active = TRUE;
|
|
gdisp->idle_render.idleid = gtk_idle_add_priority (GTK_PRIORITY_LOW,
|
|
idlerender_callback,
|
|
gdisp);
|
|
}
|
|
|
|
/* Caller frees gdisp->update_areas */
|
|
}
|
|
|
|
|
|
static void
|
|
gimp_display_flush_whenever (GimpDisplay *gdisp,
|
|
gboolean now)
|
|
{
|
|
GSList *list;
|
|
GimpArea *ga;
|
|
|
|
/* Flush the items in the displays and updates lists -
|
|
* but only if gdisplay has been mapped and exposed
|
|
*/
|
|
if (!gdisp->select)
|
|
return;
|
|
|
|
/* First the updates... */
|
|
if (now)
|
|
{
|
|
/* Synchronous */
|
|
|
|
list = gdisp->update_areas;
|
|
while (list)
|
|
{
|
|
/* Paint the area specified by the GimpArea */
|
|
ga = (GimpArea *) list->data;
|
|
|
|
if ((ga->x1 != ga->x2) && (ga->y1 != ga->y2))
|
|
{
|
|
gimp_display_paint_area (gdisp, ga->x1, ga->y1,
|
|
(ga->x2 - ga->x1), (ga->y2 - ga->y1));
|
|
}
|
|
|
|
list = g_slist_next (list);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Asynchronous */
|
|
|
|
if (gdisp->update_areas)
|
|
gimp_display_idlerender_init (gdisp);
|
|
}
|
|
/* Free the update lists */
|
|
gdisp->update_areas = gimp_display_area_list_free (gdisp->update_areas);
|
|
|
|
/* Next the displays... */
|
|
gimp_display_shell_flush (GIMP_DISPLAY_SHELL (gdisp->shell));
|
|
|
|
/* update the gdisplay's info dialog */
|
|
info_window_update (gdisp);
|
|
|
|
/* update the gdisplay's qmask buttons */
|
|
qmask_buttons_update (gdisp);
|
|
|
|
/* ensure the consistency of the tear-off menus */
|
|
if (! now && gimp_context_get_display (gimp_get_user_context
|
|
(gdisp->gimage->gimp)) == gdisp)
|
|
{
|
|
gimp_display_shell_set_menu_sensitivity (GIMP_DISPLAY_SHELL (gdisp->shell));
|
|
}
|
|
}
|
|
|
|
void
|
|
gdisplay_flush (GimpDisplay *gdisp)
|
|
{
|
|
g_return_if_fail (GIMP_IS_DISPLAY (gdisp));
|
|
|
|
/* Redraw on idle time */
|
|
gimp_display_flush_whenever (gdisp, FALSE);
|
|
}
|
|
|
|
void
|
|
gdisplay_flush_now (GimpDisplay *gdisp)
|
|
{
|
|
g_return_if_fail (GIMP_IS_DISPLAY (gdisp));
|
|
|
|
/* Redraw NOW */
|
|
gimp_display_flush_whenever (gdisp, TRUE);
|
|
}
|
|
|
|
/* Force all gdisplays to finish their idlerender projection */
|
|
void
|
|
gdisplays_finish_draw (void)
|
|
{
|
|
GSList *list;
|
|
GimpDisplay *gdisp;
|
|
|
|
for (list = display_list; list; list = g_slist_next (list))
|
|
{
|
|
gdisp = (GimpDisplay *) list->data;
|
|
|
|
if (gdisp->idle_render.active)
|
|
{
|
|
g_source_remove (gdisp->idle_render.idleid);
|
|
gdisp->idle_render.idleid = 0;
|
|
|
|
while (idlerender_callback (gdisp));
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
gdisplay_add_update_area (GimpDisplay *gdisp,
|
|
gint x,
|
|
gint y,
|
|
gint w,
|
|
gint h)
|
|
{
|
|
GimpArea *ga;
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY (gdisp));
|
|
|
|
ga = g_new (GimpArea, 1);
|
|
|
|
ga->x1 = CLAMP (x, 0, gdisp->gimage->width);
|
|
ga->y1 = CLAMP (y, 0, gdisp->gimage->height);
|
|
ga->x2 = CLAMP (x + w, 0, gdisp->gimage->width);
|
|
ga->y2 = CLAMP (y + h, 0, gdisp->gimage->height);
|
|
|
|
gdisp->update_areas = gimp_display_area_list_process (gdisp->update_areas, ga);
|
|
}
|
|
|
|
|
|
static void
|
|
gimp_display_paint_area (GimpDisplay *gdisp,
|
|
gint x,
|
|
gint y,
|
|
gint w,
|
|
gint h)
|
|
{
|
|
GimpDisplayShell *shell;
|
|
gint x1, y1, x2, y2;
|
|
|
|
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
|
|
|
|
/* Bounds check */
|
|
x1 = CLAMP (x, 0, gdisp->gimage->width);
|
|
y1 = CLAMP (y, 0, gdisp->gimage->height);
|
|
x2 = CLAMP (x + w, 0, gdisp->gimage->width);
|
|
y2 = CLAMP (y + h, 0, gdisp->gimage->height);
|
|
x = x1;
|
|
y = y1;
|
|
w = (x2 - x1);
|
|
h = (y2 - y1);
|
|
|
|
/* calculate the extents of the update as limited by what's visible */
|
|
gdisplay_untransform_coords (gdisp,
|
|
0, 0,
|
|
&x1, &y1,
|
|
FALSE, FALSE);
|
|
gdisplay_untransform_coords (gdisp,
|
|
shell->disp_width, shell->disp_height,
|
|
&x2, &y2,
|
|
FALSE, FALSE);
|
|
|
|
gimp_image_invalidate (gdisp->gimage, x, y, w, h, x1, y1, x2, y2);
|
|
|
|
/* display the area */
|
|
gdisplay_transform_coords (gdisp, x, y, &x1, &y1, FALSE);
|
|
gdisplay_transform_coords (gdisp, x + w, y + h, &x2, &y2, FALSE);
|
|
|
|
gimp_display_shell_add_expose_area (shell,
|
|
x1, y1, (x2 - x1), (y2 - y1));
|
|
}
|
|
|
|
void
|
|
gdisplay_transform_coords (GimpDisplay *gdisp,
|
|
gint x,
|
|
gint y,
|
|
gint *nx,
|
|
gint *ny,
|
|
gboolean use_offsets)
|
|
{
|
|
GimpDisplayShell *shell;
|
|
gdouble scalex;
|
|
gdouble scaley;
|
|
gint offset_x;
|
|
gint offset_y;
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY (gdisp));
|
|
g_return_if_fail (nx != NULL);
|
|
g_return_if_fail (ny != NULL);
|
|
|
|
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
|
|
|
|
/* transform from image coordinates to screen coordinates */
|
|
scalex = SCALEFACTOR_X (gdisp);
|
|
scaley = SCALEFACTOR_Y (gdisp);
|
|
|
|
if (use_offsets)
|
|
{
|
|
gimp_drawable_offsets (gimp_image_active_drawable (gdisp->gimage),
|
|
&offset_x, &offset_y);
|
|
}
|
|
else
|
|
{
|
|
offset_x = offset_y = 0;
|
|
}
|
|
|
|
*nx = (gint) (scalex * (x + offset_x) - shell->offset_x);
|
|
*ny = (gint) (scaley * (y + offset_y) - shell->offset_y);
|
|
|
|
*nx += shell->disp_xoffset;
|
|
*ny += shell->disp_yoffset;
|
|
}
|
|
|
|
void
|
|
gdisplay_untransform_coords (GimpDisplay *gdisp,
|
|
gint x,
|
|
gint y,
|
|
gint *nx,
|
|
gint *ny,
|
|
gboolean round,
|
|
gboolean use_offsets)
|
|
{
|
|
GimpDisplayShell *shell;
|
|
gdouble scalex;
|
|
gdouble scaley;
|
|
gint offset_x;
|
|
gint offset_y;
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY (gdisp));
|
|
g_return_if_fail (nx != NULL);
|
|
g_return_if_fail (ny != NULL);
|
|
|
|
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
|
|
|
|
x -= shell->disp_xoffset;
|
|
y -= shell->disp_yoffset;
|
|
|
|
/* transform from screen coordinates to image coordinates */
|
|
scalex = SCALEFACTOR_X (gdisp);
|
|
scaley = SCALEFACTOR_Y (gdisp);
|
|
|
|
if (use_offsets)
|
|
{
|
|
gimp_drawable_offsets (gimp_image_active_drawable (gdisp->gimage),
|
|
&offset_x, &offset_y);
|
|
}
|
|
else
|
|
{
|
|
offset_x = offset_y = 0;
|
|
}
|
|
|
|
if (round)
|
|
{
|
|
*nx = ROUND ((x + shell->offset_x) / scalex - offset_x);
|
|
*ny = ROUND ((y + shell->offset_y) / scaley - offset_y);
|
|
}
|
|
else
|
|
{
|
|
*nx = (int) ((x + shell->offset_x) / scalex - offset_x);
|
|
*ny = (int) ((y + shell->offset_y) / scaley - offset_y);
|
|
}
|
|
}
|
|
|
|
void
|
|
gdisplay_transform_coords_f (GimpDisplay *gdisp,
|
|
gdouble x,
|
|
gdouble y,
|
|
gdouble *nx,
|
|
gdouble *ny,
|
|
gboolean use_offsets)
|
|
{
|
|
GimpDisplayShell *shell;
|
|
gdouble scalex;
|
|
gdouble scaley;
|
|
gint offset_x;
|
|
gint offset_y;
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY (gdisp));
|
|
g_return_if_fail (nx != NULL);
|
|
g_return_if_fail (ny != NULL);
|
|
|
|
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
|
|
|
|
/* transform from gimp coordinates to screen coordinates */
|
|
scalex = SCALEFACTOR_X (gdisp);
|
|
scaley = SCALEFACTOR_Y (gdisp);
|
|
|
|
if (use_offsets)
|
|
{
|
|
gimp_drawable_offsets (gimp_image_active_drawable (gdisp->gimage),
|
|
&offset_x, &offset_y);
|
|
}
|
|
else
|
|
{
|
|
offset_x = offset_y = 0;
|
|
}
|
|
|
|
*nx = scalex * (x + offset_x) - shell->offset_x;
|
|
*ny = scaley * (y + offset_y) - shell->offset_y;
|
|
|
|
*nx += shell->disp_xoffset;
|
|
*ny += shell->disp_yoffset;
|
|
}
|
|
|
|
void
|
|
gdisplay_untransform_coords_f (GimpDisplay *gdisp,
|
|
gdouble x,
|
|
gdouble y,
|
|
gdouble *nx,
|
|
gdouble *ny,
|
|
gboolean use_offsets)
|
|
{
|
|
GimpDisplayShell *shell;
|
|
gdouble scalex;
|
|
gdouble scaley;
|
|
gint offset_x;
|
|
gint offset_y;
|
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY (gdisp));
|
|
g_return_if_fail (nx != NULL);
|
|
g_return_if_fail (ny != NULL);
|
|
|
|
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
|
|
|
|
x -= shell->disp_xoffset;
|
|
y -= shell->disp_yoffset;
|
|
|
|
/* transform from screen coordinates to gimp coordinates */
|
|
scalex = SCALEFACTOR_X (gdisp);
|
|
scaley = SCALEFACTOR_Y (gdisp);
|
|
|
|
if (use_offsets)
|
|
{
|
|
gimp_drawable_offsets (gimp_image_active_drawable (gdisp->gimage),
|
|
&offset_x, &offset_y);
|
|
}
|
|
else
|
|
{
|
|
offset_x = offset_y = 0;
|
|
}
|
|
|
|
*nx = (x + shell->offset_x) / scalex - offset_x;
|
|
*ny = (y + shell->offset_y) / scaley - offset_y;
|
|
}
|
|
|
|
void
|
|
gdisplay_selection_visibility (GimpDisplay *gdisp,
|
|
GimpSelectionControl control)
|
|
{
|
|
g_return_if_fail (GIMP_IS_DISPLAY (gdisp));
|
|
|
|
if (gdisp->select)
|
|
{
|
|
switch (control)
|
|
{
|
|
case GIMP_SELECTION_OFF:
|
|
selection_invis (gdisp->select);
|
|
break;
|
|
case GIMP_SELECTION_LAYER_OFF:
|
|
selection_layer_invis (gdisp->select);
|
|
break;
|
|
case GIMP_SELECTION_ON:
|
|
selection_start (gdisp->select, TRUE);
|
|
break;
|
|
case GIMP_SELECTION_PAUSE:
|
|
selection_pause (gdisp->select);
|
|
break;
|
|
case GIMP_SELECTION_RESUME:
|
|
selection_resume (gdisp->select);
|
|
break;
|
|
}
|
|
}
|
|
}
|