gnome-games r8416 - in trunk: aisleriot blackjack/src libgames-support
- From: chpe svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-games r8416 - in trunk: aisleriot blackjack/src libgames-support
- Date: Tue, 6 Jan 2009 18:17:59 +0000 (UTC)
Author: chpe
Date: Tue Jan 6 18:17:59 2009
New Revision: 8416
URL: http://svn.gnome.org/viewvc/gnome-games?rev=8416&view=rev
Log:
Refactor card themes by splitting it into an abstract base class
GamesCardTheme and two implementations for SVG themes and prerendered
themes. Adapt callers to the new API.
Added:
trunk/libgames-support/games-card-theme-fixed.c
trunk/libgames-support/games-card-theme-private.h
trunk/libgames-support/games-card-theme-svg.c
Modified:
trunk/aisleriot/board-noclutter.c
trunk/aisleriot/board.c
trunk/blackjack/src/card.cpp
trunk/libgames-support/Makefile.am
trunk/libgames-support/games-card-theme.c
trunk/libgames-support/games-card-theme.h
trunk/libgames-support/render-cards.c
Modified: trunk/aisleriot/board-noclutter.c
==============================================================================
--- trunk/aisleriot/board-noclutter.c (original)
+++ trunk/aisleriot/board-noclutter.c Tue Jan 6 18:17:59 2009
@@ -3357,7 +3357,11 @@
g_assert (priv->game != NULL);
/* Create this down here since we need to have the scalable_cards value */
- priv->theme = games_card_theme_new (NULL, priv->scalable_cards);
+ if (priv->scalable_cards)
+ priv->theme = games_card_theme_svg_new ();
+ else
+ priv->theme = games_card_theme_fixed_new ();
+
priv->images = games_card_images_new (priv->theme);
return object;
@@ -3659,7 +3663,7 @@
priv->geometry_set = FALSE;
priv->slot_image = NULL;
- retval = games_card_theme_set_theme (priv->theme, card_theme);
+ retval = games_card_theme_set_theme (priv->theme, NULL, card_theme);
/* NOTE! We need to do this even if setting the theme failed, since
* the attempt will have wiped out the old theme data!
Modified: trunk/aisleriot/board.c
==============================================================================
--- trunk/aisleriot/board.c (original)
+++ trunk/aisleriot/board.c Tue Jan 6 18:17:59 2009
@@ -3184,7 +3184,11 @@
g_assert (priv->game != NULL);
/* Create this down here since we need to have the scalable_cards value */
- priv->theme = games_card_theme_new (NULL, priv->scalable_cards);
+ if (priv->scalable_cards)
+ priv->theme = games_card_theme_svg_new ();
+ else
+ priv->theme = games_card_theme_fixed_new ();
+
priv->images = games_card_images_new (priv->theme);
priv->textures = games_card_textures_cache_new (priv->images);
@@ -3513,7 +3517,7 @@
priv->geometry_set = FALSE;
- retval = games_card_theme_set_theme (priv->theme, card_theme);
+ retval = games_card_theme_set_theme (priv->theme, NULL, card_theme);
/* NOTE! We need to do this even if setting the theme failed, since
* the attempt will have wiped out the old theme data!
Modified: trunk/blackjack/src/card.cpp
==============================================================================
--- trunk/blackjack/src/card.cpp (original)
+++ trunk/blackjack/src/card.cpp Tue Jan 6 18:17:59 2009
@@ -126,7 +126,10 @@
env = g_getenv ("BLACKJACK_CARDS_SCALABLE");
scalable = env == NULL || g_ascii_strtoll (env, NULL, 10) != 0;
- theme = games_card_theme_new (NULL, scalable);
+ if (scalable)
+ theme = games_card_theme_svg_new ();
+ else
+ theme = games_card_theme_fixed_new ();
images = games_card_images_new (theme);
g_object_unref (theme);
@@ -135,7 +138,7 @@
games_card_images_set_drawable (images, playing_area->window);
card_theme = bj_get_card_style ();
- if (!games_card_theme_set_theme (theme, card_theme)) {
+ if (!games_card_theme_set_theme (theme, NULL, card_theme)) {
g_warning ("Failed to load theme %s!", card_theme);
}
g_free (card_theme);
@@ -154,7 +157,7 @@
void
bj_card_set_theme (gchar *card_theme)
{
- games_card_theme_set_theme (theme, card_theme);
+ games_card_theme_set_theme (theme, NULL, card_theme);
bj_draw_rescale_cards ();
mask = games_card_images_get_card_mask (images);
Modified: trunk/libgames-support/Makefile.am
==============================================================================
--- trunk/libgames-support/Makefile.am (original)
+++ trunk/libgames-support/Makefile.am Tue Jan 6 18:17:59 2009
@@ -30,6 +30,8 @@
games-card-images.h \
games-card-theme.c \
games-card-theme.h \
+ games-card-theme-private.h \
+ games-card-theme-fixed.c \
games-conf.c \
games-conf.h \
games-files.c \
@@ -87,6 +89,12 @@
endif
endif
+if HAVE_RSVG
+libgames_support_la_SOURCES += \
+ games-card-theme-svg.c \
+ $(NULL)
+endif
+
if HAVE_CLUTTER
libgames_support_la_SOURCES += \
games-card-textures-cache.c \
Added: trunk/libgames-support/games-card-theme-fixed.c
==============================================================================
--- (empty file)
+++ trunk/libgames-support/games-card-theme-fixed.c Tue Jan 6 18:17:59 2009
@@ -0,0 +1,406 @@
+/*
+ Copyright  2004 Callum McKenzie
+ Copyright  2007, 2008 Christian Persch
+
+ This library is free software; you can redistribute it and'or modify
+ it under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Authors: Callum McKenzie <callum physics otago ac nz> */
+
+#include <config.h>
+
+#include <string.h>
+#include <glib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtk.h>
+
+#include "games-find-file.h"
+#include "games-files.h"
+#include "games-preimage.h"
+#include "games-runtime.h"
+
+#include "games-card-theme.h"
+#include "games-card-theme-private.h"
+
+struct _GamesCardThemeFixedClass {
+ GamesCardThemeClass parent_class;
+};
+
+struct _GamesCardThemeFixed {
+ GamesCardTheme parent_instance;
+
+ char *theme_dir;
+ char *theme_name;
+
+ /* Switched on GamesCardThemeFixed.use_scalable */
+ char *themesizepath;
+ CardSize *card_sizes;
+ guint n_card_sizes;
+
+ CardSize slot_size;
+ CardSize card_size;
+
+ guint use_scalable : 1;
+ guint theme_loaded : 1;
+ guint size_available : 1;
+
+ guint subrender : 1;
+ guint prescaled : 1;
+};
+
+/* #defining this prints out the time it takes to render the theme */
+/* #define INSTRUMENT_LOADING */
+
+#ifdef INSTRUMENT_LOADING
+static long totaltime = 0;
+#endif
+
+/* Class implementation */
+
+G_DEFINE_TYPE (GamesCardThemeFixed, games_card_theme_fixed, GAMES_TYPE_CARD_THEME);
+
+static void
+games_card_theme_fixed_clear_theme_data (GamesCardThemeFixed *theme)
+{
+#ifdef INSTRUMENT_LOADING
+ /* Reset the time */
+ totaltime = 0;
+#endif
+
+ g_free (theme->theme_name);
+ theme->theme_name = NULL;
+
+ g_free (theme->theme_dir);
+ theme->theme_dir = NULL;
+
+ g_free (theme->card_sizes);
+ theme->card_sizes = NULL;
+ theme->n_card_sizes = 0;
+
+ g_free (theme->themesizepath);
+ theme->themesizepath = NULL;
+
+ theme->size_available = FALSE;
+
+ theme->theme_loaded = FALSE;
+
+ theme->card_size.width = theme->card_size.height = theme->slot_size.width =
+ theme->slot_size.width = -1;
+}
+
+static gboolean
+games_card_theme_fixed_load_theme (GamesCardTheme *card_theme,
+ const char *theme_dir,
+ const char *theme_name,
+ GError **error__)
+{
+ GamesCardThemeFixed *theme = (GamesCardThemeFixed *) card_theme;
+ GKeyFile *key_file;
+ char *filename, *path;
+ GError *error = NULL;
+ int *sizes = NULL;
+ gsize n_sizes, i;
+ gboolean retval = FALSE;
+
+ if (theme->theme_name != NULL &&
+ strcmp (theme_name, theme->theme_name) == 0)
+ return TRUE;
+
+ games_card_theme_fixed_clear_theme_data (theme);
+
+ if (!theme_dir)
+ theme_dir = games_runtime_get_directory (GAMES_RUNTIME_PRERENDERED_CARDS_DIRECTORY);
+
+ filename = g_strdup_printf ("%s.card-theme", theme_name);
+ path = g_build_filename (theme_dir, filename, NULL);
+ g_free (filename);
+
+ key_file = g_key_file_new ();
+ if (!g_key_file_load_from_file (key_file, path, 0, &error)) {
+ g_warning ("Failed to load prerendered card theme from %s: %s\n", path,
+ error->message);
+ g_error_free (error);
+ goto loser;
+ }
+
+ sizes =
+ g_key_file_get_integer_list (key_file, "Card Theme", "Sizes", &n_sizes,
+ &error);
+ if (error) {
+ g_warning ("Failed to get card sizes: %s\n", error->message);
+ g_error_free (error);
+ goto loser;
+ }
+
+ if (n_sizes == 0) {
+ g_warning ("Card theme contains no sizes\n");
+ goto loser;
+ }
+
+ theme->card_sizes = g_new (CardSize, n_sizes);
+ theme->n_card_sizes = n_sizes;
+
+ for (i = 0; i < n_sizes; ++i) {
+ char group[32];
+ GError *err = NULL;
+ int width, height;
+
+ g_snprintf (group, sizeof (group), "%d", sizes[i]);
+
+ width = g_key_file_get_integer (key_file, group, "Width", &err);
+ if (err) {
+ g_warning ("Error loading width for size %d: %s\n", sizes[i],
+ err->message);
+ g_error_free (err);
+ goto loser;
+ }
+ height = g_key_file_get_integer (key_file, group, "Height", &err);
+ if (err) {
+ g_warning ("Error loading height for size %d: %s\n", sizes[i],
+ err->message);
+ g_error_free (err);
+ goto loser;
+ }
+
+ theme->card_sizes[i].width = width;
+ theme->card_sizes[i].height = height;
+ }
+
+ retval = TRUE;
+
+ theme->theme_name = g_strdup (theme_name);
+ theme->theme_dir = g_strdup (theme_dir);
+
+ theme->theme_loaded = TRUE;
+
+loser:
+
+ g_free (sizes);
+
+ g_key_file_free (key_file);
+ g_free (path);
+
+ if (!retval) {
+ games_card_theme_fixed_clear_theme_data (theme);
+ }
+
+ _games_card_theme_emit_changed (card_theme);
+
+ return retval;
+}
+
+static GdkPixbuf *
+games_card_theme_fixed_load_card (GamesCardThemeFixed *theme,
+ int card_id)
+{
+ GdkPixbuf *pixbuf;
+ GError *error = NULL;
+ char name[64], filename[64];
+ char *path;
+
+ if (!theme->theme_loaded || !theme->size_available)
+ return NULL;
+
+ g_return_val_if_fail (!theme->use_scalable, NULL);
+
+ games_card_get_name_by_id_snprintf (name, sizeof (name), card_id);
+ g_snprintf (filename, sizeof (filename), "%s.png", name);
+ path = g_build_filename (theme->themesizepath, filename, NULL);
+
+ pixbuf = gdk_pixbuf_new_from_file (path, &error);
+ if (!pixbuf) {
+ g_warning ("Failed to load card image %s: %s\n", filename,
+ error->message);
+ g_error_free (error);
+ }
+
+ g_free (path);
+
+ return pixbuf;
+}
+
+static void
+games_card_theme_fixed_finalize (GObject * object)
+{
+ GamesCardThemeFixed *theme = GAMES_CARD_THEME_FIXED (object);
+
+ games_card_theme_fixed_clear_theme_data (theme);
+
+ G_OBJECT_CLASS (games_card_theme_fixed_parent_class)->finalize (object);
+}
+
+static void
+games_card_theme_fixed_init (GamesCardThemeFixed *theme)
+{
+ theme->card_size.width = theme->card_size.height = -1;
+ theme->theme_name = NULL;
+}
+
+static const gchar *
+games_card_theme_fixed_get_theme_name (GamesCardTheme *card_theme)
+{
+ GamesCardThemeFixed *theme = (GamesCardThemeFixed *) card_theme;
+
+ return theme->theme_name;
+}
+
+static gboolean
+games_card_theme_fixed_set_card_size (GamesCardTheme *card_theme,
+ int width,
+ int height,
+ double proportion)
+{
+ GamesCardThemeFixed *theme = (GamesCardThemeFixed *) card_theme;
+
+ if (!theme->theme_loaded) {
+ g_warning ("Theme not loaded yet; cannot set size!");
+ return FALSE;
+ }
+
+ if ((width == theme->slot_size.width) &&
+ (height == theme->slot_size.height))
+ return FALSE;
+
+ theme->slot_size.width = width;
+ theme->slot_size.height = height;
+
+ {
+ guint i;
+ int twidth, theight;
+ CardSize size = { -1, -1 }, fit_size = { -1, -1};
+
+ twidth = FLOAT_TO_INT_CEIL (((double) width) * proportion);
+ theight = FLOAT_TO_INT_CEIL (((double) height) * proportion);
+
+ /* Find the closest prerendered size */
+ for (i = 0; i < theme->n_card_sizes; ++i) {
+ CardSize info = theme->card_sizes[i];
+
+ if (info.width > width || info.height > height)
+ continue;
+
+ if (info.width > fit_size.width && info.height > fit_size.height)
+ fit_size = info;
+
+ /* FIXMEchpe */
+ if (info.width <= twidth && info.height <= theight &&
+ info.width > size.width && info.height > size.height)
+ size = info;
+ }
+
+ if (size.width < 0 || size.height < 0)
+ size = fit_size;
+
+ if (size.width > 0 && size.height > 0) {
+ char sizestr[16];
+
+ if (size.width == theme->card_size.width &&
+ size.height == theme->card_size.height)
+ return FALSE;
+
+ g_free (theme->themesizepath);
+
+ g_snprintf (sizestr, sizeof (sizestr), "%d", size.width);
+ theme->themesizepath =
+ g_build_filename (theme->theme_dir, theme->theme_name, sizestr, NULL);
+
+ theme->size_available = TRUE;
+ theme->card_size = size;
+ } else {
+ g_warning ("No prerendered size available for %d:%d\n", width, height);
+ theme->size_available = FALSE;
+
+ /* FIXMEchpe: at least use the smallest available size here, or
+ * programme will surely crash when trying to render NULL pixbufs
+ * later on!
+ */
+ return FALSE;
+ }
+ }
+
+ _games_card_theme_emit_changed (card_theme);
+
+ return TRUE;
+}
+
+static CardSize
+games_card_theme_fixed_get_card_size (GamesCardTheme *card_theme)
+{
+ GamesCardThemeFixed *theme = (GamesCardThemeFixed *) card_theme;
+
+ return theme->card_size;
+}
+
+static double
+games_card_theme_fixed_get_card_aspect (GamesCardTheme *card_theme)
+{
+ GamesCardThemeFixed *theme = (GamesCardThemeFixed *) card_theme;
+
+ return ((double) theme->card_size.width) / ((double) theme->card_size.height);
+}
+
+static GdkPixbuf *
+games_card_theme_fixed_get_card_pixbuf (GamesCardTheme *card_theme,
+ int card_id)
+{
+ GamesCardThemeFixed *theme = (GamesCardThemeFixed *) card_theme;
+ GdkPixbuf *pixbuf;
+
+#ifdef INSTRUMENT_LOADING
+ clock_t t1, t2;
+
+ t1 = clock ();
+#endif
+
+ pixbuf = games_card_theme_fixed_load_card (theme, card_id);
+
+#ifdef INSTRUMENT_LOADING
+ t2 = clock ();
+ totaltime += (t2 - t1);
+ g_print ("took %.3fs to render card %d (cumulative: %.3fs)\n",
+ (t2 - t1) * 1.0 / CLOCKS_PER_SEC, card_id,
+ totaltime * 1.0 / CLOCKS_PER_SEC);
+#endif
+
+ return pixbuf;
+}
+
+static void
+games_card_theme_fixed_class_init (GamesCardThemeFixedClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GamesCardThemeClass *theme_class = GAMES_CARD_THEME_CLASS (klass);
+
+ gobject_class->finalize = games_card_theme_fixed_finalize;
+
+ theme_class->load_theme = games_card_theme_fixed_load_theme;
+ theme_class->get_theme_name = games_card_theme_fixed_get_theme_name;
+ theme_class->set_card_size = games_card_theme_fixed_set_card_size;
+ theme_class->get_card_size = games_card_theme_fixed_get_card_size;
+ theme_class->get_card_aspect = games_card_theme_fixed_get_card_aspect;
+ theme_class->get_card_pixbuf = games_card_theme_fixed_get_card_pixbuf;
+}
+
+/* public API */
+
+/**
+ * games_card_theme_fixed_new:
+ *
+ * Returns: a new #GamesCardThemeFixed
+ */
+GamesCardTheme *
+games_card_theme_fixed_new (void)
+{
+ return g_object_new (GAMES_TYPE_CARD_THEME_FIXED, NULL);
+}
Added: trunk/libgames-support/games-card-theme-private.h
==============================================================================
--- (empty file)
+++ trunk/libgames-support/games-card-theme-private.h Tue Jan 6 18:17:59 2009
@@ -0,0 +1,55 @@
+/*
+ Copyright  2004 Callum McKenzie
+ Copyright  2007, 2008 Christian Persch
+
+ This library is free software; you can redistribute it and'or modify
+ it under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Authors: Callum McKenzie <callum physics otago ac nz> */
+
+#define FLOAT_TO_INT_CEIL(f) ((int) (f + 0.5f))
+
+struct _GamesCardThemeClass {
+ GObjectClass parent_class;
+
+ /* vfuncs */
+ gboolean (* load_theme) (GamesCardTheme *theme,
+ const char *theme_dir,
+ const char *theme_name,
+ GError **error);
+ const char* (* get_theme_name) (GamesCardTheme *theme);
+ gboolean (* set_card_size) (GamesCardTheme *theme,
+ int width,
+ int height,
+ double proportion);
+ CardSize (* get_card_size) (GamesCardTheme *theme);
+ double (* get_card_aspect) (GamesCardTheme *theme);
+ GdkPixbuf* (* get_card_pixbuf) (GamesCardTheme *theme,
+ int card_id);
+
+#if GTK_CHECK_VERSION (2, 10, 0)
+ void (* set_font_options) (GamesCardTheme *theme,
+ const cairo_font_options_t *font_options);
+#endif
+};
+
+struct _GamesCardTheme {
+ GObject parent;
+
+ GamesCardThemeClass *klass;
+
+ char *theme_name;
+};
+
+void _games_card_theme_emit_changed (GamesCardTheme * theme);
Added: trunk/libgames-support/games-card-theme-svg.c
==============================================================================
--- (empty file)
+++ trunk/libgames-support/games-card-theme-svg.c Tue Jan 6 18:17:59 2009
@@ -0,0 +1,531 @@
+/*
+ Copyright  2004 Callum McKenzie
+ Copyright  2007, 2008 Christian Persch
+
+ This library is free software; you can redistribute it and'or modify
+ it under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Authors: Callum McKenzie <callum physics otago ac nz> */
+
+#include <config.h>
+
+#include <string.h>
+#include <glib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtk.h>
+
+#include "games-find-file.h"
+#include "games-files.h"
+#include "games-preimage.h"
+#include "games-runtime.h"
+
+#include "games-card-theme.h"
+#include "games-card-theme-private.h"
+
+struct _GamesCardThemeSVGClass {
+ GamesCardThemeClass parent_class;
+};
+
+struct _GamesCardThemeSVG {
+ GamesCardTheme parent_instance;
+
+ char *theme_dir;
+ char *theme_name;
+
+ GamesPreimage *cards_preimage;
+ GamesPreimage *slot_preimage;
+ GdkPixbuf *source;
+ CardSize subsize;
+
+ CardSize slot_size;
+ CardSize card_size;
+
+ guint theme_loaded : 1;
+ guint size_available : 1;
+
+ guint subrender : 1;
+ guint prescaled : 1;
+
+ cairo_font_options_t *font_options;
+};
+
+#define N_ROWS ((double) 5.0)
+#define N_COLS ((double) 13.0)
+
+#define DELTA (0.0f)
+
+/* #defining this prints out the time it takes to render the theme */
+/* #define INSTRUMENT_LOADING */
+
+#ifdef INSTRUMENT_LOADING
+static long totaltime = 0;
+#endif
+
+/* Class implementation */
+
+G_DEFINE_TYPE (GamesCardThemeSVG, games_card_theme_svg, GAMES_TYPE_CARD_THEME);
+
+static void
+games_card_theme_svg_clear_source_pixbuf (GamesCardThemeSVG *theme)
+{
+ if (theme->source) {
+ g_object_unref (theme->source);
+ theme->source = NULL;
+ }
+
+#ifdef INSTRUMENT_LOADING
+ /* Reset the time */
+ totaltime = 0;
+#endif
+}
+
+static void
+games_card_theme_svg_clear_theme_data (GamesCardThemeSVG *theme)
+{
+ games_card_theme_svg_clear_source_pixbuf (theme);
+
+ if (theme->cards_preimage != NULL) {
+ g_object_unref (theme->cards_preimage);
+ theme->cards_preimage = NULL;
+ }
+ if (theme->slot_preimage != NULL) {
+ g_object_unref (theme->slot_preimage);
+ theme->slot_preimage = NULL;
+ }
+
+ theme->subsize.width = -1;
+ theme->subsize.height = -1;
+
+ theme->theme_loaded = FALSE;
+
+ theme->card_size.width = theme->card_size.height = theme->slot_size.width =
+ theme->slot_size.width = -1;
+}
+
+static gboolean
+games_card_theme_svg_load_theme (GamesCardTheme *card_theme,
+ const char *theme_dir,
+ const char *theme_name,
+ GError **error)
+{
+ GamesCardThemeSVG *theme = (GamesCardThemeSVG *) card_theme;
+ GamesPreimage *preimage;
+ const char *slot_dir, *env;
+ gchar *filename, *path;
+
+#ifdef INSTRUMENT_LOADING
+ clock_t t1, t2;
+
+ t1 = clock ();
+#endif
+
+ if (theme->theme_name != NULL &&
+ strcmp (theme_name, theme->theme_name) == 0)
+ return TRUE;
+
+ games_card_theme_svg_clear_theme_data (theme);
+
+ g_free (theme->theme_name);
+ theme->theme_name = NULL;
+
+ // FIXMEchpe wtf?
+ if (theme->cards_preimage != NULL)
+ return TRUE;
+
+ if (!theme_dir)
+ theme_dir = games_runtime_get_directory (GAMES_RUNTIME_SCALABLE_CARDS_DIRECTORY);
+
+ /* First try and load the given file. */
+ filename = g_strdup_printf ("%s.svg", theme_name);
+ path = g_build_filename (theme_dir, filename, NULL);
+ preimage = games_preimage_new_from_file (path, NULL);
+ g_free (path);
+
+ /* Failing that, try and find a similar file (e.g. a suffix change). */
+ if (!preimage) {
+ path = games_find_similar_file (filename, theme_dir);
+ if (path) {
+ preimage = games_preimage_new_from_file (path, NULL);
+ g_free (path);
+ }
+ }
+
+ g_free (filename);
+
+ if (!preimage)
+ goto out;
+
+ if (theme->font_options) {
+ games_preimage_set_font_options (preimage, theme->font_options);
+ }
+
+ theme->cards_preimage = preimage;
+ theme->prescaled = games_preimage_is_scalable (preimage);
+
+ /* If we don't have a scalable format, build a scaled pixbuf that we'll cut up later */
+ if (!theme->prescaled) {
+ theme->source =
+ games_preimage_render_unscaled_pixbuf (theme->
+ cards_preimage);
+ }
+
+ /* And the slot image */
+ /* FIXMEchpe: use uninstalled data dir for rendering the card theme! */
+ slot_dir = games_runtime_get_directory (GAMES_RUNTIME_PIXMAP_DIRECTORY);
+ path = g_build_filename (slot_dir, "slot.svg", NULL);
+ theme->slot_preimage = games_preimage_new_from_file (path, NULL);
+ g_free (path);
+ g_return_val_if_fail (theme->slot_preimage != NULL, FALSE);
+
+ if (theme->font_options) {
+ games_preimage_set_font_options (theme->slot_preimage,
+ theme->font_options);
+ }
+
+ /* Use subrendering by default, but allow to override with the env var */
+ theme->subrender = TRUE;
+
+ env = g_getenv ("GAMES_CARDS_SUBRENDERING");
+ if (env != NULL) {
+ theme->subrender = g_ascii_strtoull (env, NULL, 0) != 0;
+ }
+#ifdef GNOME_ENABLE_DEBUG
+ if (theme->subrender)
+ g_print ("Using subrendering for theme \"%s\"\n", theme_name);
+ else
+ g_print ("Not using subrendering for theme \"%s\"\n", theme_name);
+#endif
+
+out:
+
+#ifdef INSTRUMENT_LOADING
+ t2 = clock ();
+ totaltime += (t2 - t1);
+ g_print ("took %.3fs to create preimage (cumulative %.3fs)\n",
+ (t2 - t1) * 1.0 / CLOCKS_PER_SEC,
+ totaltime * 1.0 / CLOCKS_PER_SEC);
+#endif
+
+ if (theme->cards_preimage != NULL) {
+ theme->theme_name = g_strdup (theme_name);
+
+ theme->theme_loaded = TRUE;
+
+ _games_card_theme_emit_changed (card_theme);
+ return TRUE;
+ }
+
+ games_card_theme_svg_clear_theme_data (theme);
+ _games_card_theme_emit_changed (card_theme);
+
+ return FALSE;
+}
+
+static gboolean
+games_card_theme_svg_prerender_scalable (GamesCardThemeSVG * theme)
+{
+#ifdef INSTRUMENT_LOADING
+ clock_t t1, t2;
+
+ t1 = clock ();
+#endif
+
+ g_return_val_if_fail (theme->cards_preimage != NULL, FALSE);
+ g_return_val_if_fail (theme->prescaled
+ || theme->source != NULL, FALSE);
+
+ theme->source =
+ games_preimage_render (theme->cards_preimage,
+ theme->card_size.width * 13,
+ theme->card_size.height * 5);
+ if (!theme->source)
+ return FALSE;
+
+ theme->subsize.width =
+ gdk_pixbuf_get_width (theme->source) / 13;
+ theme->subsize.height =
+ gdk_pixbuf_get_height (theme->source) / 5;
+
+#ifdef INSTRUMENT_LOADING
+ t2 = clock ();
+ g_print ("took %.3fs to prerender\n", (t2 - t1) * 1.0 / CLOCKS_PER_SEC);
+#endif
+
+ return TRUE;
+}
+
+static GdkPixbuf *
+games_card_theme_svg_render_card (GamesCardThemeSVG * theme, int card_id)
+{
+ GamesPreimage *preimage = theme->cards_preimage;
+ GdkPixbuf *subpixbuf, *card_pixbuf;
+ int suit, rank;
+
+ if (!theme->theme_loaded)
+ return NULL;
+
+ suit = card_id / 13;
+ rank = card_id % 13;
+
+ if (G_UNLIKELY (card_id == GAMES_CARD_SLOT)) {
+ subpixbuf = games_preimage_render (theme->slot_preimage,
+ theme->card_size.width,
+ theme->card_size.height);
+
+ return subpixbuf;
+ }
+
+ if (theme->subrender) {
+ double card_width, card_height;
+ double width, height;
+ double offsetx, offsety;
+ double zoomx, zoomy;
+ char node[64];
+
+ card_width = ((double) games_preimage_get_width (preimage)) / N_COLS;
+ card_height = ((double) games_preimage_get_height (preimage)) / N_ROWS;
+
+ width = theme->card_size.width - 2 * DELTA;
+ height = theme->card_size.height - 2 * DELTA;
+
+ offsetx = -((double) rank) * card_width + DELTA;
+ offsety = -((double) suit) * card_height + DELTA;
+
+ zoomx = width / card_width;
+ zoomy = height / card_height;
+
+ games_card_get_node_by_suit_and_rank_snprintf (node, sizeof (node), suit, rank);
+
+ subpixbuf = games_preimage_render_sub (preimage,
+ node,
+ theme->card_size.width, theme->card_size.height,
+ offsetx, offsety,
+ zoomx, zoomy);
+
+ return subpixbuf;
+ }
+
+ /* Not using subrendering */
+ if (!theme->source &&
+ !games_card_theme_svg_prerender_scalable (theme))
+ return NULL;
+
+ subpixbuf = gdk_pixbuf_new_subpixbuf (theme->source,
+ rank *
+ theme->subsize.width,
+ suit *
+ theme->subsize.height,
+ theme->subsize.width,
+ theme->subsize.height);
+ if (theme->prescaled) {
+ card_pixbuf = subpixbuf;
+ } else {
+ card_pixbuf = gdk_pixbuf_scale_simple (subpixbuf,
+ theme->card_size.width,
+ theme->card_size.height,
+ GDK_INTERP_BILINEAR);
+ g_object_unref (subpixbuf);
+ }
+
+ return card_pixbuf;
+}
+
+static void
+games_card_theme_svg_finalize (GObject * object)
+{
+ GamesCardThemeSVG *theme = GAMES_CARD_THEME_SVG (object);
+
+ games_card_theme_svg_clear_theme_data (theme);
+
+ g_free (theme->theme_name);
+ g_free (theme->theme_dir);
+
+ if (theme->font_options) {
+ cairo_font_options_destroy (theme->font_options);
+ }
+
+ G_OBJECT_CLASS (games_card_theme_svg_parent_class)->finalize (object);
+}
+
+static void
+games_card_theme_svg_init (GamesCardThemeSVG * cardtheme)
+{
+ cardtheme->card_size.width = cardtheme->card_size.height = -1;
+ cardtheme->theme_name = NULL;
+
+ cardtheme->prescaled = FALSE;
+
+ cardtheme->subrender = FALSE;
+}
+
+static void
+games_card_theme_svg_set_font_options (GamesCardTheme *card_theme,
+ const cairo_font_options_t *font_options)
+{
+ GamesCardThemeSVG *theme = (GamesCardThemeSVG *) card_theme;
+
+ if (font_options &&
+ theme->font_options &&
+ cairo_font_options_equal (font_options, theme->font_options))
+ return;
+
+ if (theme->font_options) {
+ cairo_font_options_destroy (theme->font_options);
+ }
+
+ if (font_options) {
+ theme->font_options = cairo_font_options_copy (font_options);
+ } else {
+ theme->font_options = NULL;
+ }
+
+ games_card_theme_svg_clear_source_pixbuf (theme);
+ _games_card_theme_emit_changed (card_theme);
+}
+
+static const gchar *
+games_card_theme_svg_get_theme_name (GamesCardTheme *card_theme)
+{
+ GamesCardThemeSVG *theme = (GamesCardThemeSVG *) card_theme;
+
+ return theme->theme_name;
+}
+
+static gboolean
+games_card_theme_svg_set_card_size (GamesCardTheme *card_theme,
+ int width,
+ int height,
+ double proportion)
+{
+ GamesCardThemeSVG *theme = (GamesCardThemeSVG *) card_theme;
+ double aspect_ratio, twidth, theight;
+
+ if (!theme->theme_loaded) {
+ g_warning ("Theme not loaded yet; cannot set size!");
+ return FALSE;
+ }
+
+ if ((width == theme->slot_size.width) &&
+ (height == theme->slot_size.height))
+ return FALSE;
+
+ theme->slot_size.width = width;
+ theme->slot_size.height = height;
+
+ /* Now calculate the card size: find the maximum size that fits
+ * into the given area, preserving the card's aspect ratio.
+ */
+ aspect_ratio = games_card_theme_get_aspect (card_theme);
+
+ twidth = proportion * width;
+ theight = proportion * height;
+ if (twidth / theight < aspect_ratio) {
+ theight = twidth / aspect_ratio;
+ } else {
+ twidth = theight * aspect_ratio;
+ }
+
+ if (theme->card_size.width == (int) twidth &&
+ theme->card_size.height == (int) theight)
+ return FALSE;
+
+ theme->card_size.width = twidth;
+ theme->card_size.height = theight;
+
+ games_card_theme_svg_clear_source_pixbuf (theme);
+ _games_card_theme_emit_changed (card_theme);
+
+ return TRUE;
+}
+
+static CardSize
+games_card_theme_svg_get_card_size (GamesCardTheme *card_theme)
+{
+ GamesCardThemeSVG *theme = (GamesCardThemeSVG *) card_theme;
+
+ return theme->card_size;
+}
+
+static double
+games_card_theme_svg_get_card_aspect (GamesCardTheme* card_theme)
+{
+ GamesCardThemeSVG *theme = (GamesCardThemeSVG *) card_theme;
+ double aspect;
+
+ g_return_val_if_fail (GAMES_IS_CARD_THEME_SVG (theme), 1.0);
+
+ aspect =
+ (((double) games_preimage_get_width (theme->cards_preimage))
+ * N_ROWS) /
+ (((double) games_preimage_get_height (theme->cards_preimage))
+ * N_COLS);
+
+ return aspect;
+}
+
+static GdkPixbuf *
+games_card_theme_svg_get_card_pixbuf (GamesCardTheme *card_theme,
+ int card_id)
+{
+ GamesCardThemeSVG *theme = (GamesCardThemeSVG *) card_theme;
+ GdkPixbuf *pixbuf;
+
+#ifdef INSTRUMENT_LOADING
+ clock_t t1, t2;
+
+ t1 = clock ();
+#endif
+
+ pixbuf = games_card_theme_svg_render_card (theme, card_id);
+
+#ifdef INSTRUMENT_LOADING
+ t2 = clock ();
+ totaltime += (t2 - t1);
+ g_print ("took %.3fs to render card %d (cumulative: %.3fs)\n",
+ (t2 - t1) * 1.0 / CLOCKS_PER_SEC, card_id,
+ totaltime * 1.0 / CLOCKS_PER_SEC);
+#endif
+
+ return pixbuf;
+}
+
+static void
+games_card_theme_svg_class_init (GamesCardThemeSVGClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GamesCardThemeClass *theme_class = GAMES_CARD_THEME_CLASS (klass);
+
+ gobject_class->finalize = games_card_theme_svg_finalize;
+
+ theme_class->load_theme = games_card_theme_svg_load_theme;
+ theme_class->get_theme_name = games_card_theme_svg_get_theme_name;
+ theme_class->set_card_size = games_card_theme_svg_set_card_size;
+ theme_class->get_card_size = games_card_theme_svg_get_card_size;
+ theme_class->get_card_aspect = games_card_theme_svg_get_card_aspect;
+ theme_class->get_card_pixbuf = games_card_theme_svg_get_card_pixbuf;
+ theme_class->set_font_options = games_card_theme_svg_set_font_options;
+}
+
+/* public API */
+
+/**
+ * games_card_theme_svg_new:
+ *
+ * Returns: a new #GamesCardThemeSVG
+ */
+GamesCardTheme*
+games_card_theme_svg_new (void)
+{
+ return g_object_new (GAMES_TYPE_CARD_THEME_SVG, NULL);
+}
Modified: trunk/libgames-support/games-card-theme.c
==============================================================================
--- trunk/libgames-support/games-card-theme.c (original)
+++ trunk/libgames-support/games-card-theme.c Tue Jan 6 18:17:59 2009
@@ -1,6 +1,6 @@
/*
Copyright  2004 Callum McKenzie
- Copyright  2007 Christian Persch
+ Copyright  2007, 2008 Christian Persch
This library is free software; you can redistribute it and'or modify
it under the terms of the GNU Library General Public License as published
@@ -31,52 +31,7 @@
#include "games-runtime.h"
#include "games-card-theme.h"
-
-struct _GamesCardThemeClass {
- GObjectClass parent_class;
-};
-
-struct _GamesCardTheme {
- GObject parent;
-
- gchar *theme_dir;
- gchar *theme_name;
-
- /* Switched on GamesCardTheme.use_scalable */
- union {
- struct {
- GamesPreimage *cards_preimage;
- GamesPreimage *slot_preimage;
- GdkPixbuf *source;
- CardSize subsize;
- } scalable;
- struct {
- char *themesizepath;
- CardSize *card_sizes;
- guint n_card_sizes;
- } prerendered;
- } theme_data;
-
- CardSize slot_size;
- CardSize card_size;
-
- guint use_scalable : 1;
- guint theme_loaded : 1;
- guint size_available : 1;
-
- guint subrender : 1;
- guint prescaled : 1;
-
-#if GTK_CHECK_VERSION (2, 10, 0)
- cairo_font_options_t *font_options;
-#endif
-};
-
-enum {
- PROP_0,
- PROP_SCALABLE,
- PROP_THEME_DIRECTORY
-};
+#include "games-card-theme-private.h"
enum {
CHANGED,
@@ -85,12 +40,6 @@
static guint signals[LAST_SIGNAL];
-#define N_ROWS ((double) 5.0)
-#define N_COLS ((double) 13.0)
-
-#define FLOAT_TO_INT_CEIL(f) ((int) (f + 0.5f))
-#define DELTA (0.0f)
-
/* #defining this prints out the time it takes to render the theme */
/* #define INSTRUMENT_LOADING */
@@ -98,284 +47,37 @@
static long totaltime = 0;
#endif
-static void
-games_card_theme_clear_source_pixbuf (GamesCardTheme * theme)
-{
-#ifdef HAVE_RSVG
- if (theme->use_scalable) {
- if (theme->theme_data.scalable.source) {
- g_object_unref (theme->theme_data.scalable.source);
- }
-
- theme->theme_data.scalable.source = NULL;
- }
-#endif /* HAVE_RSVG */
-
-#ifdef INSTRUMENT_LOADING
- /* Reset the time */
- totaltime = 0;
-#endif
-}
-
-static void
-games_card_theme_clear_theme_data (GamesCardTheme * theme)
-{
-#ifdef HAVE_RSVG
- if (theme->use_scalable) {
- if (theme->theme_data.scalable.cards_preimage != NULL) {
- g_object_unref (theme->theme_data.scalable.cards_preimage);
- theme->theme_data.scalable.cards_preimage = NULL;
- }
- if (theme->theme_data.scalable.slot_preimage != NULL) {
- g_object_unref (theme->theme_data.scalable.slot_preimage);
- theme->theme_data.scalable.slot_preimage = NULL;
- }
-
- theme->theme_data.scalable.subsize.width = -1;
- theme->theme_data.scalable.subsize.height = -1;
- } else
-#endif /* HAVE_RSVG */
- {
- g_free (theme->theme_data.prerendered.card_sizes);
- theme->theme_data.prerendered.card_sizes = NULL;
- theme->theme_data.prerendered.n_card_sizes = 0;
-
- g_free (theme->theme_data.prerendered.themesizepath);
- theme->theme_data.prerendered.themesizepath = NULL;
-
- theme->size_available = FALSE;
- }
-
- theme->theme_loaded = FALSE;
-}
-
-#ifdef HAVE_RSVG
-
-static gboolean
-games_card_theme_load_theme_scalable (GamesCardTheme * theme,
- const gchar * theme_name)
-{
- GamesPreimage *preimage;
- const char *theme_dir, *slot_dir, *env;
- gchar *filename, *path;
-
-#ifdef INSTRUMENT_LOADING
- clock_t t1, t2;
-
- t1 = clock ();
-#endif
-
- if (theme->theme_data.scalable.cards_preimage != NULL)
- return TRUE;
-
- theme_dir = theme->theme_dir;
- if (!theme_dir)
- return FALSE;
-
- /* First try and load the given file. */
- filename = g_strdup_printf ("%s.svg", theme_name);
- path = g_build_filename (theme_dir, filename, NULL);
- preimage = games_preimage_new_from_file (path, NULL);
- g_free (path);
-
- /* Failing that, try and find a similar file (e.g. a suffix change). */
- if (!preimage) {
- path = games_find_similar_file (filename, theme_dir);
- if (path) {
- preimage = games_preimage_new_from_file (path, NULL);
- g_free (path);
- }
- }
-
- g_free (filename);
-
- if (!preimage)
- goto out;
-
-#if GTK_CHECK_VERSION (2, 10, 0)
- if (theme->font_options) {
- games_preimage_set_font_options (preimage, theme->font_options);
- }
-#endif
-
- theme->theme_data.scalable.cards_preimage = preimage;
- theme->prescaled = games_preimage_is_scalable (preimage);
-
- /* If we don't have a scalable format, build a scaled pixbuf that we'll cut up later */
- if (!theme->prescaled) {
- theme->theme_data.scalable.source =
- games_preimage_render_unscaled_pixbuf (theme->theme_data.scalable.
- cards_preimage);
- }
-
- /* And the slot image */
- /* FIXMEchpe: use uninstalled data dir for rendering the card theme! */
- slot_dir = games_runtime_get_directory (GAMES_RUNTIME_PIXMAP_DIRECTORY);
- path = g_build_filename (slot_dir, "slot.svg", NULL);
- theme->theme_data.scalable.slot_preimage = games_preimage_new_from_file (path, NULL);
- g_free (path);
- g_return_val_if_fail (theme->theme_data.scalable.slot_preimage != NULL, FALSE);
-
-#if GTK_CHECK_VERSION (2, 10, 0)
- if (theme->font_options) {
- games_preimage_set_font_options (theme->theme_data.scalable.slot_preimage,
- theme->font_options);
- }
-#endif
-
- /* Use subrendering by default, but allow to override with the env var */
- theme->subrender = TRUE;
-
- env = g_getenv ("GAMES_CARDS_SUBRENDERING");
- if (env != NULL) {
- theme->subrender = g_ascii_strtoull (env, NULL, 0) != 0;
- }
-#ifdef GNOME_ENABLE_DEBUG
- if (theme->subrender)
- g_print ("Using subrendering for theme \"%s\"\n", theme_name);
- else
- g_print ("Not using subrendering for theme \"%s\"\n", theme_name);
-#endif
-
-out:
-
-#ifdef INSTRUMENT_LOADING
- t2 = clock ();
- totaltime += (t2 - t1);
- g_print ("took %.3fs to create preimage (cumulative %.3fs)\n",
- (t2 - t1) * 1.0 / CLOCKS_PER_SEC,
- totaltime * 1.0 / CLOCKS_PER_SEC);
-#endif
-
- if (theme->theme_data.scalable.cards_preimage == NULL) {
- games_card_theme_clear_theme_data (theme);
- }
-
- return theme->theme_data.scalable.cards_preimage != NULL;
-}
-
-#endif /* HAVE_RSVG */
-
static gboolean
-games_card_theme_load_theme_prerendered (GamesCardTheme * theme,
- const gchar * theme_name)
+games_card_theme_load_theme (GamesCardTheme *theme,
+ const char *theme_dir,
+ const char *theme_name)
{
- GKeyFile *key_file;
- const char *theme_dir;
- char *filename, *path;
- GError *error = NULL;
- int *sizes = NULL;
- gsize n_sizes, i;
- gboolean retval = FALSE;
-
- theme_dir = games_runtime_get_directory (GAMES_RUNTIME_PRERENDERED_CARDS_DIRECTORY);
- filename = g_strdup_printf ("%s.card-theme", theme_name);
- path = g_build_filename (theme_dir, filename, NULL);
- g_free (filename);
-
- key_file = g_key_file_new ();
- if (!g_key_file_load_from_file (key_file, path, 0, &error)) {
- g_warning ("Failed to load prerendered card theme from %s: %s\n", path,
- error->message);
- g_error_free (error);
- goto loser;
- }
-
- sizes =
- g_key_file_get_integer_list (key_file, "Card Theme", "Sizes", &n_sizes,
- &error);
- if (error) {
- g_warning ("Failed to get card sizes: %s\n", error->message);
- g_error_free (error);
- goto loser;
- }
-
- if (n_sizes == 0) {
- g_warning ("Card theme contains no sizes\n");
- goto loser;
- }
-
- theme->theme_data.prerendered.card_sizes = g_new (CardSize, n_sizes);
- theme->theme_data.prerendered.n_card_sizes = n_sizes;
-
- for (i = 0; i < n_sizes; ++i) {
- char group[32];
- GError *err = NULL;
- int width, height;
-
- g_snprintf (group, sizeof (group), "%d", sizes[i]);
-
- width = g_key_file_get_integer (key_file, group, "Width", &err);
- if (err) {
- g_warning ("Error loading width for size %d: %s\n", sizes[i],
- err->message);
- g_error_free (err);
- goto loser;
- }
- height = g_key_file_get_integer (key_file, group, "Height", &err);
- if (err) {
- g_warning ("Error loading height for size %d: %s\n", sizes[i],
- err->message);
- g_error_free (err);
- goto loser;
- }
-
- theme->theme_data.prerendered.card_sizes[i].width = width;
- theme->theme_data.prerendered.card_sizes[i].height = height;
- }
-
- retval = TRUE;
-
-loser:
-
- g_free (sizes);
-
- g_key_file_free (key_file);
- g_free (path);
-
- if (!retval) {
- games_card_theme_clear_theme_data (theme);
- }
-
- return retval;
+ return theme->klass->load_theme (theme, theme_dir, theme_name, NULL);
}
static gboolean
-games_card_theme_load_theme (GamesCardTheme * theme, const gchar * theme_name)
+games_card_theme_load_theme_with_fallback (GamesCardTheme *theme,
+ const char *theme_dir,
+ const char *theme_name)
{
- gboolean success;
-
-#ifdef HAVE_RSVG
- if (theme->use_scalable) {
- success = games_card_theme_load_theme_scalable (theme, theme_name);
- } else
-#endif /* HAVE_RSVG */
- {
- success = games_card_theme_load_theme_prerendered (theme, theme_name);
- }
-
- if (success) {
- g_free (theme->theme_name);
- theme->theme_name = g_strdup (theme_name);
-
- theme->theme_loaded = TRUE;
- }
-
- return success;
-}
+ if (games_card_theme_load_theme (theme, theme_dir, theme_name))
+ return TRUE;
-static gboolean
-games_card_theme_load_theme_with_fallback (GamesCardTheme * theme,
- const gchar * theme_name)
-{
- if (games_card_theme_load_theme (theme, theme_name))
+ // FIXMEchpe: compare strict dir equality, not just != NULL
+ /* Try fallback in default theme directory */
+ if (theme_dir != NULL &&
+ games_card_theme_load_theme (theme, NULL, theme_name))
return TRUE;
g_warning ("Failed to load theme '%s'; trying fallback theme '%s'",
theme_name, GAMES_CARD_THEME_DEFAULT);
if (strcmp (theme_name, GAMES_CARD_THEME_DEFAULT) != 0 &&
- games_card_theme_load_theme (theme, GAMES_CARD_THEME_DEFAULT))
+ (games_card_theme_load_theme (theme, theme_dir, GAMES_CARD_THEME_DEFAULT)))
+ return FALSE;
+ if (theme_dir != NULL &&
+ strcmp (theme_name, GAMES_CARD_THEME_DEFAULT) != 0 &&
+ (games_card_theme_load_theme (theme, NULL, GAMES_CARD_THEME_DEFAULT)))
return FALSE;
g_warning ("Failed to load fallback theme!");
@@ -383,220 +85,34 @@
return FALSE;
}
-#ifdef HAVE_RSVG
-
-static gboolean
-games_card_theme_prerender_scalable (GamesCardTheme * theme)
-{
-#ifdef INSTRUMENT_LOADING
- clock_t t1, t2;
-
- t1 = clock ();
-#endif
-
- g_return_val_if_fail (theme->use_scalable, FALSE);
- g_return_val_if_fail (theme->theme_data.scalable.cards_preimage != NULL, FALSE);
- g_return_val_if_fail (theme->prescaled
- || theme->theme_data.scalable.source != NULL, FALSE);
-
- theme->theme_data.scalable.source =
- games_preimage_render (theme->theme_data.scalable.cards_preimage,
- theme->card_size.width * 13,
- theme->card_size.height * 5);
- if (!theme->theme_data.scalable.source)
- return FALSE;
-
- theme->theme_data.scalable.subsize.width =
- gdk_pixbuf_get_width (theme->theme_data.scalable.source) / 13;
- theme->theme_data.scalable.subsize.height =
- gdk_pixbuf_get_height (theme->theme_data.scalable.source) / 5;
-
-#ifdef INSTRUMENT_LOADING
- t2 = clock ();
- g_print ("took %.3fs to prerender\n", (t2 - t1) * 1.0 / CLOCKS_PER_SEC);
-#endif
-
- return TRUE;
-}
-
-static GdkPixbuf *
-games_card_theme_render_card (GamesCardTheme * theme, int card_id)
-{
- GamesPreimage *preimage = theme->theme_data.scalable.cards_preimage;
- GdkPixbuf *subpixbuf, *card_pixbuf;
- int suit, rank;
-
- if (!theme->theme_loaded)
- return NULL;
-
- g_return_val_if_fail (theme->use_scalable, NULL);
-
- suit = card_id / 13;
- rank = card_id % 13;
-
- if (G_UNLIKELY (card_id == GAMES_CARD_SLOT)) {
- subpixbuf = games_preimage_render (theme->theme_data.scalable.slot_preimage,
- theme->card_size.width,
- theme->card_size.height);
-
- return subpixbuf;
- }
-
- if (theme->subrender) {
- double card_width, card_height;
- double width, height;
- double offsetx, offsety;
- double zoomx, zoomy;
- char node[64];
-
- card_width = ((double) games_preimage_get_width (preimage)) / N_COLS;
- card_height = ((double) games_preimage_get_height (preimage)) / N_ROWS;
-
- width = theme->card_size.width - 2 * DELTA;
- height = theme->card_size.height - 2 * DELTA;
-
- offsetx = -((double) rank) * card_width + DELTA;
- offsety = -((double) suit) * card_height + DELTA;
-
- zoomx = width / card_width;
- zoomy = height / card_height;
-
- games_card_get_node_by_suit_and_rank_snprintf (node, sizeof (node), suit, rank);
-
- subpixbuf = games_preimage_render_sub (preimage,
- node,
- theme->card_size.width, theme->card_size.height,
- offsetx, offsety,
- zoomx, zoomy);
-
- return subpixbuf;
- }
-
- /* Not using subrendering */
- if (!theme->theme_data.scalable.source &&
- !games_card_theme_prerender_scalable (theme))
- return NULL;
-
- subpixbuf = gdk_pixbuf_new_subpixbuf (theme->theme_data.scalable.source,
- rank *
- theme->theme_data.scalable.subsize.width,
- suit *
- theme->theme_data.scalable.subsize.height,
- theme->theme_data.scalable.subsize.width,
- theme->theme_data.scalable.subsize.height);
- if (theme->prescaled) {
- card_pixbuf = subpixbuf;
- } else {
- card_pixbuf = gdk_pixbuf_scale_simple (subpixbuf,
- theme->card_size.width,
- theme->card_size.height,
- GDK_INTERP_BILINEAR);
- g_object_unref (subpixbuf);
- }
-
- return card_pixbuf;
-}
-
-#endif /* HAVE_RSVG */
-
-static GdkPixbuf *
-games_card_theme_load_card (GamesCardTheme * theme, int card_id)
-{
- GdkPixbuf *pixbuf;
- GError *error = NULL;
- char name[64], filename[64];
- char *path;
-
- if (!theme->theme_loaded || !theme->size_available)
- return NULL;
-
- g_return_val_if_fail (!theme->use_scalable, NULL);
-
- games_card_get_name_by_id_snprintf (name, sizeof (name), card_id);
- g_snprintf (filename, sizeof (filename), "%s.png", name);
- path = g_build_filename (theme->theme_data.prerendered.themesizepath, filename, NULL);
-
- pixbuf = gdk_pixbuf_new_from_file (path, &error);
- if (!pixbuf) {
- g_warning ("Failed to load card image %s: %s\n", filename,
- error->message);
- g_error_free (error);
- return NULL;
- }
- g_free (path);
-
- return pixbuf;
-}
-
/* Class implementation */
-G_DEFINE_TYPE (GamesCardTheme, games_card_theme, G_TYPE_OBJECT);
+G_DEFINE_ABSTRACT_TYPE (GamesCardTheme, games_card_theme, G_TYPE_OBJECT);
static void
-games_card_theme_finalize (GObject * object)
+games_card_theme_init (GamesCardTheme * theme)
{
- GamesCardTheme *theme = GAMES_CARD_THEME (object);
-
- games_card_theme_clear_source_pixbuf (theme);
-
- games_card_theme_clear_theme_data (theme);
-
- g_free (theme->theme_name);
- g_free (theme->theme_dir);
-
-#if GTK_CHECK_VERSION (2, 10, 0)
- if (theme->font_options) {
- cairo_font_options_destroy (theme->font_options);
- }
-#endif
-
- G_OBJECT_CLASS (games_card_theme_parent_class)->finalize (object);
}
-static void
-games_card_theme_init (GamesCardTheme * cardtheme)
+static GObject *
+games_card_theme_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
{
- cardtheme->card_size.width = cardtheme->card_size.height = -1;
- cardtheme->theme_name = NULL;
+ GObject *object;
+ GamesCardTheme *theme;
- cardtheme->prescaled = FALSE;
+ object = G_OBJECT_CLASS (games_card_theme_parent_class)->constructor
+ (type, n_construct_properties, construct_params);
-#ifdef HAVE_RSVG
- cardtheme->subrender = FALSE;
- cardtheme->use_scalable = TRUE;
-#else
- cardtheme->use_scalable = FALSE;
-#endif /* HAVE_RSVG */
-}
+ theme = GAMES_CARD_THEME (object);
-static void
-games_card_theme_set_property (GObject * object,
- guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GamesCardTheme *theme = GAMES_CARD_THEME (object);
-
- switch (prop_id) {
- case PROP_SCALABLE: {
- gboolean use_scalable = (g_value_get_boolean (value) != FALSE);
-
-#ifndef HAVE_RSVG
- if (use_scalable) {
- g_warning ("Cannot enable scalable cards since RSVG support is not compiled in\n");
- use_scalable = FALSE;
- }
-#endif
- theme->use_scalable = use_scalable;
- break;
- }
- case PROP_THEME_DIRECTORY:
- theme->theme_dir = g_value_dup_string (value);
- if (!theme->theme_dir)
- theme->theme_dir = g_strdup (games_runtime_get_directory (theme->use_scalable ? GAMES_RUNTIME_SCALABLE_CARDS_DIRECTORY
- : GAMES_RUNTIME_PRERENDERED_CARDS_DIRECTORY));
+ /* NOTE! We have to do this here, since it returns the wrong class
+ * (GamesCardThemeClass) when called in games_card_theme_init() !
+ */
+ theme->klass = GAMES_CARD_THEME_GET_CLASS (theme);
- break;
- }
+ return object;
}
static void
@@ -604,8 +120,7 @@
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- gobject_class->set_property = games_card_theme_set_property;
- gobject_class->finalize = games_card_theme_finalize;
+ gobject_class->constructor = games_card_theme_constructor;
/**
* GamesCardTheme:changed:
@@ -624,48 +139,18 @@
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0, NULL);
-
- g_object_class_install_property
- (gobject_class,
- PROP_SCALABLE,
- g_param_spec_boolean ("scalable", NULL, NULL,
- FALSE,
- G_PARAM_WRITABLE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB |
- G_PARAM_CONSTRUCT_ONLY));
- g_object_class_install_property
- (gobject_class,
- PROP_THEME_DIRECTORY,
- g_param_spec_string ("theme-directory", NULL, NULL,
- NULL,
- G_PARAM_WRITABLE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB |
- G_PARAM_CONSTRUCT_ONLY));
}
-/* public API */
+/* private API */
-/**
- * games_card_theme_new:
- * @theme_dir: the directory to load the theme data from, or %NULL to use
- * the default directory
- * @scalable: whether to use scalable themes, or prerendered themes
- *
- * Returns: a new #GamesCardTheme
- */
-GamesCardTheme *
-games_card_theme_new (const char *theme_dir, gboolean scalable)
+void
+_games_card_theme_emit_changed (GamesCardTheme *theme)
{
- return g_object_new (GAMES_TYPE_CARD_THEME,
- "scalable", scalable,
- "theme-directory", theme_dir,
- NULL);
+ g_signal_emit (theme, signals[CHANGED], 0);
}
+/* public API */
+
#if GTK_CHECK_VERSION (2, 10, 0)
/**
@@ -676,28 +161,15 @@
* Sets the font options to use when drawing the card images.
*/
void
-games_card_theme_set_font_options (GamesCardTheme * theme,
+games_card_theme_set_font_options (GamesCardTheme *theme,
const cairo_font_options_t *font_options)
{
g_return_if_fail (GAMES_IS_CARD_THEME (theme));
- if (font_options &&
- theme->font_options &&
- cairo_font_options_equal (font_options, theme->font_options))
+ if (!theme->klass->set_font_options)
return;
- if (theme->font_options) {
- cairo_font_options_destroy (theme->font_options);
- }
-
- if (font_options) {
- theme->font_options = cairo_font_options_copy (font_options);
- } else {
- theme->font_options = NULL;
- }
-
- games_card_theme_clear_source_pixbuf (theme);
- g_signal_emit (theme, signals[CHANGED], 0);
+ theme->klass->set_font_options (theme, font_options);
}
#endif /* GTK 2.10.0 */
@@ -705,6 +177,7 @@
/**
* games_card_theme_set_theme:
* @theme:
+ * @theme_dir: the theme directory, or %NULL to use the default
* @theme_name: the name of the theme to load
*
* Loads the card theme @theme_name. If the card theme cannot be loaded,
@@ -716,23 +189,14 @@
* Returns: %TRUE iff loading the new card theme succeeded
*/
gboolean
-games_card_theme_set_theme (GamesCardTheme * theme, const gchar * theme_name)
+games_card_theme_set_theme (GamesCardTheme *theme,
+ const char *theme_dir,
+ const char *theme_name)
{
g_return_val_if_fail (GAMES_IS_CARD_THEME (theme), FALSE);
g_return_val_if_fail (theme_name != NULL && theme_name[0] != '\0', FALSE);
- if (theme->theme_name != NULL
- && strcmp (theme_name, theme->theme_name) == 0)
- return TRUE;
-
- games_card_theme_clear_source_pixbuf (theme);
- games_card_theme_clear_theme_data (theme);
- g_signal_emit (theme, signals[CHANGED], 0);
-
- theme->card_size.width = theme->card_size.height = theme->slot_size.width =
- theme->slot_size.width = -1;
-
- return games_card_theme_load_theme_with_fallback (theme, theme_name);
+ return games_card_theme_load_theme_with_fallback (theme, theme_dir, theme_name);
}
/**
@@ -742,12 +206,12 @@
* Returns: the name of the currently loaded card theme, or %NULL if no theme
* is loaded
*/
-const gchar *
-games_card_theme_get_theme (GamesCardTheme * theme)
+const char *
+games_card_theme_get_theme (GamesCardTheme *theme)
{
g_return_val_if_fail (GAMES_IS_CARD_THEME (theme), NULL);
- return theme->theme_name;
+ return theme->klass->get_theme_name (theme);
}
/**
@@ -766,105 +230,14 @@
* Returns: %TRUE iff the card size was changed
*/
gboolean
-games_card_theme_set_size (GamesCardTheme * theme,
- gint width, gint height, gdouble proportion)
+games_card_theme_set_size (GamesCardTheme *theme,
+ int width,
+ int height,
+ double proportion)
{
- if (!theme->theme_loaded) {
- g_warning ("Theme not loaded yet; cannot set size!");
- return FALSE;
- }
-
- if ((width == theme->slot_size.width) &&
- (height == theme->slot_size.height))
- return FALSE;
-
- theme->slot_size.width = width;
- theme->slot_size.height = height;
-
-#ifdef HAVE_RSVG
- if (theme->use_scalable) {
- double aspect_ratio, twidth, theight;
-
- /* Now calculate the card size: find the maximum size that fits
- * into the given area, preserving the card's aspect ratio.
- */
- aspect_ratio = games_card_theme_get_aspect (theme);
-
- twidth = proportion * width;
- theight = proportion * height;
- if (twidth / theight < aspect_ratio) {
- theight = twidth / aspect_ratio;
- } else {
- twidth = theight * aspect_ratio;
- }
-
- if (theme->card_size.width == (int) twidth
- && theme->card_size.height == (int) theight)
- return FALSE;
-
- theme->card_size.width = twidth;
- theme->card_size.height = theight;
-
- } else
-#endif /* HAVE_RSVG */
- {
- guint i;
- int twidth, theight;
- CardSize size = { -1, -1 }, fit_size = { -1, -1};
-
- twidth = FLOAT_TO_INT_CEIL (((double) width) * proportion);
- theight = FLOAT_TO_INT_CEIL (((double) height) * proportion);
-
- /* Find the closest prerendered size */
- for (i = 0; i < theme->theme_data.prerendered.n_card_sizes; ++i) {
- CardSize info = theme->theme_data.prerendered.card_sizes[i];
-
- if (info.width > width || info.height > height)
- continue;
-
- if (info.width > fit_size.width && info.height > fit_size.height)
- fit_size = info;
-
- /* FIXMEchpe */
- if (info.width <= twidth && info.height <= theight &&
- info.width > size.width && info.height > size.height)
- size = info;
- }
-
- if (size.width < 0 || size.height < 0)
- size = fit_size;
-
- if (size.width > 0 && size.height > 0) {
- char sizestr[16];
-
- if (size.width == theme->card_size.width &&
- size.height == theme->card_size.height)
- return FALSE;
-
- g_free (theme->theme_data.prerendered.themesizepath);
-
- g_snprintf (sizestr, sizeof (sizestr), "%d", size.width);
- theme->theme_data.prerendered.themesizepath =
- g_build_filename (theme->theme_dir, theme->theme_name, sizestr, NULL);
-
- theme->size_available = TRUE;
- theme->card_size = size;
- } else {
- g_warning ("No prerendered size available for %d:%d\n", width, height);
- theme->size_available = FALSE;
-
- /* FIXMEchpe: at least use the smallest available size here, or
- * programme will surely crash when trying to render NULL pixbufs
- * later on!
- */
- return FALSE;
- }
- }
-
- games_card_theme_clear_source_pixbuf (theme);
- g_signal_emit (theme, signals[CHANGED], 0);
+ g_return_val_if_fail (GAMES_IS_CARD_THEME (theme), FALSE);
- return TRUE;
+ return theme->klass->set_card_size (theme, width, height, proportion);
}
/**
@@ -874,9 +247,9 @@
* Returns: the currently selected card size
*/
CardSize
-games_card_theme_get_size (GamesCardTheme * theme)
+games_card_theme_get_size (GamesCardTheme *theme)
{
- return theme->card_size;
+ return theme->klass->get_card_size (theme);
}
/**
@@ -888,25 +261,9 @@
double
games_card_theme_get_aspect (GamesCardTheme * theme)
{
- double aspect;
-
g_return_val_if_fail (GAMES_IS_CARD_THEME (theme), 1.0);
-#ifdef HAVE_RSVG
- if (theme->use_scalable) {
- aspect =
- (((double) games_preimage_get_width (theme->theme_data.scalable.cards_preimage))
- * N_ROWS) /
- (((double) games_preimage_get_height (theme->theme_data.scalable.cards_preimage))
- * N_COLS);
- } else
-#endif
- {
- aspect =
- ((double) theme->card_size.width) / ((double) theme->card_size.height);
- }
-
- return aspect;
+ return theme->klass->get_card_aspect (theme);
}
/**
@@ -933,14 +290,7 @@
t1 = clock ();
#endif
-#ifdef HAVE_RSVG
- if (theme->use_scalable) {
- pixbuf = games_card_theme_render_card (theme, card_id);
- } else
-#endif /* HAVE_RSVG */
- {
- pixbuf = games_card_theme_load_card (theme, card_id);
- }
+ pixbuf = theme->klass->get_card_pixbuf (theme, card_id);
#ifdef INSTRUMENT_LOADING
t2 = clock ();
Modified: trunk/libgames-support/games-card-theme.h
==============================================================================
--- trunk/libgames-support/games-card-theme.h (original)
+++ trunk/libgames-support/games-card-theme.h Tue Jan 6 18:17:59 2009
@@ -1,6 +1,6 @@
/*
Copyright  2004 Callum McKenzie
- Copyright  2007 Christian Persch
+ Copyright  2007, 2008 Christian Persch
This library is free software; you can redistribute it and'or modify
it under the terms of the GNU Library General Public License as published
@@ -28,12 +28,20 @@
G_BEGIN_DECLS
+#define GAMES_CARD_THEME_ERROR (g_quark_from_static_string ("games-card-theme"))
+
+typedef enum {
+ GAMES_CARD_THEME_ERROR_GENERIC = 0
+} GamesCardThemeError;
+
+/* GamesCardTheme */
+
#define GAMES_TYPE_CARD_THEME (games_card_theme_get_type ())
#define GAMES_CARD_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME, GamesCardTheme))
#define GAMES_CARD_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME, GamesCardThemeClass))
#define GAMES_IS_CARD_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME))
#define GAMES_IS_CARD_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME))
-#define GAMES_CARD_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME))
+#define GAMES_CARD_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME, GamesCardThemeClass))
typedef struct {
gint width;
@@ -45,29 +53,60 @@
GType games_card_theme_get_type (void);
-GamesCardTheme *games_card_theme_new (const char *theme_dir,
- gboolean scalable);
-
#if GTK_CHECK_VERSION (2, 10, 0)
void games_card_theme_set_font_options (GamesCardTheme *theme,
const cairo_font_options_t *font_options);
#endif
-gboolean games_card_theme_set_theme (GamesCardTheme * theme,
- const gchar * name);
+gboolean games_card_theme_set_theme (GamesCardTheme *theme,
+ const char *theme_dir,
+ const char *theme_name);
const gchar *games_card_theme_get_theme (GamesCardTheme * theme);
gboolean games_card_theme_set_size (GamesCardTheme * theme,
- gint width,
- gint height, gdouble proportion);
+ int width,
+ int height,
+ double proportion);
CardSize games_card_theme_get_size (GamesCardTheme * theme);
double games_card_theme_get_aspect (GamesCardTheme * theme);
GdkPixbuf *games_card_theme_get_card_pixbuf (GamesCardTheme * theme,
- gint cardid);
+ int cardid);
+
+/* GamesCardThemeSVG */
+
+#define GAMES_TYPE_CARD_THEME_SVG (games_card_theme_svg_get_type ())
+#define GAMES_CARD_THEME_SVG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_SVG, GamesCardThemeSVG))
+#define GAMES_CARD_THEME_SVG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_SVG, GamesCardThemeSVGClass))
+#define GAMES_IS_CARD_THEME_SVG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_SVG))
+#define GAMES_IS_CARD_THEME_SVG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_SVG))
+#define GAMES_CARD_THEME_SVG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_SVG, GamesCardThemeSVGClass))
+
+typedef struct _GamesCardThemeSVGClass GamesCardThemeSVGClass;
+typedef struct _GamesCardThemeSVG GamesCardThemeSVG;
+
+GType games_card_theme_svg_get_type (void);
+
+GamesCardTheme* games_card_theme_svg_new (void);
+
+/* GamesCardThemeFixed */
+
+#define GAMES_TYPE_CARD_THEME_FIXED (games_card_theme_fixed_get_type ())
+#define GAMES_CARD_THEME_FIXED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_FIXED, GamesCardThemeFixed))
+#define GAMES_CARD_THEME_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_FIXED, GamesCardThemeFixedClass))
+#define GAMES_IS_CARD_THEME_FIXED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_FIXED))
+#define GAMES_IS_CARD_THEME_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_FIXED))
+#define GAMES_CARD_THEME_FIXED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_FIXED, GamesCardThemeFixedClass))
+
+typedef struct _GamesCardThemeFixedClass GamesCardThemeFixedClass;
+typedef struct _GamesCardThemeFixed GamesCardThemeFixed;
+
+GType games_card_theme_fixed_get_type (void);
+
+GamesCardTheme* games_card_theme_fixed_new (void);
G_END_DECLS
Modified: trunk/libgames-support/render-cards.c
==============================================================================
--- trunk/libgames-support/render-cards.c (original)
+++ trunk/libgames-support/render-cards.c Tue Jan 6 18:17:59 2009
@@ -130,7 +130,7 @@
goto loser;
}
- theme = games_card_theme_new (NULL, TRUE);
+ theme = games_card_theme_svg_new ();
if (antialias_set) {
cairo_font_options_t *font_options;
@@ -142,7 +142,7 @@
cairo_font_options_destroy (font_options);
}
- if (!games_card_theme_set_theme (theme, theme_name)) {
+ if (!games_card_theme_set_theme (theme, theme_dir, theme_name)) {
g_warning ("Failed to load theme '%s'\n", theme_name);
goto loser;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]