Fixed compile issues in AxWin2 WM
[tpg/acess2.git] / Usermode / Applications / axwin2_src / WM / video_text.c
1 /*
2  * Acess GUI (AxWin) Version 2
3  * By John Hodge (thePowersGang)
4  */
5 #include "common.h"
6
7 typedef struct sGlyph {
8         struct sGlyph   *Next;
9         struct sGlyph   *Prev;
10         
11         uint32_t        Codepoint;
12         
13         // Effective dimensions (distance to move 'cursor')
14         short   Width;
15         short   Height;
16         
17         // Distance from the current cursor position to render at
18         short   OffsetX;
19         short   OffsetY;
20         
21         // True dimensions (size of the bitmap
22         short   TrueWidth;
23         short   TrueHeight;
24         
25         // Bitmap Data
26         uint8_t Bitmap[];
27         
28 }       tGlyph;
29
30 struct sFont {
31         struct sFont    *Next;
32          int    ReferenceCount;
33         
34         tGlyph  *AsciiGlyphs[128];      // Glyphs 0-127
35         
36         tGlyph  *FirstGlyph;
37         tGlyph  *LastGlyph;
38         
39         tGlyph  *(*CacheGlyph)(struct sFont *this, uint32_t Codepoint);
40         
41 };
42
43
44 // === PROTOTYPES ===
45  int    Video_DrawText(short X, short Y, short W, short H, tFont *Font, uint32_t Color, char *Text);
46 tGlyph  *_GetGlyph(tFont *Font, uint32_t Codepoint);
47 void    _RenderGlyph(short X, short Y, tGlyph *Glyph, uint32_t Color);
48 tGlyph  *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint);
49  int    ReadUTF8(char *Input, uint32_t *Output);
50
51 // === GLOBALS ===
52 tFont   gSystemFont = {
53         CacheGlyph: _SystemFont_CacheGlyph
54 };
55
56 // === CODE ===
57 /**
58  * \brief Draw text to the screen
59  */
60 int Video_DrawText(short X, short Y, short W, short H, tFont *Font, uint32_t Color, char *Text)
61 {
62          int    xOfs = 0;
63         tGlyph  *glyph;
64         uint32_t        ch = 0;
65         
66         // Check the bounds
67         if(W < 0 || X < 0 || X >= giScreenWidth)        return 0;
68         if(X + W > giScreenWidth)       W = giScreenWidth - X;
69         
70         if(H < 0 || Y < 0 || Y >= giScreenHeight)       return 0;
71         if(Y + H > giScreenHeight)      H = giScreenHeight - Y;
72         
73         // Handle NULL font (system default monospace)
74         if( !Font )     Font = &gSystemFont;
75         
76         while( *Text )
77         {
78                 // Read character
79                 Text += ReadUTF8(Text, &ch);
80                 
81                 // Find (or load) the glyph
82                 glyph = _GetGlyph(Font, ch);
83                 if( glyph )
84                         continue ;      // If not found, just don't render it
85                 
86                 // End render if it will overflow the perscribed range
87                 if( xOfs + glyph->TrueWidth > W )
88                         break;
89                 
90                 xOfs += glyph->Width;
91                 _RenderGlyph(X + xOfs, Y, glyph, Color);
92         }
93         
94         return xOfs;
95 }
96
97 tGlyph  *_GetGlyph(tFont *Font, uint32_t Codepoint)
98 {
99         tGlyph  *next = NULL, *prev = NULL;
100         tGlyph  *new;
101         
102         // Check for ASCII
103         if( Codepoint < 128 )
104         {
105                 if( Font->AsciiGlyphs[Codepoint] == NULL ) {
106                         Font->CacheGlyph(Font, Codepoint);
107                 }
108                 
109                 return Font->AsciiGlyphs[Codepoint];
110         }
111         
112         // If within the range
113         if( Font->FirstGlyph && Font->FirstGlyph->Codepoint < Codepoint && Codepoint < Font->LastGlyph->Codepoint )
114         {
115                 // Find what end is "closest"
116                 if( Codepoint - Font->FirstGlyph->Codepoint < Font->LastGlyph->Codepoint - Codepoint )
117                 {
118                         // Start from the bottom
119                         for( next = Font->FirstGlyph;
120                                  next && next->Codepoint < Codepoint;
121                                  prev = next, next = next->Next
122                                  );
123                         
124                         if( next->Codepoint == Codepoint )
125                                 return next;
126                         
127                 }
128                 else
129                 {
130                         // Start at the top
131                         // NOTE: The roles of next and prev are reversed here to allow 
132                         //       the insert to be able to assume that `prev` is the
133                         //       previous entry, and `next` is the next.
134                         for( prev = Font->LastGlyph;
135                                  prev && prev->Codepoint > Codepoint;
136                                  next = prev, prev = prev->Prev
137                                  );
138                         if( prev->Codepoint == Codepoint )
139                                 return prev;
140                 }
141         }
142         else
143         {
144                 // If below first
145                 if( !Font->FirstGlyph ||  Font->FirstGlyph->Codepoint > Codepoint ) {
146                         prev = NULL;
147                         next = Font->FirstGlyph;
148                 }
149                 // Above last
150                 else {
151                         prev = Font->LastGlyph;
152                         next = NULL;
153                 }
154         }
155         
156         // Load new
157         new = Font->CacheGlyph(Font, Codepoint);
158         if( !new )      return NULL;
159         
160         // Add to list
161         // - Forward link
162         if( prev ) {
163                 new->Next = prev->Next;
164                 prev->Next = new;
165         }
166         else {
167                 new->Next = Font->FirstGlyph;
168                 Font->FirstGlyph = new;
169         }
170         
171         // - Backlink
172         if( next ) {
173                 new->Prev = next->Prev;
174                 next->Prev = new;
175         }
176         else {
177                 new->Prev = Font->LastGlyph;
178                 Font->LastGlyph = new;
179         }
180         
181         // Return
182         return new;
183 }
184
185 /**
186  */
187 void _RenderGlyph(short X, short Y, tGlyph *Glyph, uint32_t Color)
188 {
189         
190 }
191
192 // Load system font (8x16 monospace)
193 #include "font_8x16.h"
194
195 /*
196  */
197 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint)
198 {
199          int    i;
200         uint8_t index = 0;
201         tGlyph  *ret;
202         
203         if( Codepoint < 128 ) {
204                 index = Codepoint;
205         }
206         else {
207                 index = '?';    // Unknowns come out as a question mark
208         }
209
210         ret = malloc( sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT );
211
212         ret->Width = FONT_WIDTH;
213         ret->Height = FONT_HEIGHT;
214         
215         ret->TrueWidth = FONT_WIDTH;
216         ret->TrueHeight = FONT_HEIGHT;
217
218         ret->OffsetX = 0;
219         ret->OffsetY = 0;
220         
221         for( i = 0; i < FONT_HEIGHT; i ++ )
222         {
223                 ret->Bitmap[ i * 8 + 0 ] = VTermFont[index] & (1 << 0) ? 255 : 0;
224                 ret->Bitmap[ i * 8 + 1 ] = VTermFont[index] & (1 << 1) ? 255 : 0;
225                 ret->Bitmap[ i * 8 + 2 ] = VTermFont[index] & (1 << 2) ? 255 : 0;
226                 ret->Bitmap[ i * 8 + 3 ] = VTermFont[index] & (1 << 3) ? 255 : 0;
227                 ret->Bitmap[ i * 8 + 4 ] = VTermFont[index] & (1 << 4) ? 255 : 0;
228                 ret->Bitmap[ i * 8 + 5 ] = VTermFont[index] & (1 << 5) ? 255 : 0;
229                 ret->Bitmap[ i * 8 + 6 ] = VTermFont[index] & (1 << 6) ? 255 : 0;
230                 ret->Bitmap[ i * 8 + 7 ] = VTermFont[index] & (1 << 7) ? 255 : 0;
231         }
232
233         return ret;
234 }
235
236
237 /**
238  * \fn int ReadUTF8(char *Input, uint32_t *Val)
239  * \brief Read a UTF-8 character from a string
240  */
241 int ReadUTF8(char *Input, uint32_t *Val)
242 {
243         uint8_t *str = (uint8_t *)Input;
244         *Val = 0xFFFD;  // Assume invalid character
245         
246         // ASCII
247         if( !(*str & 0x80) ) {
248                 *Val = *str;
249                 return 1;
250         }
251         
252         // Middle of a sequence
253         if( (*str & 0xC0) == 0x80 ) {
254                 return 1;
255         }
256         
257         // Two Byte
258         if( (*str & 0xE0) == 0xC0 ) {
259                 *Val = (*str & 0x1F) << 6;      // Upper 6 Bits
260                 str ++;
261                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
262                 *Val |= (*str & 0x3F);  // Lower 6 Bits
263                 return 2;
264         }
265         
266         // Three Byte
267         if( (*str & 0xF0) == 0xE0 ) {
268                 *Val = (*str & 0x0F) << 12;     // Upper 4 Bits
269                 str ++;
270                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
271                 *Val |= (*str & 0x3F) << 6;     // Middle 6 Bits
272                 str ++;
273                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
274                 *Val |= (*str & 0x3F);  // Lower 6 Bits
275                 return 3;
276         }
277         
278         // Four Byte
279         if( (*str & 0xF1) == 0xF0 ) {
280                 *Val = (*str & 0x07) << 18;     // Upper 3 Bits
281                 str ++;
282                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
283                 *Val |= (*str & 0x3F) << 12;    // Middle-upper 6 Bits
284                 str ++;
285                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
286                 *Val |= (*str & 0x3F) << 6;     // Middle-lower 6 Bits
287                 str ++;
288                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
289                 *Val |= (*str & 0x3F);  // Lower 6 Bits
290                 return 4;
291         }
292         
293         // UTF-8 Doesn't support more than four bytes
294         return 4;
295 }
296
297
298
299

UCC git Repository :: git.ucc.asn.au