replaced the RGB buffer with a Cairo surface.

2007-11-04  Sven Neumann  <sven@gimp.org>

	* app/widgets/gimpviewrenderer.[ch]: replaced the RGB buffer 
with
	a Cairo surface.

	* app/widgets/gimpviewrendererbuffer.c
	* app/widgets/gimpviewrendererbrush.c
	* app/widgets/gimpviewrendererdrawable.c
	* app/widgets/gimpviewrenderergradient.c
	* app/widgets/gimpviewrendererimage.c
	* app/widgets/gimpviewrendererpalette.c
	* app/widgets/gimpviewrenderervectors.c: changed accordingly. 
There
	are some loose ends here that will be fixed over the next days.

	* app/widgets/gimprender.c: removed gimp_render_temp_buf; it is
	not any longer needed.

	* app/core/gimpgradient.c (gimp_gradient_get_preview_size): 
return
	an odd preview height to make the border align with the pixel 
grid.


svn path=/trunk/; revision=24056
This commit is contained in:
Sven Neumann 2007-11-04 19:14:32 +00:00 committed by Sven Neumann
parent 982ae0eb0c
commit fa7e312a2c
13 changed files with 385 additions and 328 deletions

View File

@ -1,3 +1,23 @@
2007-11-04 Sven Neumann <sven@gimp.org>
* app/widgets/gimpviewrenderer.[ch]: replaced the RGB buffer with
a Cairo surface.
* app/widgets/gimpviewrendererbuffer.c
* app/widgets/gimpviewrendererbrush.c
* app/widgets/gimpviewrendererdrawable.c
* app/widgets/gimpviewrenderergradient.c
* app/widgets/gimpviewrendererimage.c
* app/widgets/gimpviewrendererpalette.c
* app/widgets/gimpviewrenderervectors.c: changed accordingly. There
are some loose ends here that will be fixed over the next days.
* app/widgets/gimprender.c: removed gimp_render_temp_buf; it is
not any longer needed.
* app/core/gimpgradient.c (gimp_gradient_get_preview_size): return
an odd preview height to make the border align with the pixel grid.
2007-11-04 Sven Neumann <sven@gimp.org>
* app/tools/gimplevelstool.c (levels_input_area_event): minor cleanup.

View File

@ -151,7 +151,7 @@ gimp_gradient_get_preview_size (GimpViewable *viewable,
gint *height)
{
*width = size;
*height = size / 2;
*height = 1 + size / 2;
}
static gboolean

View File

