Patch from Brian Cameron to implement the vertical/horizontal striped

2002-11-04  Havoc Pennington  <hp@pobox.com>

        Patch from Brian Cameron to implement the vertical/horizontal
	striped image accelerated scaling from the gtk pixbuf engine.

	* src/theme.c (scale_and_alpha_pixbuf): if an image is
	vertical/horizontal stripes, use special extra-fast scaling
	routines.

	* src/theme-parser.c (parse_draw_op_element): when loading an
	image, mark it as vertically/horizontally striped when appropriate
This commit is contained in:
Havoc Pennington 2002-11-04 17:55:56 +00:00 committed by Havoc Pennington
parent 373f6de13e
commit 5efd276a22
4 changed files with 244 additions and 24 deletions

View File

@ -1,3 +1,15 @@
2002-11-04 Havoc Pennington <hp@pobox.com>
Patch from Brian Cameron to implement the vertical/horizontal
striped image accelerated scaling from the gtk pixbuf engine.
* src/theme.c (scale_and_alpha_pixbuf): if an image is
vertical/horizontal stripes, use special extra-fast scaling
routines.
* src/theme-parser.c (parse_draw_op_element): when loading an
image, mark it as vertically/horizontally striped when appropriate
2002-11-04 Erwann Chenede - <erwann.chenede@sun.com> 2002-11-04 Erwann Chenede - <erwann.chenede@sun.com>
* src/xprops.c (meta_prop_get_values): changed __FUNCTION__ * src/xprops.c (meta_prop_get_values): changed __FUNCTION__

View File

