gnome-games r8418 - trunk/libgames-support



Author: chpe
Date: Tue Jan  6 18:18:03 2009
New Revision: 8418
URL: http://svn.gnome.org/viewvc/gnome-games?rev=8418&view=rev

Log:
Split the slicing rendering of the pre-2.19 legacy theme format off into
its own class, and make it and the SVG theme class use a common abstract
base class GamesCardThemePreimage.

Added:
   trunk/libgames-support/games-card-theme-preimage.c
   trunk/libgames-support/games-card-theme-sliced.c
Modified:
   trunk/libgames-support/Makefile.am
   trunk/libgames-support/games-card-theme-private.h
   trunk/libgames-support/games-card-theme-svg.c
   trunk/libgames-support/games-card-theme.h

Modified: trunk/libgames-support/Makefile.am
==============================================================================
--- trunk/libgames-support/Makefile.am	(original)
+++ trunk/libgames-support/Makefile.am	Tue Jan  6 18:18:03 2009
@@ -60,6 +60,8 @@
 	games-gridframe.h		\
 	games-card-selector.c		\
 	games-card-selector.h		\
+	games-card-theme-preimage.c	\
+	games-card-theme-sliced.c	\
 	games-preimage.c                \
 	games-preimage.h                \
 	games-score.h			\

