Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2005:
[Freeciv-Dev] (PR#12636) Split Sprite in two
Home

[Freeciv-Dev] (PR#12636) Split Sprite in two

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12636) Split Sprite in two
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Fri, 25 Mar 2005 05:18:07 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12636 >

For OpenGL we would want to upload graphics into video memory as textures.
This complicates the use of the Sprite primitive in the freeciv codebase.

Currently we use Sprite both for collections of sprites (a PNG full of
smaller sprites) and for individual sprites. However, for OpenGL we do not
want to upload the collections to video memory. They may be too big to fit
into a texture, and they are easier to handle and manipulate in main
memory where we can access memory directly.

So I would like to propose a split of the Sprite into 1) a new "struct
sprite_album" and 2) a "struct Sprite" (as before).

We would have then

        struct sprite_collection *load_sprite_album(const char *filename)
        struct Sprite *load_sprite_single(const char *filename)
        struct Sprite *crop_sprite(struct sprite_album *source, ...)
        void get_sprite_album_dimensions(...)
        void get_sprite_dimensions(...)
        void free_sprite_album(struct sprite_album *s)
        void free_sprite(struct Sprite *s)

where load_sprite_single() for the OpenGL case would call
load_sprite_album() and then crop_sprite() it all, whereas the other
clients would just

        #define sprite_album Sprite
        #define load_sprite_album load_sprite_single
        #define get_sprite_album_dimensions get_sprite_dimensions
        #define free_sprite_album free_sprite

I began doing this (see attached patch), but encountered the overlays code
that would require some redesign. It uses crop_sprite() to copy sprites
with various masks. I think this is an API abuse. crop_sprite() should not
IMHO be used for this purpose, instead a separate function should do this.
I am not sure if it would be best to do this against a "big sprite"/sprite
album, or against a "small sprite"/Sprite/texture - I think either way
will work fine, but a choice has to be made for either. I am unsure how to
redesign this code to fit.

  - Per

PS Why is Sprite capitalized?

Index: tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.275
diff -u -r1.275 tilespec.c
--- tilespec.c  23 Mar 2005 17:49:38 -0000      1.275
+++ tilespec.c  25 Mar 2005 13:10:55 -0000
@@ -288,7 +288,7 @@
 };
 
 struct specfile {
-  struct Sprite *big_sprite;
+  struct sprite_album *album;
   char *file_name;
 };
 
@@ -862,10 +862,38 @@
 }
 
 /**************************************************************************
+  Loads the given album file (found in the data path) into a newly
+  allocated sprite album.
+**************************************************************************/
+static struct sprite_album *find_and_load_sprite_album(const char 
*gfx_filename)
+{
+  const char **gfx_fileexts = gfx_fileextensions(), *gfx_fileext;
+  struct sprite_album *s;
+
+  /* Try out all supported file extensions to find one that works. */
+  while ((gfx_fileext = *gfx_fileexts++)) {
+    char *real_full_name;
+    char full_name[strlen(gfx_filename) + strlen(gfx_fileext) + 2];
+
+    sprintf(full_name, "%s.%s", gfx_filename, gfx_fileext);
+    if ((real_full_name = datafilename(full_name))) {
+      freelog(LOG_DEBUG, "trying to load gfx file %s", real_full_name);
+      s = load_sprite_album(real_full_name);
+      if (s) {
+       return s;
+      }
+    }
+  }
+
+  freelog(LOG_VERBOSE, "Could not load gfx file %s.", gfx_filename);
+  return NULL;
+}
+
+/**************************************************************************
   Loads the given graphics file (found in the data path) into a newly
   allocated sprite.
 **************************************************************************/
