2 * Acess GUI (AxWin) Version 2
3 * By John Hodge (thePowersGang)
7 typedef struct sGlyph {
13 // Effective dimensions (distance to move 'cursor')
17 // Distance from the current cursor position to render at
21 // True dimensions (size of the bitmap
34 tGlyph *AsciiGlyphs[128]; // Glyphs 0-127
39 tGlyph *(*CacheGlyph)(struct sFont *this, uint32_t Codepoint);
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);
53 CacheGlyph: _SystemFont_CacheGlyph
58 * \brief Draw text to the screen
60 int Video_DrawText(short X, short Y, short W, short H, tFont *Font, uint32_t Color, char *Text)
67 if(W < 0 || X < 0 || X >= giScreenWidth) return 0;
68 if(X + W > giScreenWidth) W = giScreenWidth - X;
70 if(H < 0 || Y < 0 || Y >= giScreenHeight) return 0;
71 if(Y + H > giScreenHeight) H = giScreenHeight - Y;
73 // Handle NULL font (system default monospace)
74 if( !Font ) Font = &gSystemFont;
79 Text += ReadUTF8(Text, &ch);
81 // Find (or load) the glyph
82 glyph = _GetGlyph(Font, ch);
84 continue ; // If not found, just don't render it
86 // End render if it will overflow the perscribed range
87 if( xOfs + glyph->TrueWidth > W )
91 _RenderGlyph(X + xOfs, Y, glyph, Color);
97 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint)
99 tGlyph *next = NULL, *prev = NULL;
103 if( Codepoint < 128 )
105 if( Font->AsciiGlyphs[Codepoint] == NULL ) {
106 Font->CacheGlyph(Font, Codepoint);
109 return Font->AsciiGlyphs[Codepoint];
112 // If within the range
113 if( Font->FirstGlyph && Font->FirstGlyph->Codepoint < Codepoint && Codepoint < Font->LastGlyph->Codepoint )
115 // Find what end is "closest"
116 if( Codepoint - Font->FirstGlyph->Codepoint < Font->LastGlyph->Codepoint - Codepoint )
118 // Start from the bottom
119 for( next = Font->FirstGlyph;
120 next && next->Codepoint < Codepoint;
121 prev = next, next = next->Next
124 if( next->Codepoint == Codepoint )
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
138 if( prev->Codepoint == Codepoint )
145 if( !Font->FirstGlyph || Font->FirstGlyph->Codepoint > Codepoint ) {
147 next = Font->FirstGlyph;
151 prev = Font->LastGlyph;
157 new = Font->CacheGlyph(Font, Codepoint);
158 if( !new ) return NULL;
163 new->Next = prev->Next;
167 new->Next = Font->FirstGlyph;
168 Font->FirstGlyph = new;
173 new->Prev = next->Prev;
177 new->Prev = Font->LastGlyph;
178 Font->LastGlyph = new;
187 void _RenderGlyph(short X, short Y, tGlyph *Glyph, uint32_t Color)
192 // Load system font (8x16 monospace)
193 #include "font_8x16.h"
197 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint)
203 if( Codepoint < 128 ) {
207 index = '?'; // Unknowns come out as a question mark
210 ret = malloc( sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT );
212 ret->Width = FONT_WIDTH;
213 ret->Height = FONT_HEIGHT;
215 ret->TrueWidth = FONT_WIDTH;
216 ret->TrueHeight = FONT_HEIGHT;
221 for( i = 0; i < FONT_HEIGHT; i ++ )
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;
238 * \fn int ReadUTF8(char *Input, uint32_t *Val)
239 * \brief Read a UTF-8 character from a string
241 int ReadUTF8(char *Input, uint32_t *Val)
243 uint8_t *str = (uint8_t *)Input;
244 *Val = 0xFFFD; // Assume invalid character
247 if( !(*str & 0x80) ) {
252 // Middle of a sequence
253 if( (*str & 0xC0) == 0x80 ) {
258 if( (*str & 0xE0) == 0xC0 ) {
259 *Val = (*str & 0x1F) << 6; // Upper 6 Bits
261 if( (*str & 0xC0) != 0x80) return -1; // Validity check
262 *Val |= (*str & 0x3F); // Lower 6 Bits
267 if( (*str & 0xF0) == 0xE0 ) {
268 *Val = (*str & 0x0F) << 12; // Upper 4 Bits
270 if( (*str & 0xC0) != 0x80) return -1; // Validity check
271 *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
273 if( (*str & 0xC0) != 0x80) return -1; // Validity check
274 *Val |= (*str & 0x3F); // Lower 6 Bits
279 if( (*str & 0xF1) == 0xF0 ) {
280 *Val = (*str & 0x07) << 18; // Upper 3 Bits
282 if( (*str & 0xC0) != 0x80) return -1; // Validity check
283 *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
285 if( (*str & 0xC0) != 0x80) return -1; // Validity check
286 *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
288 if( (*str & 0xC0) != 0x80) return -1; // Validity check
289 *Val |= (*str & 0x3F); // Lower 6 Bits
293 // UTF-8 Doesn't support more than four bytes