2 * Acess2 GUI (AxWin) Version 3
3 * - By John Hodge (thePowersGang)
9 #include <wm_internals.h>
14 typedef struct sGlyph tGlyph;
23 // Effective dimensions (distance to move 'cursor')
27 // Distance from the current cursor position to render at
31 // True dimensions (size of the bitmap
36 uint8_t Bitmap[]; // 8-bit alpha
44 tGlyph *AsciiGlyphs[128]; // Glyphs 0-127
49 tGlyph *(*CacheGlyph)(struct sFont *this, uint32_t Codepoint);
55 int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Color, const char *Text, int MaxLen);
56 void WM_Render_GetTextDims(tFont *Font, const char *Text, int MaxLen, int *W, int *H);
57 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint);
58 void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Color);
59 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint);
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, int MaxLen)
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);
81 if(MaxLen < 0) MaxLen = INT_MAX;
87 if(W < 0 || X < 0 || X >= Window->RealW) return 0;
88 if(X + W > Window->RealW) W = Window->RealW - X;
90 if(H < 0 || Y < 0 || Y >= Window->RealH) return 0;
91 if(Y + H > Window->RealH) H = Window->RealH - Y;
93 // TODO: Catch trampling of decorations
95 // Handle NULL font (system default monospace)
96 if( !Font ) Font = &gSystemFont;
98 while( MaxLen > 0 && *Text )
102 len = ReadUTF8(Text, &ch);
106 // Find (or load) the glyph
107 glyph = _GetGlyph(Font, ch);
108 if( !glyph ) continue ; // If not found, just don't render it
110 // End render if it will overflow the provided range
111 if( xOfs + glyph->TrueWidth > W )
114 _RenderGlyph(Window, X + xOfs, Y, glyph, Colour);
115 xOfs += glyph->Width;
121 void WM_Render_GetTextDims(tFont *Font, const char *Text, int MaxLen, int *W, int *H)
126 if( !Font ) Font = &gSystemFont;
128 if(MaxLen < 0) MaxLen = INT_MAX;
130 while( MaxLen > 0 && *Text )
133 len = ReadUTF8(Text, &ch);
136 glyph = _GetGlyph(Font, ch);
137 if( !glyph ) continue;
140 if( h < glyph->Height ) h = glyph->Height;
147 tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint)
149 tGlyph *next = NULL, *prev = NULL;
153 if( Codepoint < 128 )
155 if( Font->AsciiGlyphs[Codepoint] == NULL ) {
156 Font->AsciiGlyphs[Codepoint] = Font->CacheGlyph(Font, Codepoint);
159 return Font->AsciiGlyphs[Codepoint];
162 // If within the range
163 if( Font->FirstGlyph && Font->FirstGlyph->Codepoint < Codepoint && Codepoint < Font->LastGlyph->Codepoint )
165 // Find what end is "closest"
166 if( Codepoint - Font->FirstGlyph->Codepoint < Font->LastGlyph->Codepoint - Codepoint )
168 // Start from the bottom
169 for( next = Font->FirstGlyph;
170 next && next->Codepoint < Codepoint;
171 prev = next, next = next->Next
174 if( next && next->Codepoint == Codepoint )
181 // NOTE: The roles of next and prev are reversed here to allow
182 // the insert to be able to assume that `prev` is the
183 // previous entry, and `next` is the next.
184 for( prev = Font->LastGlyph;
185 prev && prev->Codepoint > Codepoint;
186 next = prev, prev = prev->Prev
188 if( prev && prev->Codepoint == Codepoint )
195 if( !Font->FirstGlyph || Font->FirstGlyph->Codepoint > Codepoint ) {
197 next = Font->FirstGlyph;
201 prev = Font->LastGlyph;
207 new = Font->CacheGlyph(Font, Codepoint);
208 if( !new ) return NULL;
213 new->Next = prev->Next;
217 new->Next = Font->FirstGlyph;
218 Font->FirstGlyph = new;
223 new->Prev = next->Prev;
227 new->Prev = Font->LastGlyph;
228 Font->LastGlyph = new;
237 void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Color)
239 int xStart = 0, yStart = 0;
245 if( X < 0 ) { // If -ve, skip the first -X pixels
251 if( Y < 0 ) { // If -ve, skip the first -Y lines
256 // _SysDebug("X = %i, Y = %i", X, Y);
257 outBuf = (uint32_t*)Window->RenderBuffer + Y*Window->RealW + X;
258 inBuf = Glyph->Bitmap + yStart*Glyph->TrueWidth;
260 for( y = yStart; y < Glyph->TrueHeight; y ++ )
262 for( x = xStart, dst_x = 0; x < Glyph->TrueWidth; x ++, dst_x ++ )
264 outBuf[dst_x] = Video_AlphaBlend( outBuf[dst_x], Color, inBuf[x] );
266 outBuf += Window->RealW;
267 inBuf += Glyph->TrueWidth;
271 // Load system font (8x16 monospace)
272 #include "font_8x16.h"
276 tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint)
283 // _SysDebug("_SystemFont_CacheGlyph: (Font=%p, Codepoint=0x%06x)", Font, Codepoint);
285 if( Codepoint < 128 ) {
289 index = '?'; // Unknown glyphs come out as a question mark
292 // _SysDebug(" index = %i", index);
294 ret = malloc( sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT );
296 _SysDebug("ERROR: malloc(%i) failed", sizeof(tGlyph) + FONT_WIDTH*FONT_HEIGHT);
300 ret->Codepoint = Codepoint;
302 ret->Width = FONT_WIDTH;
303 ret->Height = FONT_HEIGHT;
305 ret->TrueWidth = FONT_WIDTH;
306 ret->TrueHeight = FONT_HEIGHT;
311 data = &VTermFont[index * FONT_HEIGHT];
313 for( i = 0; i < FONT_HEIGHT; i ++ )
315 ret->Bitmap[ i * 8 + 0 ] = data[i] & (1 << 7) ? 255 : 0;
316 ret->Bitmap[ i * 8 + 1 ] = data[i] & (1 << 6) ? 255 : 0;
317 ret->Bitmap[ i * 8 + 2 ] = data[i] & (1 << 5) ? 255 : 0;
318 ret->Bitmap[ i * 8 + 3 ] = data[i] & (1 << 4) ? 255 : 0;
319 ret->Bitmap[ i * 8 + 4 ] = data[i] & (1 << 3) ? 255 : 0;
320 ret->Bitmap[ i * 8 + 5 ] = data[i] & (1 << 2) ? 255 : 0;
321 ret->Bitmap[ i * 8 + 6 ] = data[i] & (1 << 1) ? 255 : 0;
322 ret->Bitmap[ i * 8 + 7 ] = data[i] & (1 << 0) ? 255 : 0;