]> Shamusworld >> Repos - virtualjaguar/blob - src/gui/guimisc.cpp
Major refactoring of GUI: Phase I
[virtualjaguar] / src / gui / guimisc.cpp
1 //
2 // Miscellaneous GUI utility functions
3 //
4 // by James L. Hammons
5 //
6
7 #include "guimisc.h"
8
9 #include <stdarg.h>
10 #include "font1.h"
11 #include "font14pt.h"
12 #include "guielements.h"        // Make this go away...
13 #include "sdlemu_opengl.h"
14 #include "vj_title_small.c"
15 //#include "video.h"
16
17 //
18 // Case insensitive string compare function
19 // Taken straight out of Thinking In C++ by Bruce Eckel. Thanks Bruce!
20 //
21
22 int stringCmpi(const std::string &s1, const std::string &s2)
23 {
24         // Select the first element of each string:
25         std::string::const_iterator p1 = s1.begin(), p2 = s2.begin();
26
27         while (p1 != s1.end() && p2 != s2.end())                // Don�t run past the end
28         {
29                 if (toupper(*p1) != toupper(*p2))                       // Compare upper-cased chars
30                         return (toupper(*p1) < toupper(*p2) ? -1 : 1);// Report which was lexically greater
31
32                 p1++;
33                 p2++;
34         }
35
36         // If they match up to the detected eos, say which was longer. Return 0 if the same.
37         return s2.size() - s1.size();
38 }
39
40 //
41 // Draw text at the given x/y coordinates. Can invert text as well.
42 //
43 void DrawString(uint32 * screen, uint32 x, uint32 y, bool invert, const char * text, ...)
44 {
45         char string[4096];
46         va_list arg;
47
48         va_start(arg, text);
49         vsprintf(string, text, arg);
50         va_end(arg);
51
52         uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
53         uint32 length = strlen(string), address = x + (y * pitch);
54
55         uint32 color1 = 0x0080FF;
56         uint8 nBlue = (color1 >> 16) & 0xFF, nGreen = (color1 >> 8) & 0xFF, nRed = color1 & 0xFF;
57         uint8 xorMask = (invert ? 0xFF : 0x00);
58
59         for(uint32 i=0; i<length; i++)
60         {
61                 uint8 c = string[i];
62                 uint32 fontAddr = (uint32)(c < 32 ? 0 : c - 32) * FONT_WIDTH * FONT_HEIGHT;
63
64                 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
65                 {
66                         for(uint32 xx=0; xx<FONT_WIDTH; xx++)
67                         {
68                                 uint32 existingColor = *(screen + address + xx + (yy * pitch));
69
70                                 uint8 eBlue = (existingColor >> 16) & 0xFF,
71                                         eGreen = (existingColor >> 8) & 0xFF,
72                                         eRed = existingColor & 0xFF;
73
74                                 uint8 trans = font2[fontAddr] ^ xorMask;
75                                 uint8 invTrans = trans ^ 0xFF;
76
77                                 uint32 bRed = (eRed * invTrans + nRed * trans) / 255,
78                                         bGreen = (eGreen * invTrans + nGreen * trans) / 255,
79                                         bBlue = (eBlue * invTrans + nBlue * trans) / 255;
80
81                                 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
82                                 fontAddr++;
83                         }
84                 }
85
86                 address += FONT_WIDTH;
87         }
88 }
89
90 //
91 // Draw text at the given x/y coordinates, using FG/BG colors.
92 //
93 void DrawStringOpaque(uint32 * screen, uint32 x, uint32 y, uint32 color1, uint32 color2, const char * text, ...)
94 {
95         char string[4096];
96         va_list arg;
97
98         va_start(arg, text);
99         vsprintf(string, text, arg);
100         va_end(arg);
101
102         uint32 pitch = sdlemuGetOverlayWidthInPixels();
103         uint32 length = strlen(string), address = x + (y * pitch);
104
105         uint8 eBlue = (color2 >> 16) & 0xFF, eGreen = (color2 >> 8) & 0xFF, eRed = color2 & 0xFF,
106                 nBlue = (color1 >> 16) & 0xFF, nGreen = (color1 >> 8) & 0xFF, nRed = color1 & 0xFF;
107
108         for(uint32 i=0; i<length; i++)
109         {
110                 uint8 c = string[i];
111                 c = (c < 32 ? 0 : c - 32);
112                 uint32 fontAddr = (uint32)c * FONT_WIDTH * FONT_HEIGHT;
113
114                 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
115                 {
116                         for(uint32 xx=0; xx<FONT_WIDTH; xx++)
117                         {
118                                 uint8 trans = font2[fontAddr++];
119                                 uint8 invTrans = trans ^ 0xFF;
120
121                                 uint32 bRed   = (eRed   * invTrans + nRed   * trans) / 255;
122                                 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
123                                 uint32 bBlue  = (eBlue  * invTrans + nBlue  * trans) / 255;
124
125                                 *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
126                         }
127                 }
128
129                 address += FONT_WIDTH;
130         }
131 }
132
133 //
134 // Draw text at the given x/y coordinates with transparency (0 is fully opaque, 32 is fully transparent).
135 //
136 void DrawStringTrans(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 trans, const char * text, ...)
137 {
138         char string[4096];
139         va_list arg;
140
141         va_start(arg, text);
142         vsprintf(string, text, arg);
143         va_end(arg);
144
145         uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
146         uint32 length = strlen(string), address = x + (y * pitch);
147
148         for(uint32 i=0; i<length; i++)
149         {
150                 uint32 fontAddr = (uint32)string[i] * 64;
151
152                 for(uint32 yy=0; yy<8; yy++)
153                 {
154                         for(uint32 xx=0; xx<8; xx++)
155                         {
156                                 if (font1[fontAddr])
157                                 {
158                                         uint32 existingColor = *(screen + address + xx + (yy * pitch));
159
160                                         uint8 eBlue = (existingColor >> 16) & 0xFF,
161                                                 eGreen = (existingColor >> 8) & 0xFF,
162                                                 eRed = existingColor & 0xFF,
163 //This could be done ahead of time, instead of on each pixel...
164                                                 nBlue = (color >> 16) & 0xFF,
165                                                 nGreen = (color >> 8) & 0xFF,
166                                                 nRed = color & 0xFF;
167
168 //This could be sped up by using a table of 5 + 5 + 5 bits (32 levels transparency -> 32768 entries)
169 //Here we've modified it to have 33 levels of transparency (could have any # we want!)
170 //because dividing by 32 is faster than dividing by 31...!
171                                         uint8 invTrans = 32 - trans;
172
173                                         uint32 bRed = (eRed * trans + nRed * invTrans) / 32;
174                                         uint32 bGreen = (eGreen * trans + nGreen * invTrans) / 32;
175                                         uint32 bBlue = (eBlue * trans + nBlue * invTrans) / 32;
176
177                                         *(screen + address + xx + (yy * pitch)) = 0xFF000000 | (bBlue << 16) | (bGreen << 8) | bRed;
178                                 }
179
180                                 fontAddr++;
181                         }
182                 }
183
184                 address += 8;
185         }
186 }
187
188 //
189 // Draw text at the given x/y coordinates, using FG color and overlay alpha blending.
190 //
191 void DrawString2(uint32 * screen, uint32 x, uint32 y, uint32 color, uint8 transparency, const char * text, ...)
192 {
193         char string[4096];
194         va_list arg;
195
196         va_start(arg, text);
197         vsprintf(string, text, arg);
198         va_end(arg);
199
200         uint32 pitch = sdlemuGetOverlayWidthInPixels();
201         uint32 length = strlen(string), address = x + (y * pitch);
202
203         color &= 0x00FFFFFF;                                            // Just in case alpha was passed in...
204
205         for(uint32 i=0; i<length; i++)
206         {
207                 uint8 c = string[i];
208                 c = (c < 32 ? 0 : c - 32);
209                 uint32 fontAddr = (uint32)c * FONT_WIDTH * FONT_HEIGHT;
210
211                 for(uint32 yy=0; yy<FONT_HEIGHT; yy++)
212                 {
213                         for(uint32 xx=0; xx<FONT_WIDTH; xx++)
214                         {
215                                 uint8 fontTrans = font2[fontAddr++];
216                                 uint32 newTrans = (fontTrans * transparency / 255) << 24;
217                                 uint32 pixel = newTrans | color;
218
219                                 *(screen + address + xx + (yy * pitch)) = pixel;
220                         }
221                 }
222
223                 address += FONT_WIDTH;
224         }
225 }
226
227 //
228 // Draw "picture"
229 // Uses zero as transparent color
230 // Can also use an optional alpha channel
231 // Alpha channel is now mandatory! ;-)
232 //
233 //void DrawTransparentBitmap(int16 * screen, uint32 x, uint32 y, uint16 * bitmap, uint8 * alpha/*=NULL*/)
234 /*void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap, uint8 * alpha)
235 {
236         uint32 width = bitmap[0], height = bitmap[1];
237         bitmap += 2;
238
239 //      uint32 pitch = GetSDLScreenPitch() / 2;                 // Returns pitch in bytes but we need words...
240         uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
241         uint32 address = x + (y * pitch);
242
243         for(uint32 yy=0; yy<height; yy++)
244         {
245                 for(uint32 xx=0; xx<width; xx++)
246                 {
247                         if (alpha == NULL)
248                         {
249                                 if (*bitmap && x + xx < pitch)                  // NOTE: Still doesn't clip the Y val...
250                                         *(screen + address + xx + (yy * pitch)) = *bitmap;
251                         }
252                         else
253                         {
254                                 uint8 trans = *alpha;
255                                 uint32 color = *bitmap;
256                                 uint32 existingColor = *(screen + address + xx + (yy * pitch));
257
258                                 uint8 eRed = existingColor & 0xFF,
259                                         eGreen = (existingColor >> 8) & 0xFF,
260                                         eBlue = (existingColor >> 16) & 0xFF,
261
262                                         nRed = color & 0xFF,
263                                         nGreen = (color >> 8) & 0xFF,
264                                         nBlue = (color >> 16) & 0xFF;
265
266                                 uint8 invTrans = 255 - trans;
267                                 uint32 bRed = (eRed * trans + nRed * invTrans) / 255;
268                                 uint32 bGreen = (eGreen * trans + nGreen * invTrans) / 255;
269                                 uint32 bBlue = (eBlue * trans + nBlue * invTrans) / 255;
270
271                                 uint32 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
272
273                                 *(screen + address + xx + (yy * pitch)) = blendedColor;
274
275                                 alpha++;
276                         }
277
278                         bitmap++;
279                 }
280         }
281 }*/
282 void DrawTransparentBitmapDeprecated(uint32 * screen, uint32 x, uint32 y, uint32 * bitmap)
283 {
284         uint32 width = bitmap[0], height = bitmap[1];
285         bitmap += 2;
286
287         uint32 pitch = sdlemuGetOverlayWidthInPixels();//GetSDLScreenWidthInPixels();
288         uint32 address = x + (y * pitch);
289
290         for(uint32 yy=0; yy<height; yy++)
291         {
292                 for(uint32 xx=0; xx<width; xx++)
293                 {
294                         uint32 color = *bitmap;
295                         uint32 blendedColor = color;
296                         uint32 existingColor = *(screen + address + xx + (yy * pitch));
297
298                         if (existingColor >> 24 != 0x00)                // Pixel needs blending
299                         {
300                                 uint8 trans = color >> 24;
301                                 uint8 invTrans = trans ^ 0xFF;//255 - trans;
302
303                                 uint8 eRed = existingColor & 0xFF,
304                                         eGreen = (existingColor >> 8) & 0xFF,
305                                         eBlue = (existingColor >> 16) & 0xFF,
306
307                                         nRed = color & 0xFF,
308                                         nGreen = (color >> 8) & 0xFF,
309                                         nBlue = (color >> 16) & 0xFF;
310
311                                 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
312                                 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
313                                 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
314
315                                 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
316                         }
317
318                         *(screen + address + xx + (yy * pitch)) = blendedColor;
319                         bitmap++;
320                 }
321         }
322 }
323
324 void DrawTransparentBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap)
325 {
326         uint32 pitch = sdlemuGetOverlayWidthInPixels();
327         uint32 address = x + (y * pitch);
328         uint32 count = 0;
329
330         for(uint32 yy=0; yy<((Bitmap *)bitmap)->height; yy++)
331         {
332                 for(uint32 xx=0; xx<((Bitmap *)bitmap)->width; xx++)
333                 {
334                         uint32 color = ((uint32 *)((Bitmap *)bitmap)->pixelData)[count];
335                         uint32 blendedColor = color;
336                         uint32 existingColor = *(screen + address + xx + (yy * pitch));
337
338                         if (existingColor >> 24 != 0x00)        // Pixel needs blending
339                         {
340                                 uint8 trans = color >> 24;
341                                 uint8 invTrans = trans ^ 0xFF;
342
343                                 uint8 eRed = existingColor & 0xFF,
344                                         eGreen = (existingColor >> 8) & 0xFF,
345                                         eBlue = (existingColor >> 16) & 0xFF,
346
347                                         nRed = color & 0xFF,
348                                         nGreen = (color >> 8) & 0xFF,
349                                         nBlue = (color >> 16) & 0xFF;
350
351                                 uint32 bRed = (eRed * invTrans + nRed * trans) / 255;
352                                 uint32 bGreen = (eGreen * invTrans + nGreen * trans) / 255;
353                                 uint32 bBlue = (eBlue * invTrans + nBlue * trans) / 255;
354
355 // Instead of $FF, should use the alpha from the destination pixel as the final alpha value...
356                                 blendedColor = 0xFF000000 | bRed | (bGreen << 8) | (bBlue << 16);
357                         }
358
359                         *(screen + address + xx + (yy * pitch)) = blendedColor;
360                         count++;
361                 }
362         }
363 }
364
365 //
366 // Draw a bitmap without using blending
367 //
368 void DrawBitmap(uint32 * screen, uint32 x, uint32 y, const void * bitmap)
369 {
370         uint32 pitch = sdlemuGetOverlayWidthInPixels();
371         uint32 address = x + (y * pitch);
372         uint32 count = 0;
373
374         for(uint32 yy=0; yy<((Bitmap *)bitmap)->height; yy++)
375         {
376                 for(uint32 xx=0; xx<((Bitmap *)bitmap)->width; xx++)
377                 {
378                         *(screen + address + xx + (yy * pitch)) = ((uint32 *)((Bitmap *)bitmap)->pixelData)[count];
379                         count++;
380                 }
381         }
382 }
383
384 //
385 // Fill a portion of the screen with the passed in color
386 //
387 void FillScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h, uint32 color)
388 //void ClearScreenRectangle(uint32 * screen, uint32 x, uint32 y, uint32 w, uint32 h)
389 {
390         uint32 pitch = sdlemuGetOverlayWidthInPixels();
391         uint32 address = x + (y * pitch);
392
393         for(uint32 yy=0; yy<h; yy++)
394                 for(uint32 xx=0; xx<w; xx++)
395                         *(screen + address + xx + (yy * pitch)) = color;
396 }
397