mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-12-26 19:21:50 +01:00
481 lines
8.7 KiB
C++
481 lines
8.7 KiB
C++
/****************************************************************************
|
|
* libwiigui
|
|
*
|
|
* Tantric 2009
|
|
*
|
|
* gui_text.cpp
|
|
*
|
|
* GUI class definitions
|
|
***************************************************************************/
|
|
|
|
#include "gui.h"
|
|
#include "../utils/gettext.h"
|
|
|
|
static GXColor presetColor = (GXColor){255, 255, 255, 255};
|
|
static int currentSize = 0;
|
|
static int presetSize = 0;
|
|
static int presetMaxWidth = 0;
|
|
static int presetAlignmentHor = 0;
|
|
static int presetAlignmentVert = 0;
|
|
static u16 presetStyle = 0;
|
|
|
|
#define TEXT_SCROLL_DELAY 8
|
|
#define TEXT_SCROLL_INITIAL_DELAY 6
|
|
|
|
/**
|
|
* Constructor for the GuiText class.
|
|
*/
|
|
GuiText::GuiText(const char * t, int s, GXColor c)
|
|
{
|
|
origText = NULL;
|
|
text = NULL;
|
|
size = s;
|
|
color = c;
|
|
alpha = c.a;
|
|
style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE;
|
|
maxWidth = 0;
|
|
wrap = false;
|
|
textDynNum = 0;
|
|
textScroll = SCROLL_NONE;
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
|
|
|
alignmentHor = ALIGN_CENTRE;
|
|
alignmentVert = ALIGN_MIDDLE;
|
|
|
|
if(t)
|
|
{
|
|
origText = strdup(t);
|
|
text = charToWideChar(gettext(t));
|
|
}
|
|
|
|
for(int i=0; i < 20; i++)
|
|
textDyn[i] = NULL;
|
|
}
|
|
|
|
/**
|
|
* Constructor for the GuiText class, uses presets
|
|
*/
|
|
GuiText::GuiText(const char * t)
|
|
{
|
|
origText = NULL;
|
|
text = NULL;
|
|
size = presetSize;
|
|
color = presetColor;
|
|
alpha = presetColor.a;
|
|
style = presetStyle;
|
|
maxWidth = presetMaxWidth;
|
|
wrap = false;
|
|
textDynNum = 0;
|
|
textScroll = SCROLL_NONE;
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
|
|
|
alignmentHor = presetAlignmentHor;
|
|
alignmentVert = presetAlignmentVert;
|
|
|
|
if(t)
|
|
{
|
|
origText = strdup(t);
|
|
text = charToWideChar(gettext(t));
|
|
}
|
|
|
|
for(int i=0; i < 20; i++)
|
|
textDyn[i] = NULL;
|
|
}
|
|
|
|
/**
|
|
* Destructor for the GuiText class.
|
|
*/
|
|
GuiText::~GuiText()
|
|
{
|
|
if(origText)
|
|
free(origText);
|
|
if(text)
|
|
delete[] text;
|
|
|
|
if(textDynNum > 0)
|
|
{
|
|
for(int i=0; i < textDynNum; i++)
|
|
if(textDyn[i])
|
|
delete[] textDyn[i];
|
|
}
|
|
}
|
|
|
|
void GuiText::SetText(const char * t)
|
|
{
|
|
if(origText)
|
|
free(origText);
|
|
if(text)
|
|
delete[] text;
|
|
|
|
if(textDynNum > 0)
|
|
{
|
|
for(int i=0; i < textDynNum; i++)
|
|
if(textDyn[i])
|
|
delete[] textDyn[i];
|
|
}
|
|
|
|
origText = NULL;
|
|
text = NULL;
|
|
textDynNum = 0;
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
|
|
if(t)
|
|
{
|
|
origText = strdup(t);
|
|
text = charToWideChar(gettext(t));
|
|
}
|
|
}
|
|
|
|
void GuiText::SetWText(wchar_t * t)
|
|
{
|
|
if(origText)
|
|
free(origText);
|
|
if(text)
|
|
delete[] text;
|
|
|
|
if(textDynNum > 0)
|
|
{
|
|
for(int i=0; i < textDynNum; i++)
|
|
if(textDyn[i])
|
|
delete[] textDyn[i];
|
|
}
|
|
|
|
origText = NULL;
|
|
text = NULL;
|
|
textDynNum = 0;
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
|
|
if(t)
|
|
text = wcsdup(t);
|
|
}
|
|
|
|
int GuiText::GetLength()
|
|
{
|
|
if(!text)
|
|
return 0;
|
|
|
|
return wcslen(text);
|
|
}
|
|
|
|
void GuiText::SetPresets(int sz, GXColor c, int w, u16 s, int h, int v)
|
|
{
|
|
presetSize = sz;
|
|
presetColor = c;
|
|
presetStyle = s;
|
|
presetMaxWidth = w;
|
|
presetAlignmentHor = h;
|
|
presetAlignmentVert = v;
|
|
}
|
|
|
|
void GuiText::SetFontSize(int s)
|
|
{
|
|
size = s;
|
|
}
|
|
|
|
void GuiText::SetMaxWidth(int width)
|
|
{
|
|
maxWidth = width;
|
|
|
|
for(int i=0; i < textDynNum; i++)
|
|
{
|
|
if(textDyn[i])
|
|
{
|
|
delete[] textDyn[i];
|
|
textDyn[i] = NULL;
|
|
}
|
|
}
|
|
|
|
textDynNum = 0;
|
|
}
|
|
|
|
int GuiText::GetTextWidth()
|
|
{
|
|
if(!text)
|
|
return 0;
|
|
|
|
if(currentSize != size)
|
|
{
|
|
ChangeFontSize(size);
|
|
|
|
if(!fontSystem[size])
|
|
fontSystem[size] = new FreeTypeGX(size);
|
|
|
|
currentSize = size;
|
|
}
|
|
return fontSystem[size]->getWidth(text);
|
|
}
|
|
|
|
void GuiText::SetWrap(bool w, int width)
|
|
{
|
|
wrap = w;
|
|
maxWidth = width;
|
|
|
|
for(int i=0; i < textDynNum; i++)
|
|
{
|
|
if(textDyn[i])
|
|
{
|
|
delete[] textDyn[i];
|
|
textDyn[i] = NULL;
|
|
}
|
|
}
|
|
|
|
textDynNum = 0;
|
|
}
|
|
|
|
void GuiText::SetScroll(int s)
|
|
{
|
|
if(textScroll == s)
|
|
return;
|
|
|
|
for(int i=0; i < textDynNum; i++)
|
|
{
|
|
if(textDyn[i])
|
|
{
|
|
delete[] textDyn[i];
|
|
textDyn[i] = NULL;
|
|
}
|
|
}
|
|
|
|
textDynNum = 0;
|
|
|
|
textScroll = s;
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
textScrollDelay = TEXT_SCROLL_DELAY;
|
|
}
|
|
|
|
void GuiText::SetColor(GXColor c)
|
|
{
|
|
color = c;
|
|
alpha = c.a;
|
|
}
|
|
|
|
void GuiText::SetStyle(u16 s)
|
|
{
|
|
style = s;
|
|
}
|
|
|
|
void GuiText::SetAlignment(int hor, int vert)
|
|
{
|
|
style = 0;
|
|
|
|
switch(hor)
|
|
{
|
|
case ALIGN_LEFT:
|
|
style |= FTGX_JUSTIFY_LEFT;
|
|
break;
|
|
case ALIGN_RIGHT:
|
|
style |= FTGX_JUSTIFY_RIGHT;
|
|
break;
|
|
default:
|
|
style |= FTGX_JUSTIFY_CENTER;
|
|
break;
|
|
}
|
|
switch(vert)
|
|
{
|
|
case ALIGN_TOP:
|
|
style |= FTGX_ALIGN_TOP;
|
|
break;
|
|
case ALIGN_BOTTOM:
|
|
style |= FTGX_ALIGN_BOTTOM;
|
|
break;
|
|
default:
|
|
style |= FTGX_ALIGN_MIDDLE;
|
|
break;
|
|
}
|
|
|
|
alignmentHor = hor;
|
|
alignmentVert = vert;
|
|
}
|
|
|
|
void GuiText::ResetText()
|
|
{
|
|
if(!origText)
|
|
return;
|
|
if(text)
|
|
delete[] text;
|
|
|
|
text = charToWideChar(gettext(origText));
|
|
|
|
for(int i=0; i < textDynNum; i++)
|
|
{
|
|
if(textDyn[i])
|
|
{
|
|
delete[] textDyn[i];
|
|
textDyn[i] = NULL;
|
|
}
|
|
}
|
|
|
|
textDynNum = 0;
|
|
currentSize = 0;
|
|
}
|
|
|
|
/**
|
|
* Draw the text on screen
|
|
*/
|
|
void GuiText::Draw()
|
|
{
|
|
if(!text)
|
|
return;
|
|
|
|
if(!this->IsVisible())
|
|
return;
|
|
|
|
GXColor c = color;
|
|
c.a = this->GetAlpha();
|
|
|
|
int newSize = size*this->GetScale();
|
|
|
|
if(newSize > MAX_FONT_SIZE)
|
|
newSize = MAX_FONT_SIZE;
|
|
|
|
if(newSize != currentSize)
|
|
{
|
|
ChangeFontSize(newSize);
|
|
if(!fontSystem[newSize])
|
|
fontSystem[newSize] = new FreeTypeGX(newSize);
|
|
currentSize = newSize;
|
|
}
|
|
|
|
if(maxWidth == 0)
|
|
{
|
|
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style);
|
|
this->UpdateEffects();
|
|
return;
|
|
}
|
|
|
|
u32 textlen = wcslen(text);
|
|
|
|
if(wrap)
|
|
{
|
|
if(textDynNum == 0)
|
|
{
|
|
u32 n = 0, ch = 0;
|
|
int linenum = 0;
|
|
int lastSpace = -1;
|
|
int lastSpaceIndex = -1;
|
|
|
|
while(ch < textlen && linenum < 20)
|
|
{
|
|
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(fontSystem[currentSize]->getWidth(textDyn[linenum]) > maxWidth)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
if(text[ch] == ' ' && n >= 0)
|
|
{
|
|
lastSpace = ch;
|
|
lastSpaceIndex = n;
|
|
}
|
|
++ch;
|
|
++n;
|
|
}
|
|
textDynNum = linenum;
|
|
}
|
|
|
|
int lineheight = newSize + 6;
|
|
int voffset = 0;
|
|
|
|
if(alignmentVert == ALIGN_MIDDLE)
|
|
voffset = (lineheight >> 1) * (1-textDynNum);
|
|
|
|
int left = this->GetLeft();
|
|
int top = this->GetTop() + voffset;
|
|
|
|
for(int i=0; i < textDynNum; ++i)
|
|
fontSystem[currentSize]->drawText(left, top+i*lineheight, textDyn[i], c, style);
|
|
}
|
|
else
|
|
{
|
|
if(textDynNum == 0)
|
|
{
|
|
textDynNum = 1;
|
|
textDyn[0] = wcsdup(text);
|
|
int len = wcslen(textDyn[0]);
|
|
|
|
while(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth)
|
|
textDyn[0][--len] = 0;
|
|
}
|
|
|
|
if(textScroll == SCROLL_HORIZONTAL)
|
|
{
|
|
if(fontSystem[currentSize]->getWidth(text) > maxWidth && (FrameTimer % textScrollDelay == 0))
|
|
{
|
|
if(textScrollInitialDelay)
|
|
{
|
|
--textScrollInitialDelay;
|
|
}
|
|
else
|
|
{
|
|
++textScrollPos;
|
|
if((u32)textScrollPos > textlen-1)
|
|
{
|
|
textScrollPos = 0;
|
|
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
|
}
|
|
|
|
wcscpy(textDyn[0], &text[textScrollPos]);
|
|
u32 dynlen = wcslen(textDyn[0]);
|
|
|
|
if(dynlen+2 < textlen)
|
|
{
|
|
textDyn[0][dynlen] = ' ';
|
|
textDyn[0][dynlen+1] = ' ';
|
|
textDyn[0][dynlen+2] = 0;
|
|
dynlen += 2;
|
|
}
|
|
|
|
if(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth)
|
|
{
|
|
while(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth)
|
|
textDyn[0][--dynlen] = 0;
|
|
}
|
|
else
|
|
{
|
|
int i = 0;
|
|
|
|
while(fontSystem[currentSize]->getWidth(textDyn[0]) < maxWidth && dynlen+1 < textlen)
|
|
{
|
|
textDyn[0][dynlen] = text[i++];
|
|
textDyn[0][++dynlen] = 0;
|
|
}
|
|
|
|
if(fontSystem[currentSize]->getWidth(textDyn[0]) > maxWidth)
|
|
textDyn[0][dynlen-2] = 0;
|
|
else
|
|
textDyn[0][dynlen-1] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn[0], c, style);
|
|
}
|
|
this->UpdateEffects();
|
|
}
|