#include <common.h>
#include <wm_internals.h>
#include <stdlib.h>
+#include <unicode.h>
+#include <limits.h> // INT_MAX
// === TYPES ===
typedef struct sGlyph tGlyph;
// === PROTOTYPES ===
- int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Color, const char *Text);
-void WM_Render_GetTextDims(tFont *Font, const char *Text, int *W, int *H);
+ int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Color, const char *Text, int MaxLen);
+void WM_Render_GetTextDims(tFont *Font, const char *Text, int MaxLen, int *W, int *H);
tGlyph *_GetGlyph(tFont *Font, uint32_t Codepoint);
void _RenderGlyph(tWindow *Window, short X, short Y, tGlyph *Glyph, uint32_t Color);
tGlyph *_SystemFont_CacheGlyph(tFont *Font, uint32_t Codepoint);
- int ReadUTF8(const char *Input, uint32_t *Output);
// === GLOBALS ===
tFont gSystemFont = {
/**
* \brief Draw text to the screen
*/
-int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Colour, const char *Text)
+int WM_Render_DrawText(tWindow *Window, int X, int Y, int W, int H, tFont *Font, tColour Colour, const char *Text, int MaxLen)
{
int xOfs = 0;
tGlyph *glyph;
if(!Text) return 0;
+ if(MaxLen < 0) MaxLen = INT_MAX;
+
+ X += Window->BorderL;
+ Y += Window->BorderT;
+
// Check the bounds
- if(W < 0 || X < 0 || X >= Window->W) return 0;
- if(X + W > Window->W) W = Window->W - X;
+ if(W < 0 || X < 0 || X >= Window->RealW) return 0;
+ if(X + W > Window->RealW) W = Window->RealW - X;
- if(H < 0 || Y < 0 || Y >= Window->H) return 0;
- if(Y + H > Window->H) H = Window->H - Y;
+ if(H < 0 || Y < 0 || Y >= Window->RealH) return 0;
+ if(Y + H > Window->RealH) H = Window->RealH - Y;
+ // TODO: Catch trampling of decorations
+
// Handle NULL font (system default monospace)
if( !Font ) Font = &gSystemFont;
- while( *Text )
+ while( MaxLen > 0 && *Text )
{
+ int len;
// Read character
- Text += ReadUTF8(Text, &ch);
+ len = ReadUTF8(Text, &ch);
+ Text += len;
+ MaxLen -= len;
// Find (or load) the glyph
glyph = _GetGlyph(Font, ch);
return xOfs;
}
-void WM_Render_GetTextDims(tFont *Font, const char *Text, int *W, int *H)
+void WM_Render_GetTextDims(tFont *Font, const char *Text, int MaxLen, int *W, int *H)
{
int w=0, h=0;
uint32_t ch;
tGlyph *glyph;
if( !Font ) Font = &gSystemFont;
- while( *Text )
+ if(MaxLen < 0) MaxLen = INT_MAX;
+
+ while( MaxLen > 0 && *Text )
{
- Text += ReadUTF8(Text, &ch);
+ int len;
+ len = ReadUTF8(Text, &ch);
+ Text += len;
+ MaxLen -= len;
glyph = _GetGlyph(Font, ch);
if( !glyph ) continue;
prev = next, next = next->Next
);
- if( next->Codepoint == Codepoint )
+ if( next && next->Codepoint == Codepoint )
return next;
}
prev && prev->Codepoint > Codepoint;
next = prev, prev = prev->Prev
);
- if( prev->Codepoint == Codepoint )
+ if( prev && prev->Codepoint == Codepoint )
return prev;
}
}
}
// _SysDebug("X = %i, Y = %i", X, Y);
- outBuf = (uint32_t*)Window->RenderBuffer + Y*Window->W + X;
+ outBuf = (uint32_t*)Window->RenderBuffer + Y*Window->RealW + X;
inBuf = Glyph->Bitmap + yStart*Glyph->TrueWidth;
for( y = yStart; y < Glyph->TrueHeight; y ++ )
{
outBuf[dst_x] = Video_AlphaBlend( outBuf[dst_x], Color, inBuf[x] );
}
- outBuf += Window->W;
+ outBuf += Window->RealW;
inBuf += Glyph->TrueWidth;
}
}
return ret;
}
-
-/**
- * \fn int ReadUTF8(char *Input, uint32_t *Val)
- * \brief Read a UTF-8 character from a string
- */
-int ReadUTF8(const char *Input, uint32_t *Val)
-{
- const uint8_t *str = (const uint8_t *)Input;
- *Val = 0xFFFD; // Assume invalid character
-
- // ASCII
- if( !(*str & 0x80) ) {
- *Val = *str;
- return 1;
- }
-
- // Middle of a sequence
- if( (*str & 0xC0) == 0x80 ) {
- return 1;
- }
-
- // Two Byte
- if( (*str & 0xE0) == 0xC0 ) {
- *Val = (*str & 0x1F) << 6; // Upper 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F); // Lower 6 Bits
- return 2;
- }
-
- // Three Byte
- if( (*str & 0xF0) == 0xE0 ) {
- *Val = (*str & 0x0F) << 12; // Upper 4 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F); // Lower 6 Bits
- return 3;
- }
-
- // Four Byte
- if( (*str & 0xF1) == 0xF0 ) {
- *Val = (*str & 0x07) << 18; // Upper 3 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F); // Lower 6 Bits
- return 4;
- }
-
- // UTF-8 Doesn't support more than four bytes
- return 4;
-}
-
-
-
-