@ -41,7 +41,6 @@ static void gimp_render_setup_notify (gpointer config,
guchar *gimp_render_check_buf = NULL;
guchar *gimp_render_empty_buf = NULL;
guchar *gimp_render_white_buf = NULL;
guchar *gimp_render_temp_buf = NULL;
guchar *gimp_render_blend_dark_check = NULL;
guchar *gimp_render_blend_light_check = NULL;
@ -104,12 +103,6 @@ gimp_render_exit (Gimp *gimp)
g_free (gimp_render_white_buf);
gimp_render_white_buf = NULL;
}
if (gimp_render_temp_buf)
{
g_free (gimp_render_temp_buf);
gimp_render_temp_buf = NULL;
}
}
@ -149,7 +142,6 @@ gimp_render_setup_notify (gpointer config,
g_free (gimp_render_check_buf);
g_free (gimp_render_empty_buf);
g_free (gimp_render_white_buf);
g_free (gimp_render_temp_buf);
#define BUF_SIZE (MAX (GIMP_RENDER_BUF_WIDTH, \
GIMP_VIEWABLE_MAX_PREVIEW_SIZE) + 4)
@ -157,7 +149,6 @@ gimp_render_setup_notify (gpointer config,
gimp_render_check_buf = g_new (guchar, BUF_SIZE * 3);
gimp_render_empty_buf = g_new0 (guchar, BUF_SIZE * 3);
gimp_render_white_buf = g_new (guchar, BUF_SIZE * 3);
gimp_render_temp_buf = g_new (guchar, BUF_SIZE * 3);
/* calculate check buffer for previews */

View File

@ -27,7 +27,6 @@
extern guchar *gimp_render_check_buf;
extern guchar *gimp_render_empty_buf;
extern guchar *gimp_render_white_buf;
extern guchar *gimp_render_temp_buf;
extern guchar *gimp_render_blend_dark_check;
extern guchar *gimp_render_blend_light_check;

View File

@ -61,28 +61,26 @@ static void gimp_view_renderer_real_set_context (GimpViewRenderer *render
GimpContext *context);
static void gimp_view_renderer_real_invalidate (GimpViewRenderer *renderer);
static void gimp_view_renderer_real_draw (GimpViewRenderer *renderer,
GdkWindow *window,
GtkWidget *widget,
const GdkRectangle *draw_area,
const GdkRectangle *expose_area);
cairo_t *cr,
const GdkRectangle *draw_area);
static void gimp_view_renderer_real_render (GimpViewRenderer *renderer,
GtkWidget *widget);
static void gimp_view_renderer_size_changed (GimpViewRenderer *renderer,
GimpViewable *viewable);
static cairo_pattern_t *
gimp_view_renderer_create_pattern (GimpViewRenderer *renderer,
GtkWidget *widget);
static void gimp_view_render_to_buffer (TempBuf *temp_buf,
gint channel,
GimpViewBG inside_bg,
GimpViewBG outside_bg,
guchar *dest_buffer,
gint dest_width,
gint dest_height,
gint dest_rowstride,
gint dest_bytes);
static void gimp_view_render_to_surface (TempBuf *temp_buf,
gint channel,
GimpViewBG inside_bg,
GimpViewBG outside_bg,
cairo_surface_t *surface,
gint dest_width,
gint dest_height);
@ -150,12 +148,8 @@ gimp_view_renderer_init (GimpViewRenderer *renderer)
renderer->border_type = GIMP_VIEW_BORDER_BLACK;
renderer->border_color = black_color;
renderer->surface = NULL;
renderer->pattern = NULL;
renderer->buffer = NULL;
renderer->rowstride = 0;
renderer->bytes = 3;
renderer->pixbuf = NULL;
renderer->bg_stock_id = NULL;
@ -185,10 +179,16 @@ gimp_view_renderer_finalize (GObject *object)
{
GimpViewRenderer *renderer = GIMP_VIEW_RENDERER (object);
if (renderer->buffer)
if (renderer->pattern)
{
g_free (renderer->buffer);
renderer->buffer = NULL;
cairo_pattern_destroy (renderer->pattern);
renderer->pattern = NULL;
}
if (renderer->surface)
{
cairo_surface_destroy (renderer->surface);
renderer->surface = NULL;
}
if (renderer->pixbuf)
@ -203,12 +203,6 @@ gimp_view_renderer_finalize (GObject *object)
renderer->bg_stock_id = NULL;
}
if (renderer->pattern)
{
cairo_pattern_destroy (renderer->pattern);
renderer->pattern = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -318,10 +312,10 @@ gimp_view_renderer_set_viewable (GimpViewRenderer *renderer,
if (viewable == renderer->viewable)
return;
if (renderer->buffer)
if (renderer->surface)
{
g_free (renderer->buffer);
renderer->buffer = NULL;
cairo_surface_destroy (renderer->surface);
renderer->surface = NULL;
}
if (renderer->pixbuf)
@ -378,7 +372,8 @@ gimp_view_renderer_set_size (GimpViewRenderer *renderer,
gint view_size,
gint border_width)
{
gint width, height;
gint width;
gint height;
g_return_if_fail (GIMP_IS_VIEW_RENDERER (renderer));
g_return_if_fail (view_size > 0 &&
@ -427,12 +422,10 @@ gimp_view_renderer_set_size_full (GimpViewRenderer *renderer,
renderer->height = height;
renderer->border_width = border_width;
renderer->rowstride = (renderer->width * renderer->bytes + 3) & ~3;
if (renderer->buffer)
if (renderer->surface)
{
g_free (renderer->buffer);
renderer->buffer = NULL;
cairo_surface_destroy (renderer->surface);
renderer->surface = NULL;
}
if (renderer->viewable)
@ -586,24 +579,35 @@ gimp_view_renderer_draw (GimpViewRenderer *renderer,
const GdkRectangle *draw_area,
const GdkRectangle *expose_area)
{
cairo_t *cr;
GdkRectangle render_rect;
g_return_if_fail (GIMP_IS_VIEW_RENDERER (renderer));
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (draw_area != NULL);
g_return_if_fail (expose_area != NULL);
if (G_UNLIKELY (renderer->context == NULL))
g_warning ("%s: renderer->context is NULL", G_STRFUNC);
if (! GTK_WIDGET_DRAWABLE (widget))
return;
if (G_UNLIKELY (renderer->context == NULL))
g_warning ("%s: renderer->context is NULL", G_STRFUNC);
if (! gdk_rectangle_intersect ((GdkRectangle *) draw_area,
(GdkRectangle *) expose_area,
&render_rect))
return;
cr = gdk_cairo_create (window);
gdk_cairo_rectangle (cr, &render_rect);
cairo_clip (cr);
if (renderer->viewable)
{
GIMP_VIEW_RENDERER_GET_CLASS (renderer)->draw (renderer,
window, widget,
draw_area,
expose_area);
widget, cr, draw_area);
}
else
{
@ -617,28 +621,27 @@ gimp_view_renderer_draw (GimpViewRenderer *renderer,
g_type_class_unref (viewable_class);
gimp_view_renderer_real_draw (renderer,
window, widget, draw_area, expose_area);
gimp_view_renderer_real_draw (renderer, widget, cr, draw_area);
}
if (renderer->border_width > 0)
{
cairo_t *cr = gdk_cairo_create (window);
gint width = renderer->width + renderer->border_width;
gint height = renderer->height + renderer->border_width;
gint width = renderer->width + renderer->border_width;
gint height = renderer->height + renderer->border_width;
gdouble x, y;
cairo_set_line_width (cr, renderer->border_width);
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
gimp_cairo_set_source_color (cr, &renderer->border_color);
cairo_translate (cr,
draw_area->x + (draw_area->width - width) / 2,
draw_area->y + (draw_area->height - height) / 2);
cairo_rectangle (cr, 0, 0, width, height);
cairo_stroke (cr);
x = draw_area->x + (draw_area->width - width) / 2.0;
y = draw_area->y + (draw_area->height - height) / 2.0;
cairo_destroy (cr);
cairo_rectangle (cr, x, y, width, height);
cairo_stroke (cr);
}
cairo_destroy (cr);
}
@ -675,80 +678,48 @@ gimp_view_renderer_real_invalidate (GimpViewRenderer *renderer)
static void
gimp_view_renderer_real_draw (GimpViewRenderer *renderer,
GdkWindow *window,
GtkWidget *widget,
const GdkRectangle *draw_area,
const GdkRectangle *expose_area)
cairo_t *cr,
const GdkRectangle *draw_area)
{
GdkRectangle render_rect;
if (renderer->needs_render)
GIMP_VIEW_RENDERER_GET_CLASS (renderer)->render (renderer, widget);
if (renderer->pixbuf)
{
if (gdk_rectangle_intersect ((GdkRectangle *) draw_area,
(GdkRectangle *) expose_area,
&render_rect))
gint width = gdk_pixbuf_get_width (renderer->pixbuf);
gint height = gdk_pixbuf_get_height (renderer->pixbuf);
gint x, y;
if (renderer->bg_stock_id)
{
cairo_t *cr = gdk_cairo_create (window);
gint width = gdk_pixbuf_get_width (renderer->pixbuf);
gint height = gdk_pixbuf_get_height (renderer->pixbuf);
if (! renderer->pattern)
renderer->pattern = gimp_view_renderer_create_pattern (renderer,
widget);
gdk_cairo_rectangle (cr, &render_rect);
cairo_clip (cr);
if (renderer->bg_stock_id)
{
if (! renderer->pattern)
renderer->pattern = gimp_view_renderer_create_pattern (renderer,
widget);
cairo_set_source (cr, renderer->pattern);
cairo_paint (cr);
}
cairo_translate (cr,
draw_area->x + (draw_area->width - width) / 2,
draw_area->y + (draw_area->height - height) / 2);
gdk_cairo_set_source_pixbuf (cr, renderer->pixbuf, 0, 0);
cairo_rectangle (cr, 0, 0, width, height);
cairo_fill (cr);
cairo_destroy (cr);
}
}
else if (renderer->buffer)
{
GdkRectangle rect;
rect.width = renderer->width;
rect.height = renderer->height;
rect.x = draw_area->x + (draw_area->width - rect.width) / 2;
rect.y = draw_area->y + (draw_area->height - rect.height) / 2;
if (gdk_rectangle_intersect (&rect, (GdkRectangle *) expose_area,
&render_rect))
{
guchar *buf;
buf = (renderer->buffer +
(render_rect.y - rect.y) * renderer->rowstride +
(render_rect.x - rect.x) * renderer->bytes);
gdk_draw_rgb_image_dithalign (window,
widget->style->black_gc,
render_rect.x,
render_rect.y,
render_rect.width,
render_rect.height,
GDK_RGB_DITHER_NORMAL,
buf,
renderer->rowstride,
expose_area->x - draw_area->x,
expose_area->y - draw_area->y);
cairo_set_source (cr, renderer->pattern);
cairo_paint (cr);
}
x = draw_area->x + (draw_area->width - width) / 2;
y = draw_area->y + (draw_area->height - height) / 2;
gdk_cairo_set_source_pixbuf (cr, renderer->pixbuf, x, y);
cairo_rectangle (cr, x, y, width, height);
cairo_fill (cr);
}
else if (renderer->surface)
{
gint width = renderer->width;
gint height = renderer->height;
gint x, y;
x = draw_area->x + (draw_area->width - width) / 2;
y = draw_area->y + (draw_area->height - height) / 2;
cairo_set_source_surface (cr, renderer->surface, x, y);
cairo_rectangle (cr, x, y, width, height);
cairo_fill (cr);
}
}
@ -776,7 +747,7 @@ gimp_view_renderer_real_render (GimpViewRenderer *renderer,
renderer->height);
if (temp_buf)
{
gimp_view_renderer_default_render_buffer (renderer, widget, temp_buf);
gimp_view_renderer_default_render_surface (renderer, widget, temp_buf);
return;
}
@ -799,9 +770,9 @@ gimp_view_renderer_size_changed (GimpViewRenderer *renderer,
/* protected functions */
void
gimp_view_renderer_default_render_buffer (GimpViewRenderer *renderer,
GtkWidget *widget,
TempBuf *temp_buf)
gimp_view_renderer_default_render_surface (GimpViewRenderer *renderer,
GtkWidget *widget,
TempBuf *temp_buf)
{
g_return_if_fail (GIMP_IS_VIEW_RENDERER (renderer));
g_return_if_fail (GTK_IS_WIDGET (widget));
@ -813,9 +784,9 @@ gimp_view_renderer_default_render_buffer (GimpViewRenderer *renderer,
if (temp_buf->height < renderer->height)
temp_buf->y = (renderer->height - temp_buf->height) / 2;
gimp_view_renderer_render_buffer (renderer, temp_buf, -1,
GIMP_VIEW_BG_CHECKS,
GIMP_VIEW_BG_WHITE);
gimp_view_renderer_render_surface (renderer, temp_buf, -1,
GIMP_VIEW_BG_CHECKS,
GIMP_VIEW_BG_WHITE);
}
void
@ -836,10 +807,10 @@ gimp_view_renderer_default_render_stock (GimpViewRenderer *renderer,
renderer->pixbuf = NULL;
}
if (renderer->buffer)
if (renderer->surface)
{
g_free (renderer->buffer);
renderer->buffer = NULL;
cairo_surface_destroy (renderer->surface);
renderer->surface = NULL;
}
icon_size = gimp_get_icon_size (widget, stock_id, GTK_ICON_SIZE_INVALID,
@ -878,11 +849,11 @@ gimp_view_renderer_default_render_stock (GimpViewRenderer *renderer,
}
void
gimp_view_renderer_render_buffer (GimpViewRenderer *renderer,
TempBuf *temp_buf,
gint channel,
GimpViewBG inside_bg,
GimpViewBG outside_bg)
gimp_view_renderer_render_surface (GimpViewRenderer *renderer,
TempBuf *temp_buf,
gint channel,
GimpViewBG inside_bg,
GimpViewBG outside_bg)
{
if (renderer->pixbuf)
{
@ -890,40 +861,39 @@ gimp_view_renderer_render_buffer (GimpViewRenderer *renderer,
renderer->pixbuf = NULL;
}
if (! renderer->buffer)
renderer->buffer = g_new0 (guchar, renderer->height * renderer->rowstride);
if (! renderer->surface)
renderer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
renderer->width,
renderer->height);
gimp_view_render_to_buffer (temp_buf,
channel,
inside_bg,
outside_bg,
renderer->buffer,
renderer->width,
renderer->height,
renderer->rowstride,
renderer->bytes);
gimp_view_render_to_surface (temp_buf,
channel,
inside_bg,
outside_bg,
renderer->surface,
renderer->width,
renderer->height);
renderer->needs_render = FALSE;
}
static void
gimp_view_render_to_buffer (TempBuf *temp_buf,
gint channel,
GimpViewBG inside_bg,
GimpViewBG outside_bg,
guchar *dest_buffer,
gint dest_width,
gint dest_height,
gint dest_rowstride,
gint dest_bytes)
gimp_view_render_to_surface (TempBuf *temp_buf,
gint channel,
GimpViewBG inside_bg,
GimpViewBG outside_bg,
cairo_surface_t *surface,
gint dest_width,
gint dest_height)
{
const guchar *src, *s;
guchar *cb;
guchar *pad_buf;
gint a;
gint i, j, b;
gint x1, y1, x2, y2;
const guchar *src;
const guchar *pad_buf;
guchar *dest;
gint i, j;
gint x1, y1;
gint x2, y2;
gint rowstride;
gint dest_stride;
gboolean color;
gboolean has_alpha;
gboolean render_composite;
@ -931,10 +901,12 @@ gimp_view_render_to_buffer (TempBuf *temp_buf,
gint green_component;
gint blue_component;
gint alpha_component;
gint offset;
g_return_if_fail (temp_buf != NULL);
g_return_if_fail (dest_buffer != NULL);
g_return_if_fail (surface != NULL);
dest = cairo_image_surface_get_data (surface);
dest_stride = cairo_image_surface_get_stride (surface);
/* Here are the different cases this functions handles correctly:
* 1) Offset temp_buf which does not necessarily cover full image area
@ -998,6 +970,10 @@ gimp_view_render_to_buffer (TempBuf *temp_buf,
for (i = 0; i < dest_height; i++)
{
guchar *d = dest;
const guchar *cb;
gint offset;
if (i & 0x4)
{
offset = 4;
@ -1014,77 +990,116 @@ gimp_view_render_to_buffer (TempBuf *temp_buf,
*/
if (i >= y1 && i < y2)
{
const guchar *s = src;
/* Handle the leading transparency */
for (j = 0; j < x1; j++)
for (b = 0; b < dest_bytes; b++)
gimp_render_temp_buf[j * dest_bytes + b] = cb[j * 3 + b];
for (j = 0; j < x1; j++, d += 4, cb += 3)
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
d[0] = cb[2];
d[1] = cb[1];
d[2] = cb[0];
#else
d[1] = cb[0];
d[2] = cb[1];
d[3] = cb[2];
#endif
}
/* The stuff in the middle */
s = src;
for (j = x1; j < x2; j++)
for (j = x1; j < x2; j++, d += 4, s += temp_buf->bytes)
{
if (has_alpha && render_composite)
{
a = s[alpha_component] << 8;
const guint a = s[alpha_component] << 8;
if (inside_bg == GIMP_VIEW_BG_CHECKS)
{
if ((j + offset) & 0x4)
{
gimp_render_temp_buf[j * 3 + 0] =
gimp_render_blend_dark_check [(a | s[red_component])];
gimp_render_temp_buf[j * 3 + 1] =
gimp_render_blend_dark_check [(a | s[green_component])];
gimp_render_temp_buf[j * 3 + 2] =
gimp_render_blend_dark_check [(a | s[blue_component])];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
d[0] = gimp_render_blend_dark_check [(a | s[blue_component])];
d[1] = gimp_render_blend_dark_check [(a | s[green_component])];
d[2] = gimp_render_blend_dark_check [(a | s[red_component])];
#else
d[1] = gimp_render_blend_dark_check [(a | s[red_component])];
d[2] = gimp_render_blend_dark_check [(a | s[green_component])];
d[3] = gimp_render_blend_dark_check [(a | s[blue_component])];
#endif
}
else
{
gimp_render_temp_buf[j * 3 + 0] =
gimp_render_blend_light_check [(a | s[red_component])];
gimp_render_temp_buf[j * 3 + 1] =
gimp_render_blend_light_check [(a | s[green_component])];
gimp_render_temp_buf[j * 3 + 2] =
gimp_render_blend_light_check [(a | s[blue_component])];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
d[0] = gimp_render_blend_light_check [(a | s[blue_component])];
d[1] = gimp_render_blend_light_check [(a | s[green_component])];
d[2] = gimp_render_blend_light_check [(a | s[red_component])];
#else
d[1] = gimp_render_blend_light_check [(a | s[red_component])];
d[2] = gimp_render_blend_light_check [(a | s[green_component])];
d[3] = gimp_render_blend_light_check [(a | s[blue_component])];
#endif
}
}
else /* GIMP_VIEW_BG_WHITE */
{
gimp_render_temp_buf[j * 3 + 0] =
gimp_render_blend_white [(a | s[red_component])];
gimp_render_temp_buf[j * 3 + 1] =
gimp_render_blend_white [(a | s[green_component])];
gimp_render_temp_buf[j * 3 + 2] =
gimp_render_blend_white [(a | s[blue_component])];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
d[0] = gimp_render_blend_white [(a | s[blue_component])];
d[1] = gimp_render_blend_white [(a | s[green_component])];
d[2] = gimp_render_blend_white [(a | s[red_component])];
#else
d[1] = gimp_render_blend_white [(a | s[red_component])];
d[2] = gimp_render_blend_white [(a | s[green_component])];
d[3] = gimp_render_blend_white [(a | s[blue_component])];
#endif
}
}
else
{
gimp_render_temp_buf[j * 3 + 0] = s[red_component];
gimp_render_temp_buf[j * 3 + 1] = s[green_component];
gimp_render_temp_buf[j * 3 + 2] = s[blue_component];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
d[0] = s[blue_component];
d[1] = s[green_component];
d[2] = s[red_component];
#else
d[1] = s[red_component];
d[2] = s[green_component];
d[3] = s[blue_component];
#endif
}
s += temp_buf->bytes;
}
/* Handle the trailing transparency */
for (j = x2; j < dest_width; j++)
for (b = 0; b < dest_bytes; b++)
gimp_render_temp_buf[j * dest_bytes + b] = cb[j * 3 + b];
for (j = x2; j < dest_width; j++, d+= 4, cb += 3)
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
d[0] = cb[2];
d[1] = cb[1];
d[2] = cb[0];
#else
d[1] = cb[0];
d[2] = cb[1];
d[3] = cb[2];
#endif
}
src += rowstride;
}
else
{
for (j = 0; j < dest_width; j++)
for (b = 0; b < dest_bytes; b++)
gimp_render_temp_buf[j * dest_bytes + b] = cb[j * 3 + b];
for (j = 0; j < dest_width; j++, d+= 4, cb += 3)
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
d[0] = cb[2];
d[1] = cb[1];
d[2] = cb[0];
#else
d[1] = cb[0];
d[2] = cb[1];
d[3] = cb[2];
#endif
}
}
memcpy (dest_buffer + i * dest_rowstride,
gimp_render_temp_buf,
dest_width * dest_bytes);
dest += dest_stride;
}
}
@ -1092,10 +1107,10 @@ void
gimp_view_renderer_render_pixbuf (GimpViewRenderer *renderer,
GdkPixbuf *pixbuf)
{
if (renderer->buffer)
if (renderer->surface)
{
g_free (renderer->buffer);
renderer->buffer = NULL;
cairo_surface_destroy (renderer->surface);
renderer->surface = NULL;
}
g_object_ref (pixbuf);

View File

@ -54,12 +54,11 @@ struct _GimpViewRenderer
GimpViewBorderType border_type;
GimpRGB border_color;
/*< protected >*/
cairo_surface_t *surface;
/*< private >*/
cairo_pattern_t *pattern;
guchar *buffer;
gint rowstride;
gint bytes;
GdkPixbuf *pixbuf;
gchar *bg_stock_id;
@ -86,10 +85,9 @@ struct _GimpViewRendererClass
GimpContext *context);
void (* invalidate) (GimpViewRenderer *renderer);
void (* draw) (GimpViewRenderer *renderer,
GdkWindow *window,
GtkWidget *widget,
const GdkRectangle *draw_area,
const GdkRectangle *expose_area);
cairo_t *cr,
const GdkRectangle *draw_area);
void (* render) (GimpViewRenderer *renderer,
GtkWidget *widget);
};
@ -142,19 +140,20 @@ void gimp_view_renderer_draw (GimpViewRenderer *renderer,
/* protected */
void gimp_view_renderer_default_render_buffer (GimpViewRenderer *renderer,
GtkWidget *widget,
TempBuf *temp_buf);
void gimp_view_renderer_default_render_stock (GimpViewRenderer *renderer,
GtkWidget *widget,
const gchar *stock_id);
void gimp_view_renderer_render_buffer (GimpViewRenderer *renderer,
TempBuf *temp_buf,
gint channel,
GimpViewBG inside_bg,
GimpViewBG outside_bg);
void gimp_view_renderer_render_pixbuf (GimpViewRenderer *renderer,
GdkPixbuf *pixbuf);
void gimp_view_renderer_default_render_surface (GimpViewRenderer *renderer,
GtkWidget *widget,
TempBuf *temp_buf);
void gimp_view_renderer_default_render_stock (GimpViewRenderer *renderer,
GtkWidget *widget,
const gchar *stock_id);
void gimp_view_renderer_render_surface (GimpViewRenderer *renderer,
TempBuf *temp_buf,
gint channel,
GimpViewBG inside_bg,
GimpViewBG outside_bg);
void gimp_view_renderer_render_pixbuf (GimpViewRenderer *renderer,
GdkPixbuf *pixbuf);

View File

@ -108,9 +108,9 @@ gimp_view_renderer_brush_render (GimpViewRenderer *renderer,
if (renderer->is_popup)
{
gimp_view_renderer_render_buffer (renderer, temp_buf, -1,
GIMP_VIEW_BG_WHITE,
GIMP_VIEW_BG_WHITE);
gimp_view_renderer_render_surface (renderer, temp_buf, -1,
GIMP_VIEW_BG_WHITE,
GIMP_VIEW_BG_WHITE);
temp_buf_free (temp_buf);
@ -125,12 +125,16 @@ gimp_view_renderer_brush_render (GimpViewRenderer *renderer,
return;
}
gimp_view_renderer_render_buffer (renderer, temp_buf, -1,
GIMP_VIEW_BG_WHITE,
GIMP_VIEW_BG_WHITE);
gimp_view_renderer_render_surface (renderer, temp_buf, -1,
GIMP_VIEW_BG_WHITE,
GIMP_VIEW_BG_WHITE);
temp_buf_free (temp_buf);
/* FIXME: port brush indicator drawing to Cairo */
#if 0
#define INDICATOR_WIDTH 7
#define INDICATOR_HEIGHT 7
@ -278,6 +282,8 @@ gimp_view_renderer_brush_render (GimpViewRenderer *renderer,
#undef INDICATOR_WIDTH
#undef INDICATOR_HEIGHT
#endif
}
static gboolean
@ -318,9 +324,9 @@ gimp_view_renderer_brush_render_timeout (gpointer data)
if (temp_buf->height < renderer->height)
temp_buf->y = (renderer->height - temp_buf->height) / 2;
gimp_view_renderer_render_buffer (renderer, temp_buf, -1,
GIMP_VIEW_BG_WHITE,
GIMP_VIEW_BG_WHITE);
gimp_view_renderer_render_surface (renderer, temp_buf, -1,
GIMP_VIEW_BG_WHITE,
GIMP_VIEW_BG_WHITE);
temp_buf_free (temp_buf);

View File

@ -103,7 +103,7 @@ gimp_view_renderer_buffer_render (GimpViewRenderer *renderer,
if (render_buf)
{
gimp_view_renderer_default_render_buffer (renderer, widget, render_buf);
gimp_view_renderer_default_render_surface (renderer, widget, render_buf);
temp_buf_free (render_buf);
}

View File

@ -210,9 +210,9 @@ gimp_view_renderer_drawable_render (GimpViewRenderer *renderer,
render_buf->y = (height - view_height) / 2;
}
gimp_view_renderer_render_buffer (renderer, render_buf, -1,
GIMP_VIEW_BG_CHECKS,
GIMP_VIEW_BG_CHECKS);
gimp_view_renderer_render_surface (renderer, render_buf, -1,
GIMP_VIEW_BG_CHECKS,
GIMP_VIEW_BG_CHECKS);
temp_buf_free (render_buf);
}

View File

@ -183,21 +183,18 @@ static void
gimp_view_renderer_gradient_render (GimpViewRenderer *renderer,
GtkWidget *widget)
{
GimpViewRendererGradient *rendergrad;
GimpGradient *gradient;
GimpGradientSegment *seg = NULL;
GimpViewRendererGradient *rendergrad = GIMP_VIEW_RENDERER_GRADIENT (renderer);
GimpGradient *gradient = GIMP_GRADIENT (renderer->viewable);
GimpGradientSegment *seg = NULL;
guchar *even;
guchar *odd;
guchar *buf;
guchar *dest;
gint dest_stride;
gint x;
gint y;
gdouble dx, cur_x;
GimpRGB color;
rendergrad = GIMP_VIEW_RENDERER_GRADIENT (renderer);
gradient = GIMP_GRADIENT (renderer->viewable);
if (renderer->width != rendergrad->width)
{
if (rendergrad->even)
@ -206,8 +203,8 @@ gimp_view_renderer_gradient_render (GimpViewRenderer *renderer,
if (rendergrad->odd)
g_free (rendergrad->odd);
rendergrad->even = g_new (guchar, renderer->rowstride);
rendergrad->odd = g_new (guchar, renderer->rowstride);
rendergrad->even = g_new (guchar, 4 * renderer->width);
rendergrad->odd = g_new (guchar, 4 * renderer->width);
rendergrad->width = renderer->width;
}
@ -218,7 +215,7 @@ gimp_view_renderer_gradient_render (GimpViewRenderer *renderer,
dx = (rendergrad->right - rendergrad->left) / (renderer->width - 1);
cur_x = rendergrad->left;
for (x = 0; x < renderer->width; x++)
for (x = 0; x < renderer->width; x++, even += 4, odd += 4)
{
guchar r, g, b, a;
@ -230,39 +227,66 @@ gimp_view_renderer_gradient_render (GimpViewRenderer *renderer,
if (x & 0x4)
{
*even++ = gimp_render_blend_dark_check[(a << 8) | r];
*even++ = gimp_render_blend_dark_check[(a << 8) | g];
*even++ = gimp_render_blend_dark_check[(a << 8) | b];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
even[0] = gimp_render_blend_dark_check[(a << 8) | b];
even[1] = gimp_render_blend_dark_check[(a << 8) | g];
even[2] = gimp_render_blend_dark_check[(a << 8) | r];
#else
even[1] = gimp_render_blend_dark_check[(a << 8) | r];
even[2] = gimp_render_blend_dark_check[(a << 8) | g];
even[3] = gimp_render_blend_dark_check[(a << 8) | b];
#endif
*odd++ = gimp_render_blend_light_check[(a << 8) | r];
*odd++ = gimp_render_blend_light_check[(a << 8) | g];
*odd++ = gimp_render_blend_light_check[(a << 8) | b];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
odd[0] = gimp_render_blend_light_check[(a << 8) | b];
odd[1] = gimp_render_blend_light_check[(a << 8) | g];
odd[2] = gimp_render_blend_light_check[(a << 8) | r];
#else
odd[1] = gimp_render_blend_light_check[(a << 8) | r];
odd[2] = gimp_render_blend_light_check[(a << 8) | g];
odd[3] = gimp_render_blend_light_check[(a << 8) | b];
#endif
}
else
{
*even++ = gimp_render_blend_light_check[(a << 8) | r];
*even++ = gimp_render_blend_light_check[(a << 8) | g];
*even++ = gimp_render_blend_light_check[(a << 8) | b];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
even[0] = gimp_render_blend_light_check[(a << 8) | b];
even[1] = gimp_render_blend_light_check[(a << 8) | g];
even[2] = gimp_render_blend_light_check[(a << 8) | r];
#else
even[1] = gimp_render_blend_light_check[(a << 8) | r];
even[2] = gimp_render_blend_light_check[(a << 8) | g];
even[3] = gimp_render_blend_light_check[(a << 8) | b];
#endif
*odd++ = gimp_render_blend_dark_check[(a << 8) | r];
*odd++ = gimp_render_blend_dark_check[(a << 8) | g];
*odd++ = gimp_render_blend_dark_check[(a << 8) | b];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
odd[0] = gimp_render_blend_dark_check[(a << 8) | b];
odd[1] = gimp_render_blend_dark_check[(a << 8) | g];
odd[2] = gimp_render_blend_dark_check[(a << 8) | r];
#else
odd[1] = gimp_render_blend_dark_check[(a << 8) | r];
odd[2] = gimp_render_blend_dark_check[(a << 8) | g];
odd[3] = gimp_render_blend_dark_check[(a << 8) | b];
#endif
}
}
if (! renderer->buffer)
renderer->buffer = g_new (guchar, renderer->height * renderer->rowstride);
if (! renderer->surface)
renderer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
renderer->width,
renderer->height);
buf = renderer->buffer;
dest = cairo_image_surface_get_data (renderer->surface);
dest_stride = cairo_image_surface_get_stride (renderer->surface);
for (y = 0; y < renderer->height; y++)
{
if (y & 0x4)
memcpy (buf, rendergrad->even, renderer->rowstride);
memcpy (dest, rendergrad->even, renderer->width * 4);
else
memcpy (buf, rendergrad->odd, renderer->rowstride);
memcpy (dest, rendergrad->odd, renderer->width * 4);
buf += renderer->rowstride;
dest += dest_stride;
}
renderer->needs_render = FALSE;

View File

@ -141,10 +141,10 @@ gimp_view_renderer_image_render (GimpViewRenderer *renderer,
component_index =
gimp_image_get_component_index (image, rendererimage->channel);
gimp_view_renderer_render_buffer (renderer, render_buf,
component_index,
GIMP_VIEW_BG_CHECKS,
GIMP_VIEW_BG_WHITE);
gimp_view_renderer_render_surface (renderer, render_buf,
component_index,
GIMP_VIEW_BG_CHECKS,
GIMP_VIEW_BG_WHITE);
temp_buf_free (render_buf);

View File

@ -82,10 +82,11 @@ gimp_view_renderer_palette_render (GimpViewRenderer *renderer,
GimpViewRendererPalette *renderpal = GIMP_VIEW_RENDERER_PALETTE (renderer);
GimpPalette *palette;
guchar *row;
guchar *dest_row;
guchar *dest;
GList *list;
gdouble cell_width;
gint grid_width;
gint dest_stride;
gint y;
palette = GIMP_PALETTE (renderer->viewable);
@ -93,9 +94,6 @@ gimp_view_renderer_palette_render (GimpViewRenderer *renderer,
if (palette->n_colors < 1)
return;
if (! renderer->buffer)
renderer->buffer = g_new (guchar, renderer->height * renderer->rowstride);
grid_width = renderpal->draw_grid ? 1 : 0;
if (renderpal->cell_size > 0)
@ -135,13 +133,15 @@ gimp_view_renderer_palette_render (GimpViewRenderer *renderer,
list = palette->colors;
memset (renderer->buffer,
renderpal->draw_grid ? 0 : 255,
renderer->height * renderer->rowstride);
if (! renderer->surface)
renderer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
renderer->width,
renderer->height);
row = g_new (guchar, renderer->rowstride);
row = g_new (guchar, renderer->width * 4);
dest_row = renderer->buffer;
dest = cairo_image_surface_get_data (renderer->surface);
dest_stride = cairo_image_surface_get_stride (renderer->surface);
for (y = 0; y < renderer->height; y++)
{
@ -150,15 +150,13 @@ gimp_view_renderer_palette_render (GimpViewRenderer *renderer,
guchar r, g, b;
gint x;
gint n = 0;
guchar *p = row;
guchar *d = row;
memset (row,
renderpal->draw_grid ? 0 : 255,
renderer->rowstride);
memset (row, renderpal->draw_grid ? 0 : 255, renderer->width * 4);
r = g = b = (renderpal->draw_grid ? 0 : 255);
for (x = 0; x < renderer->width; x++)
for (x = 0; x < renderer->width; x++, d += 4)
{
if ((x % renderpal->cell_width) == 0)
{
@ -180,29 +178,41 @@ gimp_view_renderer_palette_render (GimpViewRenderer *renderer,
if (renderpal->draw_grid && (x % renderpal->cell_width) == 0)
{
*p++ = 0;
*p++ = 0;
*p++ = 0;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
d[0] = 0;
d[1] = 0;
d[2] = 0;
#else
d[1] = 0;
d[2] = 0;
d[3] = 0;
#endif
}
else
{
*p++ = r;
*p++ = g;
*p++ = b;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
d[0] = b;
d[1] = g;
d[2] = r;
#else
d[1] = r;
d[2] = g;
d[3] = b;
#endif
}
}
}
if (renderpal->draw_grid && (y % renderpal->cell_height) == 0)
{
memset (dest_row, 0, renderer->rowstride);
memset (dest, 0, renderer->width * 4);
}
else
{
memcpy (dest_row, row, renderer->rowstride);
memcpy (dest, row, renderer->width * 4);
}
dest_row += renderer->rowstride;
dest += dest_stride;
}
g_free (row);

View File

@ -39,10 +39,9 @@
static void gimp_view_renderer_vectors_draw (GimpViewRenderer *renderer,
GdkWindow *window,
GtkWidget *widget,
const GdkRectangle *draw_area,
const GdkRectangle *expose_area);
cairo_t *cr,
const GdkRectangle *draw_area);
G_DEFINE_TYPE (GimpViewRendererVectors, gimp_view_renderer_vectors,
@ -66,51 +65,46 @@ gimp_view_renderer_vectors_init (GimpViewRendererVectors *renderer)
static void
gimp_view_renderer_vectors_draw (GimpViewRenderer *renderer,
GdkWindow *window,
GtkWidget *widget,
const GdkRectangle *draw_area,
const GdkRectangle *expose_area)
cairo_t *cr,
const GdkRectangle *draw_area)
{
GimpVectors *vectors;
GimpVectors *vectors = GIMP_VECTORS (renderer->viewable);
GimpStroke *stroke;
GdkRectangle rect, area;
gdouble xscale, yscale;
gdouble xscale;
gdouble yscale;
gint x, y;
rect.width = renderer->width;
rect.height = renderer->height;
rect.x = draw_area->x + (draw_area->width - rect.width) / 2;
rect.y = draw_area->y + (draw_area->height - rect.height) / 2;
gdk_cairo_set_source_color (cr, &widget->style->white);
if (! gdk_rectangle_intersect (&rect, (GdkRectangle *) expose_area, &area))
return;
x = draw_area->x + (draw_area->width - renderer->width) / 2;
y = draw_area->y + (draw_area->height - renderer->height) / 2;
gdk_draw_rectangle (window, widget->style->white_gc, TRUE,
area.x, area.y, area.width, area.height);
cairo_rectangle (cr, x, y, renderer->width, renderer->height);
cairo_fill (cr);
vectors = GIMP_VECTORS (renderer->viewable);
/* FIXME: port vector previews to Cairo */
xscale = (gdouble) GIMP_ITEM (vectors)->width / (gdouble) rect.width;
yscale = (gdouble) GIMP_ITEM (vectors)->height / (gdouble) rect.height;
gdk_gc_set_clip_rectangle (widget->style->black_gc, &area);
xscale = (gdouble) GIMP_ITEM (vectors)->width / (gdouble) renderer->width;
yscale = (gdouble) GIMP_ITEM (vectors)->height / (gdouble) renderer->height;
for (stroke = gimp_vectors_stroke_get_next (vectors, NULL);
stroke != NULL;
stroke = gimp_vectors_stroke_get_next (vectors, stroke))
{
GArray *coordinates;
GdkPoint *points;
gint i;
GArray *coordinates;
coordinates = gimp_stroke_interpolate (stroke,
MIN (xscale, yscale) / 2,
NULL);
if (!coordinates)
if (! coordinates)
continue;
#if 0
if (coordinates->len > 0)
{
points = g_new (GdkPoint, coordinates->len);
GdkPoint *points = g_new (GdkPoint, coordinates->len);
gint i;
for (i = 0; i < coordinates->len; i++)
{
@ -127,9 +121,8 @@ gimp_view_renderer_vectors_draw (GimpViewRenderer *renderer,
g_free (points);
}
#endif
g_array_free (coordinates, TRUE);
}
gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL);
}