no need to include gimpdisplayshell-render.h here.

2004-10-01  Sven Neumann  <sven@gimp.org>

	* app/display/gimpdisplayshell-callbacks.c: no need to include
	gimpdisplayshell-render.h here.

	* app/display/gimpdisplayshell-draw.c
	* app/display/gimpdisplayshell-render.[ch]

	* app/display/gimpdisplayshell.[ch]: added an API to highlight a
	rectangle (specified in image coordinates). Actually it doesn't
	highlight but dims the area outside the rectangle.

	* app/tools/gimpcroptool.c: use the new functionality to show the
	area to be cropped. Fixes bug #93360.
This commit is contained in:
Sven Neumann 2004-10-01 09:50:04 +00:00 committed by Sven Neumann
parent efc2187e80
commit 297b53a466
8 changed files with 208 additions and 13 deletions

View file

@ -1,3 +1,18 @@
2004-10-01 Sven Neumann <sven@gimp.org>
* app/display/gimpdisplayshell-callbacks.c: no need to include
gimpdisplayshell-render.h here.
* app/display/gimpdisplayshell-draw.c
* app/display/gimpdisplayshell-render.[ch]
* app/display/gimpdisplayshell.[ch]: added an API to highlight a
rectangle (specified in image coordinates). Actually it doesn't
highlight but dims the area outside the rectangle.
* app/tools/gimpcroptool.c: use the new functionality to show the
area to be cropped. Fixes bug #93360.
2004-09-30 Michael Natterer <mitch@gimp.org>
* plug-ins/script-fu/script-fu-types.h (struct SFScript): renamed

View file

@ -65,7 +65,6 @@
#include "gimpdisplayshell-draw.h"
#include "gimpdisplayshell-layer-select.h"
#include "gimpdisplayshell-preview.h"
#include "gimpdisplayshell-render.h"
#include "gimpdisplayshell-scale.h"
#include "gimpdisplayshell-scroll.h"
#include "gimpdisplayshell-selection.h"

View file

@ -399,12 +399,21 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
sx, sy, sw, sh,
&x, &y, &w, &h))
{
gint x2, y2;
gint i, j;
GdkRectangle rect;
gint x2, y2;
gint i, j;
x2 = x + w;
y2 = y + h;
if (shell->highlight)
{
rect.x = SCALEX (shell, shell->highlight->x);
rect.y = SCALEY (shell, shell->highlight->y);
rect.width = SCALEX (shell, shell->highlight->width);
rect.height = SCALEY (shell, shell->highlight->height);
}
/* display the image in RENDER_BUF_WIDTH x RENDER_BUF_HEIGHT
* sized chunks
*/
@ -420,7 +429,8 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
gimp_display_shell_render (shell,
j - shell->disp_xoffset,
i - shell->disp_yoffset,
dx, dy);
dx, dy,
shell->highlight ? &rect : NULL);
#ifdef STRESS_TEST
/* Invalidate the projection just after we render it! */

View file

