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
26 uint8_t Bitmap[]; // 8-bit alpha
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(const 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)
66 _SysDebug("Video_DrawText: (X=%i,Y=%i,W=%i,H=%i,Font=%p,", X, Y, W, H, Font);
67 _SysDebug(" Color=%08x,Text='%s')", Color, Text);
70 if(W < 0 || X < 0 || X >= giScreenWidth) return 0;
71 if(X + W > giScreenWidth) W = giScreenWidth - X;
73 if(H < 0 || Y < 0 || Y >= giScreenHeight) return 0;
74 if(Y + H > giScreenHeight) H = giScreenHeight - Y;
76 // Handle NULL font (system default monospace)
77 if( !Font ) Font = &gSystemFont;
82 Text += ReadUTF8(Text, &ch);
84 // Find (or load) the glyph
85 glyph = _GetGlyph(Font, ch);
86 if( !glyph ) continue ; // If not found, just don't render it
88 // End render if it will overflow the perscribed range
89 if( xOfs + glyph->TrueWidth > W )
93 _RenderGlyph(X + xOfs, Y, glyph, Color);
99 void Video_GetTextDims(tFont *Font, const char *Text, int *W, int *H)
104 if( !Font ) Font = &gSystemFont;
108 Text += ReadUTF8(Text, &ch);
109 glyph = _GetGlyph(Font, ch);
110 if( !glyph ) continue;
113 if( h < glyph->Height ) h = glyph->Height;
120 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint)
122 tGlyph *next = NULL, *prev = NULL;
126 if( Codepoint < 128 )
128 if( Font->AsciiGlyphs[Codepoint] == NULL ) {
129 Font->AsciiGlyphs[Codepoint] = Font->CacheGlyph(Font, Codepoint);
132 return Font->AsciiGlyphs[Codepoint];
135 // If within the range
136 if( Font->FirstGlyph && Font->FirstGlyph->Codepoint < Codepoint && Codepoint < Font->LastGlyph->Codepoint )
138 // Find what end is "closest"
139 if( Codepoint - Font->FirstGlyph->Codepoint < Font->LastGlyph->Codepoint - Codepoint )
141 // Start from the bottom
142 for( next = Font->FirstGlyph;
143 next && next->Codepoint < Codepoint;
144 prev = next, next = next->Next
147 if( next->Codepoint == Codepoint )
154 // NOTE: The roles of next and prev are reversed here to allow
155 // the insert to be able to assume that `prev` is the
156 // previous entry, and `next` is the next.
157 for( prev = Font->LastGlyph;
158 prev && prev->Codepoint > Codepoint;
159 next = prev, prev = prev->Prev
161 if( prev->Codepoint == Codepoint )
168 if( !Font->FirstGlyph || Font->FirstGlyph->Codepoint > Codepoint ) {
170 next = Font->FirstGlyph;
174 prev = Font->LastGlyph;
180 new = Font->CacheGlyph(Font, Codepoint);
181 if( !new ) return NULL;
186 new->Next = prev->Next;
190 new->Next = Font->FirstGlyph;
191 Font->FirstGlyph = new;
196 new->Prev = next->Prev;
200 new->Prev = Font->LastGlyph;
201 Font->LastGlyph = new;
210 void _RenderGlyph(short X, short Y, tGlyph *Glyph, uint32_t Color)
212 int xStart = 0, yStart = 0;
219 if( X < 0 ) { // If -ve, skip the first -X collums
225 if( Y < 0 ) { // If -ve, skip the first -Y lines
230 outBuf = gpScreenBuffer + Y*giScreenWidth + X;
231 inBuf = Glyph->Bitmap + yStart*Glyph->TrueWidth;
233 for( y = yStart; y < Glyph->TrueHeight; y ++ )
235 for( x = xStart; x < Glyph->TrueWidth; x ++ )
237 outBuf[x] = Video_AlphaBlend( outBuf[x], Color, inBuf[x] );
239 outBuf += giScreenWidth;
240 inBuf += Glyph->TrueWidth;
245 // Load system font (8x16 monospace)
246 #include "font_8x16.h"
250 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint)
257 _SysDebug("_SystemFont_CacheGlyph: (Font=%p, Codepoint=0x%06x)", Font, Codepoint);
259 if( Codepoint < 128 ) {
263 index = '?'; // Unknowns come out as a question mark
266 _SysDebug(" index = %i", index);
268 ret = malloc( sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT );
270 _SysDebug("ERROR: malloc(%i) failed", sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT);
274 ret->Codepoint = Codepoint;
276 ret->Width = FONT_WIDTH;
277 ret->Height = FONT_HEIGHT;
279 ret->TrueWidth = FONT_WIDTH;
280 ret->TrueHeight = FONT_HEIGHT;
285 data = &VTermFont[index * FONT_HEIGHT];
287 for( i = 0; i < FONT_HEIGHT; i ++ )
289 ret->Bitmap[ i * 8 + 0 ] = data[i] & (1 << 7) ? 255 : 0;
290 ret->Bitmap[ i * 8 + 1 ] = data[i] & (1 << 6) ? 255 : 0;
291 ret->Bitmap[ i * 8 + 2 ] = data[i] & (1 << 5) ? 255 : 0;
292 ret->Bitmap[ i * 8 + 3 ] = data[i] & (1 << 4) ? 255 : 0;
293 ret->Bitmap[ i * 8 + 4 ] = data[i] & (1 << 3) ? 255 : 0;
294 ret->Bitmap[ i * 8 + 5 ] = data[i] & (1 << 2) ? 255 : 0;
295 ret->Bitmap[ i * 8 + 6 ] = data[i] & (1 << 1) ? 255 : 0;
296 ret->Bitmap[ i * 8 + 7 ] = data[i] & (1 << 0) ? 255 : 0;
304 * \fn int ReadUTF8(char *Input, uint32_t *Val)
305 * \brief Read a UTF-8 character from a string
307 int ReadUTF8(const char *Input, uint32_t *Val)
309 const uint8_t *str = (const uint8_t *)Input;
310 *Val = 0xFFFD; // Assume invalid character
313 if( !(*str & 0x80) ) {
318 // Middle of a sequence
319 if( (*str & 0xC0) == 0x80 ) {
324 if( (*str & 0xE0) == 0xC0 ) {
325 *Val = (*str & 0x1F) << 6; // Upper 6 Bits
327 if( (*str & 0xC0) != 0x80) return -1; // Validity check
328 *Val |= (*str & 0x3F); // Lower 6 Bits
333 if( (*str & 0xF0) == 0xE0 ) {
334 *Val = (*str & 0x0F) << 12; // Upper 4 Bits
336 if( (*str & 0xC0) != 0x80) return -1; // Validity check
337 *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
339 if( (*str & 0xC0) != 0x80) return -1; // Validity check
340 *Val |= (*str & 0x3F); // Lower 6 Bits
345 if( (*str & 0xF1) == 0xF0 ) {
346 *Val = (*str & 0x07) << 18; // Upper 3 Bits
348 if( (*str & 0xC0) != 0x80) return -1; // Validity check
349 *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
351 if( (*str & 0xC0) != 0x80) return -1; // Validity check
352 *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
354 if( (*str & 0xC0) != 0x80) return -1; // Validity check
355 *Val |= (*str & 0x3F); // Lower 6 Bits
359 // UTF-8 Doesn't support more than four bytes