2 * Graphics Routines -- graphics.c
3 * $Id: graphics.c,v 1.1.2.20 2004/01/14 05:18:19 sparrow_hawk Exp $
5 * Copyright (C) 2003 Kevin Riggle
6 * http://cmancala.sourcefoge.net
7 * Copyright (C) 2009 Reto Zingg
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details, a copy of which may be found in
18 * the file COPYING provided in the main directory of this release.
25 #include "SDL_endian.h" /* Used for the endian-dependent 24 bpp mode */
27 #include "SDL_image.h"
35 static SDL_Surface *ShiftColors(SDL_Surface *old, Uint8 red, Uint8 blue, Uint8 green, Uint8 alpha);
37 SDL_Surface *LoadRes(char *filename) {
39 return IMG_LoadPNG_RW(SDL_RWFromFile(filename, "r"));
44 SDL_Rect SurfaceToRect(SDL_Surface *src) {
57 /* create a new, blank surface with another's properties */
58 static SDL_Surface *NewSurfaceFrom(SDL_Surface *old, Uint32 flags) {
60 return SDL_CreateRGBSurface(
61 flags, old->w, old->h, old->format->BitsPerPixel,
62 old->format->Rmask, old->format->Gmask,
63 old->format->Bmask, old->format->Amask
68 static SDL_Surface *FillHole(int stones, TTF_Font *font,
69 SDL_Surface **stone_gfx) {
73 char stone_string[STRING_MAX];
76 /* do we have a graphic for this number of stones? */
77 if (stones <= STONE_MAX) {
79 return *(stone_gfx + stones);
85 /* convert the integer to text */
86 if (sprintf(stone_string, "%d", stones)<=0)
87 fprintf(stderr, "String conversion problem.\n");
88 /* get the size of the rendered text */
89 if (TTF_SizeText(font, stone_string, &w, &h)<0)
90 fprintf(stderr, "SDL_ttf: %s\n", TTF_GetError());
91 /* if the text is too large, render a '?' */
92 if ((w > (*stone_gfx)->w) || (h > (*stone_gfx)->h))
93 sprintf(stone_string, "?");
94 if (!(text = TTF_RenderText_Blended(font, stone_string,
96 fprintf(stderr, "SDL_ttf: %s\n", TTF_GetError());
107 SDL_Surface *DrawBoard(int *aiBoard, int *humanBoard,
108 TTF_Font *board_font, TTF_Font *home_font,
109 SDL_Surface *tile, SDL_Surface **stone_gfx,
110 int active, int highlight) {
112 SDL_Surface *board, *stones;
113 SDL_Rect tile_rect, blit_rect;
114 SDL_Color home_color;
115 char home_string[STRING_MAX];
118 /* initialize the board surface */
119 board = SDL_CreateRGBSurface(SDL_SWSURFACE, tile->w*(BOARD_MAX+2),
120 tile->h*2, tile->format->BitsPerPixel, 0, 0, 0, 0);
122 fprintf(stderr, "DrawBoard: %s\n", SDL_GetError());
126 tile_rect = SurfaceToRect(tile);
127 /*printf("tile is %dx%d\n", tile_rect.w, tile_rect.h);*/
129 /* set the color of text in the home */
134 for (i=0; i<=BOARD_MAX+1; i++)
136 /* update current tile location */
137 tile_rect.x = i * tile_rect.w;
139 /*printf("Currently a %dx%d rectangle at %d,%d.\n", tile_rect.w,
140 tile_rect.h, tile_rect.x, tile_rect.y);*/
141 blit_rect = tile_rect;
142 /* is this is the first or last tile? */
143 if ((i==0) || (i==BOARD_MAX+1)) {
145 if (SDL_BlitSurface(tile, NULL, board, &blit_rect)<0)
146 fprintf(stderr,"DrawBoard: %s\n",
148 blit_rect = tile_rect;
149 blit_rect.y = blit_rect.h;
150 SDL_BlitSurface(tile, NULL, board, &blit_rect);
151 /* render the number of stones in each home */
153 if (sprintf(home_string,"%d",humanBoard[0])<=0)
154 printf("Human string problems.\n");
157 if (sprintf(home_string, "%d", aiBoard[0])<=0)
158 printf("AI string problems.\n");
160 if (!(stones = TTF_RenderText_Blended(home_font,
161 home_string, home_color)))
162 fprintf(stderr, "DrawBoard: %s\n",
164 blit_rect.w = stones->w;
165 blit_rect.h = stones->h;
166 blit_rect.x += ((tile_rect.w - blit_rect.w)/2);
167 blit_rect.y = ((tile_rect.h*2 - blit_rect.h)/2);
168 SDL_BlitSurface(stones, NULL, board, &blit_rect);
170 /* otherwise, draw a hole and fill it */
172 SDL_BlitSurface(stone_gfx[0], NULL, board, &blit_rect);
173 if (humanBoard[i] > 0) {
174 if (!(stones = FillHole(humanBoard[i],
175 board_font, stone_gfx)))
176 fprintf(stderr,"FillHole() problems\n");
178 stones = ShiftColors(stones,128,128,128,255);
180 stones = ShiftColors(stones,0,0,0,160);
181 blit_rect.w = stones->w;
182 blit_rect.h = stones->h;
183 blit_rect.x += ((tile_rect.w - blit_rect.w)/2);
184 blit_rect.y += ((tile_rect.h - blit_rect.h)/2);
185 SDL_BlitSurface(stones,NULL,board,&blit_rect);
188 blit_rect = tile_rect;
189 blit_rect.y = blit_rect.h;
190 SDL_BlitSurface(stone_gfx[0], NULL, board, &blit_rect);
191 if (aiBoard[BOARD_MAX-i+1] > 0) {
192 if (!(stones = FillHole(aiBoard[BOARD_MAX-i+1],
193 board_font, stone_gfx)))
194 fprintf(stderr,"FillHole() problems\n");
196 stones = ShiftColors(stones,0,0,0,160);
197 blit_rect.w = stones->w;
198 blit_rect.h = stones->h;
199 blit_rect.x += ((tile_rect.w - blit_rect.w)/2);
200 blit_rect.y += ((tile_rect.h - blit_rect.h)/2);
201 SDL_BlitSurface(stones,NULL,board,&blit_rect);
206 SDL_FreeSurface(stones);
212 /* flagrantly stol^H^H^Hborrowed from SDL Introduction */
213 /* passing 0 for red, green, or blue leaves them alone */
214 /* passing 0 for alpha makes the image transparent */
216 SDL_Surface *ShiftColors(SDL_Surface *old, Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha)
222 new = NewSurfaceFrom(old, (SDL_SWSURFACE|SDL_SRCALPHA));
224 if ( SDL_MUSTLOCK(old) ) {
225 if (SDL_LockSurface(old) < 0 ) {
230 if ( SDL_MUSTLOCK(new) ) {
231 if ( SDL_LockSurface(new) < 0 ) {
236 for (x=0; x<old->w; x++)
237 for (y=0; y<old->h; y++) {
241 switch (old->format->BytesPerPixel) {
242 case 1: { /* Assuming 8-bpp */
245 bufp = (Uint8 *)old->pixels + y*old->pitch + x;
246 bufq = (Uint8 *)new->pixels + y*new->pitch + x;
247 SDL_GetRGBA((Uint32)*bufp, old->format, &r, &g, &b, &a);
248 a *= alpha/SDL_ALPHA_OPAQUE;
249 *bufq = (Uint8)SDL_MapRGBA(new->format, r, g, b, a);
253 case 2: { /* Probably 15-bpp or 16-bpp */
256 bufp = (Uint16 *)old->pixels + y*old->pitch/2 + x;
257 bufq = (Uint16 *)new->pixels + y*new->pitch + x;
258 SDL_GetRGBA((Uint32)*bufp, new->format, &r, &g, &b, &a);
259 a *= alpha/SDL_ALPHA_OPAQUE;
260 *bufq = (Uint8)SDL_MapRGBA(new->format, r, g, b, a);
264 case 3: { /* Slow 24-bpp mode, usually not used */
268 bufp = (Uint8 *)old->pixels + y*old->pitch + x * 3;
269 bufq = (Uint8 *)new->pixels + y*new->pitch + x * 3;
270 SDL_GetRGBA((Uint32)*bufp, old->format, &r, &g, &b, &a);
271 a *= alpha/SDL_ALPHA_OPAQUE;
272 color = SDL_MapRGBA(new->format, r, g, b, a);
273 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {
275 bufq[1] = color >> 8;
276 bufq[2] = color >> 16;
279 bufq[1] = color >> 8;
280 bufq[0] = color >> 16;
285 case 4: { /* Probably 32-bpp */
288 bufp = (Uint32 *)old->pixels + y*old->pitch/4 + x;
289 bufq = (Uint32 *)new->pixels + y*new->pitch/4 + x;
290 SDL_GetRGBA(*bufp, old->format, &r, &g, &b, &a);
291 a = (int)((long)a * (long)alpha/SDL_ALPHA_OPAQUE);
292 r += (int)((long)(SDL_ALPHA_OPAQUE - r) * (long)red/SDL_ALPHA_OPAQUE);
293 g += (int)((long)(SDL_ALPHA_OPAQUE - g) * (long)green/SDL_ALPHA_OPAQUE);
294 b += (int)((long)(SDL_ALPHA_OPAQUE - b) * (long)blue/SDL_ALPHA_OPAQUE);
295 *bufq = SDL_MapRGBA(new->format, r, g, b, a);
301 if ( SDL_MUSTLOCK(new) ) {
302 SDL_UnlockSurface(new);
305 if ( SDL_MUSTLOCK(old) ) {
306 SDL_UnlockSurface(old);