2 * Acess GUI (AxWin) Version 2
3 * By John Hodge (thePowersGang)
8 typedef struct sGlyph {
14 // Effective dimensions (distance to move 'cursor')
18 // Distance from the current cursor position to render at
22 // True dimensions (size of the bitmap
27 uint8_t Bitmap[]; // 8-bit alpha
35 tGlyph *AsciiGlyphs[128]; // Glyphs 0-127
40 tGlyph *(*CacheGlyph)(struct sFont *this, uint32_t Codepoint);
46 int Video_DrawText(short X, short Y, short W, short H, tFont *Font, uint32_t Color, char *Text);
47 void Video_GetTextDims(tFont *Font, const char *Text, int *W, int *H);
48 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint);
49 void _RenderGlyph(short X, short Y, tGlyph *Glyph, uint32_t Color);
50 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint);
51 int ReadUTF8(const char *Input, uint32_t *Output);
55 .CacheGlyph = _SystemFont_CacheGlyph
60 * \brief Draw text to the screen
62 int Video_DrawText(short X, short Y, short W, short H, tFont *Font, uint32_t Color, char *Text)
68 _SysDebug("Video_DrawText: (X=%i,Y=%i,W=%i,H=%i,Font=%p,", X, Y, W, H, Font);
69 _SysDebug(" Color=%08x,Text='%s')", Color, Text);
72 if(W < 0 || X < 0 || X >= giScreenWidth) return 0;
73 if(X + W > giScreenWidth) W = giScreenWidth - X;
75 if(H < 0 || Y < 0 || Y >= giScreenHeight) return 0;
76 if(Y + H > giScreenHeight) H = giScreenHeight - Y;
78 // Handle NULL font (system default monospace)
79 if( !Font ) Font = &gSystemFont;
84 Text += ReadUTF8(Text, &ch);
86 // Find (or load) the glyph
87 glyph = _GetGlyph(Font, ch);
88 if( !glyph ) continue ; // If not found, just don't render it
90 // End render if it will overflow the perscribed range
91 if( xOfs + glyph->TrueWidth > W )
95 _RenderGlyph(X + xOfs, Y, glyph, Color);
101 void Video_GetTextDims(tFont *Font, const char *Text, int *W, int *H)
106 if( !Font ) Font = &gSystemFont;
110 Text += ReadUTF8(Text, &ch);
111 glyph = _GetGlyph(Font, ch);
112 if( !glyph ) continue;
115 if( h < glyph->Height ) h = glyph->Height;
122 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint)
124 tGlyph *next = NULL, *prev = NULL;
128 if( Codepoint < 128 )
130 if( Font->AsciiGlyphs[Codepoint] == NULL ) {
131 Font->AsciiGlyphs[Codepoint] = Font->CacheGlyph(Font, Codepoint);
134 return Font->AsciiGlyphs[Codepoint];
137 // If within the range
138 if( Font->FirstGlyph && Font->FirstGlyph->Codepoint < Codepoint && Codepoint < Font->LastGlyph->Codepoint )
140 // Find what end is "closest"
141 if( Codepoint - Font->FirstGlyph->Codepoint < Font->LastGlyph->Codepoint - Codepoint )
143 // Start from the bottom
144 for( next = Font->FirstGlyph;
145 next && next->Codepoint < Codepoint;
146 prev = next, next = next->Next
149 if( next->Codepoint == Codepoint )
156 // NOTE: The roles of next and prev are reversed here to allow
157 // the insert to be able to assume that `prev` is the
158 // previous entry, and `next` is the next.
159 for( prev = Font->LastGlyph;
160 prev && prev->Codepoint > Codepoint;
161 next = prev, prev = prev->Prev
163 if( prev->Codepoint == Codepoint )
170 if( !Font->FirstGlyph || Font->FirstGlyph->Codepoint > Codepoint ) {
172 next = Font->FirstGlyph;
176 prev = Font->LastGlyph;
182 new = Font->CacheGlyph(Font, Codepoint);
183 if( !new ) return NULL;
188 new->Next = prev->Next;
192 new->Next = Font->FirstGlyph;
193 Font->FirstGlyph = new;
198 new->Prev = next->Prev;
202 new->Prev = Font->LastGlyph;
203 Font->LastGlyph = new;
212 void _RenderGlyph(short X, short Y, tGlyph *Glyph, uint32_t Color)
214 int xStart = 0, yStart = 0;
221 if( X < 0 ) { // If -ve, skip the first -X collums
227 if( Y < 0 ) { // If -ve, skip the first -Y lines
232 outBuf = gpScreenBuffer + Y*giScreenWidth + X;
233 inBuf = Glyph->Bitmap + yStart*Glyph->TrueWidth;
235 for( y = yStart; y < Glyph->TrueHeight; y ++ )
237 for( x = xStart; x < Glyph->TrueWidth; x ++ )
239 outBuf[x] = Video_AlphaBlend( outBuf[x], Color, inBuf[x] );
241 outBuf += giScreenWidth;
242 inBuf += Glyph->TrueWidth;
247 // Load system font (8x16 monospace)
248 #include "font_8x16.h"
252 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint)
259 _SysDebug("_SystemFont_CacheGlyph: (Font=%p, Codepoint=0x%06x)", Font, Codepoint);
261 if( Codepoint < 128 ) {
265 index = '?'; // Unknowns come out as a question mark
268 _SysDebug(" index = %i", index);
270 ret = malloc( sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT );
272 _SysDebug("ERROR: malloc(%i) failed", sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT);
276 ret->Codepoint = Codepoint;
278 ret->Width = FONT_WIDTH;
279 ret->Height = FONT_HEIGHT;
281 ret->TrueWidth = FONT_WIDTH;
282 ret->TrueHeight = FONT_HEIGHT;
287 data = &VTermFont[index * FONT_HEIGHT];
289 for( i = 0; i < FONT_HEIGHT; i ++ )
291 ret->Bitmap[ i * 8 + 0 ] = data[i] & (1 << 7) ? 255 : 0;
292 ret->Bitmap[ i * 8 + 1 ] = data[i] & (1 << 6) ? 255 : 0;
293 ret->Bitmap[ i * 8 + 2 ] = data[i] & (1 << 5) ? 255 : 0;
294 ret->Bitmap[ i * 8 + 3 ] = data[i] & (1 << 4) ? 255 : 0;
295 ret->Bitmap[ i * 8 + 4 ] = data[i] & (1 << 3) ? 255 : 0;
296 ret->Bitmap[ i * 8 + 5 ] = data[i] & (1 << 2) ? 255 : 0;
297 ret->Bitmap[ i * 8 + 6 ] = data[i] & (1 << 1) ? 255 : 0;
298 ret->Bitmap[ i * 8 + 7 ] = data[i] & (1 << 0) ? 255 : 0;
306 * \fn int ReadUTF8(char *Input, uint32_t *Val)
307 * \brief Read a UTF-8 character from a string
309 int ReadUTF8(const char *Input, uint32_t *Val)
311 const uint8_t *str = (const uint8_t *)Input;
312 *Val = 0xFFFD; // Assume invalid character
315 if( !(*str & 0x80) ) {
320 // Middle of a sequence
321 if( (*str & 0xC0) == 0x80 ) {
326 if( (*str & 0xE0) == 0xC0 ) {
327 *Val = (*str & 0x1F) << 6; // Upper 6 Bits
329 if( (*str & 0xC0) != 0x80) return -1; // Validity check
330 *Val |= (*str & 0x3F); // Lower 6 Bits
335 if( (*str & 0xF0) == 0xE0 ) {
336 *Val = (*str & 0x0F) << 12; // Upper 4 Bits
338 if( (*str & 0xC0) != 0x80) return -1; // Validity check
339 *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
341 if( (*str & 0xC0) != 0x80) return -1; // Validity check
342 *Val |= (*str & 0x3F); // Lower 6 Bits
347 if( (*str & 0xF1) == 0xF0 ) {
348 *Val = (*str & 0x07) << 18; // Upper 3 Bits
350 if( (*str & 0xC0) != 0x80) return -1; // Validity check
351 *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
353 if( (*str & 0xC0) != 0x80) return -1; // Validity check
354 *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
356 if( (*str & 0xC0) != 0x80) return -1; // Validity check
357 *Val |= (*str & 0x3F); // Lower 6 Bits
361 // UTF-8 Doesn't support more than four bytes