@ -297,6 +297,14 @@ static RenderFunc render_funcs[6] =
};
static void gimp_display_shell_render_highlight (GimpDisplayShell *shell,
gint x,
gint y,
gint w,
gint h,
GdkRectangle *highlight);
/*****************************************************************/
/* This function is the core of the display--it offsets and */
/* scales the image according to the current parameters in the */
@ -309,7 +317,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
gint x,
gint y,
gint w,
gint h)
gint h,
GdkRectangle *highlight)
{
RenderInfo info;
GimpImageType image_type;
@ -346,6 +355,10 @@ gimp_display_shell_render (GimpDisplayShell *shell,
3,
3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH);
/* dim pixels outside the highlighted rectangle */
if (highlight)
gimp_display_shell_render_highlight (shell, x, y, w, h, highlight);
/* put it to the screen */
gimp_canvas_draw_rgb (GIMP_CANVAS (shell->canvas), GIMP_CANVAS_STYLE_RENDER,
x + shell->disp_xoffset, y + shell->disp_yoffset,
@ -356,6 +369,76 @@ gimp_display_shell_render (GimpDisplayShell *shell,
}
#define GIMP_DISPLAY_SHELL_DIM_PIXEL(buf,x) \
{ \
buf[3 * (x) + 0] >>= 1; \
buf[3 * (x) + 1] >>= 1; \
buf[3 * (x) + 2] >>= 1; \
}
/* This function highlights the given area by dimming all pixels outside. */
static void
gimp_display_shell_render_highlight (GimpDisplayShell *shell,
gint x,
gint y,
gint w,
gint h,
GdkRectangle *highlight)
{
guchar *buf = shell->render_buf;
GdkRectangle rect;
rect.x = shell->offset_x + x;
rect.y = shell->offset_y + y;
rect.width = w;
rect.height = h;
if (gdk_rectangle_intersect (highlight, &rect, &rect))
{
rect.x -= shell->offset_x + x;
rect.y -= shell->offset_y + y;
for (y = 0; y < rect.y; y++)
{
for (x = 0; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
}
for ( ; y < rect.y + rect.height; y++)
{
for (x = 0; x < rect.x; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
for (x += rect.width; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
}
for ( ; y < h; y++)
{
for (x = 0; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
}
}
else
{
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
buf += 3 * GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH;
}
}
}
/*************************/
/* 8 Bit functions */
/*************************/

View file

@ -31,7 +31,8 @@ void gimp_display_shell_render (GimpDisplayShell *shell,
gint x,
gint y,
gint w,
gint h);
gint h,
GdkRectangle *highlight);
/*
* Extern variables

View file

@ -18,6 +18,8 @@
#include "config.h"
#include <string.h>
#include <gtk/gtk.h>
#include "libgimpwidgets/gimpwidgets.h"
@ -311,6 +313,8 @@ gimp_display_shell_init (GimpDisplayShell *shell)
shell->scroll_start_y = 0;
shell->button_press_before_focus = FALSE;
shell->highlight = NULL;
gtk_window_set_role (GTK_WINDOW (shell), "gimp-image-window");
gtk_window_set_resizable (GTK_WINDOW (shell), TRUE);
@ -420,6 +424,12 @@ gimp_display_shell_destroy (GtkObject *object)
shell->render_buf = NULL;
}
if (shell->highlight)
{
g_free (shell->highlight);
shell->highlight = NULL;
}
if (shell->title_idle_id)
{
g_source_remove (shell->title_idle_id);
@ -1418,3 +1428,64 @@ gimp_display_shell_selection_visibility (GimpDisplayShell *shell,
}
}
}
/**
* gimp_display_shell_set_highlight:
* @shell: a #GimpDisplayShell
* @highlight: a rectangle in image coordinates that should be brought out
*
* This function allows to set an area of the image that should be
* accentuated. The actual implementation is to dim all pixels outside
* this rectangle. Passing %NULL for @highlight unsets the rectangle.
**/
void
gimp_display_shell_set_highlight (GimpDisplayShell *shell,
const GdkRectangle *highlight)
{
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
if (shell->highlight)
{
if (highlight)
{
GdkRectangle *rects;
GdkRegion *old;
GdkRegion *new;
gint num_rects, i;
if (memcmp (shell->highlight, highlight, sizeof (GdkRectangle)) == 0)
return;
old = gdk_region_rectangle (shell->highlight);
*shell->highlight = *highlight;
new = gdk_region_rectangle (shell->highlight);
gdk_region_xor (old, new);
gdk_region_get_rectangles (old, &rects, &num_rects);
for (i = 0; i < num_rects; i++)
gimp_display_update_area (shell->gdisp, TRUE,
rects[i].x,
rects[i].y,
rects[i].width,
rects[i].height);
g_free (rects);
}
else
{
g_free (shell->highlight);
shell->highlight = NULL;
gimp_display_shell_expose_full (shell);
}
}
else if (highlight)
{
shell->highlight = g_memdup (highlight, sizeof (GdkRectangle));
gimp_display_shell_expose_full (shell);
}
}

View file

@ -166,6 +166,8 @@ struct _GimpDisplayShell
gint scroll_start_y;
gboolean button_press_before_focus;
guint32 last_motion_time;
GdkRectangle *highlight; /* in image coordinates, can be NULL */
};
struct _GimpDisplayShellClass
@ -229,6 +231,8 @@ void gimp_display_shell_shrink_wrap (GimpDisplayShell *shell);
void gimp_display_shell_selection_visibility (GimpDisplayShell *shell,
GimpSelectionControl control);
void gimp_display_shell_set_highlight (GimpDisplayShell *shell,
const GdkRectangle *highlight);
#endif /* __GIMP_DISPLAY_SHELL_H__ */

View file

@ -247,19 +247,18 @@ gimp_crop_tool_control (GimpTool *tool,
GimpToolAction action,
GimpDisplay *gdisp)
{
GimpCropTool *crop = GIMP_CROP_TOOL (tool);
switch (action)
{
case PAUSE:
break;
case RESUME:
crop_recalc (crop);
break;
case HALT:
crop_response (NULL, GTK_RESPONSE_CANCEL, crop);
gimp_display_shell_set_highlight (GIMP_DISPLAY_SHELL (gdisp->shell),
NULL);
crop_response (NULL, GTK_RESPONSE_CANCEL, GIMP_CROP_TOOL (tool));
break;
default:
@ -854,16 +853,25 @@ crop_tool_crop_image (GimpImage *gimage,
static void
crop_recalc (GimpCropTool *crop)
{
GimpTool *tool = GIMP_TOOL (crop);
GimpTool *tool = GIMP_TOOL (crop);
GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (tool->gdisp->shell);
GdkRectangle rect;
if (! tool->gdisp)
return;
gimp_display_shell_transform_xy (GIMP_DISPLAY_SHELL (tool->gdisp->shell),
rect.x = crop->x1;
rect.y = crop->y1;
rect.width = crop->x2 - crop->x1;
rect.height = crop->y2 - crop->y1;
gimp_display_shell_set_highlight (shell, &rect);
gimp_display_shell_transform_xy (shell,
crop->x1, crop->y1,
&crop->dx1, &crop->dy1,
FALSE);
gimp_display_shell_transform_xy (GIMP_DISPLAY_SHELL (tool->gdisp->shell),
gimp_display_shell_transform_xy (shell,
crop->x2, crop->y2,
&crop->dx2, &crop->dy2,
FALSE);
@ -1116,12 +1124,16 @@ crop_response (GtkWidget *widget,
GIMP_CROP_MODE_RESIZE, FALSE);
}
gimp_display_shell_set_highlight (GIMP_DISPLAY_SHELL (tool->gdisp->shell),
NULL);
crop_tool_crop_image (tool->gdisp->gimage,
GIMP_CONTEXT (options),
crop->x1, crop->y1,
crop->x2, crop->y2,
options->layer_only,
(GimpCropMode) response_id);
break;
default: