diff options
author | Havoc Pennington <hp@pobox.com> | 2002-02-02 05:09:19 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2002-02-02 05:09:19 +0000 |
commit | 089eb7e6ded4d233ea48ceab4e9954e316a7ba76 (patch) | |
tree | 3d23b50a7855f5bf668d7d98505893e55af678c1 | |
parent | add8c23c13676692a0da77ef8862feef3a5923bd (diff) | |
download | metacity-089eb7e6ded4d233ea48ceab4e9954e316a7ba76.tar.gz |
test % operator
2002-02-02 Havoc Pennington <hp@pobox.com>
* src/theme-viewer.c: test % operator
* src/theme.c (pos_tokenize): add % to switch for operators
* src/theme.c: rework theme stuff so we have
MetaDrawOp/MetaDrawOpList instead of MetaTextureSpec/MetaShapeSpec
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | src/theme-viewer.c | 36 | ||||
-rw-r--r-- | src/theme.c | 2367 | ||||
-rw-r--r-- | src/theme.h | 302 |
4 files changed, 1200 insertions, 1514 deletions
@@ -1,3 +1,12 @@ +2002-02-02 Havoc Pennington <hp@pobox.com> + + * src/theme-viewer.c: test % operator + + * src/theme.c (pos_tokenize): add % to switch for operators + + * src/theme.c: rework theme stuff so we have + MetaDrawOp/MetaDrawOpList instead of MetaTextureSpec/MetaShapeSpec + 2002-01-28 Havoc Pennington <hp@pobox.com> * src/theme.c (meta_texture_spec_render): fix shadowed variable diff --git a/src/theme-viewer.c b/src/theme-viewer.c index 928463c8..db06bf68 100644 --- a/src/theme-viewer.c +++ b/src/theme-viewer.c @@ -186,6 +186,8 @@ static const PositionExpressionTest position_expression_tests[] = { "14 - 10", 14, 24, NO_ERROR }, { { 10, 20, 40, 50 }, "8 / 2", 14, 24, NO_ERROR }, + { { 10, 20, 40, 50 }, + "8 % 3", 12, 22, NO_ERROR }, /* Binary expressions with floats and mixed float/ints */ { { 10, 20, 40, 50 }, "7.0 / 3.5", 12, 22, NO_ERROR }, @@ -294,6 +296,10 @@ static const PositionExpressionTest position_expression_tests[] = { { { 10, 20, 40, 50 }, "- width", 0, 0, META_POSITION_EXPR_ERROR_FAILED }, { { 10, 20, 40, 50 }, + "5 % 1.0", 0, 0, META_POSITION_EXPR_ERROR_MOD_ON_FLOAT }, + { { 10, 20, 40, 50 }, + "1.0 % 5", 0, 0, META_POSITION_EXPR_ERROR_MOD_ON_FLOAT }, + { { 10, 20, 40, 50 }, "! * 2", 0, 0, META_POSITION_EXPR_ERROR_BAD_CHARACTER }, { { 10, 20, 40, 50 }, " ", 0, 0, META_POSITION_EXPR_ERROR_FAILED }, @@ -313,7 +319,8 @@ static void run_position_expression_tests (void) { int i; - + MetaPositionExprEnv env; + i = 0; while (i < G_N_ELEMENTS (position_expression_tests)) { @@ -329,12 +336,16 @@ run_position_expression_tests (void) test->expr, test->expected_x, test->expected_y); err = NULL; + + env.x = test->rect.x; + env.y = test->rect.y; + env.width = test->rect.width; + env.height = test->rect.height; + env.object_width = -1; + env.object_height = -1; retval = meta_parse_position_expression (test->expr, - test->rect.x, - test->rect.y, - test->rect.width, - test->rect.height, + &env, &x, &y, &err); @@ -377,7 +388,8 @@ run_position_expression_timings (void) int iters; clock_t start; clock_t end; - + MetaPositionExprEnv env; + #define ITERATIONS 100000 start = clock (); @@ -390,12 +402,16 @@ run_position_expression_timings (void) int x, y; test = &position_expression_tests[i]; + + env.x = test->rect.x; + env.y = test->rect.y; + env.width = test->rect.width; + env.height = test->rect.height; + env.object_width = -1; + env.object_height = -1; meta_parse_position_expression (test->expr, - test->rect.x, - test->rect.y, - test->rect.width, - test->rect.height, + &env, &x, &y, NULL); ++iters; diff --git a/src/theme.c b/src/theme.c index c82517f8..e7add4e4 100644 --- a/src/theme.c +++ b/src/theme.c @@ -38,6 +38,8 @@ (((color).green / 256) << 8) | \ (((color).blue / 256))) +#define ALPHA_TO_UCHAR(d) ((unsigned char) ((d) * 255)) + static void color_composite (const GdkColor *bg, const GdkColor *fg, @@ -300,6 +302,210 @@ meta_frame_layout_calc_geometry (const MetaFrameLayout *layout, } } + +MetaGradientSpec* +meta_gradient_spec_new (MetaGradientType type) +{ + MetaGradientSpec *spec; + + spec = g_new (MetaGradientSpec, 1); + + spec->type = type; + spec->color_specs = NULL; + + return spec; +} + +void +meta_gradient_spec_free (MetaGradientSpec *spec) +{ + g_return_if_fail (spec != NULL); + + g_slist_foreach (spec->color_specs, (GFunc) meta_color_spec_free, NULL); + g_slist_free (spec->color_specs); + g_free (spec); +} + +GdkPixbuf* +meta_gradient_spec_render (const MetaGradientSpec *spec, + GtkWidget *widget, + int width, + int height) +{ + int n_colors; + GdkColor *colors; + GSList *tmp; + int i; + GdkPixbuf *pixbuf; + + n_colors = g_slist_length (spec->color_specs); + + if (n_colors == 0) + return NULL; + + colors = g_new (GdkColor, n_colors); + + i = 0; + tmp = spec->color_specs; + while (tmp != NULL) + { + meta_color_spec_render (tmp->data, widget, &colors[i]); + + tmp = tmp->next; + ++i; + } + + pixbuf = meta_gradient_create_multi (width, height, + colors, n_colors, + spec->type); + + g_free (colors); + + return pixbuf; +} + +MetaColorSpec* +meta_color_spec_new (MetaColorSpecType type) +{ + MetaColorSpec *spec; + MetaColorSpec dummy; + int size; + + size = G_STRUCT_OFFSET (MetaColorSpec, data); + + switch (type) + { + case META_COLOR_SPEC_BASIC: + size += sizeof (dummy.data.basic); + break; + + case META_COLOR_SPEC_GTK: + size += sizeof (dummy.data.gtk); + break; + + case META_COLOR_SPEC_BLEND: + size += sizeof (dummy.data.blend); + break; + } + + spec = g_malloc0 (size); + + spec->type = type; + + return spec; +} + +void +meta_color_spec_free (MetaColorSpec *spec) +{ + g_return_if_fail (spec != NULL); + + switch (spec->type) + { + case META_COLOR_SPEC_BASIC: + break; + + case META_COLOR_SPEC_GTK: + break; + + case META_COLOR_SPEC_BLEND: + if (spec->data.blend.foreground) + meta_color_spec_free (spec->data.blend.foreground); + if (spec->data.blend.background) + meta_color_spec_free (spec->data.blend.background); + break; + } + + g_free (spec); +} + +MetaColorSpec* +meta_color_spec_new_from_string (const char *str, + GError **err) +{ + /* FIXME handle GTK colors, etc. */ + MetaColorSpec *spec; + + spec = meta_color_spec_new (META_COLOR_SPEC_BASIC); + + gdk_color_parse (str, &spec->data.basic.color); + + return spec; +} + +MetaColorSpec* +meta_color_spec_new_gtk (MetaGtkColorComponent component, + GtkStateType state) +{ + /* FIXME handle GTK colors, etc. */ + MetaColorSpec *spec; + + spec = meta_color_spec_new (META_COLOR_SPEC_GTK); + + spec->data.gtk.component = component; + spec->data.gtk.state = state; + + return spec; +} + +void +meta_color_spec_render (MetaColorSpec *spec, + GtkWidget *widget, + GdkColor *color) +{ + g_return_if_fail (spec != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (widget->style != NULL); + + switch (spec->type) + { + case META_COLOR_SPEC_BASIC: + *color = spec->data.basic.color; + break; + + case META_COLOR_SPEC_GTK: + switch (spec->data.gtk.component) + { + case META_GTK_COLOR_BG: + *color = widget->style->bg[spec->data.gtk.state]; + break; + case META_GTK_COLOR_FG: + *color = widget->style->fg[spec->data.gtk.state]; + break; + case META_GTK_COLOR_BASE: + *color = widget->style->base[spec->data.gtk.state]; + break; + case META_GTK_COLOR_TEXT: + *color = widget->style->text[spec->data.gtk.state]; + break; + case META_GTK_COLOR_LIGHT: + *color = widget->style->light[spec->data.gtk.state]; + break; + case META_GTK_COLOR_DARK: + *color = widget->style->dark[spec->data.gtk.state]; + break; + case META_GTK_COLOR_MID: + *color = widget->style->mid[spec->data.gtk.state]; + break; + case META_GTK_COLOR_TEXT_AA: + *color = widget->style->text_aa[spec->data.gtk.state]; + break; + } + break; + + case META_COLOR_SPEC_BLEND: + { + GdkColor bg, fg; + + meta_color_spec_render (spec->data.blend.background, widget, &bg); + meta_color_spec_render (spec->data.blend.foreground, widget, &fg); + + color_composite (&bg, &fg, spec->data.blend.alpha, color); + } + break; + } +} + typedef enum { POS_TOKEN_INT, @@ -467,6 +673,7 @@ pos_tokenize (const char *expr, case '/': case '+': case '-': /* negative numbers aren't allowed so this is easy */ + case '%': next->type = POS_TOKEN_OPERATOR; next->d.o.op = *p; ++n_tokens; @@ -844,12 +1051,11 @@ do_operations (PosExpr *exprs, } static gboolean -pos_eval_helper (PosToken *tokens, - int n_tokens, - int width, - int height, - PosExpr *result, - GError **err) +pos_eval_helper (PosToken *tokens, + int n_tokens, + const MetaPositionExprEnv *env, + PosExpr *result, + GError **err) { /* lazy-ass hardcoded limit on expression size */ #define MAX_EXPRS 32 @@ -917,9 +1123,15 @@ pos_eval_helper (PosToken *tokens, exprs[n_exprs].type = POS_EXPR_INT; if (strcmp (t->d.v.name, "width") == 0) - exprs[n_exprs].d.int_val = width; + exprs[n_exprs].d.int_val = env->width; else if (strcmp (t->d.v.name, "height") == 0) - exprs[n_exprs].d.int_val = height; + exprs[n_exprs].d.int_val = env->height; + else if (env->object_width >= 0 && + strcmp (t->d.v.name, "object_width") == 0) + exprs[n_exprs].d.int_val = env->object_width; + else if (env->object_height >= 0 && + strcmp (t->d.v.name, "object_height") == 0) + exprs[n_exprs].d.int_val = env->object_height; else { g_set_error (err, META_POSITION_EXPR_ERROR, @@ -960,7 +1172,7 @@ pos_eval_helper (PosToken *tokens, /* We closed a toplevel paren group, so recurse */ if (!pos_eval_helper (&tokens[first_paren+1], i - first_paren - 1, - width, height, + env, &exprs[n_exprs], err)) return FALSE; @@ -1018,18 +1230,17 @@ pos_eval_helper (PosToken *tokens, * so very not worth fooling with bison, yet so very painful by hand. */ static gboolean -pos_eval (PosToken *tokens, - int n_tokens, - int width, - int height, - int *val_p, - GError **err) +pos_eval (PosToken *tokens, + int n_tokens, + const MetaPositionExprEnv *env, + int *val_p, + GError **err) { PosExpr expr; *val_p = 0; - if (pos_eval_helper (tokens, n_tokens, width, height, &expr, err)) + if (pos_eval_helper (tokens, n_tokens, env, &expr, err)) { switch (expr.type) { @@ -1056,19 +1267,17 @@ pos_eval (PosToken *tokens, */ gboolean -meta_parse_position_expression (const char *expr, - int x, - int y, - int width, - int height, - int *x_return, - int *y_return, - GError **err) +meta_parse_position_expression (const char *expr, + const MetaPositionExprEnv *env, + int *x_return, + int *y_return, + GError **err) { /* All positions are in a coordinate system with x, y at the origin. - * The expression can have -, +, *, / as operators, floating - * point or integer constants, and the two variables "width" - * and "height". Negative numbers aren't allowed. + * The expression can have -, +, *, / as operators, floating point + * or integer constants, and the variables "width" and "height" and + * optionally "object_width" and object_height". Negative numbers + * aren't allowed. */ PosToken *tokens; int n_tokens; @@ -1085,12 +1294,12 @@ meta_parse_position_expression (const char *expr, debug_print_tokens (tokens, n_tokens); #endif - if (pos_eval (tokens, n_tokens, width, height, &val, err)) + if (pos_eval (tokens, n_tokens, env, &val, err)) { if (x_return) - *x_return = x + val; + *x_return = env->x + val; if (y_return) - *y_return = y + val; + *y_return = env->y + val; free_tokens (tokens, n_tokens); return TRUE; } @@ -1104,17 +1313,11 @@ meta_parse_position_expression (const char *expr, gboolean -meta_parse_size_expression (const char *expr, - int width, - int height, - int *val_return, - GError **err) +meta_parse_size_expression (const char *expr, + const MetaPositionExprEnv *env, + int *val_return, + GError **err) { - /* All positions are in a coordinate system with x, y at the origin. - * The expression can have -, +, *, / as operators, floating - * point or integer constants, and the two variables "width" - * and "height". Negative numbers aren't allowed. - */ PosToken *tokens; int n_tokens; int val; @@ -1130,7 +1333,7 @@ meta_parse_size_expression (const char *expr, debug_print_tokens (tokens, n_tokens); #endif - if (pos_eval (tokens, n_tokens, width, height, &val, err)) + if (pos_eval (tokens, n_tokens, env, &val, err)) { if (val_return) *val_return = val; @@ -1146,17 +1349,15 @@ meta_parse_size_expression (const char *expr, } static int -parse_x_position_unchecked (const char *expr, - int x, - int width, - int height) +parse_x_position_unchecked (const char *expr, + const MetaPositionExprEnv *env) { int retval; GError *error; retval = 0; error = NULL; - if (!meta_parse_position_expression (expr, x, 0, width, height, + if (!meta_parse_position_expression (expr, env, &retval, NULL, &error)) { @@ -1170,17 +1371,15 @@ parse_x_position_unchecked (const char *expr, } static int -parse_y_position_unchecked (const char *expr, - int y, - int width, - int height) +parse_y_position_unchecked (const char *expr, + const MetaPositionExprEnv *env) { int retval; GError *error; retval = 0; error = NULL; - if (!meta_parse_position_expression (expr, 0, y, width, height, + if (!meta_parse_position_expression (expr, env, NULL, &retval, &error)) { @@ -1194,16 +1393,15 @@ parse_y_position_unchecked (const char *expr, } static int -parse_size_unchecked (const char *expr, - int width, - int height) +parse_size_unchecked (const char *expr, + MetaPositionExprEnv *env) { int retval; GError *error; retval = 0; error = NULL; - if (!meta_parse_size_expression (expr, width, height, + if (!meta_parse_size_expression (expr, env, &retval, &error)) { meta_warning (_("Theme contained an expression \"%s\" that resulted in an error: %s\n"), @@ -1216,116 +1414,143 @@ parse_size_unchecked (const char *expr, } -MetaShapeSpec* -meta_shape_spec_new (MetaShapeType type) +MetaDrawOp* +meta_draw_op_new (MetaDrawType type) { - MetaShapeSpec *spec; - MetaShapeSpec dummy; + MetaDrawOp *op; + MetaDrawOp dummy; int size; - size = G_STRUCT_OFFSET (MetaShapeSpec, data); + size = G_STRUCT_OFFSET (MetaDrawOp, data); switch (type) { - case META_SHAPE_LINE: + case META_DRAW_LINE: size += sizeof (dummy.data.line); break; - case META_SHAPE_RECTANGLE: + case META_DRAW_RECTANGLE: size += sizeof (dummy.data.rectangle); break; - case META_SHAPE_ARC: + case META_DRAW_ARC: size += sizeof (dummy.data.arc); break; - case META_SHAPE_TEXTURE: - size += sizeof (dummy.data.texture); + case META_DRAW_TINT: + size += sizeof (dummy.data.tint); break; - case META_SHAPE_GTK_ARROW: + case META_DRAW_GRADIENT: + size += sizeof (dummy.data.gradient); + break; + + case META_DRAW_IMAGE: + size += sizeof (dummy.data.image); + break; + + case META_DRAW_GTK_ARROW: size += sizeof (dummy.data.gtk_arrow); break; - case META_SHAPE_GTK_BOX: + case META_DRAW_GTK_BOX: size += sizeof (dummy.data.gtk_box); break; - case META_SHAPE_GTK_VLINE: + case META_DRAW_GTK_VLINE: size += sizeof (dummy.data.gtk_vline); break; } - spec = g_malloc0 (size); + op = g_malloc0 (size); - spec->type = type; + op->type = type; - return spec; + return op; } void -meta_shape_spec_free (MetaShapeSpec *spec) +meta_draw_op_free (MetaDrawOp *op) { - g_return_if_fail (spec != NULL); + g_return_if_fail (op != NULL); - switch (spec->type) + switch (op->type) { - case META_SHAPE_LINE: - g_free (spec->data.line.x1); - g_free (spec->data.line.y1); - g_free (spec->data.line.x2); - g_free (spec->data.line.y2); + case META_DRAW_LINE: + g_free (op->data.line.x1); + g_free (op->data.line.y1); + g_free (op->data.line.x2); + g_free (op->data.line.y2); break; - case META_SHAPE_RECTANGLE: - if (spec->data.rectangle.color_spec) - g_free (spec->data.rectangle.color_spec); - g_free (spec->data.rectangle.x); - g_free (spec->data.rectangle.y); - g_free (spec->data.rectangle.width); - g_free (spec->data.rectangle.height); + case META_DRAW_RECTANGLE: + if (op->data.rectangle.color_spec) + g_free (op->data.rectangle.color_spec); + g_free (op->data.rectangle.x); + g_free (op->data.rectangle.y); + g_free (op->data.rectangle.width); + g_free (op->data.rectangle.height); break; - case META_SHAPE_ARC: - if (spec->data.arc.color_spec) - g_free (spec->data.arc.color_spec); - g_free (spec->data.arc.x); - g_free (spec->data.arc.y); - g_free (spec->data.arc.width); - g_free (spec->data.arc.height); + case META_DRAW_ARC: + if (op->data.arc.color_spec) + g_free (op->data.arc.color_spec); + g_free (op->data.arc.x); + g_free (op->data.arc.y); + g_free (op->data.arc.width); + g_free (op->data.arc.height); break; - case META_SHAPE_TEXTURE: - if (spec->data.texture.texture_spec) - meta_texture_spec_free (spec->data.texture.texture_spec); - g_free (spec->data.texture.x); - g_free (spec->data.texture.y); - g_free (spec->data.texture.width); - g_free (spec->data.texture.height); + case META_DRAW_TINT: + if (op->data.tint.color_spec) + meta_color_spec_free (op->data.tint.color_spec); + g_free (op->data.tint.x); + g_free (op->data.tint.y); + g_free (op->data.tint.width); + g_free (op->data.tint.height); break; - case META_SHAPE_GTK_ARROW: - g_free (spec->data.gtk_arrow.x); - g_free (spec->data.gtk_arrow.y); - g_free (spec->data.gtk_arrow.width); - g_free (spec->data.gtk_arrow.height); + case META_DRAW_GRADIENT: + if (op->data.gradient.gradient_spec) + meta_gradient_spec_free (op->data.gradient.gradient_spec); + g_free (op->data.gradient.x); + g_free (op->data.gradient.y); + g_free (op->data.gradient.width); + g_free (op->data.gradient.height); break; - case META_SHAPE_GTK_BOX: - g_free (spec->data.gtk_box.x); - g_free (spec->data.gtk_box.y); - g_free (spec->data.gtk_box.width); - g_free (spec->data.gtk_box.height); + case META_DRAW_IMAGE: + if (op->data.image.pixbuf) + g_object_unref (G_OBJECT (op->data.image.pixbuf)); + g_free (op->data.image.x); + g_free (op->data.image.y); + g_free (op->data.image.width); + g_free (op->data.image.height); break; - case META_SHAPE_GTK_VLINE: - g_free (spec->data.gtk_vline.x); - g_free (spec->data.gtk_vline.y1); - g_free (spec->data.gtk_vline.y2); + + case META_DRAW_GTK_ARROW: + g_free (op->data.gtk_arrow.x); + g_free (op->data.gtk_arrow.y); + g_free (op->data.gtk_arrow.width); + g_free (op->data.gtk_arrow.height); + break; + + case META_DRAW_GTK_BOX: + g_free (op->data.gtk_box.x); + g_free (op->data.gtk_box.y); + g_free (op->data.gtk_box.width); + g_free (op->data.gtk_box.height); + break; + + case META_DRAW_GTK_VLINE: + g_free (op->data.gtk_vline.x); + g_free (op->data.gtk_vline.y1); + g_free (op->data.gtk_vline.y2); break; } - g_free (spec); + g_free (op); } static GdkGC* @@ -1355,524 +1580,59 @@ get_gc_for_primitive (GtkWidget *widget, return gc; } -void -meta_shape_spec_draw (const MetaShapeSpec *spec, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - int x, - int y, - int width, - int height) -{ - GdkGC *gc; - - switch (spec->type) - { - case META_SHAPE_LINE: - { - int x1, x2, y1, y2; - - gc = get_gc_for_primitive (widget, drawable, - spec->data.line.color_spec, - clip, - spec->data.line.width); - - if (spec->data.line.dash_on_length > 0 && - spec->data.line.dash_off_length > 0) - { - gint8 dash_list[2]; - dash_list[0] = spec->data.line.dash_on_length; - dash_list[1] = spec->data.line.dash_off_length; - gdk_gc_set_dashes (gc, 0, dash_list, 2); - } - - x1 = parse_x_position_unchecked (spec->data.line.x1, - x, width, height); - - y1 = parse_y_position_unchecked (spec->data.line.y1, - y, width, height); - - x2 = parse_x_position_unchecked (spec->data.line.x2, - x, width, height); - - y2 = parse_y_position_unchecked (spec->data.line.y2, - y, width, height); - - gdk_draw_line (drawable, gc, x1, y1, x2, y2); - - g_object_unref (G_OBJECT (gc)); - } - break; - - case META_SHAPE_RECTANGLE: - { - int rx, ry, rwidth, rheight; - - gc = get_gc_for_primitive (widget, drawable, - spec->data.rectangle.color_spec, - clip, 0); - - rx = parse_x_position_unchecked (spec->data.rectangle.x, - x, width, height); - - ry = parse_y_position_unchecked (spec->data.rectangle.y, - y, width, height); - - - rwidth = parse_size_unchecked (spec->data.rectangle.width, - width, height); - - rheight = parse_size_unchecked (spec->data.rectangle.height, - width, height); - - gdk_draw_rectangle (drawable, gc, - spec->data.rectangle.filled, - rx, ry, rwidth, rheight); - - g_object_unref (G_OBJECT (gc)); - } - break; - - case META_SHAPE_ARC: - { - int rx, ry, rwidth, rheight; - - gc = get_gc_for_primitive (widget, drawable, - spec->data.arc.color_spec, - clip, 0); - - rx = parse_x_position_unchecked (spec->data.arc.x, - x, width, height); - - ry = parse_y_position_unchecked (spec->data.arc.y, - y, width, height); - - - rwidth = parse_size_unchecked (spec->data.arc.width, - width, height); - - rheight = parse_size_unchecked (spec->data.arc.height, - width, height); - - gdk_draw_arc (drawable, - gc, - spec->data.arc.filled, - rx, ry, rwidth, rheight, - spec->data.arc.start_angle * (360.0 * 64.0) - - (90.0 * 64.0), /* start at 12 instead of 3 oclock */ - spec->data.arc.extent_angle * (360.0 * 64.0)); - - g_object_unref (G_OBJECT (gc)); - } - break; - - case META_SHAPE_TEXTURE: - { - int rx, ry, rwidth, rheight; - - rx = parse_x_position_unchecked (spec->data.texture.x, - x, width, height); - - ry = parse_y_position_unchecked (spec->data.texture.y, - y, width, height); - - - rwidth = parse_size_unchecked (spec->data.texture.width, - width, height); - - rheight = parse_size_unchecked (spec->data.texture.height, - width, height); - - meta_texture_spec_draw (spec->data.texture.texture_spec, - widget, - drawable, - clip, - spec->data.texture.mode, - spec->data.texture.xalign, - spec->data.texture.yalign, - rx, ry, rwidth, rheight); - } - break; - - case META_SHAPE_GTK_ARROW: - { - int rx, ry, rwidth, rheight; - - rx = parse_x_position_unchecked (spec->data.gtk_arrow.x, - x, width, height); - - ry = parse_y_position_unchecked (spec->data.gtk_arrow.y, - y, width, height); - - - rwidth = parse_size_unchecked (spec->data.gtk_arrow.width, - width, height); - - rheight = parse_size_unchecked (spec->data.gtk_arrow.height, - width, height); - - gtk_paint_arrow (widget->style, - drawable, - spec->data.gtk_arrow.state, - spec->data.gtk_arrow.shadow, - (GdkRectangle*) clip, - widget, - "metacity", - spec->data.gtk_arrow.arrow, - spec->data.gtk_arrow.filled, - rx, ry, rwidth, rheight); - } - break; - - case META_SHAPE_GTK_BOX: - { - int rx, ry, rwidth, rheight; - - rx = parse_x_position_unchecked (spec->data.gtk_box.x, - x, width, height); - - ry = parse_y_position_unchecked (spec->data.gtk_box.y, - y, width, height); - - - rwidth = parse_size_unchecked (spec->data.gtk_box.width, - width, height); - - rheight = parse_size_unchecked (spec->data.gtk_box.height, - width, height); - - gtk_paint_box (widget->style, - drawable, - spec->data.gtk_box.state, - spec->data.gtk_box.shadow, - (GdkRectangle*) clip, - widget, - "metacity", - rx, ry, rwidth, rheight); - } - break; - - case META_SHAPE_GTK_VLINE: - { - int rx, ry1, ry2; - - rx = parse_x_position_unchecked (spec->data.gtk_vline.x, - x, width, height); - - ry1 = parse_y_position_unchecked (spec->data.gtk_vline.y1, - y, width, height); - - ry2 = parse_y_position_unchecked (spec->data.gtk_vline.y2, - y, width, height); - - gtk_paint_vline (widget->style, - drawable, - spec->data.gtk_vline.state, - (GdkRectangle*) clip, - widget, - "metacity", - rx, ry1, ry2); - } - break; - } -} - -MetaGradientSpec* -meta_gradient_spec_new (MetaGradientType type) -{ - MetaGradientSpec *spec; - - spec = g_new (MetaGradientSpec, 1); - - spec->type = type; - spec->color_specs = NULL; - - return spec; -} - -void -meta_gradient_spec_free (MetaGradientSpec *spec) -{ - g_return_if_fail (spec != NULL); - - g_slist_foreach (spec->color_specs, (GFunc) meta_color_spec_free, NULL); - g_slist_free (spec->color_specs); - g_free (spec); -} - -GdkPixbuf* -meta_gradient_spec_render (const MetaGradientSpec *spec, - GtkWidget *widget, - int width, - int height) +static GdkPixbuf* +multiply_alpha (GdkPixbuf *pixbuf, + guchar alpha) { - int n_colors; - GdkColor *colors; - GSList *tmp; - int i; - GdkPixbuf *pixbuf; - - n_colors = g_slist_length (spec->color_specs); - - if (n_colors == 0) - return NULL; - - colors = g_new (GdkColor, n_colors); + GdkPixbuf *new_pixbuf; + guchar *pixels; + int rowstride; + int height; + int row; - i = 0; - tmp = spec->color_specs; - while (tmp != NULL) - { - meta_color_spec_render (tmp->data, widget, &colors[i]); - - tmp = tmp->next; - ++i; - } + g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); - pixbuf = meta_gradient_create_multi (width, height, - colors, n_colors, - spec->type); - - g_free (colors); - - return pixbuf; -} - -MetaColorSpec* -meta_color_spec_new (MetaColorSpecType type) -{ - MetaColorSpec *spec; - MetaColorSpec dummy; - int size; + if (alpha == 255) + return pixbuf; - size = G_STRUCT_OFFSET (MetaColorSpec, data); - - switch (type) + if (!gdk_pixbuf_get_has_alpha (pixbuf)) { - case META_COLOR_SPEC_BASIC: - size += sizeof (dummy.data.basic); - break; - - case META_COLOR_SPEC_GTK: - size += sizeof (dummy.data.gtk); - break; - - case META_COLOR_SPEC_BLEND: - size += sizeof (dummy.data.blend); - break; + new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); + g_object_unref (G_OBJECT (pixbuf)); + pixbuf = new_pixbuf; } - spec = g_malloc0 (size); - - spec->type = type; - - return spec; -} + pixels = gdk_pixbuf_get_pixels (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); -void -meta_color_spec_free (MetaColorSpec *spec) -{ - g_return_if_fail (spec != NULL); - - switch (spec->type) + row = 0; + while (row < height) { - case META_COLOR_SPEC_BASIC: - break; - - case META_COLOR_SPEC_GTK: - break; - - case META_COLOR_SPEC_BLEND: - if (spec->data.blend.foreground) - meta_color_spec_free (spec->data.blend.foreground); - if (spec->data.blend.background) - meta_color_spec_free (spec->data.blend.background); - break; - } - - g_free (spec); -} - -MetaColorSpec* -meta_color_spec_new_from_string (const char *str, - GError **err) -{ - /* FIXME handle GTK colors, etc. */ - MetaColorSpec *spec; - - spec = meta_color_spec_new (META_COLOR_SPEC_BASIC); - - gdk_color_parse (str, &spec->data.basic.color); - - return spec; -} - -MetaColorSpec* -meta_color_spec_new_gtk (MetaGtkColorComponent component, - GtkStateType state) -{ - /* FIXME handle GTK colors, etc. */ - MetaColorSpec *spec; - - spec = meta_color_spec_new (META_COLOR_SPEC_GTK); - - spec->data.gtk.component = component; - spec->data.gtk.state = state; - - return spec; -} + guchar *p; + guchar *end; -void -meta_color_spec_render (MetaColorSpec *spec, - GtkWidget *widget, - GdkColor *color) -{ - g_return_if_fail (spec != NULL); - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (widget->style != NULL); - - switch (spec->type) - { - case META_COLOR_SPEC_BASIC: - *color = spec->data.basic.color; - break; + p = pixels + row * rowstride; + end = p + rowstride; - case META_COLOR_SPEC_GTK: - switch (spec->data.gtk.component) + while (p != end) { - case META_GTK_COLOR_BG: - *color = widget->style->bg[spec->data.gtk.state]; - break; - case META_GTK_COLOR_FG: - *color = widget->style->fg[spec->data.gtk.state]; - break; - case META_GTK_COLOR_BASE: - *color = widget->style->base[spec->data.gtk.state]; - break; - case META_GTK_COLOR_TEXT: - *color = widget->style->text[spec->data.gtk.state]; - break; - case META_GTK_COLOR_LIGHT: - *color = widget->style->light[spec->data.gtk.state]; - break; - case META_GTK_COLOR_DARK: - *color = widget->style->dark[spec->data.gtk.state]; - break; - case META_GTK_COLOR_MID: - *color = widget->style->mid[spec->data.gtk.state]; - break; - case META_GTK_COLOR_TEXT_AA: - *color = widget->style->text_aa[spec->data.gtk.state]; - break; - } - break; - - case META_COLOR_SPEC_BLEND: - { - GdkColor bg, fg; - - meta_color_spec_render (spec->data.blend.background, widget, &bg); - meta_color_spec_render (spec->data.blend.foreground, widget, &fg); - - color_composite (&bg, &fg, spec->data.blend.alpha, color); - } - break; - } -} - - -MetaTextureSpec* -meta_texture_spec_new (MetaTextureType type) -{ - MetaTextureSpec *spec; - MetaTextureSpec dummy; - int size; - - size = G_STRUCT_OFFSET (MetaTextureSpec, data); - - switch (type) - { - case META_TEXTURE_SOLID: - size += sizeof (dummy.data.solid); - break; - - case META_TEXTURE_GRADIENT: - size += sizeof (dummy.data.gradient); - break; - - case META_TEXTURE_IMAGE: - size += sizeof (dummy.data.image); - break; - - case META_TEXTURE_COMPOSITE: - size += sizeof (dummy.data.composite); - break; - - case META_TEXTURE_BLANK: - size += sizeof (dummy.data.blank); - break; - - case META_TEXTURE_SHAPE_LIST: - size += sizeof (dummy.data.shape_list); - break; - } - - spec = g_malloc0 (size); - - spec->type = type; - - return spec; -} - -void -meta_texture_spec_free (MetaTextureSpec *spec) -{ - g_return_if_fail (spec != NULL); - - switch (spec->type) - { - case META_TEXTURE_SOLID: - if (spec->data.solid.color_spec) - meta_color_spec_free (spec->data.solid.color_spec); - break; - - case META_TEXTURE_GRADIENT: - if (spec->data.gradient.gradient_spec) - meta_gradient_spec_free (spec->data.gradient.gradient_spec); - break; - - case META_TEXTURE_IMAGE: - if (spec->data.image.pixbuf) - g_object_unref (G_OBJECT (spec->data.image.pixbuf)); - break; - - case META_TEXTURE_COMPOSITE: - if (spec->data.composite.background) - meta_texture_spec_free (spec->data.composite.background); - if (spec->data.composite.foreground) - meta_texture_spec_free (spec->data.composite.foreground); - break; - - case META_TEXTURE_BLANK: - break; + p += 3; /* skip RGB */ - case META_TEXTURE_SHAPE_LIST: - if (spec->data.shape_list.shape_specs) - { - int i; - i = 0; - while (i < spec->data.shape_list.n_specs) - { - meta_shape_spec_free (spec->data.shape_list.shape_specs[i]); - ++i; - } - g_free (spec->data.shape_list.shape_specs); + /* multiply the two alpha channels. not sure this is right. + * but some end cases are that if the pixbuf contains 255, + * then it should be modified to contain "alpha"; if the + * pixbuf contains 0, it should remain 0. + */ + *p = (*p * alpha) / 65025; /* (*p / 255) * (alpha / 255); */ + + ++p; /* skip A */ } - break; + + ++row; } - g_free (spec); + return pixbuf; } static void @@ -1885,6 +1645,9 @@ render_pixbuf (GdkDrawable *drawable, /* grumble, render_to_drawable_alpha does not accept a clip * mask, so we have to go through some BS */ + /* FIXME once GTK 1.3.13 has been out a while we can use + * render_to_drawable() which now does alpha with clip + */ GdkRectangle pixbuf_rect; GdkRectangle draw_rect; @@ -1918,163 +1681,86 @@ render_pixbuf (GdkDrawable *drawable, draw_rect.y - pixbuf_rect.y); } - -static void -render_pixbuf_aligned (GdkDrawable *drawable, - const GdkRectangle *clip, - GdkPixbuf *pixbuf, - double xalign, - double yalign, - int x, - int y, - int width, - int height) -{ - int pix_width; - int pix_height; - int rx, ry; - - pix_width = gdk_pixbuf_get_width (pixbuf); - pix_height = gdk_pixbuf_get_height (pixbuf); - - rx = x + (width - pix_width) * xalign; - ry = y + (height - pix_height) * yalign; - - render_pixbuf (drawable, clip, pixbuf, rx, ry); -} - static GdkPixbuf* -multiply_alpha (GdkPixbuf *pixbuf, - guchar alpha) +draw_op_as_pixbuf (const MetaDrawOp *op, + GtkWidget *widget, + int width, + int height) { - GdkPixbuf *new_pixbuf; - guchar *pixels; - int rowstride; - int height; - int row; + /* Try to get the op as a pixbuf, assuming w/h in the op + * matches the width/height passed in. return NULL + * if the op can't be converted to an equivalent pixbuf. + */ + GdkPixbuf *pixbuf; - g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); + pixbuf = NULL; - if (alpha == 255) - return pixbuf; - - if (!gdk_pixbuf_get_has_alpha (pixbuf)) + switch (op->type) { - new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); - g_object_unref (G_OBJECT (pixbuf)); - pixbuf = new_pixbuf; - } - - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - - row = 0; - while (row < height) - { - guchar *p; - guchar *end; - - p = pixels + row * rowstride; - end = p + rowstride; + case META_DRAW_LINE: + break; - while (p != end) + case META_DRAW_RECTANGLE: + if (op->data.rectangle.filled) { - p += 3; /* skip RGB */ + GdkColor color; - /* multiply the two alpha channels. not sure this is right. - * but some end cases are that if the pixbuf contains 255, - * then it should be modified to contain "alpha"; if the - * pixbuf contains 0, it should remain 0. - */ - *p = (*p * alpha) / 65025; /* (*p / 255) * (alpha / 255); */ + meta_color_spec_render (op->data.rectangle.color_spec, + widget, + &color); - ++p; /* skip A */ + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + FALSE, + 8, width, height); + + gdk_pixbuf_fill (pixbuf, GDK_COLOR_RGBA (color)); } - - ++row; - } - - return pixbuf; -} - -static GdkPixbuf* -meta_texture_spec_render (const MetaTextureSpec *spec, - GtkWidget *widget, - MetaTextureDrawMode mode, - guchar alpha, - int width, - int height) -{ - GdkPixbuf *pixbuf; + break; - pixbuf = NULL; + case META_DRAW_ARC: + break; - g_return_val_if_fail (spec != NULL, NULL); - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - g_return_val_if_fail (widget->style != NULL, NULL); - - switch (spec->type) - { - case META_TEXTURE_SOLID: + case META_DRAW_TINT: { GdkColor color; + guint32 rgba; - g_return_val_if_fail (spec->data.solid.color_spec != NULL, - NULL); - - meta_color_spec_render (spec->data.solid.color_spec, - widget, &color); + meta_color_spec_render (op->data.rectangle.color_spec, + widget, + &color); + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + ALPHA_TO_UCHAR (op->data.tint.alpha) < 255, + 8, width, height); - if (alpha == 255) - { - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - FALSE, - 8, width, height); - gdk_pixbuf_fill (pixbuf, GDK_COLOR_RGBA (color)); - } - else - { - guint32 rgba; - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - TRUE, - 8, width, height); - rgba = GDK_COLOR_RGBA (color); - rgba &= ~0xff; - rgba |= alpha; - gdk_pixbuf_fill (pixbuf, rgba); - } + rgba = GDK_COLOR_RGBA (color); + rgba &= ~0xff; + rgba |= ALPHA_TO_UCHAR (op->data.tint.alpha); + + gdk_pixbuf_fill (pixbuf, rgba); } break; - case META_TEXTURE_GRADIENT: + case META_DRAW_GRADIENT: { - g_return_val_if_fail (spec->data.gradient.gradient_spec != NULL, - NULL); - - pixbuf = meta_gradient_spec_render (spec->data.gradient.gradient_spec, + pixbuf = meta_gradient_spec_render (op->data.gradient.gradient_spec, widget, width, height); - pixbuf = multiply_alpha (pixbuf, alpha); + pixbuf = multiply_alpha (pixbuf, + ALPHA_TO_UCHAR (op->data.gradient.alpha)); } break; - case META_TEXTURE_IMAGE: - { - g_return_val_if_fail (spec->data.image.pixbuf != NULL, - NULL); - - pixbuf = NULL; - - switch (mode) + case META_DRAW_IMAGE: + { + switch (op->data.image.scale_mode) { - case META_TEXTURE_DRAW_UNSCALED: - pixbuf = spec->data.image.pixbuf; + case META_SCALE_NONE: + pixbuf = op->data.image.pixbuf; g_object_ref (G_OBJECT (pixbuf)); break; - case META_TEXTURE_DRAW_SCALED_VERTICALLY: - pixbuf = spec->data.image.pixbuf; + case META_SCALE_VERTICALLY: + pixbuf = op->data.image.pixbuf; if (gdk_pixbuf_get_height (pixbuf) == height) { g_object_ref (G_OBJECT (pixbuf)); @@ -2087,8 +1773,8 @@ meta_texture_spec_render (const MetaTextureSpec *spec, GDK_INTERP_BILINEAR); } break; - case META_TEXTURE_DRAW_SCALED_HORIZONTALLY: - pixbuf = spec->data.image.pixbuf; + case META_SCALE_HORIZONTALLY: + pixbuf = op->data.image.pixbuf; if (gdk_pixbuf_get_width (pixbuf) == width) { g_object_ref (G_OBJECT (pixbuf)); @@ -2101,8 +1787,8 @@ meta_texture_spec_render (const MetaTextureSpec *spec, GDK_INTERP_BILINEAR); } break; - case META_TEXTURE_DRAW_SCALED_BOTH: - pixbuf = spec->data.image.pixbuf; + case META_SCALE_BOTH: + pixbuf = op->data.image.pixbuf; if (gdk_pixbuf_get_width (pixbuf) == width && gdk_pixbuf_get_height (pixbuf) == height) { @@ -2117,449 +1803,346 @@ meta_texture_spec_render (const MetaTextureSpec *spec, break; } - pixbuf = multiply_alpha (pixbuf, alpha); + pixbuf = multiply_alpha (pixbuf, + ALPHA_TO_UCHAR (op->data.image.alpha)); } break; - case META_TEXTURE_COMPOSITE: - case META_TEXTURE_BLANK: - case META_TEXTURE_SHAPE_LIST: - break; + + case META_DRAW_GTK_ARROW: + case META_DRAW_GTK_BOX: + case META_DRAW_GTK_VLINE: + break; } return pixbuf; } -static void -draw_color_rectangle (GtkWidget *widget, - GdkDrawable *drawable, - GdkColor *color, - const GdkRectangle *clip, - int x, - int y, - int width, - int height) +void +meta_draw_op_draw (const MetaDrawOp *op, + GtkWidget *widget, + GdkDrawable *drawable, + const GdkRectangle *clip, + int x, + int y, + int width, + int height) { GdkGC *gc; - GdkGCValues values; - - values.foreground = *color; - gdk_rgb_find_color (widget->style->colormap, &values.foreground); - - gc = gdk_gc_new_with_values (drawable, &values, GDK_GC_FOREGROUND); - - if (clip) - gdk_gc_set_clip_rectangle (gc, - (GdkRectangle*) clip); /* const cast */ - - gdk_draw_rectangle (drawable, - gc, TRUE, x, y, width, height); - - g_object_unref (G_OBJECT (gc)); -} + MetaPositionExprEnv env; -static void -draw_bg_solid_composite (const MetaTextureSpec *bg, - const MetaTextureSpec *fg, - double alpha, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - MetaTextureDrawMode mode, - double xalign, - double yalign, - int x, - int y, - int width, - int height) -{ - GdkColor bg_color; + env.x = x; + env.y = y; + env.width = width; + env.height = height; + env.object_width = -1; + env.object_height = -1; - g_assert (bg->type == META_TEXTURE_SOLID); - g_assert (fg->type != META_TEXTURE_COMPOSITE); - g_assert (fg->type != META_TEXTURE_SHAPE_LIST); - - meta_color_spec_render (bg->data.solid.color_spec, - widget, - &bg_color); - - switch (fg->type) + switch (op->type) { - case META_TEXTURE_SOLID: + case META_DRAW_LINE: { - GdkColor fg_color; - - meta_color_spec_render (fg->data.solid.color_spec, - widget, - &fg_color); + int x1, x2, y1, y2; + + gc = get_gc_for_primitive (widget, drawable, + op->data.line.color_spec, + clip, + op->data.line.width); + + if (op->data.line.dash_on_length > 0 && + op->data.line.dash_off_length > 0) + { + gint8 dash_list[2]; + dash_list[0] = op->data.line.dash_on_length; + dash_list[1] = op->data.line.dash_off_length; + gdk_gc_set_dashes (gc, 0, dash_list, 2); + } - color_composite (&bg_color, &fg_color, - alpha, &fg_color); + x1 = parse_x_position_unchecked (op->data.line.x1, &env); + y1 = parse_y_position_unchecked (op->data.line.y1, &env); + x2 = parse_x_position_unchecked (op->data.line.x2, &env); + y2 = parse_y_position_unchecked (op->data.line.y2, &env); - draw_color_rectangle (widget, drawable, &fg_color, clip, - x, y, width, height); + gdk_draw_line (drawable, gc, x1, y1, x2, y2); + + g_object_unref (G_OBJECT (gc)); } break; - case META_TEXTURE_GRADIENT: - /* FIXME I think we could just composite all the colors in - * the gradient prior to generating the gradient? - */ - /* FALL THRU */ - case META_TEXTURE_IMAGE: + case META_DRAW_RECTANGLE: { - GdkPixbuf *pixbuf; - GdkPixbuf *composited; + int rx, ry, rwidth, rheight; - pixbuf = meta_texture_spec_render (fg, widget, mode, 255, - width, height); - - if (pixbuf == NULL) - return; + gc = get_gc_for_primitive (widget, drawable, + op->data.rectangle.color_spec, + clip, 0); - composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - gdk_pixbuf_get_has_alpha (pixbuf), 8, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); + rx = parse_x_position_unchecked (op->data.rectangle.x, &env); + ry = parse_y_position_unchecked (op->data.rectangle.y, &env); + rwidth = parse_size_unchecked (op->data.rectangle.width, &env); + rheight = parse_size_unchecked (op->data.rectangle.height, &env); - if (composited == NULL) - { - g_object_unref (G_OBJECT (pixbuf)); - return; - } + gdk_draw_rectangle (drawable, gc, + op->data.rectangle.filled, + rx, ry, rwidth, rheight); - gdk_pixbuf_composite_color (pixbuf, - composited, - 0, 0, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - 0.0, 0.0, /* offsets */ - 1.0, 1.0, /* scale */ - GDK_INTERP_BILINEAR, - 255 * alpha, - 0, 0, /* check offsets */ - 0, /* check size */ - GDK_COLOR_RGB (bg_color), - GDK_COLOR_RGB (bg_color)); + g_object_unref (G_OBJECT (gc)); + } + break; - /* Need to draw background since pixbuf is not - * necessarily covering the whole thing - */ - draw_color_rectangle (widget, drawable, &bg_color, clip, - x, y, width, height); + case META_DRAW_ARC: + { + int rx, ry, rwidth, rheight; - render_pixbuf_aligned (drawable, clip, composited, - xalign, yalign, - x, y, width, height); + gc = get_gc_for_primitive (widget, drawable, + op->data.arc.color_spec, + clip, 0); - g_object_unref (G_OBJECT (pixbuf)); - g_object_unref (G_OBJECT (composited)); - } - break; + rx = parse_x_position_unchecked (op->data.arc.x, &env); + ry = parse_y_position_unchecked (op->data.arc.y, &env); + rwidth = parse_size_unchecked (op->data.arc.width, &env); + rheight = parse_size_unchecked (op->data.arc.height, &env); - case META_TEXTURE_BLANK: - case META_TEXTURE_COMPOSITE: - case META_TEXTURE_SHAPE_LIST: - g_assert_not_reached (); + gdk_draw_arc (drawable, + gc, + op->data.arc.filled, + rx, ry, rwidth, rheight, + op->data.arc.start_angle * (360.0 * 64.0) - + (90.0 * 64.0), /* start at 12 instead of 3 oclock */ + op->data.arc.extent_angle * (360.0 * 64.0)); + + g_object_unref (G_OBJECT (gc)); + } break; - } -} -static void -draw_bg_gradient_composite (const MetaTextureSpec *bg, - const MetaTextureSpec *fg, - double alpha, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - MetaTextureDrawMode mode, - double xalign, - double yalign, - int x, - int y, - int width, - int height) -{ - g_assert (bg->type == META_TEXTURE_GRADIENT); - g_assert (fg->type != META_TEXTURE_COMPOSITE); - g_assert (fg->type != META_TEXTURE_SHAPE_LIST); - - switch (fg->type) - { - case META_TEXTURE_SOLID: - case META_TEXTURE_GRADIENT: - case META_TEXTURE_IMAGE: + case META_DRAW_TINT: { - GdkPixbuf *bg_pixbuf; - GdkPixbuf *fg_pixbuf; - GdkPixbuf *composited; - int fg_width, fg_height; - - bg_pixbuf = meta_texture_spec_render (bg, widget, mode, 255, - width, height); - - if (bg_pixbuf == NULL) - return; + int rx, ry, rwidth, rheight; - fg_pixbuf = meta_texture_spec_render (fg, widget, mode, 255, - width, height); + rx = parse_x_position_unchecked (op->data.tint.x, &env); + ry = parse_y_position_unchecked (op->data.tint.y, &env); + rwidth = parse_size_unchecked (op->data.tint.width, &env); + rheight = parse_size_unchecked (op->data.tint.height, &env); - if (fg_pixbuf == NULL) + if (ALPHA_TO_UCHAR (op->data.tint.alpha) == 255) { - g_object_unref (G_OBJECT (bg_pixbuf)); - return; + gc = get_gc_for_primitive (widget, drawable, + op->data.tint.color_spec, + clip, 0); + + gdk_draw_rectangle (drawable, gc, + TRUE, + rx, ry, rwidth, rheight); + + g_object_unref (G_OBJECT (gc)); } + else + { + GdkPixbuf *pixbuf; - /* gradients always fill the entire target area */ - g_assert (gdk_pixbuf_get_width (bg_pixbuf) == width); - g_assert (gdk_pixbuf_get_height (bg_pixbuf) == height); - - composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - gdk_pixbuf_get_has_alpha (bg_pixbuf), 8, - gdk_pixbuf_get_width (bg_pixbuf), - gdk_pixbuf_get_height (bg_pixbuf)); + pixbuf = draw_op_as_pixbuf (op, widget, rwidth, rheight); - if (composited == NULL) - { - g_object_unref (G_OBJECT (bg_pixbuf)); - g_object_unref (G_OBJECT (fg_pixbuf)); - return; - } + render_pixbuf (drawable, clip, pixbuf, rx, ry); - fg_width = gdk_pixbuf_get_width (fg_pixbuf); - fg_height = gdk_pixbuf_get_height (fg_pixbuf); + g_object_unref (G_OBJECT (pixbuf)); + } + } + break; - /* If we wanted to be all cool we could deal with the - * offsets and try to composite only in the clip rectangle, - * but I just don't care enough to figure it out. - */ + case META_DRAW_GRADIENT: + { + int rx, ry, rwidth, rheight; + GdkPixbuf *pixbuf; - gdk_pixbuf_composite (fg_pixbuf, - composited, - x + (width - fg_width) * xalign, - y + (height - fg_height) * yalign, - gdk_pixbuf_get_width (fg_pixbuf), - gdk_pixbuf_get_height (fg_pixbuf), - 0.0, 0.0, /* offsets */ - 1.0, 1.0, /* scale */ - GDK_INTERP_BILINEAR, - 255 * alpha); + rx = parse_x_position_unchecked (op->data.gradient.x, &env); + ry = parse_y_position_unchecked (op->data.gradient.y, &env); + rwidth = parse_size_unchecked (op->data.gradient.width, &env); + rheight = parse_size_unchecked (op->data.gradient.height, &env); + + pixbuf = draw_op_as_pixbuf (op, widget, rwidth, rheight); - render_pixbuf (drawable, clip, composited, x, y); + render_pixbuf (drawable, clip, pixbuf, rx, ry); - g_object_unref (G_OBJECT (bg_pixbuf)); - g_object_unref (G_OBJECT (fg_pixbuf)); - g_object_unref (G_OBJECT (composited)); + g_object_unref (G_OBJECT (pixbuf)); } break; - - case META_TEXTURE_BLANK: - case META_TEXTURE_SHAPE_LIST: - case META_TEXTURE_COMPOSITE: - g_assert_not_reached (); - break; - } -} - -static void -draw_composite_fallback (const MetaTextureSpec *bg, - const MetaTextureSpec *fg, - double alpha, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - MetaTextureDrawMode mode, - double xalign, - double yalign, - int x, - int y, - int width, - int height) -{ - /* This one is tricky since the fg doesn't necessarily cover the - * entire x,y width, height rectangle, so we need to handle the fact - * that there may be existing stuff in the uncovered portions of the - * drawable that we need to composite over the top of. - * - * i.e. the "bg" we are compositing onto is equivalent to the image - * composited over the top of whatever is already in the drawable. - * - * To implement this we just draw the background to drawable, then - * render the foreground to a pixbuf, multiply its alpha channel by - * the composite alpha, then composite the foreground onto the - * drawable. - */ - - switch (fg->type) - { - case META_TEXTURE_SOLID: - case META_TEXTURE_GRADIENT: - case META_TEXTURE_IMAGE: + + case META_DRAW_IMAGE: { - GdkPixbuf *fg_pixbuf; - - meta_texture_spec_draw (bg, widget, drawable, clip, - mode, xalign, yalign, x, y, width, height); - - /* fg_pixbuf has its alpha multiplied, note */ - fg_pixbuf = meta_texture_spec_render (fg, widget, mode, - 255 * alpha, - width, height); + int rx, ry, rwidth, rheight; + GdkPixbuf *pixbuf; + + rx = parse_x_position_unchecked (op->data.image.x, &env); + ry = parse_y_position_unchecked (op->data.image.y, &env); + rwidth = parse_size_unchecked (op->data.image.width, &env); + rheight = parse_size_unchecked (op->data.image.height, &env); - if (fg_pixbuf == NULL) - return; + pixbuf = draw_op_as_pixbuf (op, widget, rwidth, rheight); - render_pixbuf_aligned (drawable, clip, fg_pixbuf, - xalign, yalign, - x, y, width, height); + env.object_width = gdk_pixbuf_get_width (pixbuf); + env.object_height = gdk_pixbuf_get_height (pixbuf); - g_object_unref (G_OBJECT (fg_pixbuf)); + render_pixbuf (drawable, clip, pixbuf, rx, ry); + + g_object_unref (G_OBJECT (pixbuf)); } break; + + case META_DRAW_GTK_ARROW: + { + int rx, ry, rwidth, rheight; - case META_TEXTURE_SHAPE_LIST: - case META_TEXTURE_BLANK: - case META_TEXTURE_COMPOSITE: - g_assert_not_reached (); + rx = parse_x_position_unchecked (op->data.gtk_arrow.x, &env); + ry = parse_y_position_unchecked (op->data.gtk_arrow.y, &env); + rwidth = parse_size_unchecked (op->data.gtk_arrow.width, &env); + rheight = parse_size_unchecked (op->data.gtk_arrow.height, &env); + + gtk_paint_arrow (widget->style, + drawable, + op->data.gtk_arrow.state, + op->data.gtk_arrow.shadow, + (GdkRectangle*) clip, + widget, + "metacity", + op->data.gtk_arrow.arrow, + op->data.gtk_arrow.filled, + rx, ry, rwidth, rheight); + } break; - } -} -void -meta_texture_spec_draw (const MetaTextureSpec *spec, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - MetaTextureDrawMode mode, - double xalign, - double yalign, - int x, - int y, - int width, - int height) -{ - g_return_if_fail (spec != NULL); - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (GDK_IS_DRAWABLE (drawable)); - g_return_if_fail (widget->style != NULL); - - switch (spec->type) - { - case META_TEXTURE_SOLID: + case META_DRAW_GTK_BOX: { - GdkColor color; - - g_return_if_fail (spec->data.solid.color_spec != NULL); + int rx, ry, rwidth, rheight; - meta_color_spec_render (spec->data.solid.color_spec, - widget, &color); + rx = parse_x_position_unchecked (op->data.gtk_box.x, &env); + ry = parse_y_position_unchecked (op->data.gtk_box.y, &env); + rwidth = parse_size_unchecked (op->data.gtk_box.width, &env); + rheight = parse_size_unchecked (op->data.gtk_box.height, &env); - draw_color_rectangle (widget, drawable, &color, clip, - x, y, width, height); + gtk_paint_box (widget->style, + drawable, + op->data.gtk_box.state, + op->data.gtk_box.shadow, + (GdkRectangle*) clip, + widget, + "metacity", + rx, ry, rwidth, rheight); } break; - case META_TEXTURE_GRADIENT: - case META_TEXTURE_IMAGE: + case META_DRAW_GTK_VLINE: { - GdkPixbuf *pixbuf; + int rx, ry1, ry2; - g_return_if_fail (spec->data.gradient.gradient_spec != NULL); + rx = parse_x_position_unchecked (op->data.gtk_vline.x, &env); + ry1 = parse_y_position_unchecked (op->data.gtk_vline.y1, &env); + ry2 = parse_y_position_unchecked (op->data.gtk_vline.y2, &env); - pixbuf = meta_texture_spec_render (spec, widget, mode, 255, - width, height); - - if (pixbuf == NULL) - return; - - render_pixbuf_aligned (drawable, clip, pixbuf, - xalign, yalign, - x, y, width, height); - - g_object_unref (G_OBJECT (pixbuf)); + gtk_paint_vline (widget->style, + drawable, + op->data.gtk_vline.state, + (GdkRectangle*) clip, + widget, + "metacity", + rx, ry1, ry2); } break; - - case META_TEXTURE_COMPOSITE: - { - MetaTextureSpec *fg; - MetaTextureSpec *bg; - - /* We could just render both things to a pixbuf then squish them - * but we are instead going to try to be all optimized for - * certain cases. - */ + } +} - fg = spec->data.composite.foreground; - bg = spec->data.composite.background; +MetaDrawOpList* +meta_draw_op_list_new (int n_preallocs) +{ + MetaDrawOpList *op_list; - g_return_if_fail (fg != NULL); - g_return_if_fail (bg != NULL); - g_return_if_fail (fg->type != META_TEXTURE_SHAPE_LIST); - g_return_if_fail (fg->type != META_TEXTURE_COMPOSITE); - g_return_if_fail (bg->type != META_TEXTURE_COMPOSITE); + g_return_val_if_fail (n_preallocs >= 0, NULL); + + op_list = g_new (MetaDrawOpList, 1); - if (fg->type == META_TEXTURE_BLANK) - { - meta_texture_spec_draw (bg, widget, drawable, clip, mode, - xalign, yalign, - x, y, width, height); - } - else - { - switch (bg->type) - { - case META_TEXTURE_SOLID: - draw_bg_solid_composite (bg, fg, spec->data.composite.alpha, - widget, drawable, clip, mode, - xalign, yalign, - x, y, width, height); - break; - - case META_TEXTURE_GRADIENT: - draw_bg_gradient_composite (bg, fg, spec->data.composite.alpha, - widget, drawable, clip, mode, - xalign, yalign, - x, y, width, height); - break; - - case META_TEXTURE_IMAGE: - case META_TEXTURE_BLANK: - case META_TEXTURE_SHAPE_LIST: - draw_composite_fallback (bg, fg, spec->data.composite.alpha, - widget, drawable, clip, mode, - xalign, yalign, - x, y, width, height); - break; - - case META_TEXTURE_COMPOSITE: - g_assert_not_reached (); - break; - } - } - } - break; + op_list->refcount = 1; + op_list->n_allocated = n_preallocs; + op_list->ops = g_new (MetaDrawOp*, op_list->n_allocated); + op_list->n_ops = 0; + + return op_list; +} + +void +meta_draw_op_list_ref (MetaDrawOpList *op_list) +{ + g_return_if_fail (op_list != NULL); + + op_list->refcount += 1; +} + +void +meta_draw_op_list_unref (MetaDrawOpList *op_list) +{ + g_return_if_fail (op_list != NULL); + g_return_if_fail (op_list->refcount > 0); + + op_list->refcount -= 1; + + if (op_list->refcount == 0) + { + int i; + + i = 0; + while (i < op_list->n_ops) + { + meta_draw_op_free (op_list->ops[i]); + ++i; + } + + g_free (op_list->ops); - case META_TEXTURE_BLANK: - /* do nothing */ - break; + g_free (op_list); + } +} - case META_TEXTURE_SHAPE_LIST: - { - int i; - i = 0; - while (i < spec->data.shape_list.n_specs) - { - meta_shape_spec_draw (spec->data.shape_list.shape_specs[i], - widget, drawable, clip, - x, y, width, height); - ++i; - } - } - break; +void +meta_draw_op_list_draw (const MetaDrawOpList *op_list, + GtkWidget *widget, + GdkDrawable *drawable, + const GdkRectangle *clip, + int x, + int y, + int width, + int height) +{ + int i; + + /* FIXME this can be optimized, potentially a lot, by + * compressing multiple ops when possible. For example, + * anything convertible to a pixbuf can be composited + * client-side, and putting a color tint over a pixbuf + * can be done without creating the solid-color pixbuf. + */ + + i = 0; + while (i < op_list->n_ops) + { + meta_draw_op_draw (op_list->ops[i], + widget, drawable, clip, + x, y, width, height); + ++i; } } +void +meta_draw_op_list_append (MetaDrawOpList *op_list, + MetaDrawOp *op) +{ + if (op_list->n_ops == op_list->n_allocated) + { + op_list->n_allocated *= 2; + op_list->ops = g_renew (MetaDrawOp*, op_list->ops, op_list->n_allocated); + } + + op_list->ops[op_list->n_ops] = op; + op_list->n_ops += 1; +} + MetaFrameStyle* meta_frame_style_new (MetaFrameStyle *parent) { @@ -2585,7 +2168,7 @@ meta_frame_style_ref (MetaFrameStyle *style) } static void -free_button_textures (MetaTextureSpec *textures[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST]) +free_button_ops (MetaDrawOpList *op_lists[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST]) { int i, j; @@ -2595,8 +2178,8 @@ free_button_textures (MetaTextureSpec *textures[META_BUTTON_TYPE_LAST][META_BUTT j = 0; while (j < META_BUTTON_STATE_LAST) { - if (textures[i][j]) - meta_texture_spec_free (textures[i][j]); + if (op_lists[i][j]) + meta_draw_op_list_unref (op_lists[i][j]); ++j; } @@ -2617,14 +2200,14 @@ meta_frame_style_unref (MetaFrameStyle *style) { int i; - free_button_textures (style->button_icons); - free_button_textures (style->button_backgrounds); + free_button_ops (style->button_icons); + free_button_ops (style->button_backgrounds); i = 0; while (i < META_FRAME_PIECE_LAST) { if (style->pieces[i]) - meta_texture_spec_free (style->pieces[i]); + meta_draw_op_list_unref (style->pieces[i]); ++i; } @@ -2745,12 +2328,9 @@ meta_frame_style_draw (MetaFrameStyle *style, { GdkRectangle rect; GdkRectangle combined_clip; - double xalign = 0.5; - double yalign = 0.5; - MetaTextureDrawMode mode = META_TEXTURE_DRAW_SCALED_BOTH; gboolean draw_title_text = FALSE; - switch (i) + switch ((MetaFramePiece) i) { case META_FRAME_PIECE_ENTIRE_BACKGROUND: rect.x = 0; @@ -2765,163 +2345,45 @@ meta_frame_style_draw (MetaFrameStyle *style, case META_FRAME_PIECE_LEFT_TITLEBAR_EDGE: rect = left_titlebar_edge; - mode = META_TEXTURE_DRAW_SCALED_VERTICALLY; - xalign = 0.0; break; case META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE: rect = right_titlebar_edge; - mode = META_TEXTURE_DRAW_SCALED_VERTICALLY; - xalign = 1.0; break; case META_FRAME_PIECE_TOP_TITLEBAR_EDGE: rect = top_titlebar_edge; - mode = META_TEXTURE_DRAW_SCALED_HORIZONTALLY; - yalign = 0.0; break; case META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE: rect = bottom_titlebar_edge; - mode = META_TEXTURE_DRAW_SCALED_HORIZONTALLY; - yalign = 1.0; - break; - - case META_FRAME_PIECE_LEFT_END_OF_TOP_TITLEBAR_EDGE: - rect = top_titlebar_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 0.0; - yalign = 0.0; - break; - - case META_FRAME_PIECE_RIGHT_END_OF_TOP_TITLEBAR_EDGE: - rect = top_titlebar_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 1.0; - yalign = 0.0; - break; - - case META_FRAME_PIECE_LEFT_END_OF_BOTTOM_TITLEBAR_EDGE: - rect = bottom_titlebar_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 0.0; - yalign = 1.0; - break; - - case META_FRAME_PIECE_RIGHT_END_OF_BOTTOM_TITLEBAR_EDGE: - rect = bottom_titlebar_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 1.0; - yalign = 1.0; - break; - - case META_FRAME_PIECE_TOP_END_OF_LEFT_TITLEBAR_EDGE: - rect = left_titlebar_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 0.0; - yalign = 0.0; break; - case META_FRAME_PIECE_BOTTOM_END_OF_LEFT_TITLEBAR_EDGE: - rect = left_titlebar_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 0.0; - yalign = 1.0; - break; - - case META_FRAME_PIECE_TOP_END_OF_RIGHT_TITLEBAR_EDGE: - rect = right_titlebar_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 1.0; - yalign = 0.0; + case META_FRAME_PIECE_TITLEBAR_MIDDLE: + rect.x = left_titlebar_edge.x + left_titlebar_edge.width; + rect.y = top_titlebar_edge.y + top_titlebar_edge.height; + rect.width = titlebar_rect.width - left_titlebar_edge.width - + right_titlebar_edge.width; + rect.height = titlebar_rect.height - top_titlebar_edge.height - bottom_titlebar_edge.height; break; - - case META_FRAME_PIECE_BOTTOM_END_OF_RIGHT_TITLEBAR_EDGE: - rect = right_titlebar_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 1.0; - yalign = 1.0; - break; - + case META_FRAME_PIECE_TITLE_BACKGROUND: rect = fgeom.title_rect; - break; - - case META_FRAME_PIECE_LEFT_TITLE_BACKGROUND: - rect = fgeom.title_rect; - mode = META_TEXTURE_DRAW_SCALED_VERTICALLY; - xalign = 0.0; - break; - - case META_FRAME_PIECE_RIGHT_TITLE_BACKGROUND: - rect = fgeom.title_rect; - mode = META_TEXTURE_DRAW_SCALED_VERTICALLY; - xalign = 1.0; - /* Trigger drawing the title itself, with the same - * clip as this texture - */ + /* Trigger drawing the title itself */ draw_title_text = TRUE; break; case META_FRAME_PIECE_LEFT_EDGE: rect = left_edge; - mode = META_TEXTURE_DRAW_SCALED_VERTICALLY; - xalign = 0.0; break; case META_FRAME_PIECE_RIGHT_EDGE: rect = right_edge; - mode = META_TEXTURE_DRAW_SCALED_VERTICALLY; - xalign = 1.0; break; case META_FRAME_PIECE_BOTTOM_EDGE: rect = bottom_edge; - mode = META_TEXTURE_DRAW_SCALED_HORIZONTALLY; - yalign = 1.0; - break; - - case META_FRAME_PIECE_TOP_END_OF_LEFT_EDGE: - rect = left_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 0.0; - yalign = 0.0; - break; - - case META_FRAME_PIECE_BOTTOM_END_OF_LEFT_EDGE: - rect = left_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 0.0; - yalign = 1.0; - break; - - case META_FRAME_PIECE_TOP_END_OF_RIGHT_EDGE: - rect = right_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 1.0; - yalign = 0.0; - break; - - case META_FRAME_PIECE_BOTTOM_END_OF_RIGHT_EDGE: - rect = right_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 1.0; - yalign = 1.0; - break; - - case META_FRAME_PIECE_LEFT_END_OF_BOTTOM_EDGE: - rect = bottom_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 0.0; - yalign = 1.0; - break; - - case META_FRAME_PIECE_RIGHT_END_OF_BOTTOM_EDGE: - rect = bottom_edge; - mode = META_TEXTURE_DRAW_UNSCALED; - xalign = 1.0; - yalign = 1.0; break; case META_FRAME_PIECE_OVERLAY: @@ -2930,6 +2392,10 @@ meta_frame_style_draw (MetaFrameStyle *style, rect.width = fgeom.width; rect.height = fgeom.height; break; + + case META_FRAME_PIECE_LAST: + g_assert_not_reached (); + break; } rect.x += x_offset; @@ -2944,23 +2410,22 @@ meta_frame_style_draw (MetaFrameStyle *style, if (combined_clip.width > 0 && combined_clip.height > 0) { - MetaTextureSpec *spec; + MetaDrawOpList *op_list; MetaFrameStyle *parent; parent = style; - spec = NULL; - while (parent && spec == NULL) + op_list = NULL; + while (parent && op_list == NULL) { - spec = style->pieces[i]; + op_list = style->pieces[i]; parent = style->parent; } - if (spec) - meta_texture_spec_draw (spec, + if (op_list) + meta_draw_op_list_draw (op_list, widget, drawable, &combined_clip, - mode, xalign, yalign, rect.x, rect.y, rect.width, rect.height); } @@ -3001,24 +2466,22 @@ meta_frame_style_draw (MetaFrameStyle *style, if (combined_clip.width > 0 && combined_clip.height > 0) { - MetaTextureSpec *spec; + MetaDrawOpList *op_list; MetaFrameStyle *parent; parent = style; - spec = NULL; - while (parent && spec == NULL) + op_list = NULL; + while (parent && op_list == NULL) { - spec = style->button_backgrounds[i][button_states[i]]; + op_list = style->button_backgrounds[i][button_states[i]]; parent = style->parent; } - if (spec) - meta_texture_spec_draw (spec, + if (op_list) + meta_draw_op_list_draw (op_list, widget, drawable, &combined_clip, - META_TEXTURE_DRAW_SCALED_BOTH, - 0.5, 0.5, rect.x, rect.y, rect.width, rect.height); } @@ -3046,24 +2509,22 @@ meta_frame_style_draw (MetaFrameStyle *style, if (combined_clip.width > 0 && combined_clip.height > 0) { - MetaTextureSpec *spec; + MetaDrawOpList *op_list; MetaFrameStyle *parent; parent = style; - spec = NULL; - while (parent && spec == NULL) + op_list = NULL; + while (parent && op_list == NULL) { - spec = style->button_icons[i][button_states[i]]; + op_list = style->button_icons[i][button_states[i]]; parent = style->parent; } - if (spec) - meta_texture_spec_draw (spec, + if (op_list) + meta_draw_op_list_draw (op_list, widget, drawable, &combined_clip, - META_TEXTURE_DRAW_SCALED_BOTH, - 0.5, 0.5, rect.x, rect.y, rect.width, rect.height); } @@ -3184,27 +2645,27 @@ meta_theme_free (MetaTheme *theme) g_free (theme); } -static MetaShapeSpec* -line_spec (MetaGtkColorComponent component, - const char *x1, - const char *y1, - const char *x2, - const char *y2) +static MetaDrawOp* +line_op (MetaGtkColorComponent component, + const char *x1, + const char *y1, + const char *x2, + const char *y2) { - MetaShapeSpec *shape; + MetaDrawOp *op; - shape = meta_shape_spec_new (META_SHAPE_LINE); - shape->data.line.color_spec = + op = meta_draw_op_new (META_DRAW_LINE); + op->data.line.color_spec = meta_color_spec_new_gtk (component, GTK_STATE_NORMAL); - shape->data.line.x1 = g_strdup (x1); - shape->data.line.x2 = g_strdup (x2); - shape->data.line.y1 = g_strdup (y1); - shape->data.line.y2 = g_strdup (y2); - shape->data.line.dash_on_length = 0; - shape->data.line.dash_off_length = 0; - shape->data.line.width = 0; - - return shape; + op->data.line.x1 = g_strdup (x1); + op->data.line.x2 = g_strdup (x2); + op->data.line.y1 = g_strdup (y1); + op->data.line.y2 = g_strdup (y2); + op->data.line.dash_on_length = 0; + op->data.line.dash_off_length = 0; + op->data.line.width = 0; + + return op; } #define DEFAULT_INNER_BUTTON_BORDER 3 @@ -3221,8 +2682,8 @@ meta_frame_style_get_test (void) DEFAULT_INNER_BUTTON_BORDER, DEFAULT_INNER_BUTTON_BORDER }; - MetaTextureSpec *texture; - MetaShapeSpec *shape; + MetaDrawOpList *op_list; + MetaDrawOp *op; MetaGradientSpec *gradient; if (style) @@ -3248,12 +2709,11 @@ meta_frame_style_get_test (void) style->layout->button_width = 17; style->layout->button_height = 17; - texture = meta_texture_spec_new (META_TEXTURE_GRADIENT); - style->pieces[META_FRAME_PIECE_ENTIRE_BACKGROUND] = texture; - + op_list = meta_draw_op_list_new (3); + + /* Gradient background */ + op = meta_draw_op_new (META_DRAW_GRADIENT); gradient = meta_gradient_spec_new (META_GRADIENT_VERTICAL); - texture->data.gradient.gradient_spec = gradient; - gradient->color_specs = g_slist_prepend (gradient->color_specs, meta_color_spec_new_gtk (META_GTK_COLOR_BG, @@ -3262,40 +2722,285 @@ meta_frame_style_get_test (void) g_slist_prepend (gradient->color_specs, meta_color_spec_new_gtk (META_GTK_COLOR_BG, GTK_STATE_SELECTED)); - - texture = meta_texture_spec_new (META_TEXTURE_SHAPE_LIST); - style->pieces[META_FRAME_PIECE_OVERLAY] = texture; - texture->data.shape_list.shape_specs = g_new (MetaShapeSpec*, 5); - texture->data.shape_list.n_specs = 5; - - shape = meta_shape_spec_new (META_SHAPE_RECTANGLE); - shape->data.rectangle.color_spec = + + op->data.gradient.gradient_spec = gradient; + op->data.gradient.alpha = 1.0; + + op->data.gradient.x = g_strdup ("0"); + op->data.gradient.y = g_strdup ("0"); + op->data.gradient.width = g_strdup ("width"); + op->data.gradient.height = g_strdup ("height"); + + meta_draw_op_list_append (op_list, op); + + /* Put orange tint on parts of window */ + op = meta_draw_op_new (META_DRAW_TINT); + op->data.tint.color_spec = meta_color_spec_new_from_string ("orange", NULL); + op->data.tint.alpha = 0.3; + op->data.gradient.x = g_strdup ("0"); + op->data.gradient.y = g_strdup ("0"); + op->data.gradient.width = g_strdup ("width / 2"); + op->data.gradient.height = g_strdup ("height / 2"); + + meta_draw_op_list_append (op_list, op); + + op = meta_draw_op_new (META_DRAW_TINT); + op->data.tint.color_spec = meta_color_spec_new_from_string ("orange", NULL); + op->data.tint.alpha = 0.3; + op->data.gradient.x = g_strdup ("width / 2 + width % 2"); + op->data.gradient.y = g_strdup ("height / 2 + height % 2"); + op->data.gradient.width = g_strdup ("width / 2"); + op->data.gradient.height = g_strdup ("height / 2"); + + meta_draw_op_list_append (op_list, op); + + style->pieces[META_FRAME_PIECE_ENTIRE_BACKGROUND] = op_list; + + op_list = meta_draw_op_list_new (5); + style->pieces[META_FRAME_PIECE_OVERLAY] = op_list; + + op = meta_draw_op_new (META_DRAW_RECTANGLE); + op->data.rectangle.color_spec = meta_color_spec_new_from_string ("#000000", NULL); - shape->data.rectangle.filled = FALSE; - shape->data.rectangle.x = g_strdup ("0"); - shape->data.rectangle.y = g_strdup ("0"); - shape->data.rectangle.width = g_strdup ("width - 1"); - shape->data.rectangle.height = g_strdup ("height - 1"); + op->data.rectangle.filled = FALSE; + op->data.rectangle.x = g_strdup ("0"); + op->data.rectangle.y = g_strdup ("0"); + op->data.rectangle.width = g_strdup ("width - 1"); + op->data.rectangle.height = g_strdup ("height - 1"); - texture->data.shape_list.shape_specs[0] = shape; + meta_draw_op_list_append (op_list, op); - texture->data.shape_list.shape_specs[1] = - line_spec (META_GTK_COLOR_LIGHT, - "1", "1", "1", "height - 2"); + meta_draw_op_list_append (op_list, + line_op (META_GTK_COLOR_LIGHT, + "1", "1", "1", "height - 2")); - texture->data.shape_list.shape_specs[2] = - line_spec (META_GTK_COLOR_LIGHT, - "1", "1", "width - 2", "1"); + meta_draw_op_list_append (op_list, + line_op (META_GTK_COLOR_LIGHT, + "1", "1", "width - 2", "1")); - texture->data.shape_list.shape_specs[3] = - line_spec (META_GTK_COLOR_DARK, - "width - 2", "1", "width - 2", "height - 2"); + meta_draw_op_list_append (op_list, + line_op (META_GTK_COLOR_DARK, + "width - 2", "1", "width - 2", "height - 2")); - texture->data.shape_list.shape_specs[4] = - line_spec (META_GTK_COLOR_DARK, - "1", "height - 2", "width - 2", "height - 2"); + meta_draw_op_list_append (op_list, + line_op (META_GTK_COLOR_DARK, + "1", "height - 2", "width - 2", "height - 2")); return style; } + + + + + + +#if 0 +/* These are some functions I'm saving to use in optimizing + * MetaDrawOpList, namely to pre-composite pixbufs on client side + * prior to rendering to the server + */ +static void +draw_bg_solid_composite (const MetaTextureSpec *bg, + const MetaTextureSpec *fg, + double alpha, + GtkWidget *widget, + GdkDrawable *drawable, + const GdkRectangle *clip, + MetaTextureDrawMode mode, + double xalign, + double yalign, + int x, + int y, + int width, + int height) +{ + GdkColor bg_color; + + g_assert (bg->type == META_TEXTURE_SOLID); + g_assert (fg->type != META_TEXTURE_COMPOSITE); + g_assert (fg->type != META_TEXTURE_SHAPE_LIST); + + meta_color_spec_render (bg->data.solid.color_spec, + widget, + &bg_color); + + switch (fg->type) + { + case META_TEXTURE_SOLID: + { + GdkColor fg_color; + + meta_color_spec_render (fg->data.solid.color_spec, + widget, + &fg_color); + + color_composite (&bg_color, &fg_color, + alpha, &fg_color); + + draw_color_rectangle (widget, drawable, &fg_color, clip, + x, y, width, height); + } + break; + + case META_TEXTURE_GRADIENT: + /* FIXME I think we could just composite all the colors in + * the gradient prior to generating the gradient? + */ + /* FALL THRU */ + case META_TEXTURE_IMAGE: + { + GdkPixbuf *pixbuf; + GdkPixbuf *composited; + + pixbuf = meta_texture_spec_render (fg, widget, mode, 255, + width, height); + + if (pixbuf == NULL) + return; + + composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + gdk_pixbuf_get_has_alpha (pixbuf), 8, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); + + if (composited == NULL) + { + g_object_unref (G_OBJECT (pixbuf)); + return; + } + + gdk_pixbuf_composite_color (pixbuf, + composited, + 0, 0, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf), + 0.0, 0.0, /* offsets */ + 1.0, 1.0, /* scale */ + GDK_INTERP_BILINEAR, + 255 * alpha, + 0, 0, /* check offsets */ + 0, /* check size */ + GDK_COLOR_RGB (bg_color), + GDK_COLOR_RGB (bg_color)); + + /* Need to draw background since pixbuf is not + * necessarily covering the whole thing + */ + draw_color_rectangle (widget, drawable, &bg_color, clip, + x, y, width, height); + + render_pixbuf_aligned (drawable, clip, composited, + xalign, yalign, + x, y, width, height); + + g_object_unref (G_OBJECT (pixbuf)); + g_object_unref (G_OBJECT (composited)); + } + break; + + case META_TEXTURE_BLANK: + case META_TEXTURE_COMPOSITE: + case META_TEXTURE_SHAPE_LIST: + g_assert_not_reached (); + break; + } +} + +static void +draw_bg_gradient_composite (const MetaTextureSpec *bg, + const MetaTextureSpec *fg, + double alpha, + GtkWidget *widget, + GdkDrawable *drawable, + const GdkRectangle *clip, + MetaTextureDrawMode mode, + double xalign, + double yalign, + int x, + int y, + int width, + int height) +{ + g_assert (bg->type == META_TEXTURE_GRADIENT); + g_assert (fg->type != META_TEXTURE_COMPOSITE); + g_assert (fg->type != META_TEXTURE_SHAPE_LIST); + + switch (fg->type) + { + case META_TEXTURE_SOLID: + case META_TEXTURE_GRADIENT: + case META_TEXTURE_IMAGE: + { + GdkPixbuf *bg_pixbuf; + GdkPixbuf *fg_pixbuf; + GdkPixbuf *composited; + int fg_width, fg_height; + + bg_pixbuf = meta_texture_spec_render (bg, widget, mode, 255, + width, height); + + if (bg_pixbuf == NULL) + return; + + fg_pixbuf = meta_texture_spec_render (fg, widget, mode, 255, + width, height); + + if (fg_pixbuf == NULL) + { + g_object_unref (G_OBJECT (bg_pixbuf)); + return; + } + + /* gradients always fill the entire target area */ + g_assert (gdk_pixbuf_get_width (bg_pixbuf) == width); + g_assert (gdk_pixbuf_get_height (bg_pixbuf) == height); + + composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + gdk_pixbuf_get_has_alpha (bg_pixbuf), 8, + gdk_pixbuf_get_width (bg_pixbuf), + gdk_pixbuf_get_height (bg_pixbuf)); + + if (composited == NULL) + { + g_object_unref (G_OBJECT (bg_pixbuf)); + g_object_unref (G_OBJECT (fg_pixbuf)); + return; + } + + fg_width = gdk_pixbuf_get_width (fg_pixbuf); + fg_height = gdk_pixbuf_get_height (fg_pixbuf); + + /* If we wanted to be all cool we could deal with the + * offsets and try to composite only in the clip rectangle, + * but I just don't care enough to figure it out. + */ + + gdk_pixbuf_composite (fg_pixbuf, + composited, + x + (width - fg_width) * xalign, + y + (height - fg_height) * yalign, + gdk_pixbuf_get_width (fg_pixbuf), + gdk_pixbuf_get_height (fg_pixbuf), + 0.0, 0.0, /* offsets */ + 1.0, 1.0, /* scale */ + GDK_INTERP_BILINEAR, + 255 * alpha); + + render_pixbuf (drawable, clip, composited, x, y); + + g_object_unref (G_OBJECT (bg_pixbuf)); + g_object_unref (G_OBJECT (fg_pixbuf)); + g_object_unref (G_OBJECT (composited)); + } + break; + + case META_TEXTURE_BLANK: + case META_TEXTURE_SHAPE_LIST: + case META_TEXTURE_COMPOSITE: + g_assert_not_reached (); + break; + } +} +#endif diff --git a/src/theme.h b/src/theme.h index 9379ba96..249cb558 100644 --- a/src/theme.h +++ b/src/theme.h @@ -28,21 +28,22 @@ typedef struct _MetaFrameStyle MetaFrameStyle; typedef struct _MetaFrameStyleSet MetaFrameStyleSet; -typedef struct _MetaTextureSpec MetaTextureSpec; +typedef struct _MetaDrawOp MetaDrawOp; +typedef struct _MetaDrawOpList MetaDrawOpList; typedef struct _MetaGradientSpec MetaGradientSpec; typedef struct _MetaColorSpec MetaColorSpec; -typedef struct _MetaShapeSpec MetaShapeSpec; typedef struct _MetaFrameLayout MetaFrameLayout; typedef struct _MetaFrameGeometry MetaFrameGeometry; typedef struct _MetaTheme MetaTheme; +typedef struct _MetaPositionExprEnv MetaPositionExprEnv; typedef enum { - META_TEXTURE_DRAW_UNSCALED, - META_TEXTURE_DRAW_SCALED_VERTICALLY, - META_TEXTURE_DRAW_SCALED_HORIZONTALLY, - META_TEXTURE_DRAW_SCALED_BOTH -} MetaTextureDrawMode; + META_SCALE_NONE, + META_SCALE_VERTICALLY, + META_SCALE_HORIZONTALLY, + META_SCALE_BOTH +} MetaScaleMode; /* Parameters used to calculate the geometry of the frame */ struct _MetaFrameLayout @@ -147,25 +148,33 @@ struct _MetaColorSpec } data; }; +struct _MetaGradientSpec +{ + MetaGradientType type; + GSList *color_specs; +}; + typedef enum { /* Basic drawing */ - META_SHAPE_LINE, - META_SHAPE_RECTANGLE, - META_SHAPE_ARC, - - /* Texture in a specific rectangle */ - META_SHAPE_TEXTURE, + META_DRAW_LINE, + META_DRAW_RECTANGLE, + META_DRAW_ARC, + + /* Texture thingies */ + META_DRAW_TINT, /* just a filled rectangle with alpha */ + META_DRAW_GRADIENT, + META_DRAW_IMAGE, /* GTK theme engine stuff */ - META_SHAPE_GTK_ARROW, - META_SHAPE_GTK_BOX, - META_SHAPE_GTK_VLINE -} MetaShapeType; + META_DRAW_GTK_ARROW, + META_DRAW_GTK_BOX, + META_DRAW_GTK_VLINE +} MetaDrawType; -struct _MetaShapeSpec +struct _MetaDrawOp { - MetaShapeType type; + MetaDrawType type; /* Positions are strings because they can be expressions */ union @@ -200,19 +209,36 @@ struct _MetaShapeSpec double start_angle; double extent_angle; } arc; + + struct { + MetaColorSpec *color_spec; + double alpha; + char *x; + char *y; + char *width; + char *height; + } tint; struct { - MetaTextureSpec *texture_spec; - MetaTextureDrawMode mode; - double xalign; - double yalign; + MetaGradientSpec *gradient_spec; + double alpha; char *x; char *y; char *width; char *height; - } texture; + } gradient; struct { + GdkPixbuf *pixbuf; + double alpha; + MetaScaleMode scale_mode; + char *x; + char *y; + char *width; + char *height; + } image; + + struct { GtkStateType state; GtkShadowType shadow; GtkArrowType arrow; @@ -242,50 +268,12 @@ struct _MetaShapeSpec } data; }; -struct _MetaGradientSpec -{ - MetaGradientType type; - GSList *color_specs; -}; - -typedef enum +struct _MetaDrawOpList { - META_TEXTURE_SOLID, - META_TEXTURE_GRADIENT, - META_TEXTURE_IMAGE, - META_TEXTURE_COMPOSITE, - META_TEXTURE_BLANK, - META_TEXTURE_SHAPE_LIST -} MetaTextureType; - -struct _MetaTextureSpec -{ - MetaTextureType type; - - union - { - struct { - MetaColorSpec *color_spec; - } solid; - struct { - MetaGradientSpec *gradient_spec; - } gradient; - struct { - GdkPixbuf *pixbuf; - } image; - struct { - MetaTextureSpec *background; - MetaTextureSpec *foreground; - double alpha; - } composite; - struct { - int dummy; - } blank; - struct { - MetaShapeSpec **shape_specs; - int n_specs; - } shape_list; - } data; + int refcount; + MetaDrawOp **ops; + int n_ops; + int n_allocated; }; typedef enum @@ -320,58 +308,30 @@ typedef enum * */ - /* place over entire frame, scaled both */ + /* entire frame */ META_FRAME_PIECE_ENTIRE_BACKGROUND, - /* place over entire titlebar background, scaled both */ + /* entire titlebar background */ META_FRAME_PIECE_TITLEBAR_BACKGROUND, - /* place on left end of titlebar, scaled vert */ + /* portion of the titlebar background inside the titlebar + * background edges + */ + META_FRAME_PIECE_TITLEBAR_MIDDLE, + /* left end of titlebar */ META_FRAME_PIECE_LEFT_TITLEBAR_EDGE, - /* place on right end of titlebar, scaled vert */ + /* right end of titlebar */ META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE, - /* place on top edge of titlebar, scaled horiz */ + /* top edge of titlebar */ META_FRAME_PIECE_TOP_TITLEBAR_EDGE, - /* place on bottom edge of titlebar, scaled horiz */ + /* bottom edge of titlebar */ META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE, - /* place on left end of top edge of titlebar, unscaled */ - META_FRAME_PIECE_LEFT_END_OF_TOP_TITLEBAR_EDGE, - /* place on right end of top edge of titlebar, unscaled */ - META_FRAME_PIECE_RIGHT_END_OF_TOP_TITLEBAR_EDGE, - /* place on left end of bottom edge of titlebar, unscaled */ - META_FRAME_PIECE_LEFT_END_OF_BOTTOM_TITLEBAR_EDGE, - /* place on right end of bottom edge of titlebar, unscaled */ - META_FRAME_PIECE_RIGHT_END_OF_BOTTOM_TITLEBAR_EDGE, - /* place on top end of left titlebar edge, unscaled */ - META_FRAME_PIECE_TOP_END_OF_LEFT_TITLEBAR_EDGE, - /* place on bottom end of left titlebar edge, unscaled */ - META_FRAME_PIECE_BOTTOM_END_OF_LEFT_TITLEBAR_EDGE, - /* place on top end of right titlebar edge, unscaled */ - META_FRAME_PIECE_TOP_END_OF_RIGHT_TITLEBAR_EDGE, - /* place on bottom end of right titlebar edge, unscaled */ - META_FRAME_PIECE_BOTTOM_END_OF_RIGHT_TITLEBAR_EDGE, - /* render over title background (text area), scaled both */ + /* render over title background (text area) */ META_FRAME_PIECE_TITLE_BACKGROUND, - /* render over left side of TITLE_BACKGROUND, scaled vert */ - META_FRAME_PIECE_LEFT_TITLE_BACKGROUND, - /* render over right side of TITLE_BACKGROUND, scaled vert */ - META_FRAME_PIECE_RIGHT_TITLE_BACKGROUND, - /* place on left edge of the frame, scaled vert */ + /* left edge of the frame */ META_FRAME_PIECE_LEFT_EDGE, - /* place on right edge of the frame, scaled vert */ + /* right edge of the frame */ META_FRAME_PIECE_RIGHT_EDGE, - /* place on bottom edge of the frame, scaled horiz */ + /* bottom edge of the frame */ META_FRAME_PIECE_BOTTOM_EDGE, - /* place on top end of left edge of the frame, unscaled */ - META_FRAME_PIECE_TOP_END_OF_LEFT_EDGE, - /* place on bottom end of left edge of the frame, unscaled */ - META_FRAME_PIECE_BOTTOM_END_OF_LEFT_EDGE, - /* place on top end of right edge of the frame, unscaled */ - META_FRAME_PIECE_TOP_END_OF_RIGHT_EDGE, - /* place on bottom end of right edge of the frame, unscaled */ - META_FRAME_PIECE_BOTTOM_END_OF_RIGHT_EDGE, - /* place on left end of bottom edge of the frame, unscaled */ - META_FRAME_PIECE_LEFT_END_OF_BOTTOM_EDGE, - /* place on right end of bottom edge of the frame, unscaled */ - META_FRAME_PIECE_RIGHT_END_OF_BOTTOM_EDGE, /* place over entire frame, after drawing everything else */ META_FRAME_PIECE_OVERLAY, /* Used to get size of the enum */ @@ -382,9 +342,9 @@ struct _MetaFrameStyle { int refcount; MetaFrameStyle *parent; - MetaTextureSpec *button_icons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST]; - MetaTextureSpec *button_backgrounds[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST]; - MetaTextureSpec *pieces[META_FRAME_PIECE_LAST]; + MetaDrawOpList *button_icons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST]; + MetaDrawOpList *button_backgrounds[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST]; + MetaDrawOpList *pieces[META_FRAME_PIECE_LAST]; MetaFrameLayout *layout; }; @@ -449,6 +409,28 @@ struct _MetaTheme MetaFrameStyleSet *style_sets_by_type[META_FRAME_TYPE_LAST]; }; +#define META_POSITION_EXPR_ERROR (g_quark_from_static_string ("meta-position-expr-error")) +typedef enum +{ + META_POSITION_EXPR_ERROR_BAD_CHARACTER, + META_POSITION_EXPR_ERROR_BAD_PARENS, + META_POSITION_EXPR_ERROR_UNKNOWN_VARIABLE, + META_POSITION_EXPR_ERROR_DIVIDE_BY_ZERO, + META_POSITION_EXPR_ERROR_MOD_ON_FLOAT, + META_POSITION_EXPR_ERROR_FAILED +} MetaPositionExprError; + +struct _MetaPositionExprEnv +{ + int x; + int y; + int width; + int height; + /* size of an image or whatever */ + int object_width; + int object_height; +}; + MetaFrameLayout* meta_frame_layout_new (void); void meta_frame_layout_free (MetaFrameLayout *layout); void meta_frame_layout_get_borders (const MetaFrameLayout *layout, @@ -467,31 +449,15 @@ void meta_frame_layout_calc_geometry (const MetaFrameLayout *layout, int client_height, MetaFrameGeometry *fgeom); -#define META_POSITION_EXPR_ERROR (g_quark_from_static_string ("meta-position-expr-error")) -typedef enum -{ - META_POSITION_EXPR_ERROR_BAD_CHARACTER, - META_POSITION_EXPR_ERROR_BAD_PARENS, - META_POSITION_EXPR_ERROR_UNKNOWN_VARIABLE, - META_POSITION_EXPR_ERROR_DIVIDE_BY_ZERO, - META_POSITION_EXPR_ERROR_MOD_ON_FLOAT, - META_POSITION_EXPR_ERROR_FAILED -} MetaPositionExprError; - -gboolean meta_parse_position_expression (const char *expr, - int x, - int y, - int width, - int height, - int *x_return, - int *y_return, - GError **err); -gboolean meta_parse_size_expression (const char *expr, - int width, - int height, - int *val_return, - GError **err); - +gboolean meta_parse_position_expression (const char *expr, + const MetaPositionExprEnv *env, + int *x_return, + int *y_return, + GError **err); +gboolean meta_parse_size_expression (const char *expr, + const MetaPositionExprEnv *env, + int *val_return, + GError **err); MetaColorSpec* meta_color_spec_new (MetaColorSpecType type); MetaColorSpec* meta_color_spec_new_from_string (const char *str, @@ -504,22 +470,32 @@ void meta_color_spec_render (MetaColorSpec *spec, GdkColor *color); -MetaShapeSpec* meta_shape_spec_new (MetaShapeType type); -void meta_shape_spec_free (MetaShapeSpec *spec); -void meta_shape_spec_draw (const MetaShapeSpec *spec, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - /* logical region being drawn, - * shape coords are offset by - * x,y and w/h variables are - * available in shape coord - * expressions. - */ - int x, - int y, - int width, - int height); +MetaDrawOp* meta_draw_op_new (MetaDrawType type); +void meta_draw_op_free (MetaDrawOp *op); +void meta_draw_op_draw (const MetaDrawOp *op, + GtkWidget *widget, + GdkDrawable *drawable, + const GdkRectangle *clip, + /* logical region being drawn */ + int x, + int y, + int width, + int height); + + +MetaDrawOpList* meta_draw_op_list_new (int n_preallocs); +void meta_draw_op_list_ref (MetaDrawOpList *op_list); +void meta_draw_op_list_unref (MetaDrawOpList *op_list); +void meta_draw_op_list_draw (const MetaDrawOpList *op_list, + GtkWidget *widget, + GdkDrawable *drawable, + const GdkRectangle *clip, + int x, + int y, + int width, + int height); +void meta_draw_op_list_append (MetaDrawOpList *op_list, + MetaDrawOp *op); MetaGradientSpec* meta_gradient_spec_new (MetaGradientType type); void meta_gradient_spec_free (MetaGradientSpec *desc); @@ -528,26 +504,6 @@ GdkPixbuf* meta_gradient_spec_render (const MetaGradientSpec *desc, int width, int height); -MetaTextureSpec* meta_texture_spec_new (MetaTextureType type); -void meta_texture_spec_free (MetaTextureSpec *desc); -void meta_texture_spec_draw (const MetaTextureSpec *desc, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - MetaTextureDrawMode mode, - /* How to align a texture - * smaller than the given area - */ - double xalign, - double yalign, - /* logical region being drawn, - * scale to this area if in SCALED - * mode - */ - int x, - int y, - int width, - int height); MetaFrameStyle* meta_frame_style_new (MetaFrameStyle *parent); void meta_frame_style_ref (MetaFrameStyle *style); |