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(); 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;
} }
/** /**
@ -238,85 +269,88 @@ void GuiText::Draw()
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; u32 n = 0, ch = 0;
int ch = 0;
int linenum = 0; int linenum = 0;
int lastSpace = -1; int lastSpace = -1;
int lastSpaceIndex = -1; int lastSpaceIndex = -1;
wchar_t * textrow[20];
while(ch < txtlen) while(ch < textlen && linenum < 20)
{ {
if(i == 0) if(n == 0)
textrow[linenum] = new wchar_t[txtlen + 1]; textDyn[linenum] = new wchar_t[textlen + 1];
textrow[linenum][i] = text[ch]; textDyn[linenum][n] = text[ch];
textrow[linenum][i+1] = 0; textDyn[linenum][n+1] = 0;
if(text[ch] == ' ' || ch == txtlen-1) if(text[ch] == ' ' || ch == textlen-1)
{ {
if(wcslen(textrow[linenum]) >= maxChar) if(wcslen(textDyn[linenum]) >= maxChar)
{ {
if(lastSpace >= 0) if(lastSpace >= 0)
{ {
textrow[linenum][lastSpaceIndex] = 0; // discard space, and everything after textDyn[linenum][lastSpaceIndex] = 0; // discard space, and everything after
ch = lastSpace; // go backwards to the last space ch = lastSpace; // go backwards to the last space
lastSpace = -1; // we have used this space lastSpace = -1; // we have used this space
lastSpaceIndex = -1; lastSpaceIndex = -1;
} }
++linenum; ++linenum;
i = -1; n = -1;
} }
else if(ch == txtlen-1) else if(ch == textlen-1)
{ {
++linenum; ++linenum;
} }
} }
if(text[ch] == ' ' && i >= 0) if(text[ch] == ' ' && n >= 0)
{ {
lastSpace = ch; lastSpace = ch;
lastSpaceIndex = i; lastSpaceIndex = n;
} }
++ch; ++ch;
++i; ++n;
}
textDynNum = linenum;
} }
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(textDynNum == 0)
{
textDynNum = 1;
textDyn[0] = wcsdup(text);
if(textlen > maxChar)
textDyn[0][maxChar] = 0;
} }
if(textScroll == SCROLL_HORIZONTAL) if(textScroll == SCROLL_HORIZONTAL)
{ {
char *tmpText = strdup(gettext(origText));
char *tmpText2 = strdup(tmpText);
int textlen = strlen(tmpText);
if(textlen > maxChar && (FrameTimer % textScrollDelay == 0)) if(textlen > maxChar && (FrameTimer % textScrollDelay == 0))
{ {
if(textScrollInitialDelay) if(textScrollInitialDelay)
@ -326,41 +360,27 @@ void GuiText::Draw()
else else
{ {
++textScrollPos; ++textScrollPos;
if(textScrollPos > textlen-1) if((u32)textScrollPos > textlen-1)
{ {
textScrollPos = 0; textScrollPos = 0;
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
} }
strncpy(tmpText, &tmpText2[textScrollPos], maxChar-1); wcsncpy(textDyn[0], &text[textScrollPos], maxChar-1);
tmpText[maxChar-1] = 0; textDyn[maxChar-1] = 0;
int dynlen = strlen(tmpText); u32 dynlen = wcslen(textDyn[0]);
if(dynlen+2 < maxChar) if(dynlen+2 < maxChar)
{ {
tmpText[dynlen] = ' '; textDyn[0][dynlen] = ' ';
tmpText[dynlen+1] = ' '; textDyn[0][dynlen+1] = ' ';
strncat(&tmpText[dynlen+2], tmpText2, maxChar - dynlen - 2); wcsncat(&textDyn[0][dynlen+2], text, maxChar - dynlen - 2);
}
if(textDyn) delete[] textDyn;
textDyn = charToWideChar(tmpText);
} }
} }
free(tmpText);
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[0], c, style);
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style); }
done:
this->UpdateEffects(); this->UpdateEffects();
} }

View File

@ -1825,7 +1825,7 @@ static int MenuGameSettings()
trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0);
GuiText mappingBtnTxt("Button Mappings", 22, (GXColor){0, 0, 0, 255}); 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 mappingBtnImg(&btnLargeOutline);
GuiImage mappingBtnImgOver(&btnLargeOutlineOver); GuiImage mappingBtnImgOver(&btnLargeOutlineOver);
GuiImage mappingBtnIcon(&iconMappings); GuiImage mappingBtnIcon(&iconMappings);