2 * Acess2 GUI (AxWin) Version 3
3 * - By John Hodge (thePowersGang)
9 #include <wm_internals.h>
13 typedef struct sGlyph tGlyph;
22 // Effective dimensions (distance to move 'cursor')
26 // Distance from the current cursor position to render at
30 // True dimensions (size of the bitmap
35 uint8_t Bitmap[]; // 8-bit alpha
43 tGlyph *AsciiGlyphs[128]; // Glyphs 0-127
48 tGlyph *(*CacheGlyph)(struct sFont *this, uint32_t Codepoint);
54 int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Color, const char *Text);
55 void WM_Render_GetTextDims(tFont *Font, const char *Text, int *W, int *H);
56 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint);
57 void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Color);
58 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint);
59 int ReadUTF8(const char *Input, uint32_t *Output);
63 .CacheGlyph = _SystemFont_CacheGlyph
68 * \brief Draw text to the screen
70 int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Colour, const char *Text)
76 _SysDebug("WM_Render_DrawText: (X=%i,Y=%i,W=%i,H=%i,Font=%p,", X, Y, W, H, Font);
77 _SysDebug(" Colour=%08x,Text='%s')", Colour, Text);
82 if(W < 0 || X < 0 || X >= Window->W) return 0;
83 if(X + W > Window->W) W = Window->W - X;
85 if(H < 0 || Y < 0 || Y >= Window->H) return 0;
86 if(Y + H > Window->H) H = Window->H - Y;
88 // Handle NULL font (system default monospace)
89 if( !Font ) Font = &gSystemFont;
94 Text += ReadUTF8(Text, &ch);
96 // Find (or load) the glyph
97 glyph = _GetGlyph(Font, ch);
98 if( !glyph ) continue ; // If not found, just don't render it
100 // End render if it will overflow the provided range
101 if( xOfs + glyph->TrueWidth > W )
104 _RenderGlyph(Window, X + xOfs, Y, glyph, Colour);
105 xOfs += glyph->Width;
111 void WM_Render_GetTextDims(tFont *Font, const char *Text, int *W, int *H)
116 if( !Font ) Font = &gSystemFont;
120 Text += ReadUTF8(Text, &ch);
121 glyph = _GetGlyph(Font, ch);
122 if( !glyph ) continue;
125 if( h < glyph->Height ) h = glyph->Height;
132 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint)
134 tGlyph *next = NULL, *prev = NULL;
138 if( Codepoint < 128 )
140 if( Font->AsciiGlyphs[Codepoint] == NULL ) {
141 Font->AsciiGlyphs[Codepoint] = Font->CacheGlyph(Font, Codepoint);
144 return Font->AsciiGlyphs[Codepoint];
147 // If within the range
148 if( Font->FirstGlyph && Font->FirstGlyph->Codepoint < Codepoint && Codepoint < Font->LastGlyph->Codepoint )
150 // Find what end is "closest"
151 if( Codepoint - Font->FirstGlyph->Codepoint < Font->LastGlyph->Codepoint - Codepoint )
153 // Start from the bottom
154 for( next = Font->FirstGlyph;
155 next && next->Codepoint < Codepoint;
156 prev = next, next = next->Next
159 if( next->Codepoint == Codepoint )
166 // NOTE: The roles of next and prev are reversed here to allow
167 // the insert to be able to assume that `prev` is the
168 // previous entry, and `next` is the next.
169 for( prev = Font->LastGlyph;
170 prev && prev->Codepoint > Codepoint;
171 next = prev, prev = prev->Prev
173 if( prev->Codepoint == Codepoint )
180 if( !Font->FirstGlyph || Font->FirstGlyph->Codepoint > Codepoint ) {
182 next = Font->FirstGlyph;
186 prev = Font->LastGlyph;
192 new = Font->CacheGlyph(Font, Codepoint);
193 if( !new ) return NULL;
198 new->Next = prev->Next;
202 new->Next = Font->FirstGlyph;
203 Font->FirstGlyph = new;
208 new->Prev = next->Prev;
212 new->Prev = Font->LastGlyph;
213 Font->LastGlyph = new;
222 void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Color)
224 int xStart = 0, yStart = 0;
230 if( X < 0 ) { // If -ve, skip the first -X pixels
236 if( Y < 0 ) { // If -ve, skip the first -Y lines
241 // _SysDebug("X = %i, Y = %i", X, Y);
242 outBuf = (uint32_t*)Window->RenderBuffer + Y*Window->W + X;
243 inBuf = Glyph->Bitmap + yStart*Glyph->TrueWidth;
245 for( y = yStart; y < Glyph->TrueHeight; y ++ )
247 for( x = xStart, dst_x = 0; x < Glyph->TrueWidth; x ++, dst_x ++ )
249 outBuf[dst_x] = Video_AlphaBlend( outBuf[dst_x], Color, inBuf[x] );
252 inBuf += Glyph->TrueWidth;
256 // Load system font (8x16 monospace)
257 #include "font_8x16.h"
261 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint)
268 // _SysDebug("_SystemFont_CacheGlyph: (Font=%p, Codepoint=0x%06x)", Font, Codepoint);
270 if( Codepoint < 128 ) {
274 index = '?'; // Unknown glyphs come out as a question mark
277 // _SysDebug(" index = %i", index);
279 ret = malloc( sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT );
281 _SysDebug("ERROR: malloc(%i) failed", sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT);
285 ret->Codepoint = Codepoint;
287 ret->Width = FONT_WIDTH;
288 ret->Height = FONT_HEIGHT;
290 ret->TrueWidth = FONT_WIDTH;
291 ret->TrueHeight = FONT_HEIGHT;
296 data = &VTermFont[index * FONT_HEIGHT];
298 for( i = 0; i < FONT_HEIGHT; i ++ )
300 ret->Bitmap[ i * 8 + 0 ] = data[i] & (1 << 7) ? 255 : 0;
301 ret->Bitmap[ i * 8 + 1 ] = data[i] & (1 << 6) ? 255 : 0;
302 ret->Bitmap[ i * 8 + 2 ] = data[i] & (1 << 5) ? 255 : 0;
303 ret->Bitmap[ i * 8 + 3 ] = data[i] & (1 << 4) ? 255 : 0;
304 ret->Bitmap[ i * 8 + 4 ] = data[i] & (1 << 3) ? 255 : 0;
305 ret->Bitmap[ i * 8 + 5 ] = data[i] & (1 << 2) ? 255 : 0;
306 ret->Bitmap[ i * 8 + 6 ] = data[i] & (1 << 1) ? 255 : 0;
307 ret->Bitmap[ i * 8 + 7 ] = data[i] & (1 << 0) ? 255 : 0;
315 * \fn int ReadUTF8(char *Input, uint32_t *Val)
316 * \brief Read a UTF-8 character from a string
318 int ReadUTF8(const char *Input, uint32_t *Val)
320 const uint8_t *str = (const uint8_t *)Input;
321 *Val = 0xFFFD; // Assume invalid character
324 if( !(*str & 0x80) ) {
329 // Middle of a sequence
330 if( (*str & 0xC0) == 0x80 ) {
335 if( (*str & 0xE0) == 0xC0 ) {
336 *Val = (*str & 0x1F) << 6; // Upper 6 Bits
338 if( (*str & 0xC0) != 0x80) return -1; // Validity check
339 *Val |= (*str & 0x3F); // Lower 6 Bits
344 if( (*str & 0xF0) == 0xE0 ) {
345 *Val = (*str & 0x0F) << 12; // Upper 4 Bits
347 if( (*str & 0xC0) != 0x80) return -1; // Validity check
348 *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
350 if( (*str & 0xC0) != 0x80) return -1; // Validity check
351 *Val |= (*str & 0x3F); // Lower 6 Bits
356 if( (*str & 0xF1) == 0xF0 ) {
357 *Val = (*str & 0x07) << 18; // Upper 3 Bits
359 if( (*str & 0xC0) != 0x80) return -1; // Validity check
360 *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
362 if( (*str & 0xC0) != 0x80) return -1; // Validity check
363 *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
365 if( (*str & 0xC0) != 0x80) return -1; // Validity check
366 *Val |= (*str & 0x3F); // Lower 6 Bits
370 // UTF-8 Doesn't support more than four bytes