diff --git a/ChangeLog b/ChangeLog index 35b01b258..4096a9fb6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2002-05-31 Havoc Pennington + + * src/theme.c: add MetaImageFillType and implement TILE in + addition to the existing SCALE + + * src/theme.h (struct _MetaDrawOp): remove no-longer-used "alpha" + field + 2002-05-31 Havoc Pennington * src/theme.c (multiply_alpha): now just uses diff --git a/src/theme-parser.c b/src/theme-parser.c index 0a1ba225e..ba686f953 100644 --- a/src/theme-parser.c +++ b/src/theme-parser.c @@ -2149,9 +2149,11 @@ parse_draw_op_element (GMarkupParseContext *context, const char *height; const char *alpha; const char *colorize; + const char *fill_type; MetaAlphaGradientSpec *alpha_spec; GdkPixbuf *pixbuf; MetaColorSpec *colorize_spec = NULL; + MetaImageFillType fill_type_val; if (!locate_attributes (context, element_name, attribute_names, attribute_values, error, @@ -2159,6 +2161,7 @@ parse_draw_op_element (GMarkupParseContext *context, "width", &width, "height", &height, "alpha", &alpha, "filename", &filename, "colorize", &colorize, + "fill_type", &fill_type, NULL)) return; @@ -2209,6 +2212,19 @@ parse_draw_op_element (GMarkupParseContext *context, if (!check_expression (height, TRUE, info->theme, context, error)) return; + fill_type_val = META_IMAGE_FILL_SCALE; + if (fill_type) + { + fill_type_val = meta_image_fill_type_from_string (fill_type); + + if (((int) fill_type_val) == -1) + { + set_error (error, context, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Did not understand fill type \"%s\" for <%s> element"), + fill_type, element_name); + } + } /* Check last so we don't have to free it when other * stuff fails @@ -2249,7 +2265,8 @@ parse_draw_op_element (GMarkupParseContext *context, op->data.image.width = optimize_expression (info->theme, width); op->data.image.height = optimize_expression (info->theme, height); op->data.image.alpha_spec = alpha_spec; - + op->data.image.fill_type = fill_type_val; + g_assert (info->op_list); meta_draw_op_list_append (info->op_list, op); @@ -2589,13 +2606,16 @@ parse_draw_op_element (GMarkupParseContext *context, const char *width; const char *height; const char *alpha; + const char *fill_type; MetaAlphaGradientSpec *alpha_spec; + MetaImageFillType fill_type_val; if (!locate_attributes (context, element_name, attribute_names, attribute_values, error, "x", &x, "y", &y, "width", &width, "height", &height, "alpha", &alpha, + "fill_type", &fill_type, NULL)) return; @@ -2639,6 +2659,20 @@ parse_draw_op_element (GMarkupParseContext *context, if (!check_expression (height, FALSE, info->theme, context, error)) return; + fill_type_val = META_IMAGE_FILL_SCALE; + if (fill_type) + { + fill_type_val = meta_image_fill_type_from_string (fill_type); + + if (((int) fill_type_val) == -1) + { + set_error (error, context, G_MARKUP_ERROR, + G_MARKUP_ERROR_PARSE, + _("Did not understand fill type \"%s\" for <%s> element"), + fill_type, element_name); + } + } + alpha_spec = NULL; if (alpha && !parse_alpha (alpha, &alpha_spec, context, error)) return; @@ -2650,7 +2684,8 @@ parse_draw_op_element (GMarkupParseContext *context, op->data.icon.width = optimize_expression (info->theme, width); op->data.icon.height = optimize_expression (info->theme, height); op->data.icon.alpha_spec = alpha_spec; - + op->data.icon.fill_type = fill_type_val; + g_assert (info->op_list); meta_draw_op_list_append (info->op_list, op); diff --git a/src/theme.c b/src/theme.c index ac6f411c1..0d1816d00 100644 --- a/src/theme.c +++ b/src/theme.c @@ -2581,9 +2581,53 @@ render_pixbuf (GdkDrawable *drawable, draw_rect.y - pixbuf_rect.y); } +static GdkPixbuf* +pixbuf_tile (GdkPixbuf *tile, + int width, + int height) +{ + GdkPixbuf *pixbuf; + int tile_width; + int tile_height; + int i, j; + + tile_width = gdk_pixbuf_get_width (tile); + tile_height = gdk_pixbuf_get_height (tile); + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + gdk_pixbuf_get_has_alpha (tile), + 8, width, height); + + i = 0; + while (i < width) + { + j = 0; + while (j < height) + { + int w, h; + + w = MIN (tile_width, width - i); + h = MIN (tile_height, height - j); + + gdk_pixbuf_copy_area (tile, + 0, 0, + w, h, + pixbuf, + i, j); + + j += tile_height; + } + + i += tile_width; + } + + return pixbuf; +} + static GdkPixbuf* scale_and_alpha_pixbuf (GdkPixbuf *src, MetaAlphaGradientSpec *alpha_spec, + MetaImageFillType fill_type, int width, int height) { @@ -2599,19 +2643,27 @@ scale_and_alpha_pixbuf (GdkPixbuf *src, } else { - if (gdk_pixbuf_get_width (pixbuf) == width || - gdk_pixbuf_get_height (pixbuf) == height) - { - pixbuf = gdk_pixbuf_scale_simple (pixbuf, - width, height, - GDK_INTERP_NEAREST); - } - else - { - pixbuf = gdk_pixbuf_scale_simple (pixbuf, - width, height, - GDK_INTERP_BILINEAR); - } + switch (fill_type) + { + case META_IMAGE_FILL_SCALE: + if (gdk_pixbuf_get_width (pixbuf) == width || + gdk_pixbuf_get_height (pixbuf) == height) + { + pixbuf = gdk_pixbuf_scale_simple (pixbuf, + width, height, + GDK_INTERP_NEAREST); + } + else + { + pixbuf = gdk_pixbuf_scale_simple (pixbuf, + width, height, + GDK_INTERP_BILINEAR); + } + break; + case META_IMAGE_FILL_TILE: + pixbuf = pixbuf_tile (pixbuf, width, height); + break; + } } if (pixbuf) @@ -2749,6 +2801,7 @@ draw_op_as_pixbuf (const MetaDrawOp *op, { pixbuf = scale_and_alpha_pixbuf (op->data.image.colorize_cache_pixbuf, op->data.image.alpha_spec, + op->data.image.fill_type, width, height); } } @@ -2756,6 +2809,7 @@ draw_op_as_pixbuf (const MetaDrawOp *op, { pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf, op->data.image.alpha_spec, + op->data.image.fill_type, width, height); } break; @@ -2772,10 +2826,12 @@ draw_op_as_pixbuf (const MetaDrawOp *op, height <= gdk_pixbuf_get_height (info->mini_icon)) pixbuf = scale_and_alpha_pixbuf (info->mini_icon, op->data.icon.alpha_spec, + op->data.image.fill_type, width, height); else if (info->icon) pixbuf = scale_and_alpha_pixbuf (info->icon, op->data.icon.alpha_spec, + op->data.image.fill_type, width, height); break; @@ -5247,6 +5303,30 @@ meta_gtk_arrow_to_string (GtkArrowType arrow) return ""; } +MetaImageFillType +meta_image_fill_type_from_string (const char *str) +{ + if (strcmp ("tile", str) == 0) + return META_IMAGE_FILL_TILE; + else if (strcmp ("scale", str) == 0) + return META_IMAGE_FILL_SCALE; + else + return -1; +} + +const char* +meta_image_fill_type_to_string (MetaImageFillType fill_type) +{ + switch (fill_type) + { + case META_IMAGE_FILL_TILE: + return "tile"; + case META_IMAGE_FILL_SCALE: + return "scale"; + } + + return ""; +} #if 0 /* These are some functions I'm saving to use in optimizing diff --git a/src/theme.h b/src/theme.h index f93157a2e..d75847375 100644 --- a/src/theme.h +++ b/src/theme.h @@ -123,6 +123,11 @@ struct _MetaFrameGeometry guint bottom_right_corner_rounded : 1; }; +typedef enum +{ + META_IMAGE_FILL_SCALE, /* default, needs to be all-bits-zero for g_new0 */ + META_IMAGE_FILL_TILE +} MetaImageFillType; typedef enum { @@ -284,13 +289,13 @@ struct _MetaDrawOp MetaColorSpec *colorize_spec; MetaAlphaGradientSpec *alpha_spec; GdkPixbuf *pixbuf; - double alpha; char *x; char *y; char *width; char *height; guint32 colorize_cache_pixel; GdkPixbuf *colorize_cache_pixbuf; + MetaImageFillType fill_type; } image; struct { @@ -326,6 +331,7 @@ struct _MetaDrawOp char *y; char *width; char *height; + MetaImageFillType fill_type; } icon; struct { @@ -800,5 +806,8 @@ GtkShadowType meta_gtk_shadow_from_string (const char *s const char* meta_gtk_shadow_to_string (GtkShadowType shadow); GtkArrowType meta_gtk_arrow_from_string (const char *str); const char* meta_gtk_arrow_to_string (GtkArrowType arrow); +MetaImageFillType meta_image_fill_type_from_string (const char *str); +const char* meta_image_fill_type_to_string (MetaImageFillType fill_type); + #endif