2 * Acess2 GUI (AxWin) Version 3
3 * - By John Hodge (thePowersGang)
9 #include <wm_internals.h>
12 #include <limits.h> // INT_MAX
15 typedef struct sGlyph tGlyph;
24 // Effective dimensions (distance to move 'cursor')
28 // Distance from the current cursor position to render at
32 // True dimensions (size of the bitmap
37 uint8_t Bitmap[]; // 8-bit alpha
45 tGlyph *AsciiGlyphs[128]; // Glyphs 0-127
50 tGlyph *(*CacheGlyph)(struct sFont *this, uint32_t Codepoint);
56 int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Color, const char *Text, int MaxLen);
57 void WM_Render_GetTextDims(tFont *Font, const char *Text, int MaxLen, int *W, int *H);
58 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint);
59 void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Color);
60 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint);
64 .CacheGlyph = _SystemFont_CacheGlyph
69 * \brief Draw text to the screen
71 int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Colour, const char *Text, int MaxLen)
77 // _SysDebug("WM_Render_DrawText: (X=%i,Y=%i,W=%i,H=%i,Font=%p,", X, Y, W, H, Font);
78 // _SysDebug(" Colour=%08x,Text='%s')", Colour, Text);
82 if(MaxLen < 0) MaxLen = INT_MAX;
88 if(W < 0 || X < 0 || X >= Window->RealW) return 0;
89 if(X + W > Window->RealW) W = Window->RealW - X;
91 if(H < 0 || Y < 0 || Y >= Window->RealH) return 0;
92 if(Y + H > Window->RealH) H = Window->RealH - Y;
94 // TODO: Catch trampling of decorations
96 // Handle NULL font (system default monospace)
97 if( !Font ) Font = &gSystemFont;
99 while( MaxLen > 0 && *Text )
103 len = ReadUTF8(Text, &ch);
107 // Find (or load) the glyph
108 glyph = _GetGlyph(Font, ch);
109 if( !glyph ) continue ; // If not found, just don't render it
111 // End render if it will overflow the provided range
112 if( xOfs + glyph->TrueWidth > W )
115 _RenderGlyph(Window, X + xOfs, Y, glyph, Colour);
116 xOfs += glyph->Width;
122 void WM_Render_GetTextDims(tFont *Font, const char *Text, int MaxLen, int *W, int *H)
127 if( !Font ) Font = &gSystemFont;
129 if(MaxLen < 0) MaxLen = INT_MAX;
131 while( MaxLen > 0 && *Text )
134 len = ReadUTF8(Text, &ch);
137 glyph = _GetGlyph(Font, ch);
138 if( !glyph ) continue;
141 if( h < glyph->Height ) h = glyph->Height;
148 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint)
150 tGlyph *next = NULL, *prev = NULL;
154 if( Codepoint < 128 )
156 if( Font->AsciiGlyphs[Codepoint] == NULL ) {
157 Font->AsciiGlyphs[Codepoint] = Font->CacheGlyph(Font, Codepoint);
160 return Font->AsciiGlyphs[Codepoint];
163 // If within the range
164 if( Font->FirstGlyph && Font->FirstGlyph->Codepoint < Codepoint && Codepoint < Font->LastGlyph->Codepoint )
166 // Find what end is "closest"
167 if( Codepoint - Font->FirstGlyph->Codepoint < Font->LastGlyph->Codepoint - Codepoint )
169 // Start from the bottom
170 for( next = Font->FirstGlyph;
171 next && next->Codepoint < Codepoint;
172 prev = next, next = next->Next
175 if( next && next->Codepoint == Codepoint )
182 // NOTE: The roles of next and prev are reversed here to allow
183 // the insert to be able to assume that `prev` is the
184 // previous entry, and `next` is the next.
185 for( prev = Font->LastGlyph;
186 prev && prev->Codepoint > Codepoint;
187 next = prev, prev = prev->Prev
189 if( prev && prev->Codepoint == Codepoint )
196 if( !Font->FirstGlyph || Font->FirstGlyph->Codepoint > Codepoint ) {
198 next = Font->FirstGlyph;
202 prev = Font->LastGlyph;
208 new = Font->CacheGlyph(Font, Codepoint);
209 if( !new ) return NULL;
214 new->Next = prev->Next;
218 new->Next = Font->FirstGlyph;
219 Font->FirstGlyph = new;
224 new->Prev = next->Prev;
228 new->Prev = Font->LastGlyph;
229 Font->LastGlyph = new;
238 void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Color)
240 int xStart = 0, yStart = 0;
246 if( X < 0 ) { // If -ve, skip the first -X pixels
252 if( Y < 0 ) { // If -ve, skip the first -Y lines
257 // _SysDebug("X = %i, Y = %i", X, Y);
258 outBuf = (uint32_t*)Window->RenderBuffer + Y*Window->RealW + X;
259 inBuf = Glyph->Bitmap + yStart*Glyph->TrueWidth;
261 for( y = yStart; y < Glyph->TrueHeight; y ++ )
263 for( x = xStart, dst_x = 0; x < Glyph->TrueWidth; x ++, dst_x ++ )
265 outBuf[dst_x] = Video_AlphaBlend( outBuf[dst_x], Color, inBuf[x] );
267 outBuf += Window->RealW;
268 inBuf += Glyph->TrueWidth;
272 // Load system font (8x16 monospace)
273 #include "font_8x16.h"
277 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint)
284 // _SysDebug("_SystemFont_CacheGlyph: (Font=%p, Codepoint=0x%06x)", Font, Codepoint);
286 if( Codepoint < 128 ) {
290 index = '?'; // Unknown glyphs come out as a question mark
293 // _SysDebug(" index = %i", index);
295 ret = malloc( sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT );
297 _SysDebug("ERROR: malloc(%i) failed", sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT);
301 ret->Codepoint = Codepoint;
303 ret->Width = FONT_WIDTH;
304 ret->Height = FONT_HEIGHT;
306 ret->TrueWidth = FONT_WIDTH;
307 ret->TrueHeight = FONT_HEIGHT;
312 data = &VTermFont[index * FONT_HEIGHT];
314 for( i = 0; i < FONT_HEIGHT; i ++ )
316 ret->Bitmap[ i * 8 + 0 ] = data[i] & (1 << 7) ? 255 : 0;
317 ret->Bitmap[ i * 8 + 1 ] = data[i] & (1 << 6) ? 255 : 0;
318 ret->Bitmap[ i * 8 + 2 ] = data[i] & (1 << 5) ? 255 : 0;
319 ret->Bitmap[ i * 8 + 3 ] = data[i] & (1 << 4) ? 255 : 0;
320 ret->Bitmap[ i * 8 + 4 ] = data[i] & (1 << 3) ? 255 : 0;
321 ret->Bitmap[ i * 8 + 5 ] = data[i] & (1 << 2) ? 255 : 0;
322 ret->Bitmap[ i * 8 + 6 ] = data[i] & (1 << 1) ? 255 : 0;
323 ret->Bitmap[ i * 8 + 7 ] = data[i] & (1 << 0) ? 255 : 0;