app/display: draw the crop highlight using cairo

Instead of dimming the actual pixels, apply a translucent fill to
the area outside the highlight rectangle.
This commit is contained in:
Sven Neumann 2010-09-28 22:04:07 +02:00
parent ccee0ec41a
commit eb5bb6363e
5 changed files with 70 additions and 123 deletions

View File

@ -2293,9 +2293,9 @@ gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
image_rect.height);
cairo_restore (cr);
gdk_region_get_rectangles (image_region, &rects, &n_rects);
cairo_save (cr);
gdk_region_get_rectangles (image_region, &rects, &n_rects);
for (i = 0; i < n_rects; i++)
gimp_display_shell_draw_area (shell, cr,
@ -2304,9 +2304,19 @@ gimp_display_shell_canvas_expose_image (GimpDisplayShell *shell,
rects[i].width,
rects[i].height);
g_free (rects);
cairo_restore (cr);
g_free (rects);
if (shell->highlight)
{
cairo_save (cr);
gimp_display_shell_draw_highlight (shell, cr,
image_rect.x,
image_rect.y,
image_rect.width,
image_rect.height);
cairo_restore (cr);
}
}
gdk_region_destroy (image_region);

View File

@ -707,9 +707,8 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
gint w,
gint h)
{
GdkRectangle rect;
gint x2, y2;
gint i, j;
gint x2, y2;
gint i, j;
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
g_return_if_fail (gimp_display_get_image (shell->display));
@ -718,14 +717,6 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
x2 = x + w;
y2 = y + h;
if (shell->highlight)
{
rect.x = ceil (shell->scale_x * shell->highlight->x);
rect.y = ceil (shell->scale_y * shell->highlight->y);
rect.width = floor (shell->scale_x * shell->highlight->width);
rect.height = floor (shell->scale_y * shell->highlight->height);
}
/* display the image in RENDER_BUF_WIDTH x RENDER_BUF_HEIGHT
* sized chunks
*/
@ -746,8 +737,7 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
gimp_display_shell_render (shell, cr,
j - disp_xoffset,
i - disp_yoffset,
dx, dy,
shell->highlight ? &rect : NULL);
dx, dy);
}
}
}
@ -792,7 +782,36 @@ gimp_display_shell_draw_checkerboard (GimpDisplayShell *shell,
cairo_rectangle (cr, x, y, w, h);
cairo_clip (cr);
cairo_translate (cr, - shell->offset_x, - shell->offset_y);
cairo_set_source (cr, shell->checkerboard);
cairo_paint (cr);
}
void
gimp_display_shell_draw_highlight (GimpDisplayShell *shell,
cairo_t *cr,
gint x,
gint y,
gint w,
gint h)
{
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
g_return_if_fail (shell->highlight != NULL);
g_return_if_fail (cr != NULL);
cairo_rectangle (cr, x, y, w, h);
cairo_translate (cr, - shell->offset_x, - shell->offset_y);
cairo_scale (cr, shell->scale_x, shell->scale_y);
cairo_rectangle (cr,
shell->highlight->x, shell->highlight->y,
shell->highlight->width, shell->highlight->height);
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_clip (cr);
/* FIXME: make this configurable or at least use gimpdisplayshell-style.c */
cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
cairo_paint (cr);
}

View File

@ -77,6 +77,12 @@ void gimp_display_shell_draw_checkerboard (GimpDisplayShell *shell,
gint y,
gint w,
gint h);
void gimp_display_shell_draw_highlight (GimpDisplayShell *shell,
cairo_t *cr,
gint x,
gint y,
gint w,
gint h);
#endif /* __GIMP_DISPLAY_SHELL_DRAW_H__ */

View File