Added: trunk/libgames-support/games-card-theme-preimage.c
==============================================================================
--- (empty file)
+++ trunk/libgames-support/games-card-theme-preimage.c	Tue Jan  6 18:18:03 2009
@@ -0,0 +1,332 @@
+/*
+   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"
+
+#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_ABSTRACT_TYPE (GamesCardThemePreimage, games_card_theme_preimage, GAMES_TYPE_CARD_THEME);
+
+void
+_games_card_theme_preimage_clear_sized_theme_data (GamesCardThemePreimage *theme)
+{
+  if (GAMES_CARD_THEME_PREIMAGE_GET_CLASS (theme)->clear_sized_theme_data)
+    GAMES_CARD_THEME_PREIMAGE_GET_CLASS (theme)->clear_sized_theme_data (theme);
+
+#ifdef INSTRUMENT_LOADING
+  /* Reset the time */
+  totaltime = 0;
+#endif
+}
+
+static void
+games_card_theme_preimage_clear_theme_data (GamesCardThemePreimage *theme)
+{
+  _games_card_theme_preimage_clear_sized_theme_data (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_preimage_load_theme (GamesCardTheme *card_theme,
+                                      const char *theme_dir,
+                                      const char *theme_name,
+                                      GError **error)
+{
+  GamesCardThemePreimage *theme = (GamesCardThemePreimage *) card_theme;
+  GamesPreimage *preimage;
+  const char *slot_dir;
+  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_preimage_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;
+
+  /* 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);
+  }
+
+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_preimage_clear_theme_data (theme);
+  _games_card_theme_emit_changed (card_theme);
+
+  return FALSE;
+}
+
+static void
+games_card_theme_preimage_finalize (GObject * object)
+{
+  GamesCardThemePreimage *theme = GAMES_CARD_THEME_PREIMAGE (object);
+
+  games_card_theme_preimage_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_preimage_parent_class)->finalize (object);
+}
+
+static void
+games_card_theme_preimage_init (GamesCardThemePreimage * theme)
+{
+  theme->card_size.width = theme->card_size.height = -1;
+  theme->theme_name = NULL;
+
+  theme->prescaled = FALSE;
+}
+
+static void
+games_card_theme_preimage_set_font_options (GamesCardTheme *card_theme,
+                                       const cairo_font_options_t *font_options)
+{
+  GamesCardThemePreimage *theme = (GamesCardThemePreimage *) 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_preimage_clear_sized_theme_data (theme);
+  _games_card_theme_emit_changed (card_theme);
+}
+
+static const gchar *
+games_card_theme_preimage_get_theme_name (GamesCardTheme *card_theme)
+{
+  GamesCardThemePreimage *theme = (GamesCardThemePreimage *) card_theme;
+
+  return theme->theme_name;
+}
+
+static gboolean
+games_card_theme_preimage_set_card_size (GamesCardTheme *card_theme,
+                                    int width,
+                                    int height,
+                                    double proportion)
+{
+  GamesCardThemePreimage *theme = (GamesCardThemePreimage *) 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_preimage_clear_sized_theme_data (theme);
+  _games_card_theme_emit_changed (card_theme);
+
+  return TRUE;
+}
+
+static CardSize
+games_card_theme_preimage_get_card_size (GamesCardTheme *card_theme)
+{
+  GamesCardThemePreimage *theme = (GamesCardThemePreimage *) card_theme;
+
+  return theme->card_size;
+}
+
+static double
+games_card_theme_preimage_get_card_aspect (GamesCardTheme* card_theme)
+{
+  GamesCardThemePreimage *theme = (GamesCardThemePreimage *) card_theme;
+  double aspect;
+
+  g_return_val_if_fail (GAMES_IS_CARD_THEME_PREIMAGE (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 void
+games_card_theme_preimage_class_init (GamesCardThemePreimageClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GamesCardThemeClass *theme_class = GAMES_CARD_THEME_CLASS (klass);
+
+  gobject_class->finalize = games_card_theme_preimage_finalize;
+
+  theme_class->load_theme = games_card_theme_preimage_load_theme;
+  theme_class->get_theme_name = games_card_theme_preimage_get_theme_name;
+  theme_class->set_card_size = games_card_theme_preimage_set_card_size;
+  theme_class->get_card_size = games_card_theme_preimage_get_card_size;
+  theme_class->get_card_aspect = games_card_theme_preimage_get_card_aspect;
+  theme_class->get_card_pixbuf = NULL;
+  theme_class->set_font_options = games_card_theme_preimage_set_font_options;
+}
+
+/* No public API */

Modified: trunk/libgames-support/games-card-theme-private.h
==============================================================================
--- trunk/libgames-support/games-card-theme-private.h	(original)
+++ trunk/libgames-support/games-card-theme-private.h	Tue Jan  6 18:18:03 2009
@@ -20,6 +20,8 @@
 
 #define FLOAT_TO_INT_CEIL(f) ((int) (f + 0.5f))
 
+/* GamesCardTheme */
+
 struct _GamesCardThemeClass {
   GObjectClass parent_class;
 
@@ -53,3 +55,39 @@
 };
 
 void _games_card_theme_emit_changed (GamesCardTheme * theme);
+
+/* GamesCardThemePreimage */
+
+#ifndef HAVE_HILDON
+
+struct _GamesCardThemePreimageClass {
+  GamesCardThemeClass parent_class;
+
+  void (* clear_sized_theme_data) (GamesCardThemePreimage *card_theme);
+};
+
+struct _GamesCardThemePreimage {
+  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 prescaled : 1;
+
+  cairo_font_options_t *font_options;
+};
+
+void _games_card_theme_preimage_clear_sized_theme_data (GamesCardThemePreimage *theme);
+
+#endif /* !HAVE_HILDON */

Added: trunk/libgames-support/games-card-theme-sliced.c
==============================================================================
--- (empty file)
+++ trunk/libgames-support/games-card-theme-sliced.c	Tue Jan  6 18:18:03 2009
@@ -0,0 +1,236 @@
+/*
+  Copyright  2004 Callum McKenzie
+  Copyright  2007, 2008 Christian Persch
+
+  This programme is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This programme 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this programme.  If not, see <http://www.gnu.org/licenses/>. */
+
+/* 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 _GamesCardThemeSlicedClass {
+  GamesCardThemePreimageClass parent_class;
+};
+
+struct _GamesCardThemeSliced {
+  GamesCardThemePreimage parent_instance;
+
+  GdkPixbuf *source;
+  CardSize subsize;
+
+  guint prescaled : 1;
+};
+
+#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 (GamesCardThemeSliced, games_card_theme_sliced, GAMES_TYPE_CARD_THEME_PREIMAGE);
+
+static void
+games_card_theme_sliced_clear_sized_theme_data (GamesCardThemePreimage *preimage_card_theme)
+{
+  GamesCardThemeSliced *theme = GAMES_CARD_THEME_SLICED (preimage_card_theme);
+
+  if (theme->source) {
+    g_object_unref (theme->source);
+    theme->source = NULL;
+  }
+
+#ifdef INSTRUMENT_LOADING
+  /* Reset the time */
+  totaltime = 0;
+#endif
+
+  GAMES_CARD_THEME_PREIMAGE_CLASS (games_card_theme_sliced_parent_class)->clear_sized_theme_data (preimage_card_theme);
+}
+
+static gboolean
+games_card_theme_sliced_load_theme (GamesCardTheme *card_theme,
+                                    const char *theme_dir,
+                                    const char *theme_name,
+                                    GError **error)
+{
+  GamesCardThemePreimage *preimage_card_theme = (GamesCardThemePreimage *) card_theme;
+  GamesCardThemeSliced *theme = (GamesCardThemeSliced *) card_theme;
+  gboolean retval = FALSE;
+
+#ifdef INSTRUMENT_LOADING
+  clock_t t1, t2;
+
+  t1 = clock ();
+#endif
+
+  if (!GAMES_CARD_THEME_CLASS (games_card_theme_sliced_parent_class)->load_theme
+    (card_theme, theme_dir, theme_name, error))
+    goto out;
+
+  /* If we don't have a scalable format, build a scaled pixbuf that we'll cut up later */
+  theme->prescaled = games_preimage_is_scalable (preimage_card_theme->cards_preimage);
+  if (!theme->prescaled) {
+    theme->source = games_preimage_render_unscaled_pixbuf (preimage_card_theme->cards_preimage);
+  }
+
+  retval = TRUE;
+
+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
+
+  return retval;
+}
+
+static gboolean
+games_card_theme_sliced_prerender_scalable (GamesCardThemeSliced * theme)
+{
+  GamesCardThemePreimage *preimage_card_theme = (GamesCardThemePreimage *) theme;
+
+#ifdef INSTRUMENT_LOADING
+  clock_t t1, t2;
+
+  t1 = clock ();
+#endif
+
+  g_return_val_if_fail (preimage_card_theme->cards_preimage != NULL, FALSE);
+  g_return_val_if_fail (preimage_card_theme->prescaled
+                        || theme->source != NULL, FALSE);
+
+  theme->source =
+    games_preimage_render (preimage_card_theme->cards_preimage,
+                           preimage_card_theme->card_size.width * 13,
+                           preimage_card_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_sliced_get_card_pixbuf (GamesCardTheme *card_theme,
+                                         int card_id)
+{
+  GamesCardThemePreimage *preimage_card_theme = (GamesCardThemePreimage *) card_theme;
+  GamesCardThemeSliced *theme = (GamesCardThemeSliced *) card_theme;
+  GdkPixbuf *subpixbuf, *card_pixbuf;
+  int suit, rank;
+
+  if (!preimage_card_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 (preimage_card_theme->slot_preimage,
+                                       preimage_card_theme->card_size.width,
+                                       preimage_card_theme->card_size.height);
+
+    return subpixbuf;
+  }
+
+  /* Not using subrendering */
+  // FIXMEchpe this doesn't look right for non-scalable
+  if (!theme->source &&
+      !games_card_theme_sliced_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,
+                                           preimage_card_theme->card_size.width,
+                                           preimage_card_theme->card_size.height,
+                                           GDK_INTERP_BILINEAR);
+    g_object_unref (subpixbuf);
+  }
+
+  return card_pixbuf;
+}
+
+static void
+games_card_theme_sliced_init (GamesCardThemeSliced *theme)
+{
+  theme->subsize.width = theme->subsize.height = -1;
+}
+
+static void
+games_card_theme_sliced_class_init (GamesCardThemeSlicedClass * klass)
+{
+  GamesCardThemeClass *theme_class = GAMES_CARD_THEME_CLASS (klass);
+  GamesCardThemePreimageClass *preimage_theme_class = GAMES_CARD_THEME_PREIMAGE_CLASS (klass);
+
+  theme_class->load_theme = games_card_theme_sliced_load_theme;
+  theme_class->get_card_pixbuf = games_card_theme_sliced_get_card_pixbuf;
+
+  preimage_theme_class->clear_sized_theme_data = games_card_theme_sliced_clear_sized_theme_data;
+}
+
+/* public API */
+
+/**
+ * games_card_theme_sliced_new:
+ *
+ * Returns: a new #GamesCardThemeSliced
+ */
+GamesCardTheme*
+games_card_theme_sliced_new (void)
+{
+  return g_object_new (GAMES_TYPE_CARD_THEME_SLICED, NULL);
+}

Modified: trunk/libgames-support/games-card-theme-svg.c
==============================================================================
--- trunk/libgames-support/games-card-theme-svg.c	(original)
+++ trunk/libgames-support/games-card-theme-svg.c	Tue Jan  6 18:18:03 2009
@@ -34,30 +34,11 @@
 #include "games-card-theme-private.h"
 
 struct _GamesCardThemeSVGClass {
-  GamesCardThemeClass parent_class;
+  GamesCardThemePreimageClass 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;
+  GamesCardThemePreimage parent_instance;
 };
 
 #define N_ROWS ((double) 5.0)
@@ -74,44 +55,7 @@
 
 /* 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;
-}
+G_DEFINE_TYPE (GamesCardThemeSVG, games_card_theme_svg, GAMES_TYPE_CARD_THEME_PREIMAGE);
 
 static gboolean
 games_card_theme_svg_load_theme (GamesCardTheme *card_theme,
@@ -119,10 +63,8 @@
                                  const char *theme_name,
                                  GError **error)
 {
-  GamesCardThemeSVG *theme = (GamesCardThemeSVG *) card_theme;
-  GamesPreimage *preimage;
-  const char *slot_dir, *env;
-  gchar *filename, *path;
+  GamesCardThemePreimage *preimage_card_theme = (GamesCardThemePreimage *) card_theme;
+  gboolean retval = FALSE;
 
 #ifdef INSTRUMENT_LOADING
   clock_t t1, t2;
@@ -130,82 +72,14 @@
   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)
+  if (!GAMES_CARD_THEME_CLASS (games_card_theme_svg_parent_class)->load_theme
+    (card_theme, theme_dir, theme_name, error))
     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;
+  if (!games_preimage_is_scalable (preimage_card_theme->cards_preimage))
+    goto out;
 
-  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
+  retval = TRUE;
 
 out:
 
@@ -217,76 +91,33 @@
            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;
+  return retval;
 }
 
 static GdkPixbuf *
-games_card_theme_svg_render_card (GamesCardThemeSVG * theme, int card_id)
+games_card_theme_svg_get_card_pixbuf (GamesCardTheme *card_theme,
+                                      int card_id)
 {
-  GamesPreimage *preimage = theme->cards_preimage;
-  GdkPixbuf *subpixbuf, *card_pixbuf;
+  GamesCardThemePreimage *preimage_card_theme = (GamesCardThemePreimage *) card_theme;
+  GamesPreimage *preimage = preimage_card_theme->cards_preimage;
+  GdkPixbuf *subpixbuf;
   int suit, rank;
 
-  if (!theme->theme_loaded)
+  if (!preimage_card_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);
+    subpixbuf = games_preimage_render (preimage_card_theme->slot_preimage,
+                                       preimage_card_theme->card_size.width,
+                                       preimage_card_theme->card_size.height);
 
     return subpixbuf;
   }
 
-  if (theme->subrender) {
+  if (TRUE) {
     double card_width, card_height;
     double width, height;
     double offsetx, offsety;
@@ -296,8 +127,8 @@
     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;
+    width = preimage_card_theme->card_size.width - 2 * DELTA;
+    height = preimage_card_theme->card_size.height - 2 * DELTA;
 
     offsetx = -((double) rank) * card_width + DELTA;
     offsety = -((double) suit) * card_height + DELTA;
@@ -309,212 +140,29 @@
 
     subpixbuf = games_preimage_render_sub (preimage,
                                            node,
-                                           theme->card_size.width, theme->card_size.height,
+                                           preimage_card_theme->card_size.width,
+                                           preimage_card_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);
+  return NULL; // FIXMEchpe
 }
 
 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 */

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:18:03 2009
@@ -34,7 +34,7 @@
   GAMES_CARD_THEME_ERROR_GENERIC = 0
 } GamesCardThemeError;
 
-/* GamesCardTheme */
+/* GamesCardTheme (abstract) */
 
 #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))
@@ -76,6 +76,20 @@
 GdkPixbuf *games_card_theme_get_card_pixbuf (GamesCardTheme * theme,
                                              int cardid);
 
+/* GamesCardThemePreimage (abstract) */
+
+#define GAMES_TYPE_CARD_THEME_PREIMAGE            (games_card_theme_preimage_get_type ())
+#define GAMES_CARD_THEME_PREIMAGE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_PREIMAGE, GamesCardThemePreimage))
+#define GAMES_CARD_THEME_PREIMAGE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_PREIMAGE, GamesCardThemePreimageClass))
+#define GAMES_IS_CARD_THEME_PREIMAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_PREIMAGE))
+#define GAMES_IS_CARD_THEME_PREIMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_PREIMAGE))
+#define GAMES_CARD_THEME_PREIMAGE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_PREIMAGE, GamesCardThemePreimageClass))
+
+typedef struct _GamesCardThemePreimageClass GamesCardThemePreimageClass;
+typedef struct _GamesCardThemePreimage      GamesCardThemePreimage;
+
+GType games_card_theme_preimage_get_type (void);
+
 /* GamesCardThemeSVG */
 
 #define GAMES_TYPE_CARD_THEME_SVG            (games_card_theme_svg_get_type ())
@@ -92,6 +106,22 @@
 
 GamesCardTheme* games_card_theme_svg_new (void);
 
+/* GamesCardThemeSliced */
+
+#define GAMES_TYPE_CARD_THEME_SLICED            (games_card_theme_sliced_get_type ())
+#define GAMES_CARD_THEME_SLICED(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_SLICED, GamesCardThemeSliced))
+#define GAMES_CARD_THEME_SLICED_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_SLICED, GamesCardThemeSlicedClass))
+#define GAMES_IS_CARD_THEME_SLICED(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_SLICED))
+#define GAMES_IS_CARD_THEME_SLICED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_SLICED))
+#define GAMES_CARD_THEME_SLICED_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_SLICED, GamesCardThemeSlicedClass))
+
+typedef struct _GamesCardThemeSlicedClass GamesCardThemeSlicedClass;
+typedef struct _GamesCardThemeSliced      GamesCardThemeSliced;
+
+GType games_card_theme_sliced_get_type (void);
+
+GamesCardTheme* games_card_theme_sliced_new (void);
+
 /* GamesCardThemeFixed */
 
 #define GAMES_TYPE_CARD_THEME_FIXED            (games_card_theme_fixed_get_type ())



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]