Advertisement
Guest User

Untitled

a guest
Aug 11th, 2019
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 28.46 KB | None | 0 0
  1. Index: source/gui/CGUI.cpp
  2. ===================================================================
  3. --- source/gui/CGUI.cpp (revision 22642)
  4. +++ source/gui/CGUI.cpp (working copy)
  5. @@ -38,11 +38,10 @@
  6.  #include "CTooltip.h"
  7.  #include "MiniMap.h"
  8.  
  9.  #include "graphics/FontMetrics.h"
  10.  #include "graphics/ShaderManager.h"
  11. -#include "graphics/TextRenderer.h"
  12.  #include "i18n/L10n.h"
  13.  #include "lib/bits.h"
  14.  #include "lib/input.h"
  15.  #include "lib/sysdep/sysdep.h"
  16.  #include "lib/timer.h"
  17. @@ -483,404 +482,10 @@ const SGUIScrollBarStyle* CGUI::GetScrol
  18.         return nullptr;
  19.  
  20.     return &it->second;
  21.  }
  22.  
  23. -// private struct used only in GenerateText(...)
  24. -struct SGenerateTextImage
  25. -{
  26. -   // Only primitve members, so move assignments are the same as copy assignments.
  27. -
  28. -   float m_YFrom,          // The image's starting location in Y
  29. -         m_YTo,            // The image's end location in Y
  30. -         m_Indentation;    // The image width in other words
  31. -
  32. -   // Some help functions
  33. -   // TODO Gee: CRect => CPoint ?
  34. -   void SetupSpriteCall(const bool Left, SGUIText::SSpriteCall& SpriteCall,
  35. -                        const float width, const float y,
  36. -                        const CSize& Size, const CStr& TextureName,
  37. -                        const float BufferZone, const int CellID)
  38. -   {
  39. -       // TODO Gee: Temp hardcoded values
  40. -       SpriteCall.m_Area.top = y+BufferZone;
  41. -       SpriteCall.m_Area.bottom = y+BufferZone + Size.cy;
  42. -
  43. -       if (Left)
  44. -       {
  45. -           SpriteCall.m_Area.left = BufferZone;
  46. -           SpriteCall.m_Area.right = Size.cx+BufferZone;
  47. -       }
  48. -       else
  49. -       {
  50. -           SpriteCall.m_Area.left = width-BufferZone - Size.cx;
  51. -           SpriteCall.m_Area.right = width-BufferZone;
  52. -       }
  53. -
  54. -       SpriteCall.m_CellID = CellID;
  55. -       SpriteCall.m_Sprite = TextureName;
  56. -
  57. -       m_YFrom = SpriteCall.m_Area.top-BufferZone;
  58. -       m_YTo = SpriteCall.m_Area.bottom+BufferZone;
  59. -       m_Indentation = Size.cx+BufferZone*2;
  60. -   }
  61. -};
  62. -
  63. -SGUIText CGUI::GenerateText(const CGUIString& string, const CStrW& FontW, const float& Width, const float& BufferZone, const IGUIObject* pObject)
  64. -{
  65. -   SGUIText Text;
  66. -
  67. -   CStrIntern Font(FontW.ToUTF8());
  68. -
  69. -   if (string.m_Words.empty())
  70. -       return Text;
  71. -
  72. -   float x = BufferZone, y = BufferZone; // drawing pointer
  73. -   int from = 0;
  74. -   bool done = false;
  75. -
  76. -   bool FirstLine = true;  // Necessary because text in the first line is shorter
  77. -                           // (it doesn't count the line spacing)
  78. -
  79. -   // Images on the left or the right side.
  80. -   std::vector<SGenerateTextImage> Images[2];
  81. -   int pos_last_img = -1;  // Position in the string where last img (either left or right) were encountered.
  82. -                           //  in order to avoid duplicate processing.
  83. -
  84. -   // Easier to read.
  85. -   bool WordWrapping = (Width != 0);
  86. -
  87. -   // get the alignment type for the control we are computing the text for since
  88. -   // we are computing the horizontal alignment in this method in order to not have
  89. -   // to run through the TextCalls a second time in the CalculateTextPosition method again
  90. -   EAlign align = EAlign_Left;
  91. -   if (pObject->SettingExists("text_align"))
  92. -       GUI<EAlign>::GetSetting(pObject, "text_align", align);
  93. -
  94. -   // Go through string word by word
  95. -   for (int i = 0; i < (int)string.m_Words.size()-1 && !done; ++i)
  96. -   {
  97. -       // Pre-process each line one time, so we know which floating images
  98. -       //  will be added for that line.
  99. -
  100. -       // Generated stuff is stored in Feedback.
  101. -       CGUIString::SFeedback Feedback;
  102. -
  103. -       // Preliminary line_height, used for word-wrapping with floating images.
  104. -       float prelim_line_height = 0.f;
  105. -
  106. -       // Width and height of all text calls generated.
  107. -       string.GenerateTextCall(this, Feedback, Font,
  108. -                               string.m_Words[i], string.m_Words[i+1],
  109. -                               FirstLine);
  110. -
  111. -       // Loop through our images queues, to see if images has been added.
  112. -
  113. -       // Check if this has already been processed.
  114. -       //  Also, floating images are only applicable if Word-Wrapping is on
  115. -       if (WordWrapping && i > pos_last_img)
  116. -       {
  117. -           // Loop left/right
  118. -           for (int j = 0; j < 2; ++j)
  119. -           {
  120. -               for (const CStr& imgname : Feedback.m_Images[j])
  121. -               {
  122. -                   SGUIText::SSpriteCall SpriteCall;
  123. -                   SGenerateTextImage Image;
  124. -
  125. -                   // Y is if no other floating images is above, y. Else it is placed
  126. -                   //  after the last image, like a stack downwards.
  127. -                   float _y;
  128. -                   if (!Images[j].empty())
  129. -                       _y = std::max(y, Images[j].back().m_YTo);
  130. -                   else
  131. -                       _y = y;
  132. -
  133. -                   // Get Size from Icon database
  134. -                   const SGUIIcon& icon = GetIcon(imgname);
  135. -
  136. -                   const CSize& size = icon.m_Size;
  137. -                   Image.SetupSpriteCall((j == CGUIString::SFeedback::Left), SpriteCall, Width, _y, size, icon.m_SpriteName, BufferZone, icon.m_CellID);
  138. -
  139. -                   // Check if image is the lowest thing.
  140. -                   Text.m_Size.cy = std::max(Text.m_Size.cy, Image.m_YTo);
  141. -
  142. -                   Images[j].emplace_back(Image);
  143. -                   Text.m_SpriteCalls.emplace_back(std::move(SpriteCall));
  144. -               }
  145. -           }
  146. -       }
  147. -
  148. -       pos_last_img = std::max(pos_last_img, i);
  149. -
  150. -       x += Feedback.m_Size.cx;
  151. -       prelim_line_height = std::max(prelim_line_height, Feedback.m_Size.cy);
  152. -
  153. -       // If Width is 0, then there's no word-wrapping, disable NewLine.
  154. -       if ((WordWrapping && (x > Width-BufferZone || Feedback.m_NewLine)) || i == (int)string.m_Words.size()-2)
  155. -       {
  156. -           // Change 'from' to 'i', but first keep a copy of its value.
  157. -           int temp_from = from;
  158. -           from = i;
  159. -
  160. -           static const int From = 0, To = 1;
  161. -           //int width_from=0, width_to=width;
  162. -           float width_range[2];
  163. -           width_range[From] = BufferZone;
  164. -           width_range[To] = Width - BufferZone;
  165. -
  166. -           // Floating images are only applicable if word-wrapping is enabled.
  167. -           if (WordWrapping)
  168. -           {
  169. -               // Decide width of the line. We need to iterate our floating images.
  170. -               //  this won't be exact because we're assuming the line_height
  171. -               //  will be as our preliminary calculation said. But that may change,
  172. -               //  although we'd have to add a couple of more loops to try straightening
  173. -               //  this problem out, and it is very unlikely to happen noticeably if one
  174. -               //  structures his text in a stylistically pure fashion. Even if not, it
  175. -               //  is still quite unlikely it will happen.
  176. -               // Loop through left and right side, from and to.
  177. -               for (int j = 0; j < 2; ++j)
  178. -               {
  179. -                   for (const SGenerateTextImage& img : Images[j])
  180. -                   {
  181. -                       // We're working with two intervals here, the image's and the line height's.
  182. -                       //  let's find the union of these two.
  183. -                       float union_from, union_to;
  184. -
  185. -                       union_from = std::max(y, img.m_YFrom);
  186. -                       union_to = std::min(y+prelim_line_height, img.m_YTo);
  187. -
  188. -                       // The union is not empty
  189. -                       if (union_to > union_from)
  190. -                       {
  191. -                           if (j == From)
  192. -                               width_range[From] = std::max(width_range[From], img.m_Indentation);
  193. -                           else
  194. -                               width_range[To] = std::min(width_range[To], Width - img.m_Indentation);
  195. -                       }
  196. -                   }
  197. -               }
  198. -           }
  199. -
  200. -           // Reset X for the next loop
  201. -           x = width_range[From];
  202. -
  203. -           // Now we'll do another loop to figure out the height and width of
  204. -           //  the line (the height of the largest character and the width is
  205. -           //  the sum of all of the individual widths). This
  206. -           //  couldn't be determined in the first loop (main loop)
  207. -           //  because it didn't regard images, so we don't know
  208. -           //  if all characters processed, will actually be involved
  209. -           //  in that line.
  210. -           float line_height = 0.f;
  211. -           float line_width = 0.f;
  212. -           for (int j = temp_from; j <= i; ++j)
  213. -           {
  214. -               // We don't want to use Feedback now, so we'll have to use
  215. -               //  another.
  216. -               CGUIString::SFeedback Feedback2;
  217. -
  218. -               // Don't attach object, it'll suppress the errors
  219. -               //  we want them to be reported in the final GenerateTextCall()
  220. -               //  so that we don't get duplicates.
  221. -               string.GenerateTextCall(this, Feedback2, Font,
  222. -                                       string.m_Words[j], string.m_Words[j+1],
  223. -                                       FirstLine);
  224. -
  225. -               // Append X value.
  226. -               x += Feedback2.m_Size.cx;
  227. -
  228. -               if (WordWrapping && x > width_range[To] && j!=temp_from && !Feedback2.m_NewLine)
  229. -               {
  230. -                   // The calculated width of each word includes the space between the current
  231. -                   // word and the next. When we're wrapping, we need subtract the width of the
  232. -                   // space after the last word on the line before the wrap.
  233. -                   CFontMetrics currentFont(Font);
  234. -                   line_width -= currentFont.GetCharacterWidth(*L" ");
  235. -                   break;
  236. -               }
  237. -
  238. -               // Let line_height be the maximum m_Height we encounter.
  239. -               line_height = std::max(line_height, Feedback2.m_Size.cy);
  240. -
  241. -               // If the current word is an explicit new line ("\n"),
  242. -               // break now before adding the width of this character.
  243. -               // ("\n" doesn't have a glyph, thus is given the same width as
  244. -               // the "missing glyph" character by CFont::GetCharacterWidth().)
  245. -               if (WordWrapping && Feedback2.m_NewLine)
  246. -                   break;
  247. -
  248. -               line_width += Feedback2.m_Size.cx;
  249. -           }
  250. -
  251. -           float dx = 0.f;
  252. -           // compute offset based on what kind of alignment
  253. -           switch (align)
  254. -           {
  255. -           case EAlign_Left:
  256. -               // don't add an offset
  257. -               dx = 0.f;
  258. -               break;
  259. -
  260. -           case EAlign_Center:
  261. -               dx = ((width_range[To] - width_range[From]) - line_width) / 2;
  262. -               break;
  263. -
  264. -           case EAlign_Right:
  265. -               dx = width_range[To] - line_width;
  266. -               break;
  267. -
  268. -           default:
  269. -               debug_warn(L"Broken EAlign in CGUI::GenerateText()");
  270. -               break;
  271. -           }
  272. -           // Reset x once more
  273. -           x = width_range[From];
  274. -           // Move down, because font drawing starts from the baseline
  275. -           y += line_height;
  276. -
  277. -           // Do the real processing now
  278. -           for (int j = temp_from; j <= i; ++j)
  279. -           {
  280. -               // We don't want to use Feedback now, so we'll have to use
  281. -               //  another one.
  282. -               CGUIString::SFeedback Feedback2;
  283. -
  284. -               // Defaults
  285. -               string.GenerateTextCall(this, Feedback2, Font,
  286. -                                       string.m_Words[j], string.m_Words[j+1],
  287. -                                       FirstLine, pObject);
  288. -
  289. -               // Iterate all and set X/Y values
  290. -               // Since X values are not set, we need to make an internal
  291. -               //  iteration with an increment that will append the internal
  292. -               //  x, that is what x_pointer is for.
  293. -               float x_pointer = 0.f;
  294. -
  295. -               for (SGUIText::STextCall& tc : Feedback2.m_TextCalls)
  296. -               {
  297. -                   tc.m_Pos = CPos(dx + x + x_pointer, y);
  298. -
  299. -                   x_pointer += tc.m_Size.cx;
  300. -
  301. -                   if (tc.m_pSpriteCall)
  302. -                       tc.m_pSpriteCall->m_Area += tc.m_Pos - CSize(0, tc.m_pSpriteCall->m_Area.GetHeight());
  303. -               }
  304. -
  305. -               // Append X value.
  306. -               x += Feedback2.m_Size.cx;
  307. -
  308. -               // The first word overrides the width limit, what we
  309. -               //  do, in those cases, are just drawing that word even
  310. -               //  though it'll extend the object.
  311. -               if (WordWrapping) // only if word-wrapping is applicable
  312. -               {
  313. -                   if (Feedback2.m_NewLine)
  314. -                   {
  315. -                       from = j+1;
  316. -
  317. -                       // Sprite call can exist within only a newline segment,
  318. -                       //  therefore we need this.
  319. -                       Text.m_SpriteCalls.insert(
  320. -                           Text.m_SpriteCalls.end(),
  321. -                           std::make_move_iterator(Feedback2.m_SpriteCalls.begin()),
  322. -                           std::make_move_iterator(Feedback2.m_SpriteCalls.end()));
  323. -                       break;
  324. -                   }
  325. -                   else if (x > width_range[To] && j == temp_from)
  326. -                   {
  327. -                       from = j+1;
  328. -                       // do not break, since we want it to be added to m_TextCalls
  329. -                   }
  330. -                   else if (x > width_range[To])
  331. -                   {
  332. -                       from = j;
  333. -                       break;
  334. -                   }
  335. -               }
  336. -
  337. -               // Add the whole Feedback2.m_TextCalls to our m_TextCalls.
  338. -               Text.m_TextCalls.insert(
  339. -                   Text.m_TextCalls.end(),
  340. -                   std::make_move_iterator(Feedback2.m_TextCalls.begin()),
  341. -                   std::make_move_iterator(Feedback2.m_TextCalls.end()));
  342. -
  343. -               Text.m_SpriteCalls.insert(
  344. -                   Text.m_SpriteCalls.end(),
  345. -                   std::make_move_iterator(Feedback2.m_SpriteCalls.begin()),
  346. -                   std::make_move_iterator(Feedback2.m_SpriteCalls.end()));
  347. -
  348. -               if (j == (int)string.m_Words.size()-2)
  349. -                   done = true;
  350. -           }
  351. -
  352. -           // Reset X
  353. -           x = BufferZone;
  354. -
  355. -           // Update dimensions
  356. -           Text.m_Size.cx = std::max(Text.m_Size.cx, line_width + BufferZone * 2);
  357. -           Text.m_Size.cy = std::max(Text.m_Size.cy, y + BufferZone);
  358. -
  359. -           FirstLine = false;
  360. -
  361. -           // Now if we entered as from = i, then we want
  362. -           //  i being one minus that, so that it will become
  363. -           //  the same i in the next loop. The difference is that
  364. -           //  we're on a new line now.
  365. -           i = from-1;
  366. -       }
  367. -   }
  368. -
  369. -   return Text;
  370. -}
  371. -
  372. -void CGUI::DrawText(SGUIText& Text, const CGUIColor& DefaultColor, const CPos& pos, const float& z, const CRect& clipping)
  373. -{
  374. -   CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text);
  375. -
  376. -   tech->BeginPass();
  377. -
  378. -   bool isClipped = (clipping != CRect());
  379. -   if (isClipped)
  380. -   {
  381. -       glEnable(GL_SCISSOR_TEST);
  382. -       glScissor(
  383. -           clipping.left * g_GuiScale,
  384. -           g_yres - clipping.bottom * g_GuiScale,
  385. -           clipping.GetWidth() * g_GuiScale,
  386. -           clipping.GetHeight() * g_GuiScale);
  387. -   }
  388. -
  389. -   CTextRenderer textRenderer(tech->GetShader());
  390. -   textRenderer.SetClippingRect(clipping);
  391. -   textRenderer.Translate(0.0f, 0.0f, z);
  392. -
  393. -   for (const SGUIText::STextCall& tc : Text.m_TextCalls)
  394. -   {
  395. -       // If this is just a placeholder for a sprite call, continue
  396. -       if (tc.m_pSpriteCall)
  397. -           continue;
  398. -
  399. -       CGUIColor color = tc.m_UseCustomColor ? tc.m_Color : DefaultColor;
  400. -
  401. -       textRenderer.Color(color);
  402. -       textRenderer.Font(tc.m_Font);
  403. -       textRenderer.Put((float)(int)(pos.x + tc.m_Pos.x), (float)(int)(pos.y + tc.m_Pos.y), &tc.m_String);
  404. -   }
  405. -
  406. -   textRenderer.Render();
  407. -
  408. -   for (const SGUIText::SSpriteCall& sc : Text.m_SpriteCalls)
  409. -       DrawSprite(sc.m_Sprite, sc.m_CellID, z, sc.m_Area + pos);
  410. -
  411. -   if (isClipped)
  412. -       glDisable(GL_SCISSOR_TEST);
  413. -
  414. -   tech->EndPass();
  415. -}
  416. -
  417.  bool CGUI::GetPreDefinedColor(const CStr& name, CGUIColor& Output) const
  418.  {
  419.     std::map<CStr, CGUIColor>::const_iterator cit = m_PreDefinedColors.find(name);
  420.     if (cit == m_PreDefinedColors.end())
  421.         return false;
  422. Index: source/gui/CGUIText.cpp
  423. ===================================================================
  424. --- source/gui/CGUIText.cpp (nonexistent)
  425. +++ source/gui/CGUIText.cpp (working copy)
  426. @@ -0,0 +1,425 @@
  427. +/* Copyright (C) 2019 Wildfire Games.
  428. + * This file is part of 0 A.D.
  429. + *
  430. + * 0 A.D. is free software: you can redistribute it and/or modify
  431. + * it under the terms of the GNU General Public License as published by
  432. + * the Free Software Foundation, either version 2 of the License, or
  433. + * (at your option) any later version.
  434. + *
  435. + * 0 A.D. is distributed in the hope that it will be useful,
  436. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  437. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  438. + * GNU General Public License for more details.
  439. + *
  440. + * You should have received a copy of the GNU General Public License
  441. + * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
  442. + */
  443. +
  444. +#include "precompiled.h"
  445. +
  446. +#include "CGUIText.h"
  447. +
  448. +#include "gui/CGUIString.h"
  449. +#include "gui/IGUIObject.h"
  450. +#include "graphics/FontMetrics.h"
  451. +#include "graphics/ShaderManager.h"
  452. +#include "renderer/Renderer.h"
  453. +
  454. +extern int g_xres, g_yres;
  455. +extern float g_GuiScale;
  456. +
  457. +void SGenerateTextImage::SetupSpriteCall(
  458. +   const bool Left, CGUIText::SSpriteCall& SpriteCall, const float width, const float y,
  459. +   const CSize& Size, const CStr& TextureName, const float BufferZone, const int CellID)
  460. +{
  461. +   // TODO Gee: Temp hardcoded values
  462. +   SpriteCall.m_Area.top = y+BufferZone;
  463. +   SpriteCall.m_Area.bottom = y+BufferZone + Size.cy;
  464. +
  465. +   if (Left)
  466. +   {
  467. +       SpriteCall.m_Area.left = BufferZone;
  468. +       SpriteCall.m_Area.right = Size.cx+BufferZone;
  469. +   }
  470. +   else
  471. +   {
  472. +       SpriteCall.m_Area.left = width-BufferZone - Size.cx;
  473. +       SpriteCall.m_Area.right = width-BufferZone;
  474. +   }
  475. +
  476. +   SpriteCall.m_CellID = CellID;
  477. +   SpriteCall.m_Sprite = TextureName;
  478. +
  479. +   m_YFrom = SpriteCall.m_Area.top-BufferZone;
  480. +   m_YTo = SpriteCall.m_Area.bottom+BufferZone;
  481. +   m_Indentation = Size.cx+BufferZone*2;
  482. +}
  483. +
  484. +CGUIText::CGUIText(const CGUI* pGUI, const CGUIString& string, const CStrW& FontW, const float Width, const float BufferZone, const IGUIObject* pObject)
  485. +{
  486. +   // Return the Text variable in any case to ease named-return-value-optimization
  487. +   if (string.m_Words.empty())
  488. +       return;
  489. +
  490. +   CStrIntern Font(FontW.ToUTF8());
  491. +   float x = BufferZone, y = BufferZone; // drawing pointer
  492. +   int from = 0;
  493. +
  494. +   bool FirstLine = true;  // Necessary because text in the first line is shorter
  495. +                           // (it doesn't count the line spacing)
  496. +
  497. +   // Images on the left or the right side.
  498. +   SGenerateTextImages Images;
  499. +   int pos_last_img = -1;  // Position in the string where last img (either left or right) were encountered.
  500. +                           //  in order to avoid duplicate processing.
  501. +
  502. +   // get the alignment type for the control we are computing the text for since
  503. +   // we are computing the horizontal alignment in this method in order to not have
  504. +   // to run through the TextCalls a second time in the CalculateTextPosition method again
  505. +   EAlign align = EAlign_Left;
  506. +   if (pObject->SettingExists("text_align"))
  507. +       GUI<EAlign>::GetSetting(pObject, "text_align", align);
  508. +
  509. +   // Go through string word by word
  510. +   for (int i = 0; i < static_cast<int>(string.m_Words.size()) - 1; ++i)
  511. +   {
  512. +       // Pre-process each line one time, so we know which floating images
  513. +       //  will be added for that line.
  514. +
  515. +       // Generated stuff is stored in Feedback.
  516. +       CGUIString::SFeedback Feedback;
  517. +
  518. +       // Preliminary line height, used for word-wrapping with floating images.
  519. +       float prelim_line_height = 0.f;
  520. +
  521. +       // Width and height of all text calls generated.
  522. +       string.GenerateTextCall(pGUI, Feedback, Font, string.m_Words[i], string.m_Words[i+1], FirstLine);
  523. +
  524. +       SetupSpriteCalls(pGUI, Feedback.m_Images, Images, i, y, pos_last_img, Width, BufferZone);
  525. +
  526. +       pos_last_img = std::max(pos_last_img, i);
  527. +
  528. +       x += Feedback.m_Size.cx;
  529. +       prelim_line_height = std::max(prelim_line_height, Feedback.m_Size.cy);
  530. +
  531. +       // If Width is 0, then there's no word-wrapping, disable NewLine.
  532. +       if (((Width != 0 && (x > Width-BufferZone || Feedback.m_NewLine)) || i == static_cast<int>(string.m_Words.size()) - 2) &&
  533. +           ComputeLine(pGUI, string, align, FirstLine, Font, Images, x, y, i, prelim_line_height, Width, BufferZone, from, pObject))
  534. +           return;
  535. +   }
  536. +}
  537. +
  538. +// compute offset based on what kind of alignment
  539. +float CGUIText::GetLineOffset(const EAlign align, const float width_range_from, const float width_range_to, const CSize& line_size)
  540. +{
  541. +   switch (align)
  542. +   {
  543. +   case EAlign_Left:
  544. +       // don't add an offset
  545. +       return 0.f;
  546. +
  547. +   case EAlign_Center:
  548. +       return ((width_range_to - width_range_from) - line_size.cx) / 2;
  549. +
  550. +   case EAlign_Right:
  551. +       return width_range_to - line_size.cx;
  552. +
  553. +   default:
  554. +       debug_warn(L"Broken EAlign in CGUI::GenerateText()");
  555. +       return 0.f;
  556. +   }
  557. +}
  558. +
  559. +// Decide width of the line. We need to iterate our floating images.
  560. +//  this won't be exact because we're assuming the line_size.cy
  561. +//  will be as our preliminary calculation said. But that may change,
  562. +//  although we'd have to add a couple of more loops to try straightening
  563. +//  this problem out, and it is very unlikely to happen noticeably if one
  564. +//  structures his text in a stylistically pure fashion. Even if not, it
  565. +//  is still quite unlikely it will happen.
  566. +// Loop through left and right side, from and to.
  567. +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)
  568. +{
  569. +   // Floating images are only applicable if word-wrapping is enabled.
  570. +   if (Width == 0)
  571. +       return;
  572. +
  573. +   for (int j = 0; j < 2; ++j)
  574. +       for (const SGenerateTextImage& img : Images[j])
  575. +       {
  576. +           // We're working with two intervals here, the image's and the line height's.
  577. +           //  let's find the union of these two.
  578. +           float union_from, union_to;
  579. +
  580. +           union_from = std::max(y, img.m_YFrom);
  581. +           union_to = std::min(y + prelim_line_height, img.m_YTo);
  582. +
  583. +           // The union is not empty
  584. +           if (union_to > union_from)
  585. +           {
  586. +               if (j == 0)
  587. +                   width_range_from = std::max(width_range_from, img.m_Indentation);
  588. +               else
  589. +                   width_range_to = std::min(width_range_to, Width - img.m_Indentation);
  590. +           }
  591. +       }
  592. +}
  593. +
  594. +// Now we'll do another loop to figure out the height and width of
  595. +//  the line (the height of the largest character and the width is
  596. +//  the sum of all of the individual widths). This
  597. +//  couldn't be determined in the first loop (main loop)
  598. +//  because it didn't regard images, so we don't know
  599. +//  if all characters processed, will actually be involved
  600. +//  in that line.
  601. +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)
  602. +{
  603. +   for (int j = temp_from; j <= i; ++j)
  604. +   {
  605. +       // We don't want to use Feedback now, so we'll have to use another.
  606. +       CGUIString::SFeedback Feedback2;
  607. +
  608. +       // Don't attach object, it'll suppress the errors
  609. +       //  we want them to be reported in the final GenerateTextCall()
  610. +       //  so that we don't get duplicates.
  611. +       string.GenerateTextCall(pGUI, Feedback2, Font, string.m_Words[j], string.m_Words[j+1], FirstLine);
  612. +
  613. +       // Append X value.
  614. +       x += Feedback2.m_Size.cx;
  615. +
  616. +       if (Width != 0 && x > width_range_to && j != temp_from && !Feedback2.m_NewLine)
  617. +       {
  618. +           // The calculated width of each word includes the space between the current
  619. +           // word and the next. When we're wrapping, we need subtract the width of the
  620. +           // space after the last word on the line before the wrap.
  621. +           CFontMetrics currentFont(Font);
  622. +           line_size.cx -= currentFont.GetCharacterWidth(*L" ");
  623. +           break;
  624. +       }
  625. +
  626. +       // Let line_size.cy be the maximum m_Height we encounter.
  627. +       line_size.cy = std::max(line_size.cy, Feedback2.m_Size.cy);
  628. +
  629. +       // If the current word is an explicit new line ("\n"),
  630. +       // break now before adding the width of this character.
  631. +       // ("\n" doesn't have a glyph, thus is given the same width as
  632. +       // the "missing glyph" character by CFont::GetCharacterWidth().)
  633. +       if (Width != 0 && Feedback2.m_NewLine)
  634. +           break;
  635. +
  636. +       line_size.cx += Feedback2.m_Size.cx;
  637. +   }
  638. +}
  639. +
  640. +// Loop through our images queues, to see if images has been added.
  641. +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)
  642. +{
  643. +   // Check if this has already been processed.
  644. +   //  Also, floating images are only applicable if Word-Wrapping is on
  645. +   if (Width == 0 || i <= pos_last_img)
  646. +       return;
  647. +
  648. +   // Loop left/right
  649. +   for (int j = 0; j < 2; ++j)
  650. +       for (const CStr& imgname : FeedbackImages[j])
  651. +       {
  652. +           SSpriteCall SpriteCall;
  653. +           SGenerateTextImage Image;
  654. +
  655. +           // Y is if no other floating images is above, y. Else it is placed
  656. +           //  after the last image, like a stack downwards.
  657. +           float _y;
  658. +           if (!Images[j].empty())
  659. +               _y = std::max(y, Images[j].back().m_YTo);
  660. +           else
  661. +               _y = y;
  662. +
  663. +           const SGUIIcon& icon = pGUI->GetIcon(imgname);
  664. +           Image.SetupSpriteCall((j == CGUIString::SFeedback::Left), SpriteCall, Width, _y, icon.m_Size, icon.m_SpriteName, BufferZone, icon.m_CellID);
  665. +
  666. +           // Check if image is the lowest thing.
  667. +           m_Size.cy = std::max(m_Size.cy, Image.m_YTo);
  668. +
  669. +           Images[j].emplace_back(Image);
  670. +           m_SpriteCalls.emplace_back(std::move(SpriteCall));
  671. +       }
  672. +}
  673. +
  674. +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)
  675. +{
  676. +   // Change 'from' to 'i', but first keep a copy of its value.
  677. +   int temp_from = from;
  678. +   from = i;
  679. +
  680. +   float width_range_from = BufferZone;
  681. +   float width_range_to = Width - BufferZone;
  682. +   ComputeLineRange(Images, y, Width, prelim_line_height, width_range_from, width_range_to);
  683. +
  684. +   // Reset X for the next loop
  685. +   x = width_range_from;
  686. +
  687. +   CSize line_size;
  688. +   ComputeLineSize(pGUI, Font, string, Width, FirstLine, i, temp_from, width_range_to, x, line_size);
  689. +
  690. +   // Reset x once more
  691. +   x = width_range_from;
  692. +
  693. +   // Move down, because font drawing starts from the baseline
  694. +   y += line_size.cy;
  695. +
  696. +   const float dx = GetLineOffset(align, width_range_from, width_range_to, line_size);
  697. +
  698. +   // Do the real processing now
  699. +   if (AssembleTextLineCalls(pGUI, Font, string, FirstLine, pObject, Width, dx, temp_from, width_range_to, y, i, x, from))
  700. +       return true;
  701. +
  702. +   // Reset X
  703. +   x = BufferZone;
  704. +
  705. +   // Update dimensions
  706. +   m_Size.cx = std::max(m_Size.cx, line_size.cx + BufferZone * 2);
  707. +   m_Size.cy = std::max(m_Size.cy, y + BufferZone);
  708. +
  709. +   FirstLine = false;
  710. +
  711. +   // Now if we entered as from = i, then we want
  712. +   //  i being one minus that, so that it will become
  713. +   //  the same i in the next loop. The difference is that
  714. +   //  we're on a new line now.
  715. +   i = from - 1;
  716. +
  717. +   return false;
  718. +}
  719. +
  720. +bool CGUIText::AssembleTextLineCalls(
  721. +   const CGUI* pGUI,
  722. +   const CStrIntern& Font,
  723. +   const CGUIString& string,
  724. +   const bool FirstLine,
  725. +   const IGUIObject* pObject,
  726. +   const float Width,
  727. +   const float dx,
  728. +   const int temp_from,
  729. +   const float width_range_to,
  730. +   const float y,
  731. +   const int i,
  732. +   float& x,
  733. +   int& from)
  734. +{
  735. +   for (int j = temp_from; j <= i; ++j)
  736. +   {
  737. +       // We don't want to use Feedback now, so we'll have to use another one.
  738. +       CGUIString::SFeedback Feedback2;
  739. +
  740. +       // Defaults
  741. +       string.GenerateTextCall(pGUI, Feedback2, Font, string.m_Words[j], string.m_Words[j+1], FirstLine, pObject);
  742. +
  743. +       // Iterate all and set X/Y values
  744. +       // Since X values are not set, we need to make an internal
  745. +       //  iteration with an increment that will append the internal
  746. +       //  x, that is what x_pointer is for.
  747. +       float x_pointer = 0.f;
  748. +
  749. +       for (STextCall& tc : Feedback2.m_TextCalls)
  750. +       {
  751. +           tc.m_Pos = CPos(dx + x + x_pointer, y);
  752. +
  753. +           x_pointer += tc.m_Size.cx;
  754. +
  755. +           if (tc.m_pSpriteCall)
  756. +               tc.m_pSpriteCall->m_Area += tc.m_Pos - CSize(0, tc.m_pSpriteCall->m_Area.GetHeight());
  757. +       }
  758. +
  759. +       // Append X value.
  760. +       x += Feedback2.m_Size.cx;
  761. +
  762. +       // The first word overrides the width limit, what we
  763. +       //  do, in those cases, are just drawing that word even
  764. +       //  though it'll extend the object.
  765. +       if (Width != 0) // only if word-wrapping is applicable
  766. +       {
  767. +           if (Feedback2.m_NewLine)
  768. +           {
  769. +               from = j+1;
  770. +
  771. +               // Sprite call can exist within only a newline segment,
  772. +               //  therefore we need this.
  773. +               m_SpriteCalls.insert(
  774. +                   m_SpriteCalls.end(),
  775. +                   std::make_move_iterator(Feedback2.m_SpriteCalls.begin()),
  776. +                   std::make_move_iterator(Feedback2.m_SpriteCalls.end()));
  777. +               break;
  778. +           }
  779. +           else if (x > width_range_to && j == temp_from)
  780. +           {
  781. +               from = j+1;
  782. +               // do not break, since we want it to be added to m_TextCalls
  783. +           }
  784. +           else if (x > width_range_to)
  785. +           {
  786. +               from = j;
  787. +               break;
  788. +           }
  789. +       }
  790. +
  791. +       // Add the whole Feedback2.m_TextCalls to our m_TextCalls.
  792. +       m_TextCalls.insert(
  793. +           m_TextCalls.end(),
  794. +           std::make_move_iterator(Feedback2.m_TextCalls.begin()),
  795. +           std::make_move_iterator(Feedback2.m_TextCalls.end()));
  796. +
  797. +       m_SpriteCalls.insert(
  798. +           m_SpriteCalls.end(),
  799. +           std::make_move_iterator(Feedback2.m_SpriteCalls.begin()),
  800. +           std::make_move_iterator(Feedback2.m_SpriteCalls.end()));
  801. +
  802. +       if (j == static_cast<int>(string.m_Words.size()) - 2)
  803. +           return true;
  804. +   }
  805. +   return false;
  806. +}
  807. +
  808. +void CGUIText::DrawText(CGUI* pGUI, const CGUIColor& DefaultColor, const CPos& pos, const float z, const CRect& clipping)
  809. +{
  810. +   CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text);
  811. +
  812. +   tech->BeginPass();
  813. +
  814. +   bool isClipped = (clipping != CRect());
  815. +   if (isClipped)
  816. +   {
  817. +       glEnable(GL_SCISSOR_TEST);
  818. +       glScissor(
  819. +           clipping.left * g_GuiScale,
  820. +           g_yres - clipping.bottom * g_GuiScale,
  821. +           clipping.GetWidth() * g_GuiScale,
  822. +           clipping.GetHeight() * g_GuiScale);
  823. +   }
  824. +
  825. +   CTextRenderer textRenderer(tech->GetShader());
  826. +   textRenderer.SetClippingRect(clipping);
  827. +   textRenderer.Translate(0.0f, 0.0f, z);
  828. +
  829. +   for (const STextCall& tc : m_TextCalls)
  830. +   {
  831. +       // If this is just a placeholder for a sprite call, continue
  832. +       if (tc.m_pSpriteCall)
  833. +           continue;
  834. +
  835. +       CGUIColor color = tc.m_UseCustomColor ? tc.m_Color : DefaultColor;
  836. +
  837. +       textRenderer.Color(color);
  838. +       textRenderer.Font(tc.m_Font);
  839. +       textRenderer.Put((float)(int)(pos.x + tc.m_Pos.x), (float)(int)(pos.y + tc.m_Pos.y), &tc.m_String);
  840. +   }
  841. +
  842. +   textRenderer.Render();
  843. +
  844. +   for (const SSpriteCall& sc : m_SpriteCalls)
  845. +       pGUI->DrawSprite(sc.m_Sprite, sc.m_CellID, z, sc.m_Area + pos);
  846. +
  847. +   if (isClipped)
  848. +       glDisable(GL_SCISSOR_TEST);
  849. +
  850. +   tech->EndPass();
  851. +}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement