make console optional, other fixes
[btb/d2x.git] / console / DT_drawtext.c
1 /*  DT_drawtext.c
2  *  Written By: Garrett Banuk <mongoose@mongeese.org>
3  *  This is free, just be sure to give me credit when using it
4  *  in any of your programs.
5  */
6
7 #include <string.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "SDL.h"
11 #include "SDL_image.h"
12 #include "DT_drawtext.h"
13 #include "internal.h"
14
15
16 static BitFont *BitFonts = NULL;        /* Linked list of fonts */
17
18
19 /* sets the transparency value for the font in question.  assumes that
20  * we're in an OpenGL context.  */
21 void DT_SetFontAlphaGL(int FontNumber, int a) {
22         unsigned char val;
23         BitFont *CurrentFont;
24         unsigned char r_targ, g_targ, b_targ;
25         int i, imax;
26         unsigned char *pix;
27
28         /* get pointer to font */
29         CurrentFont = DT_FontPointer(FontNumber);
30         if(CurrentFont == NULL) {
31                 PRINT_ERROR("Setting font alpha for non-existent font!\n");
32                 return;
33         }
34         if(CurrentFont->FontSurface->format->BytesPerPixel == 2) {
35                 PRINT_ERROR("16-bit SDL surfaces do not support alpha-blending under OpenGL\n");
36                 return;
37         }
38         if(a < SDL_ALPHA_TRANSPARENT)
39                 val = SDL_ALPHA_TRANSPARENT;
40         else if(a > SDL_ALPHA_OPAQUE)
41                 val = SDL_ALPHA_OPAQUE;
42         else
43                 val = a;
44
45         /* iterate over all pixels in the font surface.  For each
46          * pixel that is (255,0,255), set its alpha channel
47          * appropriately.  */
48         imax = CurrentFont->FontSurface->h * (CurrentFont->FontSurface->w << 2);
49         pix = (unsigned char *)(CurrentFont->FontSurface->pixels);
50         r_targ = 255;           /*pix[0]; */
51         g_targ = 0;             /*pix[1]; */
52         b_targ = 255;           /*pix[2]; */
53         for(i = 3; i < imax; i += 4)
54                 if(pix[i - 3] == r_targ && pix[i - 2] == g_targ && pix[i - 1] == b_targ)
55                         pix[i] = val;
56         /* also make sure that alpha blending is disabled for the font
57            surface. */
58         SDL_SetAlpha(CurrentFont->FontSurface, 0, SDL_ALPHA_OPAQUE);
59 }
60
61 /* Loads the font into a new struct
62  * returns -1 as an error else it returns the number
63  * of the font for the user to use
64  */
65 int DT_LoadFont(const char *BitmapName, int flags) {
66         int FontNumber = 0;
67         BitFont **CurrentFont = &BitFonts;
68         SDL_Surface *Temp;
69
70
71         while(*CurrentFont) {
72                 CurrentFont = &((*CurrentFont)->NextFont);
73                 FontNumber++;
74         }
75
76         /* load the font bitmap */
77         if(NULL == (Temp = IMG_Load(BitmapName))) {
78                 PRINT_ERROR("Cannot load file ");
79                 printf("%s\n", BitmapName);
80                 return -1;
81         }
82
83         /* Add a font to the list */
84         *CurrentFont = (BitFont *) malloc(sizeof(BitFont));
85
86         (*CurrentFont)->FontSurface = SDL_DisplayFormat(Temp);
87         SDL_FreeSurface(Temp);
88
89         (*CurrentFont)->CharWidth = (*CurrentFont)->FontSurface->w / 256;
90         (*CurrentFont)->CharHeight = (*CurrentFont)->FontSurface->h;
91         (*CurrentFont)->FontNumber = FontNumber;
92         (*CurrentFont)->NextFont = NULL;
93
94
95         /* Set font as transparent if the flag is set.  The assumption we'll go on
96          * is that the first pixel of the font image will be the color we should treat
97          * as transparent.
98          */
99         if(flags & TRANS_FONT) {
100                 if(SDL_GetVideoSurface()->flags & SDL_OPENGLBLIT)
101                         DT_SetFontAlphaGL(FontNumber, SDL_ALPHA_TRANSPARENT);
102                 else
103                         SDL_SetColorKey((*CurrentFont)->FontSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB((*CurrentFont)->FontSurface->format, 255, 0, 255));
104         } else if(SDL_GetVideoSurface()->flags & SDL_OPENGLBLIT)
105                 DT_SetFontAlphaGL(FontNumber, SDL_ALPHA_OPAQUE);
106
107         return FontNumber;
108 }
109
110 /* Takes the font type, coords, and text to draw to the surface*/
111 void DT_DrawText(const char *string, SDL_Surface *surface, int FontType, int x, int y) {
112         int loop;
113         int characters;
114         int current;
115         SDL_Rect SourceRect, DestRect;
116         BitFont *CurrentFont;
117
118         CurrentFont = DT_FontPointer(FontType);
119
120         /* see how many characters can fit on the screen */
121         if(x > surface->w || y > surface->h)
122                 return;
123
124         if(strlen(string) < (surface->w - x) / CurrentFont->CharWidth)
125                 characters = strlen(string);
126         else
127                 characters = (surface->w - x) / CurrentFont->CharWidth;
128
129         DestRect.x = x;
130         DestRect.y = y;
131         DestRect.w = CurrentFont->CharWidth;
132         DestRect.h = CurrentFont->CharHeight;
133
134         SourceRect.y = 0;
135         SourceRect.w = CurrentFont->CharWidth;
136         SourceRect.h = CurrentFont->CharHeight;
137
138         /* Now draw it */
139         for(loop = 0; loop < characters; loop++) {
140                 current = string[loop];
141                 if (current<0 || current > 255)
142                         current = 0;
143                 //SourceRect.x = string[loop] * CurrentFont->CharWidth;
144                 SourceRect.x = current * CurrentFont->CharWidth;
145                 SDL_BlitSurface(CurrentFont->FontSurface, &SourceRect, surface, &DestRect);
146                 DestRect.x += CurrentFont->CharWidth;
147         }
148         /* if we're in OpenGL-mode, we need to manually update after blitting. */
149         if(surface->flags & SDL_OPENGLBLIT) {
150                 DestRect.x = x;
151                 DestRect.w = characters * CurrentFont->CharWidth;
152                 SDL_UpdateRects(surface, 1, &DestRect);
153         }
154 }
155
156
157 /* Returns the height of the font numbers character
158  * returns 0 if the fontnumber was invalid */
159 int DT_FontHeight(int FontNumber) {
160         BitFont *CurrentFont;
161
162         CurrentFont = DT_FontPointer(FontNumber);
163         if(CurrentFont)
164                 return CurrentFont->CharHeight;
165         else
166                 return 0;
167 }
168
169 /* Returns the width of the font numbers charcter */
170 int DT_FontWidth(int FontNumber) {
171         BitFont *CurrentFont;
172
173         CurrentFont = DT_FontPointer(FontNumber);
174         if(CurrentFont)
175                 return CurrentFont->CharWidth;
176         else
177                 return 0;
178 }
179
180 /* Returns a pointer to the font struct of the number
181  * returns NULL if theres an error
182  */
183 BitFont *DT_FontPointer(int FontNumber) {
184         BitFont *CurrentFont = BitFonts;
185         BitFont *temp;
186
187         while(CurrentFont)
188                 if(CurrentFont->FontNumber == FontNumber)
189                         return CurrentFont;
190                 else {
191                         temp = CurrentFont;
192                         CurrentFont = CurrentFont->NextFont;
193                 }
194
195         return NULL;
196
197 }
198
199 /* removes all the fonts currently loaded */
200 void DT_DestroyDrawText() {
201         BitFont *CurrentFont = BitFonts;
202         BitFont *temp;
203
204         while(CurrentFont) {
205                 temp = CurrentFont;
206                 CurrentFont = CurrentFont->NextFont;
207
208                 SDL_FreeSurface(temp->FontSurface);
209                 free(temp);
210         }
211
212         BitFonts = NULL;
213 }
214
215