Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: source/gui/CGUI.cpp
- ===================================================================
- --- source/gui/CGUI.cpp (revision 22642)
- +++ source/gui/CGUI.cpp (working copy)
- @@ -38,11 +38,10 @@
- #include "CTooltip.h"
- #include "MiniMap.h"
- #include "graphics/FontMetrics.h"
- #include "graphics/ShaderManager.h"
- -#include "graphics/TextRenderer.h"
- #include "i18n/L10n.h"
- #include "lib/bits.h"
- #include "lib/input.h"
- #include "lib/sysdep/sysdep.h"
- #include "lib/timer.h"
- @@ -483,404 +482,10 @@ const SGUIScrollBarStyle* CGUI::GetScrol
- return nullptr;
- return &it->second;
- }
- -// private struct used only in GenerateText(...)
- -struct SGenerateTextImage
- -{
- - // Only primitve members, so move assignments are the same as copy assignments.
- -
- - float m_YFrom, // The image's starting location in Y
- - m_YTo, // The image's end location in Y
- - m_Indentation; // The image width in other words
- -
- - // Some help functions
- - // TODO Gee: CRect => CPoint ?
- - void SetupSpriteCall(const bool Left, SGUIText::SSpriteCall& SpriteCall,
- - const float width, const float y,
- - const CSize& Size, const CStr& TextureName,
- - const float BufferZone, const int CellID)
- - {
- - // TODO Gee: Temp hardcoded values
- - SpriteCall.m_Area.top = y+BufferZone;
- - SpriteCall.m_Area.bottom = y+BufferZone + Size.cy;
- -
- - if (Left)
- - {
- - SpriteCall.m_Area.left = BufferZone;
- - SpriteCall.m_Area.right = Size.cx+BufferZone;
- - }
- - else
- - {
- - SpriteCall.m_Area.left = width-BufferZone - Size.cx;
- - SpriteCall.m_Area.right = width-BufferZone;
- - }
- -
- - SpriteCall.m_CellID = CellID;
- - SpriteCall.m_Sprite = TextureName;
- -
- - m_YFrom = SpriteCall.m_Area.top-BufferZone;
- - m_YTo = SpriteCall.m_Area.bottom+BufferZone;
- - m_Indentation = Size.cx+BufferZone*2;
- - }
- -};
- -
- -SGUIText CGUI::GenerateText(const CGUIString& string, const CStrW& FontW, const float& Width, const float& BufferZone, const IGUIObject* pObject)
- -{
- - SGUIText Text;
- -
- - CStrIntern Font(FontW.ToUTF8());
- -
- - if (string.m_Words.empty())
- - return Text;
- -
- - float x = BufferZone, y = BufferZone; // drawing pointer
- - int from = 0;
- - bool done = false;
- -
- - bool FirstLine = true; // Necessary because text in the first line is shorter
- - // (it doesn't count the line spacing)
- -
- - // Images on the left or the right side.
- - std::vector<SGenerateTextImage> Images[2];
- - int pos_last_img = -1; // Position in the string where last img (either left or right) were encountered.
- - // in order to avoid duplicate processing.
- -
- - // Easier to read.
- - bool WordWrapping = (Width != 0);
- -
- - // get the alignment type for the control we are computing the text for since
- - // we are computing the horizontal alignment in this method in order to not have
- - // to run through the TextCalls a second time in the CalculateTextPosition method again
- - EAlign align = EAlign_Left;
- - if (pObject->SettingExists("text_align"))
- - GUI<EAlign>::GetSetting(pObject, "text_align", align);
- -
- - // Go through string word by word
- - for (int i = 0; i < (int)string.m_Words.size()-1 && !done; ++i)
- - {
- - // Pre-process each line one time, so we know which floating images
- - // will be added for that line.
- -
- - // Generated stuff is stored in Feedback.
- - CGUIString::SFeedback Feedback;
- -
- - // Preliminary line_height, used for word-wrapping with floating images.
- - float prelim_line_height = 0.f;
- -
- - // Width and height of all text calls generated.
- - string.GenerateTextCall(this, Feedback, Font,
- - string.m_Words[i], string.m_Words[i+1],
- - FirstLine);
- -
- - // Loop through our images queues, to see if images has been added.
- -
- - // Check if this has already been processed.
- - // Also, floating images are only applicable if Word-Wrapping is on
- - if (WordWrapping && i > pos_last_img)
- - {
- - // Loop left/right
- - for (int j = 0; j < 2; ++j)
- - {
- - for (const CStr& imgname : Feedback.m_Images[j])
- - {
- - SGUIText::SSpriteCall SpriteCall;
- - SGenerateTextImage Image;
- -
- - // Y is if no other floating images is above, y. Else it is placed
- - // after the last image, like a stack downwards.
- - float _y;
- - if (!Images[j].empty())
- - _y = std::max(y, Images[j].back().m_YTo);
- - else
- - _y = y;
- -
- - // Get Size from Icon database
- - const SGUIIcon& icon = GetIcon(imgname);
- -
- - const CSize& size = icon.m_Size;
- - Image.SetupSpriteCall((j == CGUIString::SFeedback::Left), SpriteCall, Width, _y, size, icon.m_SpriteName, BufferZone, icon.m_CellID);
- -
- - // Check if image is the lowest thing.
- - Text.m_Size.cy = std::max(Text.m_Size.cy, Image.m_YTo);
- -
- - Images[j].emplace_back(Image);
- - Text.m_SpriteCalls.emplace_back(std::move(SpriteCall));
- - }
- - }
- - }
- -
- - pos_last_img = std::max(pos_last_img, i);
- -
- - x += Feedback.m_Size.cx;
- - prelim_line_height = std::max(prelim_line_height, Feedback.m_Size.cy);
- -
- - // If Width is 0, then there's no word-wrapping, disable NewLine.
- - if ((WordWrapping && (x > Width-BufferZone || Feedback.m_NewLine)) || i == (int)string.m_Words.size()-2)
- - {
- - // Change 'from' to 'i', but first keep a copy of its value.
- - int temp_from = from;
- - from = i;
- -
- - static const int From = 0, To = 1;
- - //int width_from=0, width_to=width;
- - float width_range[2];
- - width_range[From] = BufferZone;
- - width_range[To] = Width - BufferZone;
- -
- - // Floating images are only applicable if word-wrapping is enabled.
- - if (WordWrapping)
- - {
- - // Decide width of the line. We need to iterate our floating images.
- - // this won't be exact because we're assuming the line_height
- - // will be as our preliminary calculation said. But that may change,
- - // although we'd have to add a couple of more loops to try straightening
- - // this problem out, and it is very unlikely to happen noticeably if one
- - // structures his text in a stylistically pure fashion. Even if not, it
- - // is still quite unlikely it will happen.
- - // Loop through left and right side, from and to.
- - for (int j = 0; j < 2; ++j)
- - {
- - for (const SGenerateTextImage& img : Images[j])
- - {
- - // We're working with two intervals here, the image's and the line height's.
- - // let's find the union of these two.
- - float union_from, union_to;
- -
- - union_from = std::max(y, img.m_YFrom);
- - union_to = std::min(y+prelim_line_height, img.m_YTo);
- -
- - // The union is not empty
- - if (union_to > union_from)
- - {
- - if (j == From)
- - width_range[From] = std::max(width_range[From], img.m_Indentation);
- - else
- - width_range[To] = std::min(width_range[To], Width - img.m_Indentation);
- - }
- - }
- - }
- - }
- -
- - // Reset X for the next loop
- - x = width_range[From];
- -
- - // Now we'll do another loop to figure out the height and width of
- - // the line (the height of the largest character and the width is
- - // the sum of all of the individual widths). This
- - // couldn't be determined in the first loop (main loop)
- - // because it didn't regard images, so we don't know
- - // if all characters processed, will actually be involved
- - // in that line.
- - float line_height = 0.f;
- - float line_width = 0.f;
- - for (int j = temp_from; j <= i; ++j)
- - {
- - // We don't want to use Feedback now, so we'll have to use
- - // another.
- - CGUIString::SFeedback Feedback2;
- -
- - // Don't attach object, it'll suppress the errors
- - // we want them to be reported in the final GenerateTextCall()
- - // so that we don't get duplicates.
- - string.GenerateTextCall(this, Feedback2, Font,
- - string.m_Words[j], string.m_Words[j+1],
- - FirstLine);
- -
- - // Append X value.
- - x += Feedback2.m_Size.cx;
- -
- - if (WordWrapping && x > width_range[To] && j!=temp_from && !Feedback2.m_NewLine)
- - {
- - // The calculated width of each word includes the space between the current
- - // word and the next. When we're wrapping, we need subtract the width of the
- - // space after the last word on the line before the wrap.
- - CFontMetrics currentFont(Font);
- - line_width -= currentFont.GetCharacterWidth(*L" ");
- - break;
- - }
- -
- - // Let line_height be the maximum m_Height we encounter.
- - line_height = std::max(line_height, Feedback2.m_Size.cy);
- -
- - // If the current word is an explicit new line ("\n"),
- - // break now before adding the width of this character.
- - // ("\n" doesn't have a glyph, thus is given the same width as
- - // the "missing glyph" character by CFont::GetCharacterWidth().)
- - if (WordWrapping && Feedback2.m_NewLine)
- - break;
- -
- - line_width += Feedback2.m_Size.cx;
- - }
- -
- - float dx = 0.f;
- - // compute offset based on what kind of alignment
- - switch (align)
- - {
- - case EAlign_Left:
- - // don't add an offset
- - dx = 0.f;
- - break;
- -
- - case EAlign_Center:
- - dx = ((width_range[To] - width_range[From]) - line_width) / 2;
- - break;
- -
- - case EAlign_Right:
- - dx = width_range[To] - line_width;
- - break;
- -
- - default:
- - debug_warn(L"Broken EAlign in CGUI::GenerateText()");
- - break;
- - }
- - // Reset x once more
- - x = width_range[From];
- - // Move down, because font drawing starts from the baseline
- - y += line_height;
- -
- - // Do the real processing now
- - for (int j = temp_from; j <= i; ++j)
- - {
- - // We don't want to use Feedback now, so we'll have to use
- - // another one.
- - CGUIString::SFeedback Feedback2;
- -
- - // Defaults
- - string.GenerateTextCall(this, Feedback2, Font,
- - string.m_Words[j], string.m_Words[j+1],
- - FirstLine, pObject);
- -
- - // Iterate all and set X/Y values
- - // Since X values are not set, we need to make an internal
- - // iteration with an increment that will append the internal
- - // x, that is what x_pointer is for.
- - float x_pointer = 0.f;
- -
- - for (SGUIText::STextCall& tc : Feedback2.m_TextCalls)
- - {
- - tc.m_Pos = CPos(dx + x + x_pointer, y);
- -
- - x_pointer += tc.m_Size.cx;
- -
- - if (tc.m_pSpriteCall)
- - tc.m_pSpriteCall->m_Area += tc.m_Pos - CSize(0, tc.m_pSpriteCall->m_Area.GetHeight());
- - }
- -
- - // Append X value.
- - x += Feedback2.m_Size.cx;
- -
- - // The first word overrides the width limit, what we
- - // do, in those cases, are just drawing that word even
- - // though it'll extend the object.
- - if (WordWrapping) // only if word-wrapping is applicable
- - {
- - if (Feedback2.m_NewLine)
- - {
- - from = j+1;
- -
- - // Sprite call can exist within only a newline segment,
- - // therefore we need this.
- - Text.m_SpriteCalls.insert(
- - Text.m_SpriteCalls.end(),
- - std::make_move_iterator(Feedback2.m_SpriteCalls.begin()),
- - std::make_move_iterator(Feedback2.m_SpriteCalls.end()));
- - break;
- - }
- - else if (x > width_range[To] && j == temp_from)
- - {
- - from = j+1;
- - // do not break, since we want it to be added to m_TextCalls
- - }
- - else if (x > width_range[To])
- - {
- - from = j;
- - break;
- - }
- - }
- -
- - // Add the whole Feedback2.m_TextCalls to our m_TextCalls.
- - Text.m_TextCalls.insert(
- - Text.m_TextCalls.end(),
- - std::make_move_iterator(Feedback2.m_TextCalls.begin()),
- - std::make_move_iterator(Feedback2.m_TextCalls.end()));
- -
- - Text.m_SpriteCalls.insert(
- - Text.m_SpriteCalls.end(),
- - std::make_move_iterator(Feedback2.m_SpriteCalls.begin()),
- - std::make_move_iterator(Feedback2.m_SpriteCalls.end()));
- -
- - if (j == (int)string.m_Words.size()-2)
- - done = true;
- - }
- -
- - // Reset X
- - x = BufferZone;
- -
- - // Update dimensions
- - Text.m_Size.cx = std::max(Text.m_Size.cx, line_width + BufferZone * 2);
- - Text.m_Size.cy = std::max(Text.m_Size.cy, y + BufferZone);
- -
- - FirstLine = false;
- -
- - // Now if we entered as from = i, then we want
- - // i being one minus that, so that it will become
- - // the same i in the next loop. The difference is that
- - // we're on a new line now.
- - i = from-1;
- - }
- - }
- -
- - return Text;
- -}
- -
- -void CGUI::DrawText(SGUIText& Text, const CGUIColor& DefaultColor, const CPos& pos, const float& z, const CRect& clipping)
- -{
- - CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text);
- -
- - tech->BeginPass();
- -
- - bool isClipped = (clipping != CRect());
- - if (isClipped)
- - {
- - glEnable(GL_SCISSOR_TEST);
- - glScissor(
- - clipping.left * g_GuiScale,
- - g_yres - clipping.bottom * g_GuiScale,
- - clipping.GetWidth() * g_GuiScale,
- - clipping.GetHeight() * g_GuiScale);
- - }
- -
- - CTextRenderer textRenderer(tech->GetShader());
- - textRenderer.SetClippingRect(clipping);
- - textRenderer.Translate(0.0f, 0.0f, z);
- -
- - for (const SGUIText::STextCall& tc : Text.m_TextCalls)
- - {
- - // If this is just a placeholder for a sprite call, continue
- - if (tc.m_pSpriteCall)
- - continue;
- -
- - CGUIColor color = tc.m_UseCustomColor ? tc.m_Color : DefaultColor;
- -
- - textRenderer.Color(color);
- - textRenderer.Font(tc.m_Font);
- - textRenderer.Put((float)(int)(pos.x + tc.m_Pos.x), (float)(int)(pos.y + tc.m_Pos.y), &tc.m_String);
- - }
- -
- - textRenderer.Render();
- -
- - for (const SGUIText::SSpriteCall& sc : Text.m_SpriteCalls)
- - DrawSprite(sc.m_Sprite, sc.m_CellID, z, sc.m_Area + pos);
- -
- - if (isClipped)
- - glDisable(GL_SCISSOR_TEST);
- -
- - tech->EndPass();
- -}
- -
- bool CGUI::GetPreDefinedColor(const CStr& name, CGUIColor& Output) const
- {
- std::map<CStr, CGUIColor>::const_iterator cit = m_PreDefinedColors.find(name);
- if (cit == m_PreDefinedColors.end())
- return false;
- Index: source/gui/CGUIText.cpp
- ===================================================================
- --- source/gui/CGUIText.cpp (nonexistent)
- +++ source/gui/CGUIText.cpp (working copy)
- @@ -0,0 +1,425 @@
- +/* Copyright (C) 2019 Wildfire Games.
- + * This file is part of 0 A.D.
- + *
- + * 0 A.D. is free software: you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation, either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * 0 A.D. is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
- + */
- +
- +#include "precompiled.h"
- +
- +#include "CGUIText.h"
- +
- +#include "gui/CGUIString.h"
- +#include "gui/IGUIObject.h"
- +#include "graphics/FontMetrics.h"
- +#include "graphics/ShaderManager.h"
- +#include "renderer/Renderer.h"
- +
- +extern int g_xres, g_yres;
- +extern float g_GuiScale;
- +
- +void SGenerateTextImage::SetupSpriteCall(
- + const bool Left, CGUIText::SSpriteCall& SpriteCall, const float width, const float y,
- + const CSize& Size, const CStr& TextureName, const float BufferZone, const int CellID)
- +{
- + // TODO Gee: Temp hardcoded values
- + SpriteCall.m_Area.top = y+BufferZone;
- + SpriteCall.m_Area.bottom = y+BufferZone + Size.cy;
- +
- + if (Left)
- + {
- + SpriteCall.m_Area.left = BufferZone;
- + SpriteCall.m_Area.right = Size.cx+BufferZone;
- + }
- + else
- + {
- + SpriteCall.m_Area.left = width-BufferZone - Size.cx;
- + SpriteCall.m_Area.right = width-BufferZone;
- + }
- +
- + SpriteCall.m_CellID = CellID;
- + SpriteCall.m_Sprite = TextureName;
- +
- + m_YFrom = SpriteCall.m_Area.top-BufferZone;
- + m_YTo = SpriteCall.m_Area.bottom+BufferZone;
- + m_Indentation = Size.cx+BufferZone*2;
- +}
- +
- +CGUIText::CGUIText(const CGUI* pGUI, const CGUIString& string, const CStrW& FontW, const float Width, const float BufferZone, const IGUIObject* pObject)
- +{
- + // Return the Text variable in any case to ease named-return-value-optimization
- + if (string.m_Words.empty())
- + return;
- +
- + CStrIntern Font(FontW.ToUTF8());
- + float x = BufferZone, y = BufferZone; // drawing pointer
- + int from = 0;
- +
- + bool FirstLine = true; // Necessary because text in the first line is shorter
- + // (it doesn't count the line spacing)
- +
- + // Images on the left or the right side.
- + SGenerateTextImages Images;
- + int pos_last_img = -1; // Position in the string where last img (either left or right) were encountered.
- + // in order to avoid duplicate processing.
- +
- + // get the alignment type for the control we are computing the text for since
- + // we are computing the horizontal alignment in this method in order to not have
- + // to run through the TextCalls a second time in the CalculateTextPosition method again
- + EAlign align = EAlign_Left;
- + if (pObject->SettingExists("text_align"))
- + GUI<EAlign>::GetSetting(pObject, "text_align", align);
- +
- + // Go through string word by word
- + for (int i = 0; i < static_cast<int>(string.m_Words.size()) - 1; ++i)
- + {
- + // Pre-process each line one time, so we know which floating images
- + // will be added for that line.
- +
- + // Generated stuff is stored in Feedback.
- + CGUIString::SFeedback Feedback;
- +
- + // Preliminary line height, used for word-wrapping with floating images.
- + float prelim_line_height = 0.f;
- +
- + // Width and height of all text calls generated.
- + string.GenerateTextCall(pGUI, Feedback, Font, string.m_Words[i], string.m_Words[i+1], FirstLine);
- +
- + SetupSpriteCalls(pGUI, Feedback.m_Images, Images, i, y, pos_last_img, Width, BufferZone);
- +
- + pos_last_img = std::max(pos_last_img, i);
- +
- + x += Feedback.m_Size.cx;
- + prelim_line_height = std::max(prelim_line_height, Feedback.m_Size.cy);
- +
- + // If Width is 0, then there's no word-wrapping, disable NewLine.
- + if (((Width != 0 && (x > Width-BufferZone || Feedback.m_NewLine)) || i == static_cast<int>(string.m_Words.size()) - 2) &&
- + ComputeLine(pGUI, string, align, FirstLine, Font, Images, x, y, i, prelim_line_height, Width, BufferZone, from, pObject))
- + return;
- + }
- +}
- +
- +// compute offset based on what kind of alignment
- +float CGUIText::GetLineOffset(const EAlign align, const float width_range_from, const float width_range_to, const CSize& line_size)
- +{
- + switch (align)
- + {
- + case EAlign_Left:
- + // don't add an offset
- + return 0.f;
- +
- + case EAlign_Center:
- + return ((width_range_to - width_range_from) - line_size.cx) / 2;
- +
- + case EAlign_Right:
- + return width_range_to - line_size.cx;
- +
- + default:
- + debug_warn(L"Broken EAlign in CGUI::GenerateText()");
- + return 0.f;
- + }
- +}
- +
- +// Decide width of the line. We need to iterate our floating images.
- +// this won't be exact because we're assuming the line_size.cy
- +// will be as our preliminary calculation said. But that may change,
- +// although we'd have to add a couple of more loops to try straightening
- +// this problem out, and it is very unlikely to happen noticeably if one
- +// structures his text in a stylistically pure fashion. Even if not, it
- +// is still quite unlikely it will happen.
- +// Loop through left and right side, from and to.
- +void CGUIText::ComputeLineRange(const SGenerateTextImages& Images, const float y, const float Width, const float prelim_line_height, float& width_range_from, float& width_range_to)
- +{
- + // Floating images are only applicable if word-wrapping is enabled.
- + if (Width == 0)
- + return;
- +
- + for (int j = 0; j < 2; ++j)
- + for (const SGenerateTextImage& img : Images[j])
- + {
- + // We're working with two intervals here, the image's and the line height's.
- + // let's find the union of these two.
- + float union_from, union_to;
- +
- + union_from = std::max(y, img.m_YFrom);
- + union_to = std::min(y + prelim_line_height, img.m_YTo);
- +
- + // The union is not empty
- + if (union_to > union_from)
- + {
- + if (j == 0)
- + width_range_from = std::max(width_range_from, img.m_Indentation);
- + else
- + width_range_to = std::min(width_range_to, Width - img.m_Indentation);
- + }
- + }
- +}
- +
- +// Now we'll do another loop to figure out the height and width of
- +// the line (the height of the largest character and the width is
- +// the sum of all of the individual widths). This
- +// couldn't be determined in the first loop (main loop)
- +// because it didn't regard images, so we don't know
- +// if all characters processed, will actually be involved
- +// in that line.
- +void CGUIText::ComputeLineSize(const CGUI* pGUI, const CStrIntern& Font, const CGUIString& string, const float Width, const bool FirstLine, const int i, const int temp_from, const float width_range_to, float& x, CSize& line_size)
- +{
- + for (int j = temp_from; j <= i; ++j)
- + {
- + // We don't want to use Feedback now, so we'll have to use another.
- + CGUIString::SFeedback Feedback2;
- +
- + // Don't attach object, it'll suppress the errors
- + // we want them to be reported in the final GenerateTextCall()
- + // so that we don't get duplicates.
- + string.GenerateTextCall(pGUI, Feedback2, Font, string.m_Words[j], string.m_Words[j+1], FirstLine);
- +
- + // Append X value.
- + x += Feedback2.m_Size.cx;
- +
- + if (Width != 0 && x > width_range_to && j != temp_from && !Feedback2.m_NewLine)
- + {
- + // The calculated width of each word includes the space between the current
- + // word and the next. When we're wrapping, we need subtract the width of the
- + // space after the last word on the line before the wrap.
- + CFontMetrics currentFont(Font);
- + line_size.cx -= currentFont.GetCharacterWidth(*L" ");
- + break;
- + }
- +
- + // Let line_size.cy be the maximum m_Height we encounter.
- + line_size.cy = std::max(line_size.cy, Feedback2.m_Size.cy);
- +
- + // If the current word is an explicit new line ("\n"),
- + // break now before adding the width of this character.
- + // ("\n" doesn't have a glyph, thus is given the same width as
- + // the "missing glyph" character by CFont::GetCharacterWidth().)
- + if (Width != 0 && Feedback2.m_NewLine)
- + break;
- +
- + line_size.cx += Feedback2.m_Size.cx;
- + }
- +}
- +
- +// Loop through our images queues, to see if images has been added.
- +void CGUIText::SetupSpriteCalls(const CGUI* pGUI, const std::array<std::vector<CStr>, 2>& FeedbackImages, SGenerateTextImages& Images, const int i, const float y, const int pos_last_img, const float Width, const float BufferZone)
- +{
- + // Check if this has already been processed.
- + // Also, floating images are only applicable if Word-Wrapping is on
- + if (Width == 0 || i <= pos_last_img)
- + return;
- +
- + // Loop left/right
- + for (int j = 0; j < 2; ++j)
- + for (const CStr& imgname : FeedbackImages[j])
- + {
- + SSpriteCall SpriteCall;
- + SGenerateTextImage Image;
- +
- + // Y is if no other floating images is above, y. Else it is placed
- + // after the last image, like a stack downwards.
- + float _y;
- + if (!Images[j].empty())
- + _y = std::max(y, Images[j].back().m_YTo);
- + else
- + _y = y;
- +
- + const SGUIIcon& icon = pGUI->GetIcon(imgname);
- + Image.SetupSpriteCall((j == CGUIString::SFeedback::Left), SpriteCall, Width, _y, icon.m_Size, icon.m_SpriteName, BufferZone, icon.m_CellID);
- +
- + // Check if image is the lowest thing.
- + m_Size.cy = std::max(m_Size.cy, Image.m_YTo);
- +
- + Images[j].emplace_back(Image);
- + m_SpriteCalls.emplace_back(std::move(SpriteCall));
- + }
- +}
- +
- +bool CGUIText::ComputeLine(const CGUI* pGUI, const CGUIString& string, const EAlign align, bool& FirstLine, const CStrIntern& Font, const SGenerateTextImages& Images, float& x, float& y, int& i, const float prelim_line_height, const float Width, const float BufferZone, int& from, const IGUIObject* pObject)
- +{
- + // Change 'from' to 'i', but first keep a copy of its value.
- + int temp_from = from;
- + from = i;
- +
- + float width_range_from = BufferZone;
- + float width_range_to = Width - BufferZone;
- + ComputeLineRange(Images, y, Width, prelim_line_height, width_range_from, width_range_to);
- +
- + // Reset X for the next loop
- + x = width_range_from;
- +
- + CSize line_size;
- + ComputeLineSize(pGUI, Font, string, Width, FirstLine, i, temp_from, width_range_to, x, line_size);
- +
- + // Reset x once more
- + x = width_range_from;
- +
- + // Move down, because font drawing starts from the baseline
- + y += line_size.cy;
- +
- + const float dx = GetLineOffset(align, width_range_from, width_range_to, line_size);
- +
- + // Do the real processing now
- + if (AssembleTextLineCalls(pGUI, Font, string, FirstLine, pObject, Width, dx, temp_from, width_range_to, y, i, x, from))
- + return true;
- +
- + // Reset X
- + x = BufferZone;
- +
- + // Update dimensions
- + m_Size.cx = std::max(m_Size.cx, line_size.cx + BufferZone * 2);
- + m_Size.cy = std::max(m_Size.cy, y + BufferZone);
- +
- + FirstLine = false;
- +
- + // Now if we entered as from = i, then we want
- + // i being one minus that, so that it will become
- + // the same i in the next loop. The difference is that
- + // we're on a new line now.
- + i = from - 1;
- +
- + return false;
- +}
- +
- +bool CGUIText::AssembleTextLineCalls(
- + const CGUI* pGUI,
- + const CStrIntern& Font,
- + const CGUIString& string,
- + const bool FirstLine,
- + const IGUIObject* pObject,
- + const float Width,
- + const float dx,
- + const int temp_from,
- + const float width_range_to,
- + const float y,
- + const int i,
- + float& x,
- + int& from)
- +{
- + for (int j = temp_from; j <= i; ++j)
- + {
- + // We don't want to use Feedback now, so we'll have to use another one.
- + CGUIString::SFeedback Feedback2;
- +
- + // Defaults
- + string.GenerateTextCall(pGUI, Feedback2, Font, string.m_Words[j], string.m_Words[j+1], FirstLine, pObject);
- +
- + // Iterate all and set X/Y values
- + // Since X values are not set, we need to make an internal
- + // iteration with an increment that will append the internal
- + // x, that is what x_pointer is for.
- + float x_pointer = 0.f;
- +
- + for (STextCall& tc : Feedback2.m_TextCalls)
- + {
- + tc.m_Pos = CPos(dx + x + x_pointer, y);
- +
- + x_pointer += tc.m_Size.cx;
- +
- + if (tc.m_pSpriteCall)
- + tc.m_pSpriteCall->m_Area += tc.m_Pos - CSize(0, tc.m_pSpriteCall->m_Area.GetHeight());
- + }
- +
- + // Append X value.
- + x += Feedback2.m_Size.cx;
- +
- + // The first word overrides the width limit, what we
- + // do, in those cases, are just drawing that word even
- + // though it'll extend the object.
- + if (Width != 0) // only if word-wrapping is applicable
- + {
- + if (Feedback2.m_NewLine)
- + {
- + from = j+1;
- +
- + // Sprite call can exist within only a newline segment,
- + // therefore we need this.
- + m_SpriteCalls.insert(
- + m_SpriteCalls.end(),
- + std::make_move_iterator(Feedback2.m_SpriteCalls.begin()),
- + std::make_move_iterator(Feedback2.m_SpriteCalls.end()));
- + break;
- + }
- + else if (x > width_range_to && j == temp_from)
- + {
- + from = j+1;
- + // do not break, since we want it to be added to m_TextCalls
- + }
- + else if (x > width_range_to)
- + {
- + from = j;
- + break;
- + }
- + }
- +
- + // Add the whole Feedback2.m_TextCalls to our m_TextCalls.
- + m_TextCalls.insert(
- + m_TextCalls.end(),
- + std::make_move_iterator(Feedback2.m_TextCalls.begin()),
- + std::make_move_iterator(Feedback2.m_TextCalls.end()));
- +
- + m_SpriteCalls.insert(
- + m_SpriteCalls.end(),
- + std::make_move_iterator(Feedback2.m_SpriteCalls.begin()),
- + std::make_move_iterator(Feedback2.m_SpriteCalls.end()));
- +
- + if (j == static_cast<int>(string.m_Words.size()) - 2)
- + return true;
- + }
- + return false;
- +}
- +
- +void CGUIText::DrawText(CGUI* pGUI, const CGUIColor& DefaultColor, const CPos& pos, const float z, const CRect& clipping)
- +{
- + CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text);
- +
- + tech->BeginPass();
- +
- + bool isClipped = (clipping != CRect());
- + if (isClipped)
- + {
- + glEnable(GL_SCISSOR_TEST);
- + glScissor(
- + clipping.left * g_GuiScale,
- + g_yres - clipping.bottom * g_GuiScale,
- + clipping.GetWidth() * g_GuiScale,
- + clipping.GetHeight() * g_GuiScale);
- + }
- +
- + CTextRenderer textRenderer(tech->GetShader());
- + textRenderer.SetClippingRect(clipping);
- + textRenderer.Translate(0.0f, 0.0f, z);
- +
- + for (const STextCall& tc : m_TextCalls)
- + {
- + // If this is just a placeholder for a sprite call, continue
- + if (tc.m_pSpriteCall)
- + continue;
- +
- + CGUIColor color = tc.m_UseCustomColor ? tc.m_Color : DefaultColor;
- +
- + textRenderer.Color(color);
- + textRenderer.Font(tc.m_Font);
- + textRenderer.Put((float)(int)(pos.x + tc.m_Pos.x), (float)(int)(pos.y + tc.m_Pos.y), &tc.m_String);
- + }
- +
- + textRenderer.Render();
- +
- + for (const SSpriteCall& sc : m_SpriteCalls)
- + pGUI->DrawSprite(sc.m_Sprite, sc.m_CellID, z, sc.m_Area + pos);
- +
- + if (isClipped)
- + glDisable(GL_SCISSOR_TEST);
- +
- + tech->EndPass();
- +}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement