Fix stupid sdl main shortcut
[neverball] / share / image.c
1 /*   
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERBALL is  free software; you can redistribute  it and/or modify
5  * it under the  terms of the GNU General  Public License as published
6  * by the Free  Software Foundation; either version 2  of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
11  * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
12  * General Public License for more details.
13  */
14
15 #include <SDL.h>
16 #include <SDL_ttf.h>
17 #include <SDL_image.h>
18 #include <string.h>
19 #include <math.h>
20
21 #include "glext.h"
22 #include "image.h"
23 #include "base_image.h"
24 #include "base_config.h"
25
26 /*---------------------------------------------------------------------------*/
27
28 void image_snap(char *filename, int w, int h)
29 {
30     int i;
31
32     SDL_Surface *buf = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 24,
33                                             RMASK, GMASK, BMASK, 0);
34     SDL_Surface *img = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 24,
35                                             RMASK, GMASK, BMASK, 0);
36
37     glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, buf->pixels);
38
39     for (i = 0; i < h; i++)
40         memcpy((GLubyte *) img->pixels + 3 * w * i,
41                (GLubyte *) buf->pixels + 3 * w * (h - i), 3 * w);
42
43     SDL_SaveBMP(img, filename);
44
45     SDL_FreeSurface(img);
46     SDL_FreeSurface(buf);
47 }
48
49 void image_size(int *W, int *H, int w, int h)
50 {
51     *W = 1;
52     *H = 1;
53
54     while (*W < w) *W *= 2;
55     while (*H < h) *H *= 2;
56 }
57
58 /*---------------------------------------------------------------------------*/
59
60 /*
61  * Create on  OpenGL texture  object using the  given SDL  surface and
62  * format,  scaled  using the  current  scale  factor.  When  scaling,
63  * assume dimensions are used only for layout and lie about the size.
64  */
65 GLuint make_image_from_surf(int *w, int *h, SDL_Surface *s)
66 {
67     /*int    t = config_get_d(CONFIG_TEXTURES);*/
68     int    t = 0; /* TODO: Fint a way to revert CONFIG_TEXTURES */
69     GLuint o = 0;
70
71     glGenTextures(1, &o);
72     glBindTexture(GL_TEXTURE_2D, o);
73
74     if (t > 1)
75     {
76         SDL_Surface *d = image_scale(s, t);
77
78         /* Load the scaled image. */
79
80         if (d->format->BitsPerPixel == 32)
81             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->w, d->h, 0,
82                          GL_RGBA, GL_UNSIGNED_BYTE, d->pixels);
83         else
84             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,  d->w, d->h, 0,
85                          GL_RGB,  GL_UNSIGNED_BYTE, d->pixels);
86
87         SDL_FreeSurface(d);
88     }
89     else
90     {
91         /* Load the unscaled image. */
92
93         if (s->format->BitsPerPixel == 32)
94             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, s->w, s->h, 0,
95                          GL_RGBA, GL_UNSIGNED_BYTE, s->pixels);
96         else
97             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,  s->w, s->h, 0,
98                          GL_RGB,  GL_UNSIGNED_BYTE, s->pixels);
99     }
100
101     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
102     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
103
104     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
105     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
106
107     if (w) *w = s->w;
108     if (h) *h = s->h;
109
110     return o;
111 }
112
113 /*---------------------------------------------------------------------------*/
114
115 /*
116  * Load  an image  from the  named file.   If the  image is  not RGBA,
117  * convert it to RGBA.  Return an OpenGL texture object.
118  */
119 GLuint make_image_from_file(int *W, int *H,
120                             int *w, int *h, const char *name)
121 {
122     SDL_Surface *src;
123     SDL_Surface *dst;
124     SDL_Rect rect;
125
126     GLuint o = 0;
127
128     /* Load the file. */
129
130     if ((src = IMG_Load(config_data(name))))
131     {
132         int w2;
133         int h2;
134
135         image_size(&w2, &h2, src->w, src->h);
136
137         if (w) *w = src->w;
138         if (h) *h = src->h;
139
140         /* Create a new destination surface. */
141         
142         if ((dst = SDL_CreateRGBSurface(SDL_SWSURFACE, w2, h2, 32,
143                                         RMASK, GMASK, BMASK, AMASK)))
144         {
145             /* Copy source pixels to the center of the destination. */
146
147             rect.x = (Sint16) (w2 - src->w) / 2;
148             rect.y = (Sint16) (h2 - src->h) / 2;
149
150             SDL_SetAlpha(src, 0, 0);
151             SDL_BlitSurface(src, NULL, dst, &rect);
152
153             o = make_image_from_surf(W, H, dst);
154
155             SDL_FreeSurface(dst);
156         }
157         SDL_FreeSurface(src);
158     }
159     return o;
160 }
161
162 /*---------------------------------------------------------------------------*/
163
164 /*
165  * Render the given  string using the given font.   Transfer the image
166  * to a  surface of  power-of-2 size large  enough to fit  the string.
167  * Return an OpenGL texture object.
168  */
169 GLuint make_image_from_font(int *W, int *H,
170                             int *w, int *h, const char *text, TTF_Font *font, int k)
171 {
172     SDL_Color fg = { 0xFF, 0xFF, 0xFF, 0xFF };
173
174     SDL_Surface *src;
175     SDL_Surface *dst;
176     SDL_Rect rect;
177
178     GLuint o = 0;
179
180     /* Render the text. */
181
182     if (text && strlen(text) > 0)
183     {
184         if ((src = TTF_RenderUTF8_Blended(font, text, fg)))
185         {
186             int w2;
187             int h2;
188
189             image_size(&w2, &h2, src->w, src->h);
190
191             if (w) *w = src->w;
192             if (h) *h = src->h;
193
194             /* Create a new destination surface. */
195             
196             if ((dst = SDL_CreateRGBSurface(SDL_SWSURFACE, w2, h2, 32,
197                                             RMASK, GMASK, BMASK, AMASK)))
198             {
199                 /* Copy source pixels to the center of the destination. */
200
201                 rect.x = (Sint16) (w2 - src->w) / 2;
202                 rect.y = (Sint16) (h2 - src->h) / 2;
203
204                 SDL_SetAlpha(src, 0, 0);
205                 SDL_BlitSurface(src, NULL, dst, &rect);
206
207                 image_white(dst);
208
209                 o = make_image_from_surf(W, H, dst);
210
211                 SDL_FreeSurface(dst);
212             }
213             SDL_FreeSurface(src);
214         }
215
216         if (W) *W *= k;
217         if (H) *H *= k;
218         if (w) *w *= k;
219         if (h) *h *= k;
220     }
221     else
222     {
223         if (W) *W = 0;
224         if (H) *H = 0;
225         if (w) *w = 0;
226         if (h) *h = 0;
227     }
228
229     return o;
230 }
231
232 /*---------------------------------------------------------------------------*/