implement wacky "tile" draw op to lose some of the PNG files in Gorilla

2002-02-09  Havoc Pennington  <hp@pobox.com>

	* src/theme.c (meta_draw_op_draw_with_env): implement wacky "tile"
	draw op to lose some of the PNG files in Gorilla theme

	* src/theme-parser.c: parse the tile primitive
This commit is contained in:
Havoc Pennington 2002-02-10 01:10:33 +00:00 committed by Havoc Pennington
parent 245c9c2d7e
commit 2bad2844f5
5 changed files with 240 additions and 4 deletions

View File

@ -1,3 +1,10 @@
2002-02-09 Havoc Pennington <hp@pobox.com>
* src/theme.c (meta_draw_op_draw_with_env): implement wacky "tile"
draw op to lose some of the PNG files in Gorilla theme
* src/theme-parser.c: parse the tile primitive
2002-02-09 Havoc Pennington <hp@pobox.com>
* src/window.c (update_icon): port to icon cache

View File

@ -57,6 +57,7 @@ typedef enum
STATE_ICON,
STATE_TITLE,
STATE_INCLUDE, /* include another draw op list */
STATE_TILE, /* tile another draw op list */
/* sub-parts of gradient */
STATE_COLOR,
/* frame style */
@ -2637,7 +2638,7 @@ parse_draw_op_element (GMarkupParseContext *context,
if (name == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
_("No \"name\" attribute on element <%s>"), element_name);
_("No \"%s\" attribute on element <%s>"), "name", element_name);
return;
}
@ -2697,6 +2698,130 @@ parse_draw_op_element (GMarkupParseContext *context,
push_state (info, STATE_INCLUDE);
}
else if (ELEMENT_IS ("tile"))
{
MetaDrawOp *op;
const char *name;
const char *x;
const char *y;
const char *width;
const char *height;
const char *tile_xoffset;
const char *tile_yoffset;
const char *tile_width;
const char *tile_height;
MetaDrawOpList *op_list;
if (!locate_attributes (context, element_name, attribute_names, attribute_values,
error,
"x", &x, "y", &y,
"width", &width, "height", &height,
"name", &name,
"tile_xoffset", &tile_xoffset,
"tile_yoffset", &tile_yoffset,
"tile_width", &tile_width,
"tile_height", &tile_height,
NULL))
return;
if (name == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
_("No \"%s\" attribute on element <%s>"), "name", element_name);
return;
}
if (tile_width == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
_("No \"%s\" attribute on element <%s>"), "tile_width", element_name);
return;
}
if (tile_height == NULL)
{
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
_("No \"%s\" attribute on element <%s>"), "tile_height", element_name);
return;
}
/* These default to 0 */
if (tile_xoffset && !check_expression (tile_xoffset, FALSE, info->theme, context, error))
return;
if (tile_yoffset && !check_expression (tile_xoffset, FALSE, info->theme, context, error))
return;
/* x/y/width/height default to 0,0,width,height - should
* probably do this for all the draw ops
*/
if (x && !check_expression (x, FALSE, info->theme, context, error))
return;
if (y && !check_expression (y, FALSE, info->theme, context, error))
return;
if (width && !check_expression (width, FALSE, info->theme, context, error))
return;
if (height && !check_expression (height, FALSE, info->theme, context, error))
return;
if (!check_expression (tile_width, FALSE, info->theme, context, error))
return;
if (!check_expression (tile_height, FALSE, info->theme, context, error))
return;
op_list = meta_theme_lookup_draw_op_list (info->theme,
name);
if (op_list == NULL)
{
set_error (error, context, G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("No <draw_ops> called \"%s\" has been defined"),
name);
return;
}
g_assert (info->op_list);
if (op_list == info->op_list ||
meta_draw_op_list_contains (op_list, info->op_list))
{
set_error (error, context, G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("Including draw_ops \"%s\" here would create a circular reference"),
name);
return;
}
op = meta_draw_op_new (META_DRAW_TILE);
meta_draw_op_list_ref (op_list);
op->data.tile.op_list = op_list;
op->data.tile.x = x ? optimize_expression (info->theme, x) :
g_strdup ("0");
op->data.tile.y = y ? optimize_expression (info->theme, y) :
g_strdup ("0");
op->data.tile.width = width ? optimize_expression (info->theme, width) :
g_strdup ("width");
op->data.tile.height = height ? optimize_expression (info->theme, height) :
g_strdup ("height");
op->data.tile.tile_xoffset = tile_xoffset ?
optimize_expression (info->theme, tile_xoffset) :
g_strdup ("0");
op->data.tile.tile_yoffset = tile_yoffset ?
optimize_expression (info->theme, tile_yoffset) :
g_strdup ("0");
op->data.tile.tile_width = optimize_expression (info->theme, tile_width);
op->data.tile.tile_height = optimize_expression (info->theme, tile_height);
meta_draw_op_list_append (info->op_list, op);
push_state (info, STATE_TILE);
}
else
{
set_error (error, context,
@ -3292,6 +3417,7 @@ start_element_handler (GMarkupParseContext *context,
case STATE_ICON:
case STATE_TITLE:
case STATE_INCLUDE:
case STATE_TILE:
set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
_("Element <%s> is not allowed inside a draw operation element"),
element_name);
@ -3525,6 +3651,10 @@ end_element_handler (GMarkupParseContext *context,
pop_state (info);
g_assert (peek_state (info) == STATE_DRAW_OPS);
break;
case STATE_TILE:
pop_state (info);
g_assert (peek_state (info) == STATE_DRAW_OPS);
break;
case STATE_COLOR:
pop_state (info);
g_assert (peek_state (info) == STATE_GRADIENT);
@ -3780,6 +3910,9 @@ text_handler (GMarkupParseContext *context,
case STATE_INCLUDE:
NO_TEXT ("include");
break;
case STATE_TILE:
NO_TEXT ("tile");
break;
case STATE_COLOR:
NO_TEXT ("color");
break;

View File

@ -2285,6 +2285,9 @@ meta_draw_op_new (MetaDrawType type)
case META_DRAW_OP_LIST:
size += sizeof (dummy.data.op_list);
break;
case META_DRAW_TILE:
size += sizeof (dummy.data.tile);
break;
}
op = g_malloc0 (size);
@ -2400,6 +2403,7 @@ meta_draw_op_free (MetaDrawOp *op)
g_free (op->data.title.x);
g_free (op->data.title.y);
break;
case META_DRAW_OP_LIST:
if (op->data.op_list.op_list)
meta_draw_op_list_unref (op->data.op_list.op_list);
@ -2408,6 +2412,19 @@ meta_draw_op_free (MetaDrawOp *op)
g_free (op->data.op_list.width);
g_free (op->data.op_list.height);
break;
case META_DRAW_TILE:
if (op->data.tile.op_list)
meta_draw_op_list_unref (op->data.tile.op_list);
g_free (op->data.tile.x);
g_free (op->data.tile.y);
g_free (op->data.tile.width);
g_free (op->data.tile.height);
g_free (op->data.tile.tile_xoffset);
g_free (op->data.tile.tile_yoffset);
g_free (op->data.tile.tile_width);
g_free (op->data.tile.tile_height);
break;
}
g_free (op);
@ -2720,7 +2737,10 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
break;
case META_DRAW_OP_LIST:
break;
break;
case META_DRAW_TILE:
break;
}
return pixbuf;
@ -3052,6 +3072,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
g_object_unref (G_OBJECT (gc));
}
break;
case META_DRAW_OP_LIST:
{
int rx, ry, rwidth, rheight;
@ -3066,6 +3087,55 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
rx, ry, rwidth, rheight);
}
break;
case META_DRAW_TILE:
{
int rx, ry, rwidth, rheight;
int tile_xoffset, tile_yoffset, tile_width, tile_height;
GdkRectangle new_clip;
int tile_x, tile_y;
rx = parse_x_position_unchecked (op->data.tile.x, env);
ry = parse_y_position_unchecked (op->data.tile.y, env);
rwidth = parse_size_unchecked (op->data.tile.width, env);
rheight = parse_size_unchecked (op->data.tile.height, env);
new_clip.x = rx;
new_clip.y = ry;
new_clip.width = rwidth;
new_clip.height = rheight;
if (clip == NULL || gdk_rectangle_intersect ((GdkRectangle*)clip, &new_clip,
&new_clip))
{
tile_xoffset = parse_x_position_unchecked (op->data.tile.tile_xoffset, env);
tile_yoffset = parse_y_position_unchecked (op->data.tile.tile_yoffset, env);
/* tile offset should not include x/y */
tile_xoffset -= x;
tile_yoffset -= y;
tile_width = parse_size_unchecked (op->data.tile.tile_width, env);
tile_height = parse_size_unchecked (op->data.tile.tile_height, env);
tile_x = rx - tile_xoffset;
while (tile_x < (rx + rwidth))
{
tile_y = ry - tile_yoffset;
while (tile_y < (ry + rheight))
{
meta_draw_op_list_draw (op->data.tile.op_list,
widget, drawable, &new_clip, info,
tile_x, tile_y, tile_width, tile_height);
tile_y += tile_height;
}
tile_x += tile_width;
}
}
}
break;
}
}
@ -3260,6 +3330,15 @@ meta_draw_op_list_contains (MetaDrawOpList *op_list,
child))
return TRUE;
}
else if (op_list->ops[i]->type == META_DRAW_TILE)
{
if (op_list->ops[i]->data.tile.op_list == child)
return TRUE;
if (meta_draw_op_list_contains (op_list->ops[i]->data.tile.op_list,
child))
return TRUE;
}
++i;
}

