Huge code merge. This reflects the current status of my rewrite/restructuring. A...
[supertux.git] / src / screen.c
1 /*
2   screen.c
3   
4   Super Tux - Screen Functions
5   
6   by Bill Kendrick
7   bill@newbreedsoftware.com
8   http://www.newbreedsoftware.com/supertux/
9   
10   April 11, 2000 - April 22, 2000
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <SDL.h>
19 #include <SDL_image.h>
20
21 #ifdef LINUX
22 #include <pwd.h>
23 #include <sys/types.h>
24 #include <ctype.h>
25 #endif
26
27 #include "defines.h"
28 #include "globals.h"
29 #include "screen.h"
30 #include "setup.h"
31 #include "type.h"
32
33 /* --- LOAD AND DISPLAY AN IMAGE --- */
34
35 void load_and_display_image(char * file)
36 {
37   SDL_Surface * img;
38   
39   img = load_image(file, IGNORE_ALPHA);
40   SDL_BlitSurface(img, NULL, screen, NULL);
41   SDL_FreeSurface(img);
42 }
43
44
45 /* --- CLEAR SCREEN --- */
46
47 void clearscreen(float r, float g, float b)
48 {
49   if(use_gl)
50   {
51   glClearColor(r/256, g/256, b/256, 1.0);
52   glClear(GL_COLOR_BUFFER_BIT);
53   }
54   else
55   SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, r, g, b));
56  
57 }
58
59
60 /* --- UPDATE SCREEN --- */
61
62 void updatescreen(void)
63 {
64   if(use_gl)  /*clearscreen(0,0,0);*/
65   SDL_GL_SwapBuffers();
66   else
67     SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
68 }
69
70 void flipscreen(void)
71 {
72 if(use_gl)
73 SDL_GL_SwapBuffers();
74 else
75 SDL_Flip(screen);
76 }
77
78 /* --- LOAD AN IMAGE --- */
79
80 SDL_Surface * load_image(char * file, int use_alpha)
81 {
82 /*
83 if(!faccessible(file))
84 {
85 if(!faccessible(st_dir,
86 */
87
88   SDL_Surface * temp, * surf;
89   
90   temp = IMG_Load(file);
91
92   if (temp == NULL)
93     st_abort("Can't load", file);
94     
95   surf = SDL_DisplayFormatAlpha(temp);
96
97   if (surf == NULL)
98     st_abort("Can't covert to display format", file);
99     
100   if (use_alpha == IGNORE_ALPHA)
101     SDL_SetAlpha(surf, 0, 0);
102   
103   SDL_FreeSurface(temp);
104
105   return(surf);
106 }
107
108 void create_gl_texture(SDL_Surface * surf, GLint * tex)
109 {
110 SDL_Surface *conv;
111 conv = SDL_CreateRGBSurface(SDL_SWSURFACE , surf->w, surf->h, 32,
112 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
113             0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
114 #else
115             0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
116 #endif
117     SDL_BlitSurface(surf, 0, conv, 0);
118                      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
119        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
120     
121   glGenTextures(1, &*tex);
122
123     glBindTexture(GL_TEXTURE_RECTANGLE_NV , *tex);
124              glEnable(GL_TEXTURE_RECTANGLE_NV);
125     glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
126     glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
127     glPixelStorei(GL_UNPACK_ROW_LENGTH, conv->pitch / conv->format->BytesPerPixel);
128     glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 3, conv->w, conv->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, conv->pixels);
129     //glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, 0, 0, conv->w, conv->h);
130     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
131     SDL_FreeSurface(conv);
132 }
133
134 /* --- DRAW AN IMAGE ONTO THE SCREEN --- */
135 /*
136 void drawimage(SDL_Surface * surf, float x, float y, int update)
137 {
138 if(use_gl)
139 {
140 GLint gl_tex;
141 create_gl_texture(surf,&gl_tex);
142     glColor4ub(255, 255, 255,255);
143 glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
144 glEnable (GL_BLEND);
145     glBindTexture(GL_TEXTURE_RECTANGLE_NV, gl_tex);
146
147     glBegin(GL_QUADS);
148         glTexCoord2f(0, 0);    glVertex2f(x, y);
149         glTexCoord2f((float)surf->w, 0);    glVertex2f((float)surf->w+x, y);
150         glTexCoord2f((float)surf->w, (float)surf->h);    glVertex2f((float)surf->w+x, (float)surf->h+y);
151         glTexCoord2f(0, (float)surf->h);    glVertex2f(x, (float)surf->h+y);
152     glEnd();
153  glDeleteTextures(1, &gl_tex);
154  }
155 else
156 {
157   SDL_Rect dest;
158   
159   dest.x = x;
160   dest.y = y;
161   dest.w = surf->w;
162   dest.h = surf->h;
163   
164   SDL_BlitSurface(surf, NULL, screen, &dest);
165   
166   if (update == UPDATE)
167     SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
168 }
169 }
170 */
171 /*
172 drawbgimage(SDL_Surface * surf, int update)
173 {
174 if(use_gl)
175 {
176 GLint gl_tex;
177 create_gl_texture(surf,&gl_tex);
178     //glColor3ub(255, 255, 255);
179
180     glEnable(GL_TEXTURE_RECTANGLE_NV);
181     glBindTexture(GL_TEXTURE_RECTANGLE_NV, gl_tex);
182
183     glBegin(GL_QUADS);
184         glTexCoord2f(0, 0);    glVertex2f(0, 0);
185         glTexCoord2f((float)surf->w, 0);    glVertex2f(screen->w, 0);
186         glTexCoord2f((float)surf->w, (float)surf->h);    glVertex2f(screen->w, screen->h);
187         glTexCoord2f(0, (float)surf->h); glVertex2f(0, screen->h);
188     glEnd();
189  glDeleteTextures(1, &gl_tex);
190  
191 }
192 else
193 {
194   SDL_Rect dest;
195   
196   dest.x = 0;
197   dest.y = 0;
198   dest.w = screen->w;
199   dest.h = screen->h;
200   
201   SDL_BlitSurface(surf, NULL, screen, &dest);
202   
203   if (update == UPDATE)
204     SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
205 }
206 }
207 */
208 void update_rect(SDL_Surface *scr, Sint32 x, Sint32 y, Sint32 w, Sint32 h)
209 {
210 if(!use_gl)
211 SDL_UpdateRect(scr, x, y, w, h);
212 }
213
214
215 /* --- DRAW PART OF AN IMAGE ONTO THE SCREEN --- */
216 /*
217 void drawpart(SDL_Surface * surf, float x, float y, float w, float h, int update)
218 {
219 if(use_gl)
220 {
221 GLint gl_tex;
222 create_gl_texture(surf,&gl_tex);
223     glColor3ub(255, 255, 255);
224
225     glEnable(GL_TEXTURE_RECTANGLE_NV);
226     glBindTexture(GL_TEXTURE_RECTANGLE_NV, gl_tex);
227
228     glBegin(GL_QUADS);
229         glTexCoord2f(x, y);    glVertex2f(x, y);
230         glTexCoord2f(x+w, y);    glVertex2f(w+x, y);
231         glTexCoord2f(x+w, y+h);    glVertex2f(w+x, h+y);
232         glTexCoord2f(x, y+h);     glVertex2f(x, h+y);
233     glEnd();
234  glDeleteTextures(1, &gl_tex);
235  }
236 else
237 {
238   SDL_Rect src, dest;
239   
240   src.x = x;
241   src.y = y;
242   src.w = w;
243   src.h = h;
244
245   dest.x = x;
246   dest.y = y;
247   dest.w = w;
248   dest.h = h;
249   
250   
251   SDL_BlitSurface(surf, &src, screen, &dest);
252   
253   if (update == UPDATE)
254     update_rect(screen, dest.x, dest.y, dest.w, dest.h);
255     }
256 }
257 */
258 /* --- DRAW TEXT ONTO THE SCREEN --- */
259
260 void drawtext(char * text, int x, int y, SDL_Surface * surf, int update, int shadowsize)
261 {
262         /* i - helps to keep tracking of the all string length
263                 j - helps to keep track of the length of the current line */
264   int i, j;
265   char c;
266   SDL_Rect src, dest;
267   
268   /* For each letter in the string... */
269   
270   for (i = 0; i < strlen(text); i++)
271     {
272       /* Set source rectangle: */
273       
274       c = text[i];
275       
276       if (c >= 'A' && c <= 'Z')
277         {
278           /* Capital letter - first row: */
279           
280           src.x = (c - 'A') * 16;
281           src.y = 0;
282         }
283       else if (c >= 'a' && c <= 'z')
284         {
285           /* Lowercase letter - first row: */
286           
287           src.x = (c - 'a') * 16;
288           src.y = 16;
289         }
290       else if (c >= '!' && c <= '9')
291         {
292           /* Punctuation (except '?') or number - third row: */
293           
294           src.x = (c - '!') * 16;
295           src.y = 32;
296         }
297       else if (c == '?')
298         {
299           /* Question mark - third row, last character: */
300           
301           src.x = 400;
302           src.y = 24;
303         }
304         else if (c == '\n')             /* support for multi-lines */
305         {
306         j = i + 1;
307         y += 18;
308         continue;
309         }
310       else
311         src.x = -1;
312       
313       src.w = 16;
314       src.h = 16;
315       
316
317       /* Draw character: */
318       
319       if (src.x != -1)
320         {
321           /* Set destination rectangle for shadow: */
322           
323           dest.x = x + (i * 16) + shadowsize;
324           dest.y = y + shadowsize;
325           dest.w = src.w;
326           dest.h = src.h;
327           
328           
329           /* Shadow: */
330           
331           SDL_BlitSurface(letters_black, &src, screen, &dest);
332           
333           
334           /* Set destination rectangle for text: */
335           
336           dest.x = x + (i * 16);
337           dest.y = y;
338           dest.w = src.w;
339           dest.h = src.h;
340           
341           
342           /* Shadow: */
343           
344           SDL_BlitSurface(surf, &src, screen, &dest);
345           
346
347 /* FIXME: Text doesn't work in OpenGL mode, below is experimental code */
348 /*
349
350           dest.x = 0;
351           dest.y = 0; 
352           dest.w = src.w;
353           
354           dest.h = src.h;
355           
356           temp = SDL_CreateRGBSurface(SDL_SWSURFACE, dest.w, dest.h, 32,
357 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
358             0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
359 #else
360             0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
361 #endif
362           SDL_BlitSurface(letters_black, &src, temp, NULL);
363           texture_type xyz;
364           texture_from_sdl_surface(&xyz,temp,IGNORE_ALPHA);
365           texture_draw(&xyz,x + (i * 16) + shadowsize,y + shadowsize, update);
366           texture_free(&xyz);
367           / * Set destination rectangle for text: * /
368           
369           dest.x = x + (i * 16);
370           dest.y = y;
371           dest.w = src.w;
372           dest.h = src.h;         
373           
374           / * Text: * /
375           
376           SDL_BlitSurface(surf, &src, temp, NULL);
377           texture_from_sdl_surface(&xyz,temp,IGNORE_ALPHA);
378           SDL_FreeSurface(temp);
379           texture_draw(&xyz,x + (i * 16) + shadowsize,y + shadowsize, update);
380           texture_free(&xyz);*/
381         }
382     }
383   
384   
385   /* Update */
386   
387   if (update == UPDATE)
388     {
389       dest.w = strlen(text) * 16 + 1;
390       
391       if (dest.w > screen->w)
392         dest.w = screen->w;
393       
394       update_rect(screen, x, y, dest.w, 17);
395     }
396     
397 }
398
399
400 /* --- DRAW HORIZONTALLY-CENTERED TEXT: --- */
401
402 void drawcenteredtext(char * text, int y, SDL_Surface * surf, int update, int shadowsize)
403 {
404   drawtext(text, screen->w / 2 - (strlen(text) * 8), y, surf, update, shadowsize);
405 }
406
407 /* --- ERASE TEXT: --- */
408
409 void erasetext(char * text, int x, int y, SDL_Surface * surf, int update, int shadowsize)
410 {
411   SDL_Rect dest;
412   
413   
414   dest.x = x;
415   dest.y = y;
416   dest.w = strlen(text) * 16 + shadowsize;
417   dest.h = 17;
418   
419   if (dest.w > screen->w)
420     dest.w = screen->w;
421   
422   SDL_BlitSurface(surf, &dest, screen, &dest);
423   
424   if (update == UPDATE)
425     update_rect(screen, dest.x, dest.y, dest.w, dest.h);
426 }
427
428
429 /* --- ERASE CENTERED TEXT: --- */
430
431 void erasecenteredtext(char * text, int y, SDL_Surface * surf, int update, int shadowsize)
432 {
433   erasetext(text, screen->w / 2 - (strlen(text) * 8), y, surf, update, shadowsize);
434 }