void CGUIFont::DrawScrollingText(float x, float y, const vector<DWORD> &colors, DWORD shadowColor, const vector<DWORD> &text, DWORD alignment, float maxWidth, CScrollInfo &scrollInfo) { if (!m_font) return; if (!shadowColor) shadowColor = m_shadowColor; float spaceWidth = GetCharWidth(L' '); unsigned int maxChars = min((long unsigned int)(text.size() + scrollInfo.suffix.size()), (long unsigned int)((maxWidth*1.05f)/spaceWidth)); //max chars on screen + extra marginchars if (!text.size() || ClippedRegionIsEmpty(x, y, maxWidth, alignment)) return; // nothing to render maxWidth = ROUND(maxWidth / g_graphicsContext.GetGUIScaleX()); // draw at our scroll position // we handle the scrolling as follows: // We scroll on a per-pixel basis up until we have scrolled the first character outside // of our viewport, whereby we cycle the string around, and reset the scroll position. // // m_PixelScroll is the amount in pixels to move the string by. // m_CharacterScroll is the amount in characters to rotate the string by. // if (!scrollInfo.waitTime) { // First update our m_PixelScroll... DWORD ch; if (scrollInfo.characterPos < text.size()) ch = text[scrollInfo.characterPos]; else if (scrollInfo.characterPos < text.size() + scrollInfo.suffix.size()) ch = scrollInfo.suffix[scrollInfo.characterPos - text.size()]; else ch = text[0]; float charWidth = GetCharWidth(ch); float scrollAmount = scrollInfo.pixelSpeed * g_graphicsContext.GetGUIScaleX(); if (scrollInfo.pixelPos < charWidth - scrollAmount) scrollInfo.pixelPos += scrollAmount; else { scrollInfo.pixelPos -= (charWidth - scrollAmount); scrollInfo.characterPos++; if (scrollInfo.characterPos >= text.size() + scrollInfo.suffix.size()) scrollInfo.Reset(); } } else scrollInfo.waitTime--; // Now rotate our string as needed, only take a slightly larger then visible part of the text. unsigned int pos = scrollInfo.characterPos; vector<DWORD> renderText; renderText.reserve(maxChars); for (unsigned int i = 0; i < maxChars; i++) { if (pos >= text.size() + scrollInfo.suffix.size()) pos = 0; if (pos < text.size()) renderText.push_back(text[pos]); else renderText.push_back(scrollInfo.suffix[pos - text.size()]); pos++; } vector<DWORD> renderColors; for (unsigned int i = 0; i < colors.size(); i++) renderColors.push_back(g_graphicsContext.MergeAlpha(colors[i] ? colors[i] : m_textColor)); if (shadowColor) m_font->DrawTextInternal(x - scrollInfo.pixelPos + 1, y + 1, g_graphicsContext.MergeAlpha(shadowColor), renderText, alignment, maxWidth + scrollInfo.pixelPos + m_font->GetLineHeight(2.0f)); m_font->DrawTextInternal(x - scrollInfo.pixelPos, y, renderColors, renderText, alignment, maxWidth + scrollInfo.pixelPos + m_font->GetLineHeight(2.0f)); g_graphicsContext.RestoreClipRegion(); }
void CGUIFont::DrawScrollingText(float x, float y, const vecColors &colors, color_t shadowColor, const vecText &text, uint32_t alignment, float maxWidth, CScrollInfo &scrollInfo) { if (!m_font) return; if (!shadowColor) shadowColor = m_shadowColor; float spaceWidth = GetCharWidth(L' '); // max chars on screen + extra margin chars vecText::size_type maxChars = std::min<vecText::size_type>( (text.size() + (vecText::size_type)scrollInfo.suffix.size()), (vecText::size_type)((maxWidth * 1.05f) / spaceWidth)); if (!text.size() || ClippedRegionIsEmpty(x, y, maxWidth, alignment)) return; // nothing to render maxWidth = ROUND(maxWidth / g_graphicsContext.GetGUIScaleX()); // draw at our scroll position // we handle the scrolling as follows: // We scroll on a per-pixel basis up until we have scrolled the first character outside // of our viewport, whereby we cycle the string around, and reset the scroll position. // // pixelPos is the amount in pixels to move the string by. // characterPos is the amount in characters to rotate the string by. // float offset = scrollInfo.pixelPos; if (!scrollInfo.waitTime) { // move along by the appropriate scroll amount float scrollAmount = fabs(scrollInfo.GetPixelsPerFrame() * g_graphicsContext.GetGUIScaleX()); if (scrollInfo.pixelSpeed > 0) { // we want to move scrollAmount, grab the next character float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); if (scrollInfo.pixelPos + scrollAmount < charWidth) scrollInfo.pixelPos += scrollAmount; // within the current character else { // past the current character, decrement scrollAmount by the charWidth and move to the next character while (scrollInfo.pixelPos + scrollAmount >= charWidth) { scrollAmount -= (charWidth - scrollInfo.pixelPos); scrollInfo.pixelPos = 0; scrollInfo.characterPos++; if (scrollInfo.characterPos >= text.size() + scrollInfo.suffix.size()) { scrollInfo.Reset(); break; } charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); } } offset = scrollInfo.pixelPos; } else if (scrollInfo.pixelSpeed < 0) { // scrolling backwards // we want to move scrollAmount, grab the next character float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); if (scrollInfo.pixelPos + scrollAmount < charWidth) scrollInfo.pixelPos += scrollAmount; // within the current character else { // past the current character, decrement scrollAmount by the charWidth and move to the next character while (scrollInfo.pixelPos + scrollAmount >= charWidth) { scrollAmount -= (charWidth - scrollInfo.pixelPos); scrollInfo.pixelPos = 0; if (scrollInfo.characterPos == 0) { scrollInfo.Reset(); scrollInfo.characterPos = text.size() + scrollInfo.suffix.size() - 1; break; } scrollInfo.characterPos--; charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text)); } } offset = charWidth - scrollInfo.pixelPos; } } else scrollInfo.waitTime--; // Now rotate our string as needed, only take a slightly larger then visible part of the text. unsigned int pos = scrollInfo.characterPos; vecText renderText; renderText.reserve(maxChars); for (vecText::size_type i = 0; i < maxChars; i++) { if (pos >= text.size() + scrollInfo.suffix.size()) pos = 0; if (pos < text.size()) renderText.push_back(text[pos]); else renderText.push_back(scrollInfo.suffix[pos - text.size()]); pos++; } vecColors renderColors; for (unsigned int i = 0; i < colors.size(); i++) renderColors.push_back(g_graphicsContext.MergeAlpha(colors[i] ? colors[i] : m_textColor)); bool scroll = !scrollInfo.waitTime && scrollInfo.pixelSpeed; if (shadowColor) { shadowColor = g_graphicsContext.MergeAlpha(shadowColor); vecColors shadowColors; for (unsigned int i = 0; i < renderColors.size(); i++) shadowColors.push_back((renderColors[i] & 0xff000000) != 0 ? shadowColor : 0); m_font->DrawTextInternal(x - offset + 1, y + 1, shadowColors, renderText, alignment, maxWidth + scrollInfo.pixelPos + m_font->GetLineHeight(2.0f), scroll); } m_font->DrawTextInternal(x - offset, y, renderColors, renderText, alignment, maxWidth + scrollInfo.pixelPos + m_font->GetLineHeight(2.0f), scroll); g_graphicsContext.RestoreClipRegion(); }