View File

@ -192,7 +192,9 @@ typedef enum
/* App's window title */
META_DRAW_TITLE,
/* a draw op list */
META_DRAW_OP_LIST
META_DRAW_OP_LIST,
/* tiled draw op list */
META_DRAW_TILE
} MetaDrawType;
struct _MetaDrawOp
@ -318,6 +320,18 @@ struct _MetaDrawOp
char *width;
char *height;
} op_list;
struct {
MetaDrawOpList *op_list;
char *x;
char *y;
char *width;
char *height;
char *tile_xoffset;
char *tile_yoffset;
char *tile_width;
char *tile_height;
} tile;
} data;
};

View File

@ -114,8 +114,11 @@ Themes are in a simple XML-subset format.
x="10" y="30" width="width / 3" height="height / 4"/>
<!-- window's title -->
<title color="gtk:text[NORMAL]" x="20" y="30"/>
<!-- include another draw ops list -->
<!-- include another draw ops list; has optional x/y/width/height attrs -->
<include name="some_other_draw_ops"/>
<!-- tile another draw ops list; has optional
x/y/width/height/tile_xoffset/tile_yoffset -->
<tile name="some_other_draw_ops" tile_width="10" tile_height="10"/>
</draw_ops>
<frame_style name="normal" geometry="normal">