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);
86 if(W < 0 || X < 0 || X >= Window->RealW) return 0;
87 if(X + W > Window->RealW) W = Window->RealW - X;
89 if(H < 0 || Y < 0 || Y >= Window->RealH) return 0;
90 if(Y + H > Window->RealH) H = Window->RealH - Y;
92 // TODO: Catch trampling of decorations
94 // Handle NULL font (system default monospace)
95 if( !Font ) Font = &gSystemFont;
100 Text += ReadUTF8(Text, &ch);
102 // Find (or load) the glyph
103 glyph = _GetGlyph(Font, ch);
104 if( !glyph ) continue ; // If not found, just don't render it
106 // End render if it will overflow the provided range
107 if( xOfs + glyph->TrueWidth > W )
110 _RenderGlyph(Window, X + xOfs, Y, glyph, Colour);
111 xOfs += glyph->Width;
117 void WM_Render_GetTextDims(tFont *Font, const char *Text, int *W, int *H)
122 if( !Font ) Font = &gSystemFont;
126 Text += ReadUTF8(Text, &ch);
127 glyph = _GetGlyph(Font, ch);
128 if( !glyph ) continue;
131 if( h < glyph->Height ) h = glyph->Height;
138 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint)
140 tGlyph *next = NULL, *prev = NULL;
144 if( Codepoint < 128 )
146 if( Font->AsciiGlyphs[Codepoint] == NULL ) {
147 Font->AsciiGlyphs[Codepoint] = Font->CacheGlyph(Font, Codepoint);
150 return Font->AsciiGlyphs[Codepoint];
153 // If within the range
154 if( Font->FirstGlyph && Font->FirstGlyph->Codepoint < Codepoint && Codepoint < Font->LastGlyph->Codepoint )
156 // Find what end is "closest"
157 if( Codepoint - Font->FirstGlyph->Codepoint < Font->LastGlyph->Codepoint - Codepoint )
159 // Start from the bottom
160 for( next = Font->FirstGlyph;
161 next && next->Codepoint < Codepoint;
162 prev = next, next = next->Next
165 if( next->Codepoint == Codepoint )
172 // NOTE: The roles of next and prev are reversed here to allow
173 // the insert to be able to assume that `prev` is the
174 // previous entry, and `next` is the next.
175 for( prev = Font->LastGlyph;
176 prev && prev->Codepoint > Codepoint;
177 next = prev, prev = prev->Prev
179 if( prev->Codepoint == Codepoint )
186 if( !Font->FirstGlyph || Font->FirstGlyph->Codepoint > Codepoint ) {
188 next = Font->FirstGlyph;
192 prev = Font->LastGlyph;
198 new = Font->CacheGlyph(Font, Codepoint);
199 if( !new ) return NULL;
204 new->Next = prev->Next;
208 new->Next = Font->FirstGlyph;
209 Font->FirstGlyph = new;
214 new->Prev = next->Prev;
218 new->Prev = Font->LastGlyph;
219 Font->LastGlyph = new;
228 void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Color)
230 int xStart = 0, yStart = 0;
236 if( X < 0 ) { // If -ve, skip the first -X pixels
242 if( Y < 0 ) { // If -ve, skip the first -Y lines
247 // _SysDebug("X = %i, Y = %i", X, Y);
248 outBuf = (uint32_t*)Window->RenderBuffer + Y*Window->RealW + X;
249 inBuf = Glyph->Bitmap + yStart*Glyph->TrueWidth;
251 for( y = yStart; y < Glyph->TrueHeight; y ++ )
253 for( x = xStart, dst_x = 0; x < Glyph->TrueWidth; x ++, dst_x ++ )
255 outBuf[dst_x] = Video_AlphaBlend( outBuf[dst_x], Color, inBuf[x] );
257 outBuf += Window->RealW;
258 inBuf += Glyph->TrueWidth;
262 // Load system font (8x16 monospace)
263 #include "font_8x16.h"
267 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint)
274 // _SysDebug("_SystemFont_CacheGlyph: (Font=%p, Codepoint=0x%06x)", Font, Codepoint);
276 if( Codepoint < 128 ) {
280 index = '?'; // Unknown glyphs come out as a question mark
283 // _SysDebug(" index = %i", index);
285 ret = malloc( sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT );
287 _SysDebug("ERROR: malloc(%i) failed", sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT);
291 ret->Codepoint = Codepoint;
293 ret->Width = FONT_WIDTH;
294 ret->Height = FONT_HEIGHT;
296 ret->TrueWidth = FONT_WIDTH;
297 ret->TrueHeight = FONT_HEIGHT;
302 data = &VTermFont[index * FONT_HEIGHT];
304 for( i = 0; i < FONT_HEIGHT; i ++ )
306 ret->Bitmap[ i * 8 + 0 ] = data[i] & (1 << 7) ? 255 : 0;
307 ret->Bitmap[ i * 8 + 1 ] = data[i] & (1 << 6) ? 255 : 0;
308 ret->Bitmap[ i * 8 + 2 ] = data[i] & (1 << 5) ? 255 : 0;
309 ret->Bitmap[ i * 8 + 3 ] = data[i] & (1 << 4) ? 255 : 0;
310 ret->Bitmap[ i * 8 + 4 ] = data[i] & (1 << 3) ? 255 : 0;
311 ret->Bitmap[ i * 8 + 5 ] = data[i] & (1 << 2) ? 255 : 0;
312 ret->Bitmap[ i * 8 + 6 ] = data[i] & (1 << 1) ? 255 : 0;
313 ret->Bitmap[ i * 8 + 7 ] = data[i] & (1 << 0) ? 255 : 0;
321 * \fn int ReadUTF8(char *Input, uint32_t *Val)
322 * \brief Read a UTF-8 character from a string
324 int ReadUTF8(const char *Input, uint32_t *Val)
326 const uint8_t *str = (const uint8_t *)Input;
327 *Val = 0xFFFD; // Assume invalid character
330 if( !(*str & 0x80) ) {
335 // Middle of a sequence
336 if( (*str & 0xC0) == 0x80 ) {
341 if( (*str & 0xE0) == 0xC0 ) {
342 *Val = (*str & 0x1F) << 6; // Upper 6 Bits
344 if( (*str & 0xC0) != 0x80) return -1; // Validity check
345 *Val |= (*str & 0x3F); // Lower 6 Bits
350 if( (*str & 0xF0) == 0xE0 ) {
351 *Val = (*str & 0x0F) << 12; // Upper 4 Bits
353 if( (*str & 0xC0) != 0x80) return -1; // Validity check
354 *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
356 if( (*str & 0xC0) != 0x80) return -1; // Validity check
357 *Val |= (*str & 0x3F); // Lower 6 Bits
362 if( (*str & 0xF1) == 0xF0 ) {
363 *Val = (*str & 0x07) << 18; // Upper 3 Bits
365 if( (*str & 0xC0) != 0x80) return -1; // Validity check
366 *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
368 if( (*str & 0xC0) != 0x80) return -1; // Validity check
369 *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
371 if( (*str & 0xC0) != 0x80) return -1; // Validity check
372 *Val |= (*str & 0x3F); // Lower 6 Bits
376 // UTF-8 Doesn't support more than four bytes