summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2006-05-29 13:44:13 +0000
committerBenjamin Otte <otte@gnome.org>2006-05-29 13:44:13 +0000
commitb1fe36389ac5f1fc4b114cb657a24ef13fa5cc05 (patch)
tree17cf07d1001757ac09a6aef946a4ed5327541553
parent12b4174f8ef17153c7092ed7ef7ceb70b49a8e79 (diff)
* libgame/game-graphic.c: (game_graphic_copy),
(game_graphic_do_create_cache), (game_graphic_class_init), (game_graphic_draw_area_no_cache), (game_graphic_draw_area), (game_graphic_get_cache), (game_cairo_pattern_matches): * libgame/game-graphic.h: update caching mechanism to use a vfunc clean up the API used for caching * libgame/game-colored.c: (game_colored_draw): update function name * libgame/game-board.c: (game_board_class_init), (game_board_init): * libgame/game-viewport.c: (game_viewport_class_init), (game_viewport_init): * games/pacman/pacman-graphic.c: (pacman_graphic_draw), (pacman_graphic_create_cache), (pacman_graphic_set_property), (pacman_graphic_class_init): use new method of saying "no cache for me" * libgame/game-animation.c: (game_animation_add_image), (game_animation_dispose), (game_animation_create_cache), (game_animation_class_init): implement caching
-rw-r--r--ChangeLog23
-rw-r--r--games/pacman/pacman-graphic.c14
-rw-r--r--libgame/game-animation.c28
-rw-r--r--libgame/game-board.c4
-rw-r--r--libgame/game-colored.c2
-rw-r--r--libgame/game-graphic.c164
-rw-r--r--libgame/game-graphic.h11
-rw-r--r--libgame/game-viewport.c4
8 files changed, 174 insertions, 76 deletions
diff --git a/ChangeLog b/ChangeLog
index 82ee49d..6d3930f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2006-05-29 Benjamin Otte <in7y118@public.uni-hamburg.de>
+
+ * libgame/game-graphic.c: (game_graphic_copy),
+ (game_graphic_do_create_cache), (game_graphic_class_init),
+ (game_graphic_draw_area_no_cache), (game_graphic_draw_area),
+ (game_graphic_get_cache), (game_cairo_pattern_matches):
+ * libgame/game-graphic.h:
+ update caching mechanism to use a vfunc
+ clean up the API used for caching
+ * libgame/game-colored.c: (game_colored_draw):
+ update function name
+ * libgame/game-board.c: (game_board_class_init), (game_board_init):
+ * libgame/game-viewport.c: (game_viewport_class_init),
+ (game_viewport_init):
+ * games/pacman/pacman-graphic.c: (pacman_graphic_draw),
+ (pacman_graphic_create_cache), (pacman_graphic_set_property),
+ (pacman_graphic_class_init):
+ use new method of saying "no cache for me"
+ * libgame/game-animation.c: (game_animation_add_image),
+ (game_animation_dispose), (game_animation_create_cache),
+ (game_animation_class_init):
+ implement caching
+
2006-05-28 Benjamin Otte <in7y118@public.uni-hamburg.de>
* libgame/game-geom-basics.c: (game_point_distance):
diff --git a/games/pacman/pacman-graphic.c b/games/pacman/pacman-graphic.c
index 6c97c62..d5221a1 100644
--- a/games/pacman/pacman-graphic.c
+++ b/games/pacman/pacman-graphic.c
@@ -69,12 +69,19 @@ pacman_graphic_draw (GameGraphic *graphic, cairo_t *cr, const GameRectangle *are
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_set_line_width (cr, 0.02);
cairo_stroke (cr);
-#if 1
/* eye */
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
cairo_arc (cr, eye_x, eye_y, 0.05, 0.0, 2 * GAME_PI);
cairo_fill (cr);
-#endif
+}
+
+static cairo_pattern_t *
+pacman_graphic_create_cache (GameGraphic *graphic, cairo_t *cr)
+{
+ if (PACMAN_GRAPHIC (graphic)->animate)
+ return NULL;
+
+ return GAME_GRAPHIC_CLASS (parent_class)->create_cache (graphic, cr);
}
static void
@@ -114,8 +121,6 @@ pacman_graphic_set_property (GObject *object, guint param_id,
break;
case PROP_ANIMATE:
graphic->animate = g_value_get_boolean (value);
- GAME_GRAPHIC (graphic)->cache_policy = graphic->animate ?
- GAME_GRAPHIC_CACHE_NEVER : GAME_GRAPHIC_CACHE_ALWAYS;
break;
case PROP_COLOR:
graphic->color = *((GameColor *) g_value_get_boxed (value));
@@ -165,6 +170,7 @@ pacman_graphic_class_init (gpointer g_class, gpointer class_data)
gameobject_class->tick_func = pacman_graphic_tick;
graphic_class->draw = pacman_graphic_draw;
+ graphic_class->create_cache = pacman_graphic_create_cache;
}
static void
diff --git a/libgame/game-animation.c b/libgame/game-animation.c
index f8b4379..d3198e7 100644
--- a/libgame/game-animation.c
+++ b/libgame/game-animation.c
@@ -32,6 +32,7 @@ enum {
typedef struct {
cairo_surface_t * surface;
+ cairo_pattern_t * cache;
guint duration;
} GameAnimationFrame;
static GameGraphicClass *parent_class = NULL;
@@ -84,7 +85,7 @@ game_animation_start (GameAnimation *anim)
static void
game_animation_add_image (GameAnimation *anim, cairo_surface_t *surface, guint duration)
{
- GameAnimationFrame frame = { surface, duration };
+ GameAnimationFrame frame = { surface, NULL, duration };
g_array_append_val (anim->frames, frame);
if (anim->frames->len == 1)
@@ -119,6 +120,8 @@ game_animation_dispose (GObject *object)
for (i = 0; i < anim->frames->len; i++) {
frame = &g_array_index(anim->frames, GameAnimationFrame, i);
cairo_surface_destroy (frame->surface);
+ if (frame->cache)
+ cairo_pattern_destroy (frame->cache);
}
g_array_free (anim->frames, TRUE);
anim->frames = NULL;
@@ -166,11 +169,32 @@ game_animation_tick (GameObject *object)
game_animation_update_image (anim, frame->surface);
}
+static cairo_pattern_t *
+game_animation_create_cache (GameGraphic *graphic, cairo_t *cr)
+{
+ GameAnimationFrame *frame;
+ GameAnimation *anim = GAME_ANIMATION (graphic);
+
+ frame = &g_array_index(anim->frames, GameAnimationFrame, anim->current);
+
+ if (frame->cache) {
+ if (game_cairo_pattern_matches (cr, frame->cache)) {
+ cairo_pattern_reference (frame->cache);
+ return frame->cache;
+ }
+ cairo_pattern_destroy (frame->cache);
+ //frame->cache = NULL;
+ }
+ frame->cache = GAME_GRAPHIC_CLASS (parent_class)->create_cache (graphic, cr);
+ return frame->cache;
+}
+
static void
game_animation_class_init (gpointer g_class, gpointer class_data)
{
GObjectClass *object_class = G_OBJECT_CLASS (g_class);
GameObjectClass *gameobject_class = GAME_OBJECT_CLASS (g_class);
+ GameGraphicClass *graphic_class = GAME_GRAPHIC_CLASS (g_class);
parent_class = g_type_class_peek_parent (g_class);
@@ -185,6 +209,8 @@ game_animation_class_init (gpointer g_class, gpointer class_data)
gameobject_class->copy = game_animation_copy;
gameobject_class->tick_func = game_animation_tick;
+
+ graphic_class->create_cache = game_animation_create_cache;
}
static void
diff --git a/libgame/game-board.c b/libgame/game-board.c
index b74d2ee..08bfc9b 100644
--- a/libgame/game-board.c
+++ b/libgame/game-board.c
@@ -255,16 +255,14 @@ game_board_class_init (gpointer g_class, gpointer class_data)
gameobject_class->game_set = game_board_game_set;
graphic_class->draw = game_board_draw;
+ graphic_class->create_cache = NULL;
}
static void
game_board_init (GTypeInstance *instance, gpointer g_class)
{
- GameGraphic *graphic = GAME_GRAPHIC (instance);
GameBoard *board = GAME_BOARD (instance);
- graphic->cache_policy = GAME_GRAPHIC_CACHE_NEVER;
-
board->sprite_type = GAME_TYPE_SPRITE;
}
diff --git a/libgame/game-colored.c b/libgame/game-colored.c
index 975a7ab..db706d5 100644
--- a/libgame/game-colored.c
+++ b/libgame/game-colored.c
@@ -133,7 +133,7 @@ game_colored_draw (GameGraphic *graphic, cairo_t *cr, const GameRectangle *area)
game_graphic_draw_area (colored->base, cr, area);
game_color_as_cairo_source (cr, &colored->color);
if (colored->mask) {
- cairo_pattern_t *mask = game_graphic_create_cache (colored->mask, cr);
+ cairo_pattern_t *mask = game_graphic_get_cache (colored->mask, cr);
if (mask) {
cairo_mask (cr, mask);
} else {
diff --git a/libgame/game-graphic.c b/libgame/game-graphic.c
index 101c367..7363eae 100644
--- a/libgame/game-graphic.c
+++ b/libgame/game-graphic.c
@@ -115,7 +115,6 @@ game_graphic_copy (GameObject *odest, GameObject *osrc)
GameGraphic *src = GAME_GRAPHIC (osrc);
dest->rect = src->rect;
- dest->cache_policy = src->cache_policy;
dest->cache = src->cache;
if (dest->cache)
cairo_pattern_reference (dest->cache);
@@ -123,11 +122,69 @@ game_graphic_copy (GameObject *odest, GameObject *osrc)
return GAME_OBJECT_CLASS (parent_class)->copy (odest, osrc);
}
+static cairo_pattern_t *
+game_graphic_do_create_cache (GameGraphic *graphic, cairo_t *cr)
+{
+ cairo_matrix_t matrix;
+ cairo_t *crc;
+ cairo_surface_t *cache;
+ cairo_pattern_t *pattern;
+ double width, height;
+
+ g_return_val_if_fail (GAME_IS_GRAPHIC (graphic), NULL);
+ g_return_val_if_fail (cr != NULL, NULL);
+
+ cairo_get_matrix (cr, &matrix);
+ if (!GAME_DOUBLE_EQUAL (matrix.xy, 0.0) ||
+ !GAME_DOUBLE_EQUAL (matrix.xy, 0.0))
+ return NULL;
+
+ width = graphic->rect.x2 - graphic->rect.x1;
+ height = graphic->rect.y2 - graphic->rect.y1;
+#if 1
+ cache = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_COLOR_ALPHA, ceil (matrix.xx * width),
+ ceil (matrix.yy * height));
+#else
+ cache = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ ceil (matrix.xx * width), ceil (matrix.yy * height));
+#endif
+ if (cairo_surface_status (cache) != CAIRO_STATUS_SUCCESS) {
+ cairo_surface_destroy (cache);
+ return NULL;
+ }
+ crc = cairo_create (cache);
+ /* clear surface */
+ cairo_save (crc);
+ cairo_set_operator (crc, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgba (crc, 0.0, 0.0, 0.0, 0.0);
+ cairo_paint (crc);
+ cairo_restore (crc);
+
+ cairo_scale (crc, matrix.xx, matrix.yy);
+ cairo_translate (crc, - graphic->rect.x1, - graphic->rect.y1);
+ if (!game_graphic_draw_area_no_cache (graphic, crc, &graphic->rect)) {
+ cairo_surface_destroy (cache);
+ cairo_destroy (crc);
+ return NULL;
+ }
+
+ pattern = cairo_pattern_create_for_surface (cache);
+ cairo_get_matrix (crc, &matrix);
+ cairo_pattern_set_matrix (pattern, &matrix);
+
+ cairo_surface_destroy (cache);
+ cairo_destroy (crc);
+
+ return pattern;
+}
+
static void
game_graphic_class_init (gpointer g_class, gpointer class_data)
{
GObjectClass *object_class = G_OBJECT_CLASS (g_class);
GameObjectClass *gameobject_class = GAME_OBJECT_CLASS (g_class);
+ GameGraphicClass *graphic_class = GAME_GRAPHIC_CLASS (g_class);
parent_class = g_type_class_peek_parent (g_class);
@@ -159,6 +216,8 @@ game_graphic_class_init (gpointer g_class, gpointer class_data)
gameobject_class->copy = game_graphic_copy;
gameobject_class->to_string = game_graphic_to_string;
+
+ graphic_class->create_cache = game_graphic_do_create_cache;
}
static void
@@ -222,8 +281,8 @@ game_graphic_invalidate_cache (GameGraphic *graphic)
}
}
-static gboolean
-game_graphic_do_draw_area (GameGraphic *graphic, cairo_t *cr,
+gboolean
+game_graphic_draw_area_no_cache (GameGraphic *graphic, cairo_t *cr,
const GameRectangle *rect)
{
GameGraphicClass *klass;
@@ -256,8 +315,8 @@ gboolean
game_graphic_draw_area (GameGraphic *graphic, cairo_t *cr, const
GameRectangle *rect)
{
- cairo_matrix_t matrix;
GameRectangle inval;
+ cairo_pattern_t *cache;
g_return_val_if_fail (GAME_IS_GRAPHIC (graphic), FALSE);
g_return_val_if_fail (cr != NULL, FALSE);
@@ -266,24 +325,15 @@ game_graphic_draw_area (GameGraphic *graphic, cairo_t *cr, const
if (!game_rectangle_intersect (&inval, &graphic->rect, rect))
return TRUE;
- if (graphic->cache_policy == GAME_GRAPHIC_CACHE_NEVER)
- return game_graphic_do_draw_area (graphic, cr, rect);
- cairo_get_matrix (cr, &matrix);
- if (!GAME_DOUBLE_EQUAL (matrix.xy, 0.0) ||
- !GAME_DOUBLE_EQUAL (matrix.yx, 0.0))
- return game_graphic_do_draw_area (graphic, cr, rect);
- if (graphic->cache != NULL) {
- cairo_matrix_t pmatrix;
- cairo_pattern_get_matrix (graphic->cache, &pmatrix);
- if (!GAME_DOUBLE_EQUAL (matrix.xx, pmatrix.xx) ||
- !GAME_DOUBLE_EQUAL (matrix.yy, pmatrix.yy))
- game_graphic_invalidate_cache (graphic);
- }
- if (graphic->cache == NULL) {
- graphic->cache = game_graphic_create_cache (graphic, cr);
- if (graphic->cache == NULL)
- return game_graphic_do_draw_area (graphic, cr, rect);
+ cache = game_graphic_get_cache (graphic, cr);
+ if (graphic->cache != cache) {
+ game_graphic_invalidate_cache (graphic);
+ graphic->cache = cache;
+ if (cache)
+ cairo_pattern_reference (cache);
}
+ if (graphic->cache == NULL)
+ return game_graphic_draw_area_no_cache (graphic, cr, rect);
cairo_save (cr);
cairo_set_source (cr, graphic->cache);
cairo_paint (cr);
@@ -292,54 +342,44 @@ game_graphic_draw_area (GameGraphic *graphic, cairo_t *cr, const
}
cairo_pattern_t *
-game_graphic_create_cache (GameGraphic *graphic, cairo_t *cr)
+game_graphic_get_cache (GameGraphic *graphic, cairo_t *cr)
{
- cairo_matrix_t matrix;
- cairo_t *crc;
- cairo_surface_t *cache;
- cairo_pattern_t *pattern;
- double width, height;
+ GameGraphicClass *klass;
+ cairo_pattern_t *cache;
g_return_val_if_fail (GAME_IS_GRAPHIC (graphic), NULL);
g_return_val_if_fail (cr != NULL, NULL);
-
- cairo_get_matrix (cr, &matrix);
- width = graphic->rect.x2 - graphic->rect.x1;
- height = graphic->rect.y2 - graphic->rect.y1;
-#if 1
- cache = cairo_surface_create_similar (cairo_get_target (cr),
- CAIRO_CONTENT_COLOR_ALPHA, ceil (matrix.xx * width),
- ceil (matrix.yy * height));
-#else
- cache = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- ceil (matrix.xx * width), ceil (matrix.yy * height));
-#endif
- if (cairo_surface_status (cache) != CAIRO_STATUS_SUCCESS) {
- cairo_surface_destroy (cache);
- return NULL;
- }
- crc = cairo_create (cache);
- /* clear surface */
- cairo_save (crc);
- cairo_set_operator (crc, CAIRO_OPERATOR_SOURCE);
- cairo_set_source_rgba (crc, 0.0, 0.0, 0.0, 0.0);
- cairo_paint (crc);
- cairo_restore (crc);
- cairo_scale (crc, matrix.xx, matrix.yy);
- cairo_translate (crc, - graphic->rect.x1, - graphic->rect.y1);
- if (!game_graphic_do_draw_area (graphic, crc, &graphic->rect)) {
- cairo_surface_destroy (cache);
- cairo_destroy (crc);
- return NULL;
+ if (graphic->cache != NULL &&
+ game_cairo_pattern_matches (cr, graphic->cache)) {
+ cairo_pattern_reference (graphic->cache);
+ return graphic->cache;
}
+ klass = GAME_GRAPHIC_GET_CLASS (graphic);
+ if (klass->create_cache)
+ cache = klass->create_cache (graphic, cr);
+ else
+ cache = NULL;
- pattern = cairo_pattern_create_for_surface (cache);
- cairo_get_matrix (crc, &matrix);
- cairo_pattern_set_matrix (pattern, &matrix);
+ return cache;
+}
- cairo_surface_destroy (cache);
- cairo_destroy (crc);
+gboolean
+game_cairo_pattern_matches (cairo_t *cr, cairo_pattern_t *pattern)
+{
+ cairo_matrix_t cmatrix, pmatrix, result;
+
+ g_return_val_if_fail (cr != NULL, FALSE);
+ g_return_val_if_fail (pattern != NULL, FALSE);
- return pattern;
+ cairo_get_matrix (cr, &cmatrix);
+ cairo_pattern_get_matrix (pattern, &pmatrix);
+ cairo_matrix_invert (&pmatrix);
+ cairo_matrix_multiply (&result, &cmatrix, &pmatrix);
+ /* FIXME: need to somehow check surface types? */
+ return GAME_DOUBLE_EQUAL (result.xx, 1.0) &&
+ GAME_DOUBLE_EQUAL (result.yy, 1.0) &&
+ GAME_DOUBLE_EQUAL (result.xy, 0.0) &&
+ GAME_DOUBLE_EQUAL (result.yx, 0.0);
}
+
diff --git a/libgame/game-graphic.h b/libgame/game-graphic.h
index 6298642..9aead8a 100644
--- a/libgame/game-graphic.h
+++ b/libgame/game-graphic.h
@@ -44,7 +44,6 @@ struct _GameGraphic {
/*< protected >*/
GameRectangle rect;
- GameGraphicCachePolicy cache_policy;
/*< private >*/
cairo_pattern_t * cache;
@@ -57,6 +56,8 @@ struct _GameGraphicClass {
void (* draw) (GameGraphic * graphic,
cairo_t * cr,
const GameRectangle * rect);
+ cairo_pattern_t * (* create_cache) (GameGraphic * graphic,
+ cairo_t * cr);
/* signals */
void (* invalidate) (GameGraphic * graphic,
const GameRectangle * rect);
@@ -74,9 +75,15 @@ gboolean game_graphic_draw (GameGraphic * graphic,
gboolean game_graphic_draw_area (GameGraphic * graphic,
cairo_t * cr,
const GameRectangle * rectangle);
+gboolean game_graphic_draw_area_no_cache (GameGraphic * graphic,
+ cairo_t * cr,
+ const GameRectangle * rect);
-cairo_pattern_t *game_graphic_create_cache (GameGraphic * graphic,
+cairo_pattern_t *game_graphic_get_cache (GameGraphic * graphic,
cairo_t * cr);
+/* FIXME: find a header/file for this */
+gboolean game_cairo_pattern_matches (cairo_t * cr,
+ cairo_pattern_t * pattern);
G_END_DECLS
diff --git a/libgame/game-viewport.c b/libgame/game-viewport.c
index f447f6d..251f2cf 100644
--- a/libgame/game-viewport.c
+++ b/libgame/game-viewport.c
@@ -171,14 +171,12 @@ game_viewport_class_init (gpointer g_class, gpointer class_data)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
graphic_class->draw = game_viewport_draw;
+ graphic_class->create_cache = NULL;
}
static void
game_viewport_init (GTypeInstance *instance, gpointer g_class)
{
- GameGraphic *graphic = GAME_GRAPHIC (instance);
-
- graphic->cache_policy = GAME_GRAPHIC_CACHE_NEVER;
}
GType