@ -95,11 +95,11 @@ struct _RenderInfo
gint64 dy;
};
static void gimp_display_shell_render_info_scale (RenderInfo *info,
GimpDisplayShell *shell,
TileManager *tiles,
gint level,
gboolean is_premult);
static void gimp_display_shell_render_info_scale (RenderInfo *info,
GimpDisplayShell *shell,
TileManager *tiles,
gint level,
gboolean is_premult);
static guchar *tile_buf = NULL;
@ -129,21 +129,14 @@ gimp_display_shell_render_exit (Gimp *gimp)
/* Render Image functions */
static void render_image_rgb_a (RenderInfo *info);
static void render_image_gray_a (RenderInfo *info);
static void render_image_rgb_a (RenderInfo *info);
static void render_image_gray_a (RenderInfo *info);
static const guchar * render_image_tile_fault (RenderInfo *info);
static const guchar * render_image_tile_fault (RenderInfo *info);
static void gimp_display_shell_render_highlight (GimpDisplayShell *shell,
RenderInfo *info,
gint x,
gint y,
gint w,
gint h,
const GdkRectangle *highlight);
static void gimp_display_shell_render_mask (GimpDisplayShell *shell,
RenderInfo *info);
static void gimp_display_shell_render_mask (GimpDisplayShell *shell,
RenderInfo *info);
/*****************************************************************/
@ -159,8 +152,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
gint x,
gint y,
gint w,
gint h,
const GdkRectangle *highlight)
gint h)
{
GimpProjection *projection;
GimpImage *image;
@ -245,12 +237,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
#endif
#if 0
/* dim pixels outside the highlighted rectangle */
if (highlight)
{
gimp_display_shell_render_highlight (shell, &info, x, y, w, h, highlight);
}
else if (shell->mask)
if (shell->mask)
{
TileManager *tiles = gimp_drawable_get_tiles (shell->mask);
@ -288,80 +275,6 @@ gimp_display_shell_render (GimpDisplayShell *shell,
#define CAIRO_RGB24_BLUE_PIXEL 3
#endif
#define GIMP_DISPLAY_SHELL_DIM_PIXEL(buf,x) \
{ \
buf[4 * (x) + CAIRO_RGB24_RED_PIXEL] >>= 1; \
buf[4 * (x) + CAIRO_RGB24_GREEN_PIXEL] >>= 1; \
buf[4 * (x) + CAIRO_RGB24_BLUE_PIXEL] >>= 1; \
}
/* This function highlights the given area by dimming all pixels outside. */
static void
gimp_display_shell_render_highlight (GimpDisplayShell *shell,
RenderInfo *info,
gint x,
gint y,
gint w,
gint h,
const GdkRectangle *highlight)
{
guchar *buf = cairo_image_surface_get_data (shell->render_surface);
GdkRectangle rect;
gint offset_x;
gint offset_y;
gimp_display_shell_scroll_get_render_start_offset (shell,
&offset_x, &offset_y);
rect.x = x + offset_x;
rect.y = y + offset_y;
rect.width = w;
rect.height = h;
if (gdk_rectangle_intersect (highlight, &rect, &rect))
{
rect.x -= x + offset_x;
rect.y -= y + offset_y;
for (y = 0; y < rect.y; y++)
{
for (x = 0; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
buf += info->dest_bpl;
}
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 += info->dest_bpl;
}
for ( ; y < h; y++)
{
for (x = 0; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
buf += info->dest_bpl;
}
}
else
{
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++)
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
buf += info->dest_bpl;
}
}
}
static void
gimp_display_shell_render_mask (GimpDisplayShell *shell,

View File

@ -23,16 +23,15 @@
#define GIMP_DISPLAY_RENDER_BUF_HEIGHT 256
void gimp_display_shell_render_init (Gimp *gimp);
void gimp_display_shell_render_exit (Gimp *gimp);
void gimp_display_shell_render_init (Gimp *gimp);
void gimp_display_shell_render_exit (Gimp *gimp);
void gimp_display_shell_render (GimpDisplayShell *shell,
cairo_t *cr,
gint x,
gint y,
gint w,
gint h,
const GdkRectangle *highlight);
void gimp_display_shell_render (GimpDisplayShell *shell,
cairo_t *cr,
gint x,
gint y,
gint w,
gint h);
#endif /* __GIMP_DISPLAY_SHELL_RENDER_H__ */