much saner and more optimized font drawing

This commit is contained in:
dborth 2010-03-22 07:51:11 +00:00
parent efdb4e7746
commit 1f372798d3
4 changed files with 122 additions and 101 deletions

View File

@ -662,9 +662,10 @@ class GuiText : public GuiElement
void Draw();
protected:
GXColor color; //!< Font color
wchar_t* text; //!< Unicode text value
wchar_t* textDyn; //!< Wrapped text value
char * origText; //!< Original text data
wchar_t* text; //!< Translated Unicode text value
wchar_t *textDyn[20]; //!< Text value, if max width, scrolling, or wrapping enabled
int textDynNum; //!< Number of text lines
char * origText; //!< Original text data (English)
int size; //!< Font size
int maxWidth; //!< Maximum width of the generated text object (for text wrapping)
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]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
fileListText[i]->SetPosition(5,0);
fileListText[i]->SetMaxWidth(450);
fileListText[i]->SetMaxWidth(380);
fileListBg[i] = new GuiImage(bgFileSelectionEntry);
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;
maxWidth = 0;
wrap = false;
textDyn = NULL;
textDynNum = 0;
textScroll = SCROLL_NONE;
textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
@ -64,7 +64,7 @@ GuiText::GuiText(const char * t)
style = presetStyle;
maxWidth = presetMaxWidth;
wrap = false;
textDyn = NULL;
textDynNum = 0;
textScroll = SCROLL_NONE;
textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
@ -89,8 +89,12 @@ GuiText::~GuiText()
free(origText);
if(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)
@ -99,12 +103,16 @@ void GuiText::SetText(const char * t)
free(origText);
if(text)
delete[] text;
if(textDyn)
delete[] textDyn;
if(textDynNum > 0)
{
for(int i=0; i < textDynNum; i++)
delete[] textDyn[i];
}
origText = NULL;
text = NULL;
textDyn = NULL;
textDynNum = 0;
textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
@ -133,12 +141,26 @@ void GuiText::SetFontSize(int s)
void GuiText::SetMaxWidth(int 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)
{
wrap = w;
maxWidth = width;
if(textDynNum > 0)
{
for(int i=0; i < textDynNum; i++)
delete[] textDyn[i];
}
textDynNum = 0;
}
void GuiText::SetScroll(int s)
@ -146,11 +168,13 @@ void GuiText::SetScroll(int s)
if(textScroll == s)
return;
if(textDyn)
if(textDynNum > 0)
{
delete[] textDyn;
textDyn = NULL;
for(int i=0; i < textDynNum; i++)
delete[] textDyn[i];
}
textDynNum = 0;
textScroll = s;
textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
@ -209,6 +233,13 @@ void GuiText::ResetText()
delete[] text;
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);
currentSize = newSize;
}
u8 maxChar;
if(maxWidth == 0)
{
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)
{
int lineheight = newSize + 6;
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(textDynNum == 0)
{
if(i == 0)
textrow[linenum] = new wchar_t[txtlen + 1];
u32 n = 0, ch = 0;
int linenum = 0;
int lastSpace = -1;
int lastSpaceIndex = -1;
textrow[linenum][i] = text[ch];
textrow[linenum][i+1] = 0;
if(text[ch] == ' ' || ch == txtlen-1)
while(ch < textlen && linenum < 20)
{
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
ch = lastSpace; // go backwards to the last space
lastSpace = -1; // we have used this space
lastSpaceIndex = -1;
if(lastSpace >= 0)
{
textDyn[linenum][lastSpaceIndex] = 0; // discard space, and everything after
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)
{
lastSpace = ch;
lastSpaceIndex = i;
}
++ch;
++i;
textDynNum = linenum;
}
int lineheight = newSize + 6;
int voffset = 0;
if(alignmentVert == ALIGN_MIDDLE)
voffset = (lineheight >> 1) * (1-linenum);
voffset = (lineheight >> 1) * (1-textDynNum);
int left = this->GetLeft();
int top = this->GetTop() + voffset;
for(i=0; i < linenum; ++i)
{
fontSystem[currentSize]->drawText(left, top+i*lineheight, textrow[i], c, style);
delete[] textrow[i];
}
goto done;
for(int i=0; i < textDynNum; ++i)
fontSystem[currentSize]->drawText(left, top+i*lineheight, textDyn[i], c, style);
}
if(textScroll == SCROLL_HORIZONTAL)
else
{
char *tmpText = strdup(gettext(origText));
char *tmpText2 = strdup(tmpText);
int textlen = strlen(tmpText);
if(textlen > maxChar && (FrameTimer % textScrollDelay == 0))
if(textDynNum == 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;
}
else
{
++textScrollPos;
if(textScrollPos > textlen-1)
if(textScrollInitialDelay)
{
textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
--textScrollInitialDelay;
}
strncpy(tmpText, &tmpText2[textScrollPos], maxChar-1);
tmpText[maxChar-1] = 0;
int dynlen = strlen(tmpText);
if(dynlen+2 < maxChar)
else
{
tmpText[dynlen] = ' ';
tmpText[dynlen+1] = ' ';
strncat(&tmpText[dynlen+2], tmpText2, maxChar - dynlen - 2);
++textScrollPos;
if((u32)textScrollPos > textlen-1)
{
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);
free(tmpText2);
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn[0], c, style);
}
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();
}

View File

@ -1825,7 +1825,7 @@ static int MenuGameSettings()
trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0);
GuiText mappingBtnTxt("Button Mappings", 22, (GXColor){0, 0, 0, 255});
mappingBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-20);
mappingBtnTxt.SetWrap(true, btnLargeOutline.GetWidth()-30);
GuiImage mappingBtnImg(&btnLargeOutline);
GuiImage mappingBtnImgOver(&btnLargeOutlineOver);
GuiImage mappingBtnIcon(&iconMappings);