initial load of http://downloads.sourceforge.net/project/cmancala/mancala-gui/mancala...
[mancala] / src / graphics.c
1 /*  
2  *  Graphics Routines -- graphics.c
3  *  $Id: graphics.c,v 1.1.2.20 2004/01/14 05:18:19 sparrow_hawk Exp $
4  *
5  *  Copyright (C) 2003 Kevin Riggle 
6  *  http://cmancala.sourcefoge.net
7  *
8  *  This program is free software; you can redistribute it and/or modify it
9  *  under the terms of the GNU General Public License as published by the
10  *  Free Software Foundation; either version 2, or (at your option) any
11  *  later version.
12  *
13  *  This program is distributed in the hope that it will be useful, but
14  *  WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  General Public License for more details, a copy of which may be found in
17  *  the file COPYING provided in the main directory of this release.
18  *
19  */
20
21 #include <stdio.h>
22
23 #include "SDL.h"
24 #include "SDL_endian.h" /* Used for the endian-dependent 24 bpp mode */
25
26 #include "SDL_image.h"
27 #include "SDL_ttf.h"
28
29 #include "graphics.h"
30 #include "main.h"
31 #include "mancala.h"
32
33 static SDL_Surface *ShiftColors(SDL_Surface *old, Uint8 red, Uint8 blue, Uint8 green, Uint8 alpha);
34
35 SDL_Surface *LoadRes(char *filename) {
36
37         return IMG_LoadPNG_RW(SDL_RWFromFile(filename, "r"));
38
39 }
40
41
42 SDL_Rect SurfaceToRect(SDL_Surface *src) {
43
44         SDL_Rect dest;
45
46         dest.x = 0;
47         dest.y = 0;
48         dest.w = src->w;
49         dest.h = src->h;
50
51         return dest;
52
53 }
54
55 /* create a new, blank surface with another's properties */
56 static SDL_Surface *NewSurfaceFrom(SDL_Surface *old, Uint32 flags) {
57
58         return SDL_CreateRGBSurface(
59                         flags, old->w, old->h, old->format->BitsPerPixel,
60                         old->format->Rmask, old->format->Gmask, 
61                         old->format->Bmask, old->format->Amask
62         );
63
64 }
65
66 static SDL_Surface *FillHole(int stones, TTF_Font *font, 
67                                 SDL_Surface **stone_gfx) {
68
69         SDL_Surface *text;
70         SDL_Color font_color;
71         char stone_string[STRING_MAX];
72         int w, h;
73
74         /* do we have a graphic for this number of stones? */
75         if (stones <= STONE_MAX) {
76
77                 return *(stone_gfx + stones);
78         }
79         else {
80                 font_color.r = 128;
81                 font_color.g = 128;
82                 font_color.b = 128;
83                 /* convert the integer to text */
84                 if (sprintf(stone_string, "%d", stones)<=0)
85                         fprintf(stderr, "String conversion problem.\n");
86                 /* get the size of the rendered text */
87                 if (TTF_SizeText(font, stone_string, &w, &h)<0) 
88                         fprintf(stderr, "SDL_ttf: %s\n", TTF_GetError());
89                 /* if the text is too large, render a '?' */
90                 if ((w > (*stone_gfx)->w) || (h > (*stone_gfx)->h))
91                         sprintf(stone_string, "?");
92                 if (!(text = TTF_RenderText_Blended(font, stone_string, 
93                         font_color))) {
94                         fprintf(stderr, "SDL_ttf: %s\n", TTF_GetError());
95                         return NULL;
96                 }
97                 return text;
98         }
99
100         /* NEVER REACHED */
101         return NULL;
102 }
103
104
105 SDL_Surface *DrawBoard(int *aiBoard, int *humanBoard,
106                         TTF_Font *board_font, TTF_Font *home_font,
107                         SDL_Surface *tile, SDL_Surface **stone_gfx,
108                         int active, int highlight) {
109
110         SDL_Surface *board, *stones;
111         SDL_Rect tile_rect, blit_rect;
112         SDL_Color home_color;
113         char home_string[STRING_MAX];
114         int i;
115
116         /* initialize the board surface */
117         board = SDL_CreateRGBSurface(SDL_SWSURFACE, tile->w*(BOARD_MAX+2),
118                 tile->h*2, tile->format->BitsPerPixel, 0, 0, 0, 0);
119         if (!board) {
120                 fprintf(stderr, "DrawBoard: %s\n", SDL_GetError());
121                 return NULL;
122         }
123
124         tile_rect = SurfaceToRect(tile);
125         /*printf("tile is %dx%d\n", tile_rect.w, tile_rect.h);*/
126
127         /* set the color of text in the home */
128         home_color.r = 0;
129         home_color.g = 0;
130         home_color.b = 0;
131
132         for (i=0; i<=BOARD_MAX+1; i++)
133         {
134                 /* update current tile location */
135                 tile_rect.x = i * tile_rect.w;
136                 tile_rect.y = 0;
137                 /*printf("Currently a %dx%d rectangle at %d,%d.\n", tile_rect.w,
138                         tile_rect.h, tile_rect.x, tile_rect.y);*/
139                 blit_rect = tile_rect;
140                 /* is this is the first or last tile? */
141                 if ((i==0) || (i==BOARD_MAX+1)) {
142                         /* make it blank */
143                         if (SDL_BlitSurface(tile, NULL, board, &blit_rect)<0)
144                                 fprintf(stderr,"DrawBoard: %s\n", 
145                                         SDL_GetError());
146                         blit_rect = tile_rect;
147                         blit_rect.y = blit_rect.h;
148                         SDL_BlitSurface(tile, NULL, board, &blit_rect);
149                         /* render the number of stones in each home */
150                         if (i==0) {
151                                 if (sprintf(home_string,"%d",humanBoard[0])<=0)
152                                         printf("Human string problems.\n");
153                         }
154                         else {
155                                 if (sprintf(home_string, "%d", aiBoard[0])<=0)
156                                         printf("AI string problems.\n");
157                         }
158                         if (!(stones = TTF_RenderText_Blended(home_font, 
159                                 home_string, home_color)))
160                                 fprintf(stderr, "DrawBoard: %s\n", 
161                                         TTF_GetError());
162                         blit_rect.w = stones->w;
163                         blit_rect.h = stones->h;
164                         blit_rect.x += ((tile_rect.w - blit_rect.w)/2);
165                         blit_rect.y = ((tile_rect.h*2 - blit_rect.h)/2);
166                         SDL_BlitSurface(stones, NULL, board, &blit_rect);
167                 }
168                 /* otherwise, draw a hole and fill it */
169                 else {
170                         SDL_BlitSurface(stone_gfx[0], NULL, board, &blit_rect);
171                         if (humanBoard[i] > 0) {
172                                 if (!(stones = FillHole(humanBoard[i], 
173                                         board_font, stone_gfx)))
174                                         fprintf(stderr,"FillHole() problems\n");
175                                 if (i == highlight)
176                                         stones = ShiftColors(stones,128,128,128,255);
177                                 if (active == 1)
178                                         stones = ShiftColors(stones,0,0,0,160);
179                                 blit_rect.w = stones->w;
180                                 blit_rect.h = stones->h;
181                                 blit_rect.x += ((tile_rect.w - blit_rect.w)/2);
182                                 blit_rect.y += ((tile_rect.h - blit_rect.h)/2);
183                                 SDL_BlitSurface(stones,NULL,board,&blit_rect);
184                         }
185
186                         blit_rect = tile_rect;
187                         blit_rect.y = blit_rect.h;
188                         SDL_BlitSurface(stone_gfx[0], NULL, board, &blit_rect);
189                         if (aiBoard[BOARD_MAX-i+1] > 0) {
190                                 if (!(stones = FillHole(aiBoard[BOARD_MAX-i+1], 
191                                         board_font, stone_gfx)))
192                                         fprintf(stderr,"FillHole() problems\n");
193                                 if (active == 0)
194                                         stones = ShiftColors(stones,0,0,0,160);
195                                 blit_rect.w = stones->w;
196                                 blit_rect.h = stones->h;
197                                 blit_rect.x += ((tile_rect.w - blit_rect.w)/2);
198                                 blit_rect.y += ((tile_rect.h - blit_rect.h)/2);
199                                 SDL_BlitSurface(stones,NULL,board,&blit_rect);
200                         }
201                 }
202         }
203
204         SDL_FreeSurface(stones);
205
206         return board;
207 }
208
209
210 /* flagrantly stol^H^H^Hborrowed from SDL Introduction */
211 /* passing 0 for red, green, or blue leaves them alone */
212 /* passing 0 for alpha makes the image transparent     */
213
214 SDL_Surface *ShiftColors(SDL_Surface *old, Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha)
215 {
216     SDL_Surface *new;
217     Uint8 r, g, b, a;
218     int x, y;
219
220     new = NewSurfaceFrom(old, (SDL_SWSURFACE|SDL_SRCALPHA));
221
222     if ( SDL_MUSTLOCK(old) ) {
223         if (SDL_LockSurface(old) < 0 ) {
224             return NULL;
225         }
226     }
227
228     if ( SDL_MUSTLOCK(new) ) {
229         if ( SDL_LockSurface(new) < 0 ) {
230             return NULL;
231         }
232     }
233
234     for (x=0; x<old->w; x++)
235     for (y=0; y<old->h; y++) {
236  
237     r = g = b = a = 0;
238
239     switch (old->format->BytesPerPixel) {
240         case 1: { /* Assuming 8-bpp */
241             Uint8 *bufp, *bufq;
242
243             bufp = (Uint8 *)old->pixels + y*old->pitch + x;
244             bufq = (Uint8 *)new->pixels + y*new->pitch + x;
245             SDL_GetRGBA((Uint32)*bufp, old->format, &r, &g, &b, &a);
246             a *= alpha/SDL_ALPHA_OPAQUE;
247             *bufq = (Uint8)SDL_MapRGBA(new->format, r, g, b, a);
248         }
249         break;
250
251         case 2: { /* Probably 15-bpp or 16-bpp */
252             Uint16 *bufp, *bufq;
253
254             bufp = (Uint16 *)old->pixels + y*old->pitch/2 + x;
255             bufq = (Uint16 *)new->pixels + y*new->pitch + x;
256             SDL_GetRGBA((Uint32)*bufp, new->format, &r, &g, &b, &a);
257             a *= alpha/SDL_ALPHA_OPAQUE;
258             *bufq = (Uint8)SDL_MapRGBA(new->format, r, g, b, a);
259         }
260         break;
261
262         case 3: { /* Slow 24-bpp mode, usually not used */
263             Uint8 *bufp, *bufq;
264             Uint32 color;
265
266             bufp = (Uint8 *)old->pixels + y*old->pitch + x * 3;
267             bufq = (Uint8 *)new->pixels + y*new->pitch + x * 3;
268             SDL_GetRGBA((Uint32)*bufp, old->format, &r, &g, &b, &a);
269             a *= alpha/SDL_ALPHA_OPAQUE;
270             color = SDL_MapRGBA(new->format, r, g, b, a);
271             if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {
272                 bufq[0] = color;
273                 bufq[1] = color >> 8;
274                 bufq[2] = color >> 16;
275             } else {
276                 bufq[2] = color;
277                 bufq[1] = color >> 8;
278                 bufq[0] = color >> 16;
279             }
280         }
281         break;
282
283         case 4: { /* Probably 32-bpp */
284             Uint32 *bufp, *bufq;
285
286             bufp = (Uint32 *)old->pixels + y*old->pitch/4 + x;
287             bufq = (Uint32 *)new->pixels + y*new->pitch/4 + x;
288             SDL_GetRGBA(*bufp, old->format, &r, &g, &b, &a);
289             a = (int)((long)a * (long)alpha/SDL_ALPHA_OPAQUE);
290             r += (int)((long)(SDL_ALPHA_OPAQUE - r) * (long)red/SDL_ALPHA_OPAQUE);
291             g += (int)((long)(SDL_ALPHA_OPAQUE - g) * (long)green/SDL_ALPHA_OPAQUE);
292             b += (int)((long)(SDL_ALPHA_OPAQUE - b) * (long)blue/SDL_ALPHA_OPAQUE);
293           *bufq = SDL_MapRGBA(new->format, r, g, b, a);
294         }
295         break;
296     }
297     }
298
299     if ( SDL_MUSTLOCK(new) ) {
300         SDL_UnlockSurface(new);
301     }
302   
303     if ( SDL_MUSTLOCK(old) ) {
304         SDL_UnlockSurface(old);
305     }
306     
307     return new;
308 }
309
310
311 /*  End graphics.c  */