[gnome-games] aisleriot: Add cairo drawing mode
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games] aisleriot: Add cairo drawing mode
- Date: Thu, 12 Aug 2010 10:40:15 +0000 (UTC)
commit 0d158a7862ad7a08f29b98efc4ac222d0d47fb24
Author: Christian Persch <chpe gnome org>
Date: Wed Aug 11 14:16:51 2010 +0200
aisleriot: Add cairo drawing mode
aisleriot/board-noclutter.c | 404 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 397 insertions(+), 7 deletions(-)
---
diff --git a/aisleriot/board-noclutter.c b/aisleriot/board-noclutter.c
index 8fb91c2..cbff1b7 100644
--- a/aisleriot/board-noclutter.c
+++ b/aisleriot/board-noclutter.c
@@ -42,6 +42,10 @@
#include "ar-pixbuf-utils.h"
#include "ar-style-gtk.h"
+#if GTK_CHECK_VERSION (2, 90, 6)
+#define CAIRO_DRAWING
+#endif
+
#define AISLERIOT_BOARD_GET_PRIVATE(board)(G_TYPE_INSTANCE_GET_PRIVATE ((board), AISLERIOT_TYPE_BOARD, AisleriotBoardPrivate))
/* Enable keynav on non-hildon by default */
@@ -83,9 +87,12 @@ struct _AisleriotBoardPrivate
ArStyle *style;
+#ifndef CAIRO_DRAWING
GdkGC *draw_gc;
GdkGC *bg_gc;
GdkGC *slot_gc;
+#endif /* !CAIRO_DRAWING */
+
GdkCursor *cursor[AR_LAST_CURSOR];
CardSize card_size;
@@ -157,7 +164,6 @@ struct _AisleriotBoardPrivate
/* Bit field */
guint droppable_supported : 1;
- guint use_pixbuf_drawing : 1;
guint show_focus : 1; /* whether the focus is drawn */
guint click_to_move : 1;
@@ -173,6 +179,10 @@ struct _AisleriotBoardPrivate
guint show_status_messages : 1;
guint force_geometry_update : 1;
+
+#ifndef CAIRO_DRAWING
+ guint use_pixbuf_drawing : 1;
+#endif
};
G_STATIC_ASSERT (LAST_STATUS < 16 /* 2^4 */);
@@ -735,7 +745,9 @@ slot_update_card_images_full (AisleriotBoard *board,
g_ptr_array_add (card_images, NULL);
}
+#ifndef CAIRO_DRAWING
if (PIXBUF_DRAWING_LIKELIHOOD (priv->use_pixbuf_drawing)) {
+#endif
for (i = first_exposed_card_id; i < n_cards; ++i) {
Card card = CARD (cards[i]);
gboolean is_highlighted;
@@ -745,6 +757,7 @@ slot_update_card_images_full (AisleriotBoard *board,
g_ptr_array_add (card_images,
ar_card_images_get_card_pixbuf (images, card, is_highlighted));
}
+#ifndef CAIRO_DRAWING
} else {
for (i = first_exposed_card_id; i < n_cards; ++i) {
Card card = CARD (cards[i]);
@@ -756,6 +769,7 @@ slot_update_card_images_full (AisleriotBoard *board,
ar_card_images_get_card_pixmap (images, card, is_highlighted));
}
}
+#endif /* !CAIRO_DRAWING */
}
static void
@@ -833,14 +847,18 @@ aisleriot_board_setup_geometry (AisleriotBoard *board)
priv->xoffset = (priv->xslotstep - card_size.width) / 2;
priv->yoffset = (priv->yslotstep - card_size.height) / 2;
+#ifndef CAIRO_DRAWING
if (PIXBUF_DRAWING_LIKELIHOOD (priv->use_pixbuf_drawing)) {
+#endif
priv->slot_image = ar_card_images_get_slot_pixbuf (priv->images, FALSE);
+#ifndef CAIRO_DRAWING
} else {
priv->slot_image = ar_card_images_get_slot_pixmap (priv->images, FALSE);
}
gdk_gc_set_clip_mask (priv->slot_gc, ar_card_images_get_slot_mask (priv->images));
gdk_gc_set_clip_mask (priv->draw_gc, ar_card_images_get_card_mask (priv->images));
+#endif /* !CAIRO_DRAWING */
/* NOTE! Updating the slots checks that geometry is set, so
* we set it to TRUE already.
@@ -874,16 +892,20 @@ drag_begin (AisleriotBoard *board)
GdkPixmap *moving_pixmap;
GdkBitmap *card_mask;
GdkBitmap *moving_mask;
- GdkGC *gc1, *gc2;
- const GdkColor masked = { 0, 0, 0, 0 };
- const GdkColor unmasked = { 1, 0xffff, 0xffff, 0xffff };
int num_moving_cards;
- gboolean use_pixbuf_drawing = priv->use_pixbuf_drawing;
guint i;
GByteArray *cards;
GdkDrawable *drawable;
GdkWindowAttr attributes;
GdkWindow *window;
+#ifdef CAIRO_DRAWING
+ cairo_t *cr1, *cr2;
+#else
+ const GdkColor masked = { 0, 0, 0, 0 };
+ const GdkColor unmasked = { 1, 0xffff, 0xffff, 0xffff };
+ GdkGC *gc1, *gc2;
+ gboolean use_pixbuf_drawing = priv->use_pixbuf_drawing;
+#endif /* CAIRO_DRAWING */
if (!priv->selection_slot ||
priv->selection_start_card_id < 0) {
@@ -955,6 +977,26 @@ drag_begin (AisleriotBoard *board)
width, height,
1);
+#ifdef CAIRO_DRAWING
+ cr1 = gdk_cairo_create (moving_pixmap);
+ cairo_set_operator (cr1, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (cr1);
+ cairo_set_operator (cr1, CAIRO_OPERATOR_OVER);
+
+ cr2 = gdk_cairo_create (moving_mask);
+ cairo_set_operator (cr2, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (cr2);
+ cairo_set_operator (cr2, CAIRO_OPERATOR_OVER);
+
+ cairo_set_source_rgba (cr2, 1., 1., 1., 0.);
+
+ card_mask = ar_card_images_get_card_mask (priv->images);
+
+// gdk_cairo_set_source_pixmap (cr1, card_mask, 0, 0);
+// gdk_cairo_set_source_pixmap (cr2, card_mask, 0, 0);
+
+ //FIXME?;
+#else
gc1 = gdk_gc_new (moving_pixmap);
gc2 = gdk_gc_new (moving_mask);
@@ -969,6 +1011,7 @@ drag_begin (AisleriotBoard *board)
card_mask = ar_card_images_get_card_mask (priv->images);
gdk_gc_set_clip_mask (gc1, card_mask);
gdk_gc_set_clip_mask (gc2, card_mask);
+#endif /* CAIRO_DRAWING */
/* FIXMEchpe: RTL issue: this doesn't work right when we allow dragging of
* more than one card from a expand-right slot. (But right now no game .scm
@@ -981,6 +1024,29 @@ drag_begin (AisleriotBoard *board)
for (i = 0; i < priv->moving_cards->len; ++i) {
Card hcard = CARD (priv->moving_cards->data[i]);
+#ifdef CAIRO_DRAWING
+ GdkPixbuf *pixbuf;
+
+ pixbuf = ar_card_images_get_card_pixbuf (priv->images, hcard, FALSE);
+ if (!pixbuf)
+ goto next;
+
+ #if 0
+ gdk_draw_pixbuf (moving_pixmap, gc1,
+ pixbuf,
+ 0, 0, x, y, width, height,
+ GDK_RGB_DITHER_NONE, 0, 0);
+ gdk_draw_rectangle (moving_mask, gc2, TRUE,
+ x, y, width, height);
+ #endif
+
+ gdk_cairo_set_source_pixbuf (cr1, pixbuf, x, y);
+ cairo_paint (cr1);
+
+ gdk_cairo_set_source_pixmap (cr2, card_mask, x, y);
+ cairo_paint (cr2);
+
+#else /* !CAIRO_DRAWING */
gdk_gc_set_clip_origin (gc1, x, y);
gdk_gc_set_clip_origin (gc2, x, y);
@@ -1009,6 +1075,7 @@ drag_begin (AisleriotBoard *board)
gdk_draw_rectangle (moving_mask, gc2, TRUE,
x, y, width, height);
}
+#endif /* CAIRO_DRAWING */
next:
@@ -1016,8 +1083,13 @@ drag_begin (AisleriotBoard *board)
y += hslot->pixeldy;
}
+#ifdef CAIRO_DRAWING
+ cairo_destroy (cr1);
+ cairo_destroy (cr2);
+#else
g_object_unref (gc1);
g_object_unref (gc2);
+#endif /* !CAIRO_DRAWING */
gdk_window_set_back_pixmap (priv->moving_cards_window,
moving_pixmap, 0);
@@ -2313,7 +2385,6 @@ aisleriot_board_realize (GtkWidget *widget)
AisleriotBoardPrivate *priv = board->priv;
GdkDisplay *display;
GdkWindow *window;
- GdkColor baize_color;
GTK_WIDGET_CLASS (aisleriot_board_parent_class)->realize (widget);
@@ -2323,6 +2394,10 @@ aisleriot_board_realize (GtkWidget *widget)
ar_card_images_set_drawable (priv->images, window);
+#ifndef CAIRO_DRAWING
+{
+ GdkColor baize_color;
+
priv->draw_gc = gdk_gc_new (window);
priv->bg_gc = gdk_gc_new (window);
@@ -2331,6 +2406,8 @@ aisleriot_board_realize (GtkWidget *widget)
gdk_gc_set_rgb_fg_color (priv->bg_gc, &baize_color);
priv->slot_gc = gdk_gc_new (window);
+}
+#endif /* !CAIRO_DRAWING */
#ifndef HAVE_HILDON
/* Create cursors */
@@ -2354,12 +2431,14 @@ aisleriot_board_unrealize (GtkWidget *widget)
priv->geometry_set = FALSE;
+#ifndef CAIRO_DRAWING
g_object_unref (priv->draw_gc);
priv->draw_gc = NULL;
g_object_unref (priv->bg_gc);
priv->bg_gc = NULL;
g_object_unref (priv->slot_gc);
priv->slot_gc = NULL;
+#endif
#ifndef HAVE_HILDON
for (i = 0; i < AR_LAST_CURSOR; ++i) {
@@ -2487,14 +2566,17 @@ aisleriot_board_sync_style (ArStyle *style,
if (realized &&
(pspec_name == NULL || pspec_name == I_(AR_STYLE_PROP_BAIZE_COLOR))) {
+#ifndef CAIRO_DRAWING
GdkColor baize_color;
ar_style_get_baize_color (priv->style, &baize_color);
gdk_gc_set_rgb_fg_color (priv->bg_gc, &baize_color);
+#endif /* !CAIRO_DRAWING */
queue_redraw = TRUE;
}
+#ifndef CAIRO_DRAWING
if (pspec_name == NULL || pspec_name == I_(AR_STYLE_PROP_PIXBUF_DRAWING)) {
gboolean pixbuf_drawing;
@@ -2505,11 +2587,12 @@ aisleriot_board_sync_style (ArStyle *style,
priv->use_pixbuf_drawing = pixbuf_drawing;
ar_card_images_set_cache_mode (priv->images,
- pixbuf_drawing ? CACHE_PIXBUFS : CACHE_PIXMAPS);
+ pixbuf_drawing ? CACHE_PIXBUFS : CACHE_PIXMAPS);
update_geometry |= TRUE;
queue_redraw |= TRUE;
}
+#endif /* !CAIRO_DRAWING */
#if GTK_CHECK_VERSION (2, 12, 0) && !defined(HAVE_HILDON)
if (pspec_name == NULL || pspec_name == I_(AR_STYLE_PROP_SHOW_TOOLTIPS)) {
@@ -3029,6 +3112,308 @@ aisleriot_board_tap_and_hold_cb (GtkWidget *widget,
#endif /* HAVE_MAEMO */
+#ifdef CAIRO_DRAWING
+
+static gboolean
+aisleriot_board_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ AisleriotBoard *board = AISLERIOT_BOARD (widget);
+ AisleriotBoardPrivate *priv = board->priv;
+ cairo_t *cr;
+#if GTK_CHECK_VERSION (2, 90, 5)
+ cairo_region_t *region = event->region;
+#else
+ GdkRegion *region = event->region;
+ GdkRectangle *rects;
+ GdkRectangle *rect;
+#endif
+ int i, n_rects;
+ GPtrArray *slots;
+ guint n_slots;
+ ArSlot **exposed_slots;
+ ArSlot *highlight_slot;
+ guint n_exposed_slots;
+ GdkWindow *window;
+ GdkColor color;
+
+ window = gtk_widget_get_window (widget);
+
+ /* NOTE: It's ok to just return instead of chaining up, since the
+ * parent class has no class closure for this event.
+ */
+
+ if (event->window != window)
+ return FALSE;
+
+#if GTK_CHECK_VERSION (2, 90, 5)
+ if (cairo_region_is_empty (region))
+ return FALSE;
+#else
+ if (gdk_region_empty (region))
+ return FALSE;
+#endif
+
+#if GTK_CHECK_VERSION (2, 90, 5)
+ n_rects = cairo_region_num_rectangles (region);
+#else
+ gdk_region_get_rectangles (region, &rects, &n_rects);
+#endif
+ if (n_rects == 0)
+ return FALSE;
+
+#if 0
+ {
+ g_print ("Exposing area %d:%d@(%d,%d) ", event->area.width, event->area.height,
+ event->area.x, event->area.y);
+ for (i = 0; i < n_rects; ++i) {
+ g_print ("[Rect %d:%d@(%d,%d)] ", rects[i].width, rects[i].height, rects[i].x, rects[i].y);
+ }
+ g_print ("\n");
+ }
+#endif
+
+ cr = gdk_cairo_create (window);
+
+ /* First paint the background */
+
+ ar_style_get_baize_color (priv->style, &color);
+ gdk_cairo_set_source_color (cr, &color);
+
+#if GTK_CHECK_VERSION (2, 90, 5)
+ gdk_cairo_region (cr, region);
+#else
+ for (i = 0; i < n_rects; ++i) {
+ rect = &rects[i];
+
+#if 0
+ gdk_draw_rectangle (window, priv->bg_gc, TRUE,
+ rect->x, rect->y,
+ rect->width, rect->height);
+#endif
+ cairo_rectangle (cr, rect->x, rect->y, rect->width, rect->height);
+ }
+ g_free (rects);
+#endif
+
+ cairo_fill (cr);
+
+ /* Only draw the the cards when the geometry is set, and we're in a resize */
+ if (!priv->geometry_set) {
+ cairo_destroy (cr);
+ return TRUE;
+ }
+
+ /* Now draw the slots and cards */
+ slots = aisleriot_game_get_slots (priv->game);
+
+ n_slots = slots->len;
+
+ /* First check which slots are exposed */
+ /* It's fine to allocate on the stack, since there'll never be very many slots */
+ exposed_slots = g_newa (ArSlot *, n_slots);
+ n_exposed_slots = 0;
+
+ for (i = 0; i < n_slots; ++i) {
+ ArSlot *slot = slots->pdata[i];
+
+ /* Check whether this slot needs to be drawn */
+#if GTK_CHECK_VERSION (2, 90, 5)
+ if (cairo_region_contains_rectangle (region, &slot->rect) == CAIRO_REGION_OVERLAP_OUT)
+ continue;
+#else
+ if (gdk_region_rect_in (region, &slot->rect) == GDK_OVERLAP_RECTANGLE_OUT)
+ continue;
+#endif
+
+ exposed_slots[n_exposed_slots++] = slot;
+ }
+
+ highlight_slot = priv->highlight_slot;
+
+ /* First draw the slots. Otherwise they'll overlap on cards
+ * (e.g. in Elevator, after a card was removed).
+ */
+ for (i = 0; i < n_exposed_slots; ++i) {
+ ArSlot *hslot = exposed_slots[i];
+ int x, y;
+ GdkPixbuf *pixbuf;
+
+ /* FIXMEchpe: if ((hslot->length - hslot->exposed) >= 0) ?? */
+ if (hslot->cards->len > 0)
+ continue;
+
+ /* If the slot it empty, draw the slot image */
+ x = hslot->rect.x;
+ y = hslot->rect.y;
+
+ #if 0
+ gdk_gc_set_clip_origin (priv->slot_gc, x, y);
+ #endif
+
+ if (G_LIKELY (hslot != highlight_slot)) {
+ pixbuf = priv->slot_image;
+ } else {
+ pixbuf = ar_card_images_get_slot_pixbuf (priv->images,
+ priv->show_highlight);
+ }
+
+ if (!pixbuf)
+ continue;
+
+ #if 0
+ gdk_draw_pixbuf (window, priv->slot_gc, pixbuf, 0, 0, x, y,
+ priv->card_size.width, priv->card_size.height,
+ GDK_RGB_DITHER_NONE, 0, 0);
+ #endif
+
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
+ cairo_paint (cr);
+ }
+
+ /* Now draw the cards */
+ for (i = 0; i < n_exposed_slots; ++i) {
+ ArSlot *hslot = exposed_slots[i];
+ GByteArray *cards = hslot->cards;
+ gpointer *card_images = hslot->card_images->pdata;
+ GdkRectangle card_rect;
+ GdkPixbuf *pixbuf;
+ guint j, n_cards;
+
+ n_cards = cards->len;
+ if (n_cards == 0)
+ continue;
+
+ card_rect.x = hslot->rect.x;
+ card_rect.y = hslot->rect.y;
+ card_rect.width = priv->card_size.width;
+ card_rect.height = priv->card_size.height;
+
+ if (priv->is_rtl &&
+ hslot->expanded_right) {
+ card_rect.x += hslot->rect.width - priv->card_size.width;
+ }
+
+ for (j = n_cards - hslot->exposed; j < n_cards; ++j) {
+ /* Check whether this card needs to be drawn */
+ /* FIXMEchpe: we can be even smarter here, by checking
+ * with the rect of the part of the card that's not going
+ * to be obscured by later drawn cards anyway.
+ */
+#if GTK_CHECK_VERSION (2, 90, 5)
+ if (cairo_region_contains_rectangle (region, &card_rect) == CAIRO_REGION_OVERLAP_OUT)
+ goto next;
+#else
+ if (gdk_region_rect_in (region, &card_rect) == GDK_OVERLAP_RECTANGLE_OUT)
+ goto next;
+#endif
+
+ pixbuf = card_images[j];
+ if (!pixbuf)
+ goto next;
+
+ #if 0
+ gdk_gc_set_clip_origin (priv->draw_gc, card_rect.x, card_rect.y);
+ gdk_draw_pixbuf (window, priv->draw_gc, pixbuf,
+ 0, 0, card_rect.x, card_rect.y, -1, -1,
+ GDK_RGB_DITHER_NONE, 0, 0);
+ #endif
+
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, card_rect.x, card_rect.y);
+ cairo_paint (cr);
+
+ next:
+
+ card_rect.x += hslot->pixeldx;
+ card_rect.y += hslot->pixeldy;
+ }
+ }
+
+ /* Draw the revealed card */
+#if GTK_CHECK_VERSION (2, 90, 5)
+ if (priv->show_card_slot != NULL &&
+ cairo_region_contains_rectangle (region, &priv->show_card_slot->rect) != CAIRO_REGION_OVERLAP_OUT)
+#else
+ if (priv->show_card_slot != NULL &&
+ gdk_region_rect_in (region, &priv->show_card_slot->rect) != GDK_OVERLAP_RECTANGLE_OUT)
+#endif
+ {
+ GdkRectangle card_rect;
+ GdkPixbuf *pixbuf;
+
+ get_rect_by_slot_and_card (board,
+ priv->show_card_slot,
+ priv->show_card_id,
+ 1, &card_rect);
+
+ pixbuf = priv->show_card_slot->card_images->pdata[priv->show_card_id];
+ if (!pixbuf)
+ goto draw_focus;
+
+ #if 0
+ gdk_gc_set_clip_origin (priv->draw_gc, card_rect.x, card_rect.y);
+ gdk_draw_pixbuf (window, priv->draw_gc, pixbuf,
+ 0, 0, card_rect.x, card_rect.y, -1, -1,
+ GDK_RGB_DITHER_NONE, 0, 0);
+ #endif
+
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, card_rect.x, card_rect.y);
+ cairo_paint (cr);
+ }
+
+draw_focus:
+
+#ifdef ENABLE_KEYNAV
+ if (G_UNLIKELY (priv->show_focus &&
+ priv->focus_slot != NULL &&
+ gtk_widget_has_focus (widget))) {
+ GdkRectangle focus_rect;
+
+ /* Check whether this needs to be drawn */
+#if GTK_CHECK_VERSION (2, 90, 5)
+ if (cairo_region_contains_rectangle (region, &priv->focus_rect) == CAIRO_REGION_OVERLAP_OUT)
+ goto expose_done;
+#else
+ if (gdk_region_rect_in (region, &priv->focus_rect) == GDK_OVERLAP_RECTANGLE_OUT)
+ goto expose_done;
+#endif
+
+ if (ar_style_get_interior_focus (priv->style)) {
+ focus_rect = priv->focus_rect;
+ } else {
+ get_rect_by_slot_and_card (board,
+ priv->focus_slot,
+ priv->focus_card_id,
+ 1,
+ &focus_rect);
+ }
+
+ #if 0
+ gtk_paint_focus (gtk_widget_get_style (widget),
+ window,
+ gtk_widget_get_state (widget),
+ &priv->focus_rect,
+ widget,
+ NULL /* FIXME ? */,
+ focus_rect.x,
+ focus_rect.y,
+ focus_rect.width,
+ focus_rect.height);
+ #endif
+ // FIXMEchpe
+ }
+
+expose_done:
+#endif /* ENABLE_KEYNAV */
+
+ cairo_destroy (cr);
+
+ /* Parent class has no expose handler, no need to chain up */
+ return TRUE;
+}
+
+#else /* !CAIRO_DRAWING */
+
static gboolean
aisleriot_board_expose_event (GtkWidget *widget,
GdkEventExpose *event)
@@ -3339,6 +3724,8 @@ expose_done:
return TRUE;
}
+#endif /* CAIRO_DRAWING */
+
/* GObjectClass methods */
static void
@@ -3366,6 +3753,9 @@ aisleriot_board_init (AisleriotBoard *board)
priv->moving_cards = g_byte_array_sized_new (SLOT_CARDS_N_PREALLOC);
priv->images = ar_card_images_new ();
+#ifdef CAIRO_DRAWING
+ ar_card_images_set_cache_mode (priv->images, CACHE_PIXBUFS);
+#endif
gtk_widget_set_events (widget,
gtk_widget_get_events (widget) |
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]