-static struct Sprite *load_gfx_file(const char *gfx_filename)
+static struct Sprite *find_and_load_sprite(const char *gfx_filename)
 {
   const char **gfx_fileexts = gfx_fileextensions(), *gfx_fileext;
   struct Sprite *s;
@@ -878,7 +906,7 @@
     sprintf(full_name, "%s.%s", gfx_filename, gfx_fileext);
     if ((real_full_name = datafilename(full_name))) {
       freelog(LOG_DEBUG, "trying to load gfx file %s", real_full_name);
-      s = load_gfxfile(real_full_name);
+      s = load_sprite_single(real_full_name);
       if (s) {
        return s;
       }
@@ -892,17 +920,17 @@
 /**************************************************************************
   Ensure that the big sprite of the given spec file is loaded.
 **************************************************************************/
-static void ensure_big_sprite(struct specfile *sf)
+static void ensure_sprite_album(struct specfile *sf)
 {
   struct section_file the_file, *file = &the_file;
   const char *gfx_filename;
 
-  if (sf->big_sprite) {
+  if (sf->album) {
     /* Looks like it's already loaded. */
     return;
   }
 
-  /* Otherwise load it.  The big sprite will sometimes be freed and will have
+  /* Otherwise load it.  The album will sometimes be freed and will have
    * to be reloaded, but most of the time it's just loaded once, the small
    * sprites are extracted, and then it's freed. */
   if (!section_file_load(file, sf->file_name)) {
@@ -917,9 +945,9 @@
 
   gfx_filename = secfile_lookup_str(file, "file.gfx");
 
-  sf->big_sprite = load_gfx_file(gfx_filename);
+  sf->album = find_and_load_sprite_album(gfx_filename);
 
-  if (!sf->big_sprite) {
+  if (!sf->album) {
     freelog(LOG_FATAL, _("Couldn't load gfx file for the spec file %s"),
            sf->file_name);
     exit(EXIT_FAILURE);
@@ -929,7 +957,7 @@
 
 /**************************************************************************
   Scan all sprites declared in the given specfile.  This means that the
-  positions of the sprites in the big_sprite are saved in the
+  positions of the sprites in the sprite album are saved in the
   small_sprite structs.
 **************************************************************************/
 static void scan_specfile(struct tileset *t, struct specfile *sf,
@@ -1421,7 +1449,7 @@
 
     freelog(LOG_DEBUG, "spec file %s", spec_filenames[i]);
     
-    sf->big_sprite = NULL;
+    sf->album = NULL;
     sf->file_name = mystrdup(datafilename_required(spec_filenames[i]));
     scan_specfile(t, sf, duplicates_ok);
 
@@ -2046,9 +2074,9 @@
 static void finish_loading_sprites(struct tileset *t)
 {
   specfile_list_iterate(t->specfiles, sf) {
-    if (sf->big_sprite) {
-      free_sprite(sf->big_sprite);
-      sf->big_sprite = NULL;
+    if (sf->album) {
+      free_sprite_album(sf->album);
+      sf->album = NULL;
     }
   } specfile_list_iterate_end;
 }
@@ -4068,9 +4096,9 @@
   specfile_list_iterate(t->specfiles, sf) {
     specfile_list_unlink(t->specfiles, sf);
     free(sf->file_name);
-    if (sf->big_sprite) {
-      free_sprite(sf->big_sprite);
-      sf->big_sprite = NULL;
+    if (sf->album) {
+      free_sprite_album(sf->album);
+      sf->album = NULL;
     }
     free(sf);
   } specfile_list_iterate_end;
@@ -4286,7 +4314,7 @@
     /* If the sprite hasn't been loaded already, then load it. */
     assert(ss->ref_count == 0);
     if (ss->file) {
-      ss->sprite = load_gfx_file(ss->file);
+      ss->sprite = find_and_load_sprite(ss->file);
       if (!ss->sprite) {
        freelog(LOG_FATAL, _("Couldn't load gfx file %s for sprite %s"),
                ss->file, tag_name);
@@ -4295,8 +4323,8 @@
     } else {
       int sf_w, sf_h;
 
-      ensure_big_sprite(ss->sf);
-      get_sprite_dimensions(ss->sf->big_sprite, &sf_w, &sf_h);
+      ensure_sprite_album(ss->sf);
+      get_sprite_album_dimensions(ss->sf->album, &sf_w, &sf_h);
       if (ss->x < 0 || ss->x + ss->width > sf_w
          || ss->y < 0 || ss->y + ss->height > sf_h) {
        freelog(LOG_ERROR,
@@ -4305,7 +4333,7 @@
        return NULL;
       }
       ss->sprite =
-       crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width, ss->height,
+       crop_sprite(ss->sf->album, ss->x, ss->y, ss->width, ss->height,
                    NULL, -1, -1);
     }
   }
Index: gui-gtk-2.0/sprite.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/sprite.c,v
retrieving revision 1.1
diff -u -r1.1 sprite.c
--- gui-gtk-2.0/sprite.c        23 Mar 2005 18:13:21 -0000      1.1
+++ gui-gtk-2.0/sprite.c        25 Mar 2005 13:10:55 -0000
@@ -36,7 +36,7 @@
   in the mask image will be used to clip pixel (0,0) in the source image
   which is pixel (-x,-y) in the new image.
 ****************************************************************************/
-struct Sprite *crop_sprite(struct Sprite *source,
+struct Sprite *crop_sprite(struct sprite_album *source,
                           int x, int y,
                           int width, int height,
                           struct Sprite *mask,
@@ -190,7 +190,7 @@
   entire image file, which may later be broken up into individual sprites
   with crop_sprite.
 ****************************************************************************/
-struct Sprite *load_gfxfile(const char *filename)
+struct Sprite *load_sprite_single(const char *filename)
 {
   GdkPixbuf *im;
 
Index: gui-gtk-2.0/sprite.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/sprite.h,v
retrieving revision 1.1
diff -u -r1.1 sprite.h
--- gui-gtk-2.0/sprite.h        23 Mar 2005 18:13:21 -0000      1.1
+++ gui-gtk-2.0/sprite.h        25 Mar 2005 13:10:55 -0000
@@ -15,6 +15,12 @@
 
 #include <gtk/gtk.h>
 
+/* We make no distinction here */
+#define sprite_album Sprite
+#define load_sprite_album load_sprite_single
+#define get_sprite_album_dimensions get_sprite_dimensions
+#define free_sprite_album free_sprite
+
 #include "sprite_g.h"
 
 struct Sprite
Index: include/sprite_g.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/include/sprite_g.h,v
retrieving revision 1.2
diff -u -r1.2 sprite_g.h
--- include/sprite_g.h  25 Mar 2005 10:31:52 -0000      1.2
+++ include/sprite_g.h  25 Mar 2005 13:10:55 -0000
@@ -13,16 +13,21 @@
 #ifndef FC__SPRITE_G_H
 #define FC__SPRITE_G_H
 
-struct Sprite;                 /* opaque type, real type is gui-dep */
+struct Sprite;                 /* GUI private; sprite for blitting */
+struct gfxfile;                 /* GUI private; intermediate graphics */
 
 const char **gfx_fileextensions(void);
 
-struct Sprite *load_gfxfile(const char *filename);
-struct Sprite *crop_sprite(struct Sprite *source,
+struct sprite_album *load_sprite_album(const char *filename);
+struct Sprite *load_sprite_single(const char *filename);
+struct Sprite *crop_sprite(struct sprite_album *source,
                           int x, int y, int width, int height,
                           struct Sprite *mask,
                           int mask_offset_x, int mask_offset_y);
+void get_sprite_album_dimensions(struct sprite_album *sprite, 
+                                 int *width, int *height);
 void get_sprite_dimensions(struct Sprite *sprite, int *width, int *height);
+void free_sprite_album(struct sprite_album *s);
 void free_sprite(struct Sprite *s);
 
 #endif  /* FC__SPRITE_G_H */

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#12636) Split Sprite in two, Per I. Mathisen <=