@ -2246,6 +2246,9 @@ parse_draw_op_element (GMarkupParseContext *context,
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
MetaColorSpec *colorize_spec = NULL; MetaColorSpec *colorize_spec = NULL;
MetaImageFillType fill_type_val; MetaImageFillType fill_type_val;
int h, w, c;
int pixbuf_width, pixbuf_height, pixbuf_n_channels, pixbuf_rowstride;
guchar *pixbuf_pixels;
if (!locate_attributes (context, element_name, attribute_names, attribute_values, if (!locate_attributes (context, element_name, attribute_names, attribute_values,
error, error,
@ -2330,16 +2333,16 @@ parse_draw_op_element (GMarkupParseContext *context,
} }
if (colorize) if (colorize)
{ {
colorize_spec = meta_color_spec_new_from_string (colorize, error); colorize_spec = meta_color_spec_new_from_string (colorize, error);
if (colorize_spec == NULL) if (colorize_spec == NULL)
{ {
add_context_to_error (error, context); add_context_to_error (error, context);
g_object_unref (G_OBJECT (pixbuf)); g_object_unref (G_OBJECT (pixbuf));
return; return;
} }
} }
alpha_spec = NULL; alpha_spec = NULL;
if (alpha && !parse_alpha (alpha, &alpha_spec, context, error)) if (alpha && !parse_alpha (alpha, &alpha_spec, context, error))
@ -2359,6 +2362,67 @@ parse_draw_op_element (GMarkupParseContext *context,
op->data.image.alpha_spec = alpha_spec; op->data.image.alpha_spec = alpha_spec;
op->data.image.fill_type = fill_type_val; op->data.image.fill_type = fill_type_val;
/* Check for vertical & horizontal stripes */
pixbuf_n_channels = gdk_pixbuf_get_n_channels(pixbuf);
pixbuf_width = gdk_pixbuf_get_width(pixbuf);
pixbuf_height = gdk_pixbuf_get_height(pixbuf);
pixbuf_rowstride = gdk_pixbuf_get_rowstride(pixbuf);
pixbuf_pixels = gdk_pixbuf_get_pixels(pixbuf);
/* Check for horizontal stripes */
for (h = 0; h < pixbuf_height; h++)
{
for (w = 1; w < pixbuf_width; w++)
{
for (c = 0; c < pixbuf_n_channels; c++)
{
if (pixbuf_pixels[(h * pixbuf_rowstride) + c] !=
pixbuf_pixels[(h * pixbuf_rowstride) + w + c])
break;
}
if (c < pixbuf_n_channels)
break;
}
if (w < pixbuf_width)
break;
}
if (h >= pixbuf_height)
{
op->data.image.horizontal_stripes = TRUE;
}
else
{
op->data.image.horizontal_stripes = FALSE;
}
/* Check for vertical stripes */
for (w = 0; w < pixbuf_width; w++)
{
for (h = 1; h < pixbuf_height; h++)
{
for (c = 0; c < pixbuf_n_channels; c++)
{
if (pixbuf_pixels[w + c] !=
pixbuf_pixels[(h * pixbuf_rowstride) + w + c])
break;
}
if (c < pixbuf_n_channels)
break;
}
if (h < pixbuf_height)
break;
}
if (w >= pixbuf_width)
{
op->data.image.vertical_stripes = TRUE;
}
else
{
op->data.image.vertical_stripes = FALSE;
}
g_assert (info->op_list); g_assert (info->op_list);
meta_draw_op_list_append (info->op_list, op); meta_draw_op_list_append (info->op_list, op);

View File

@ -2804,18 +2804,107 @@ pixbuf_tile (GdkPixbuf *tile,
return pixbuf; return pixbuf;
} }
static GdkPixbuf *
replicate_rows (GdkPixbuf *src,
int src_x,
int src_y,
int width,
int height)
{
unsigned int n_channels = gdk_pixbuf_get_n_channels (src);
unsigned int src_rowstride = gdk_pixbuf_get_rowstride (src);
unsigned char *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x
* n_channels);
unsigned char *dest_pixels;
GdkPixbuf *result;
unsigned int dest_rowstride;
int i;
result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
width, height);
dest_rowstride = gdk_pixbuf_get_rowstride (result);
dest_pixels = gdk_pixbuf_get_pixels (result);
for (i = 0; i < height; i++)
memcpy (dest_pixels + dest_rowstride * i, pixels, n_channels * width);
return result;
}
static GdkPixbuf *
replicate_cols (GdkPixbuf *src,
int src_x,
int src_y,
int width,
int height)
{
unsigned int n_channels = gdk_pixbuf_get_n_channels (src);
unsigned int src_rowstride = gdk_pixbuf_get_rowstride (src);
unsigned char *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x
* n_channels);
unsigned char *dest_pixels;
GdkPixbuf *result;
unsigned int dest_rowstride;
int i, j;
result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
width, height);
dest_rowstride = gdk_pixbuf_get_rowstride (result);
dest_pixels = gdk_pixbuf_get_pixels (result);
for (i = 0; i < height; i++)
{
unsigned char *p = dest_pixels + dest_rowstride * i;
unsigned char *q = pixels + src_rowstride * i;
unsigned char r = *(q++);
unsigned char g = *(q++);
unsigned char b = *(q++);
if (n_channels == 4)
{
unsigned char a;
a = *(q++);
for (j = 0; j < width; j++)
{
*(p++) = r;
*(p++) = g;
*(p++) = b;
*(p++) = a;
}
}
else
{
for (j = 0; j < width; j++)
{
*(p++) = r;
*(p++) = g;
*(p++) = b;
}
}
}
return result;
}
static GdkPixbuf* static GdkPixbuf*
scale_and_alpha_pixbuf (GdkPixbuf *src, scale_and_alpha_pixbuf (GdkPixbuf *src,
MetaAlphaGradientSpec *alpha_spec, MetaAlphaGradientSpec *alpha_spec,
MetaImageFillType fill_type, MetaImageFillType fill_type,
int width, int width,
int height) int height,
gboolean vertical_stripes,
gboolean horizontal_stripes)
{ {
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
GdkPixbuf *temp_pixbuf;
pixbuf = NULL; pixbuf = NULL;
pixbuf = src; pixbuf = src;
if (gdk_pixbuf_get_width (pixbuf) == width && if (gdk_pixbuf_get_width (pixbuf) == width &&
gdk_pixbuf_get_height (pixbuf) == height) gdk_pixbuf_get_height (pixbuf) == height)
{ {
@ -2823,16 +2912,61 @@ scale_and_alpha_pixbuf (GdkPixbuf *src,
} }
else else
{ {
switch (fill_type) if (fill_type == META_IMAGE_FILL_TILE)
{ {
case META_IMAGE_FILL_SCALE:
pixbuf = gdk_pixbuf_scale_simple (pixbuf,
width, height,
GDK_INTERP_BILINEAR);
break;
case META_IMAGE_FILL_TILE:
pixbuf = pixbuf_tile (pixbuf, width, height); pixbuf = pixbuf_tile (pixbuf, width, height);
break; }
else
{
int src_h, src_w, dest_h, dest_w, pixbuf_width, pixbuf_height;
src_h = gdk_pixbuf_get_height (src);
src_w = gdk_pixbuf_get_width (src);
if (vertical_stripes)
{
dest_w = width;
dest_h = gdk_pixbuf_get_height (src);
}
else if (horizontal_stripes)
{
dest_w = gdk_pixbuf_get_width (src);
dest_h = height;
}
else
{
dest_w = width;
dest_h = height;
}
if (dest_w == src_w && dest_h == src_h)
{
temp_pixbuf = src;
g_object_ref (G_OBJECT (tmp_pixbuf));
}
else
{
temp_pixbuf = gdk_pixbuf_scale_simple (src,
dest_w, dest_h,
GDK_INTERP_BILINEAR);
}
/* prefer to replicate_cols if possible, as that
* is faster (no memory reads)
*/
if (horizontal_stripes)
{
pixbuf = replicate_cols (temp_pixbuf, 0, 0, width, height);
g_object_unref (G_OBJECT (temp_pixbuf));
}
else if (vertical_stripes)
{
pixbuf = replicate_rows (temp_pixbuf, 0, 0, width, height);
g_object_unref (G_OBJECT (temp_pixbuf));
}
else
{
pixbuf = temp_pixbuf;
}
} }
} }
@ -2972,15 +3106,19 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
pixbuf = scale_and_alpha_pixbuf (op->data.image.colorize_cache_pixbuf, pixbuf = scale_and_alpha_pixbuf (op->data.image.colorize_cache_pixbuf,
op->data.image.alpha_spec, op->data.image.alpha_spec,
op->data.image.fill_type, op->data.image.fill_type,
width, height); width, height,
op->data.image.vertical_stripes,
op->data.image.horizontal_stripes);
} }
} }
else else
{ {
pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf, pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf,
op->data.image.alpha_spec, op->data.image.alpha_spec,
op->data.image.fill_type, op->data.image.fill_type,
width, height); width, height,
op->data.image.vertical_stripes,
op->data.image.horizontal_stripes);
} }
break; break;
} }
@ -2997,12 +3135,16 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
pixbuf = scale_and_alpha_pixbuf (info->mini_icon, pixbuf = scale_and_alpha_pixbuf (info->mini_icon,
op->data.icon.alpha_spec, op->data.icon.alpha_spec,
op->data.icon.fill_type, op->data.icon.fill_type,
width, height); width, height,
op->data.image.vertical_stripes,
op->data.image.horizontal_stripes);
else if (info->icon) else if (info->icon)
pixbuf = scale_and_alpha_pixbuf (info->icon, pixbuf = scale_and_alpha_pixbuf (info->icon,
op->data.icon.alpha_spec, op->data.icon.alpha_spec,
op->data.icon.fill_type, op->data.icon.fill_type,
width, height); width, height,
op->data.image.vertical_stripes,
op->data.image.horizontal_stripes);
break; break;
case META_DRAW_TITLE: case META_DRAW_TITLE:

View File

@ -325,6 +325,8 @@ struct _MetaDrawOp
guint32 colorize_cache_pixel; guint32 colorize_cache_pixel;
GdkPixbuf *colorize_cache_pixbuf; GdkPixbuf *colorize_cache_pixbuf;
MetaImageFillType fill_type; MetaImageFillType fill_type;
unsigned int vertical_stripes : 1;
unsigned int horizontal_stripes : 1;
} image; } image;
struct { struct {