/**************************************************************************** * libwiigui * * Tantric 2009 * * gui_text.cpp * * GUI class definitions ***************************************************************************/ #include "gui.h" #include "../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; textDyn = NULL; 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)); } } /** * 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; textDyn = NULL; 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)); } } /** * Destructor for the GuiText class. */ GuiText::~GuiText() { if(origText) free(origText); if(text) delete[] text; if(textDyn) delete[] textDyn; } void GuiText::SetText(const char * t) { if(origText) free(origText); if(text) delete[] text; if(textDyn) delete[] textDyn; origText = NULL; text = NULL; textDyn = NULL; textScrollPos = 0; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; if(t) { origText = strdup(t); text = charToWideChar(gettext(t)); } } 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; } void GuiText::SetWrap(bool w, int width) { wrap = w; maxWidth = width; } void GuiText::SetScroll(int s) { if(textScroll == s) return; if(textDyn) { delete[] textDyn; textDyn = NULL; } 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)); } /** * 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; } u8 maxChar; if(maxWidth == 0) { fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style); goto done; } maxChar = int((float((maxWidth<<1))) / (float(newSize))); // approximate 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(i == 0) textrow[linenum] = new wchar_t[txtlen + 1]; textrow[linenum][i] = text[ch]; textrow[linenum][i+1] = 0; if(text[ch] == ' ' || ch == txtlen-1) { if(wcslen(textrow[linenum]) >= maxChar) { if(lastSpace >= 0) { 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; } ++linenum; i = -1; } else if(ch == txtlen-1) { ++linenum; } } if(text[ch] == ' ' && i >= 0) { lastSpace = ch; lastSpaceIndex = i; } ++ch; ++i; } int voffset = 0; if(alignmentVert == ALIGN_MIDDLE) voffset = (lineheight >> 1) * (1-linenum); 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; } if(textScroll == SCROLL_HORIZONTAL) { char *tmpText = strdup(gettext(origText)); char *tmpText2 = strdup(tmpText); int textlen = strlen(tmpText); if(textlen > maxChar && (FrameTimer % textScrollDelay == 0)) { if(textScrollInitialDelay) { --textScrollInitialDelay; } else { ++textScrollPos; if(textScrollPos > textlen-1) { textScrollPos = 0; textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY; } strncpy(tmpText, &tmpText2[textScrollPos], maxChar-1); tmpText[maxChar-1] = 0; int dynlen = strlen(tmpText); if(dynlen+2 < maxChar) { tmpText[dynlen] = ' '; tmpText[dynlen+1] = ' '; strncat(&tmpText[dynlen+2], tmpText2, 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, c, style); done: this->UpdateEffects(); }