OSDN Git Service

add vs2008-specific files
[nethackexpress/trunk.git] / win / gnome / gnglyph.c
1 /*      SCCS Id: @(#)gnglyph.c  3.4     2000/07/16      */
2 /* Copyright (C) 1998 by Erik Andersen <andersee@debian.org> */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "gnglyph.h"
6 #include "tile2x11.h"
7
8 /* from tile.c */
9 extern int total_tiles_used;
10
11 static GHackGlyphs     ghack_glyphs;
12 static GdkImlibImage** ghack_tiles = NULL;
13
14 /* NAME:
15  *     ghack_init_glyphs(char* xpm_file)
16  *
17  * ARGUMENTS:
18  *     char *xpm_file -- The name of the image file.
19  *                       May be any image format imlib recognizes.
20  *                       Does not have to be XPM.
21  *
22  * RETURNS:
23  *     TRUE  upon successful loading of the glyphs.
24  *     FALSE upon failure.
25  *
26  * PURPOSE:
27  *     Constructor for the Glyph object.  Well, really each glyph
28  *     object is a collection of glyphs, or tiles.  This constructor
29  *     takes a single argument: the name of the image file that contains
30  *     the tile images.
31  *
32  * NOTES:
33  *     The glyphs (tiles) must be in the image in a certain way: the
34  *     glyphs must be stacked such that the resultant image is
35  *     TILE_X * TILES_PER_ROW wide, and
36  *     TILE_Y * (number of glyphs) / TILES_PER_ROW high (rounded up).
37  *     In this sense, TILE_X == TILE_Y, and can be any reasonable integer
38  *     say, 16 <= TILE_X <= 64.  Because the glyph number is tightly
39  *     coupled to the Nethack object it represents, the order of the
40  *     glyphs in the image is imporant: Glyph 1 is at the top of the
41  *     image, while Glyph N (the last glyph) is at the bottom.
42  *
43  *     What's the difference between a glyph and a tile?  Well, a
44  *     tile is just an image.  A glyph is a tile that knows its
45  *     place in line.
46  *
47  *     This initializer relies heavily on gdk_imlib.  Thanks, Rasterman.
48  */
49
50 int
51 ghack_init_glyphs(const char *xpmFile)
52 {
53     ghack_glyphs.im = gdk_imlib_load_image((char *) xpmFile);
54     if ( ! ghack_glyphs.im ) {
55         g_error("Couldn't load required xpmFile!");
56         return -1;
57     }
58
59     gdk_imlib_render(ghack_glyphs.im, ghack_glyphs.im->rgb_width,
60                      ghack_glyphs.im->rgb_height);
61
62     if ((ghack_glyphs.im->rgb_width % TILES_PER_ROW) != 0 ||
63         ghack_glyphs.im->rgb_width <= TILES_PER_ROW) {
64         g_error("%s is not a multiple of %d (number of tiles/row) pixels wide",
65                 xpmFile, TILES_PER_ROW);
66         return -1;
67     }
68     ghack_glyphs.count = total_tiles_used;
69     if ((ghack_glyphs.count % TILES_PER_ROW) != 0) {
70         ghack_glyphs.count +=
71             TILES_PER_ROW - (ghack_glyphs.count % TILES_PER_ROW);
72     }
73     ghack_glyphs.width = ghack_glyphs.im->rgb_width / TILES_PER_ROW;
74     ghack_glyphs.height =
75         ghack_glyphs.im->rgb_height / (ghack_glyphs.count / TILES_PER_ROW);
76
77
78     /* Assume the tiles are organized in rows of TILES_PER_ROW */
79     ghack_tiles = g_new0( GdkImlibImage*, ghack_glyphs.count );
80     return (ghack_tiles == NULL) ? -1 : 0;
81 }
82
83 void
84 ghack_free_glyphs( )
85 {
86     int i;
87     for ( i=0 ; i<ghack_glyphs.count ; i++)
88         gdk_imlib_destroy_image(ghack_tiles[i]);
89     g_free( ghack_tiles);
90     gdk_imlib_destroy_image(ghack_glyphs.im);
91     ghack_glyphs.im=NULL;
92 }
93
94
95 /* NAME:
96  *     ghack_glyph_count( )
97  *
98  * ARGUMENTS:
99  *     None.
100  *
101  * RETURNS:
102  *     int -- The number of glyphs in this object.
103  *
104  * PURPOSE:
105  *     Simply reports the number of glyphs in this object.
106  */
107
108 int
109 ghack_glyph_count( )
110 {
111   return ghack_glyphs.count;
112 }
113
114
115 /* NAME:
116  *     ghack_glyph_height()
117  *
118  * ARGUMENTS:
119  *     None
120  *
121  * RETURNS:
122  *     int -- The glyph height.
123  *
124  * PURPOSE:
125  *     Returns the standard glyph height.
126  */
127
128 int
129 ghack_glyph_height()
130 {
131   return ghack_glyphs.height;
132 }
133
134
135 /* NAME:
136  *     ghack_glyph_width()
137  *
138  * ARGUMENTS:
139  *     None
140  *
141  * RETURNS:
142  *     int -- The glyph width.
143  *
144  * PURPOSE:
145  *     Returns the standard glyph width.
146  */
147
148 int
149 ghack_glyph_width()
150 {
151   return ghack_glyphs.width;
152 }
153
154
155 /* NAME:
156  *     ghack_image_from_glyph( int glyph, gboolean force)
157  *
158  * ARGUMENTS:
159  *     int glyph  -- The glyph number.
160  *     gboolean force -- force it to re-render.
161  *
162  * RETURNS:
163  *     GdkImlibImage* -- The glyph image, as a GdkImlibImage.
164  *
165  * PURPOSE:
166  *     Decodes the glyph into an image suitable for manipulation
167  */
168
169 GdkImlibImage*
170 ghack_image_from_glyph( int glyph, gboolean force )
171 {
172   int tile = glyph2tile[glyph];
173
174   if ( tile >= ghack_glyphs.count || tile < 0 )
175     {
176       g_warning("Aiiee! I've was asked for a tile outside the allowed range!\n"
177             "Email this to other-gnomehack@lists.debian.org");
178       g_warning("Max tile: %d   Tile asked for: %d",
179                 ghack_glyphs.count, tile);
180       return NULL;
181     }
182
183   if (ghack_glyphs.im == NULL)
184     {
185     g_warning("Aiiee! I've been asked to clone from a null image.\n"
186             "Email this to other-gnomehack@lists.debian.org");
187     g_warning( "making image from tile %d, force=%s\n", tile,
188             (force==TRUE)? "TRUE": "FALSE");
189     }
190
191   if (force == TRUE)
192     {
193     g_warning("Aiiee! I've been asked to force rendering.\n"
194             "Email this to other-gnomehack@lists.debian.org");
195     g_warning( "making image from tile %d, force=%s\n", tile,
196             (force==TRUE)? "TRUE" : "FALSE");
197     }
198
199   if (!ghack_tiles[tile] || force) {
200       int src_x, src_y;
201 #if 0
202       fprintf( stderr, "crop_and_clone: glyph=%d, tile=%d, ptr=%p, x=%d, y=%d, w=%d, h=%d\n", glyph, tile,
203               (void*)&(ghack_tiles[tile]), 0,
204               tile * ghack_glyphs.width,
205               ghack_glyphs.height,
206               ghack_glyphs.width);
207 #endif
208       if (ghack_glyphs.im->pixmap == NULL)
209           g_warning( "Aiiee!  ghack_glyphs.im->pixmap==NULL!!!!\n");
210       src_x = (tile % TILES_PER_ROW) * ghack_glyphs.width;
211       src_y = (tile / TILES_PER_ROW) * ghack_glyphs.height;
212       ghack_tiles[tile] = gdk_imlib_crop_and_clone_image(ghack_glyphs.im,
213               src_x, src_y,
214               ghack_glyphs.width,
215               ghack_glyphs.height);
216   }
217
218   if (ghack_tiles[tile] && (!ghack_tiles[tile]->pixmap || force))
219   {
220       if ( gdk_imlib_render(ghack_tiles[tile],
221                   ghack_tiles[tile]->rgb_width,
222                   ghack_tiles[tile]->rgb_height) == 0) {
223           g_error("GLYPH: couldn't create tile # %d", tile);
224       }
225       if ( !ghack_tiles[tile]->pixmap )
226           g_error("Strange, tile # %d didn't get rendered???", tile);
227   }
228
229   return ghack_tiles[tile];
230 }