much saner and more optimized font drawing

This commit is contained in:
dborth 2010-03-22 07:50:22 +00:00
parent 0597f37b58
commit 5098d92c03
3 changed files with 121 additions and 100 deletions

View File

@ -662,9 +662,10 @@ class GuiText : public GuiElement
void Draw(); void Draw();
protected: protected:
GXColor color; //!< Font color GXColor color; //!< Font color
wchar_t* text; //!< Unicode text value wchar_t* text; //!< Translated Unicode text value
wchar_t* textDyn; //!< Wrapped text value wchar_t *textDyn[20]; //!< Text value, if max width, scrolling, or wrapping enabled
char * origText; //!< Original text data int textDynNum; //!< Number of text lines
char * origText; //!< Original text data (English)
int size; //!< Font size int size; //!< Font size
int maxWidth; //!< Maximum width of the generated text object (for text wrapping) int maxWidth; //!< Maximum width of the generated text object (for text wrapping)
int textScroll; //!< Scrolling toggle int textScroll; //!< Scrolling toggle

View File

@ -109,7 +109,7 @@ GuiFileBrowser::GuiFileBrowser(int w, int h)
fileListText[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff}); fileListText[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff});
fileListText[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); fileListText[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
fileListText[i]->SetPosition(5,0); fileListText[i]->SetPosition(5,0);
fileListText[i]->SetMaxWidth(450); fileListText[i]->SetMaxWidth(380);
fileListBg[i] = new GuiImage(bgFileSelectionEntry); fileListBg[i] = new GuiImage(bgFileSelectionEntry);
fileListIcon[i] = NULL; fileListIcon[i] = NULL;

View File

@ -35,7 +35,7 @@ GuiText::GuiText(const char * t, int s, GXColor c)
style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE; style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE;
maxWidth = 0; maxWidth = 0;
wrap = false; wrap = false;
textDyn = NULL; textDynNum = 0;
textScroll = SCROLL_NONE; textScroll = SCROLL_NONE;
textScrollPos = 0; textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
@ -64,7 +64,7 @@ GuiText::GuiText(const char * t)
style = presetStyle; style = presetStyle;
maxWidth = presetMaxWidth; maxWidth = presetMaxWidth;
wrap = false; wrap = false;
textDyn = NULL; textDynNum = 0;
textScroll = SCROLL_NONE; textScroll = SCROLL_NONE;
textScrollPos = 0; textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
@ -89,8 +89,12 @@ GuiText::~GuiText()
free(origText); free(origText);
if(text) if(text)
delete[] text; delete[] text;
if(textDyn)
delete[] textDyn; if(textDynNum > 0)
{
for(int i=0; i < textDynNum; i++)
delete[] textDyn[i];
}
} }
void GuiText::SetText(const char * t) void GuiText::SetText(const char * t)
@ -99,12 +103,16 @@ void GuiText::SetText(const char * t)
free(origText); free(origText);
if(text) if(text)
delete[] text; delete[] text;
if(textDyn)
delete[] textDyn; if(textDynNum > 0)
{
for(int i=0; i < textDynNum; i++)
delete[] textDyn[i];
}
origText = NULL; origText = NULL;
text = NULL; text = NULL;
textDyn = NULL; textDynNum = 0;
textScrollPos = 0; textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
@ -133,12 +141,26 @@ void GuiText::SetFontSize(int s)
void GuiText::SetMaxWidth(int width) void GuiText::SetMaxWidth(int width)
{ {
maxWidth = width; maxWidth = width;
if(textDynNum > 0)
{
for(int i=0; i < textDynNum; i++)
delete[] textDyn[i];
}
textDynNum = 0;
} }
void GuiText::SetWrap(bool w, int width) void GuiText::SetWrap(bool w, int width)
{ {
wrap = w; wrap = w;
maxWidth = width; maxWidth = width;
if(textDynNum > 0)
{
for(int i=0; i < textDynNum; i++)
delete[] textDyn[i];
}
textDynNum = 0;
} }
void GuiText::SetScroll(int s) void GuiText::SetScroll(int s)
@ -146,11 +168,13 @@ void GuiText::SetScroll(int s)
if(textScroll == s) if(textScroll == s)
return; return;
if(textDyn) if(textDynNum > 0)
{ {
delete[] textDyn; for(int i=0; i < textDynNum; i++)
textDyn = NULL; delete[] textDyn[i];
} }
textDynNum = 0;
textScroll = s; textScroll = s;
textScrollPos = 0; textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
@ -209,6 +233,13 @@ void GuiText::ResetText()
delete[] text; delete[] text;
text = charToWideChar(gettext(origText)); text = charToWideChar(gettext(origText));
if(textDynNum > 0)
{
for(int i=0; i < textDynNum; i++)
delete[] textDyn[i];
}
textDynNum = 0;
} }
/** /**
@ -237,130 +268,119 @@ void GuiText::Draw()
fontSystem[newSize] = new FreeTypeGX(newSize); fontSystem[newSize] = new FreeTypeGX(newSize);
currentSize = newSize; currentSize = newSize;
} }
u8 maxChar;
if(maxWidth == 0) if(maxWidth == 0)
{ {
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style); fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style);
goto done; this->UpdateEffects();
return;
} }
maxChar = int((float((maxWidth<<1))) / (float(newSize))); // approximate u32 maxChar = maxWidth*2.5 / (float)newSize; // approximate
u32 textlen = wcslen(text);
if(wrap) if(wrap)
{ {
int lineheight = newSize + 6; if(textDynNum == 0)
int txtlen = wcslen(text);
int i = 0;
int ch = 0;
int linenum = 0;
int lastSpace = -1;
int lastSpaceIndex = -1;
wchar_t * textrow[20];
while(ch < txtlen)
{ {
if(i == 0) u32 n = 0, ch = 0;
textrow[linenum] = new wchar_t[txtlen + 1]; int linenum = 0;
int lastSpace = -1;
int lastSpaceIndex = -1;
textrow[linenum][i] = text[ch]; while(ch < textlen && linenum < 20)
textrow[linenum][i+1] = 0;
if(text[ch] == ' ' || ch == txtlen-1)
{ {
if(wcslen(textrow[linenum]) >= maxChar) if(n == 0)
textDyn[linenum] = new wchar_t[textlen + 1];
textDyn[linenum][n] = text[ch];
textDyn[linenum][n+1] = 0;
if(text[ch] == ' ' || ch == textlen-1)
{ {
if(lastSpace >= 0) if(wcslen(textDyn[linenum]) >= maxChar)
{ {
textrow[linenum][lastSpaceIndex] = 0; // discard space, and everything after if(lastSpace >= 0)
ch = lastSpace; // go backwards to the last space {
lastSpace = -1; // we have used this space textDyn[linenum][lastSpaceIndex] = 0; // discard space, and everything after
lastSpaceIndex = -1; ch = lastSpace; // go backwards to the last space
lastSpace = -1; // we have used this space
lastSpaceIndex = -1;
}
++linenum;
n = -1;
}
else if(ch == textlen-1)
{
++linenum;
} }
++linenum;
i = -1;
} }
else if(ch == txtlen-1) if(text[ch] == ' ' && n >= 0)
{ {
++linenum; lastSpace = ch;
lastSpaceIndex = n;
} }
++ch;
++n;
} }
if(text[ch] == ' ' && i >= 0) textDynNum = linenum;
{
lastSpace = ch;
lastSpaceIndex = i;
}
++ch;
++i;
} }
int lineheight = newSize + 6;
int voffset = 0; int voffset = 0;
if(alignmentVert == ALIGN_MIDDLE) if(alignmentVert == ALIGN_MIDDLE)
voffset = (lineheight >> 1) * (1-linenum); voffset = (lineheight >> 1) * (1-textDynNum);
int left = this->GetLeft(); int left = this->GetLeft();
int top = this->GetTop() + voffset; int top = this->GetTop() + voffset;
for(i=0; i < linenum; ++i) for(int i=0; i < textDynNum; ++i)
{ fontSystem[currentSize]->drawText(left, top+i*lineheight, textDyn[i], c, style);
fontSystem[currentSize]->drawText(left, top+i*lineheight, textrow[i], c, style);
delete[] textrow[i];
}
goto done;
} }
else
if(textScroll == SCROLL_HORIZONTAL)
{ {
char *tmpText = strdup(gettext(origText)); if(textDynNum == 0)
char *tmpText2 = strdup(tmpText);
int textlen = strlen(tmpText);
if(textlen > maxChar && (FrameTimer % textScrollDelay == 0))
{ {
if(textScrollInitialDelay) textDynNum = 1;
textDyn[0] = wcsdup(text);
if(textlen > maxChar)
textDyn[0][maxChar] = 0;
}
if(textScroll == SCROLL_HORIZONTAL)
{
if(textlen > maxChar && (FrameTimer % textScrollDelay == 0))
{ {
--textScrollInitialDelay; if(textScrollInitialDelay)
}
else
{
++textScrollPos;
if(textScrollPos > textlen-1)
{ {
textScrollPos = 0; --textScrollInitialDelay;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
} }
else
strncpy(tmpText, &tmpText2[textScrollPos], maxChar-1);
tmpText[maxChar-1] = 0;
int dynlen = strlen(tmpText);
if(dynlen+2 < maxChar)
{ {
tmpText[dynlen] = ' '; ++textScrollPos;
tmpText[dynlen+1] = ' '; if((u32)textScrollPos > textlen-1)
strncat(&tmpText[dynlen+2], tmpText2, maxChar - dynlen - 2); {
textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
}
wcsncpy(textDyn[0], &text[textScrollPos], maxChar-1);
textDyn[maxChar-1] = 0;
u32 dynlen = wcslen(textDyn[0]);
if(dynlen+2 < maxChar)
{
textDyn[0][dynlen] = ' ';
textDyn[0][dynlen+1] = ' ';
wcsncat(&textDyn[0][dynlen+2], text, maxChar - dynlen - 2);
}
} }
if(textDyn) delete[] textDyn;
textDyn = charToWideChar(tmpText);
} }
} }
free(tmpText); fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn[0], c, style);
free(tmpText2);
} }
if(!textDyn)
{
char *tmpText = strdup(gettext(origText));
if(strlen(tmpText) > maxChar)
tmpText[maxChar] = 0;
textDyn = charToWideChar(tmpText);
free(tmpText);
}
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style);
done:
this->UpdateEffects(); this->UpdateEffects();
} }