1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "utils/Color.h"
12 
13 #include <stdint.h>
14 #include <string>
15 #include <vector>
16 
17 #ifdef __GNUC__
18 // under gcc, inline will only take place if optimizations are applied (-O). this will force inline even without optimizations.
19 #define XBMC_FORCE_INLINE __attribute__((always_inline))
20 #else
21 #define XBMC_FORCE_INLINE
22 #endif
23 
24 class CGUIFont;
25 class CScrollInfo;
26 
27 // Process will be:
28 
29 // 1.  String is divided up into a "multiinfo" vector via the infomanager.
30 // 2.  The multiinfo vector is then parsed by the infomanager at rendertime and the resultant string is constructed.
31 // 3.  This is saved for comparison perhaps.  If the same, we are done.  If not, go to 4.
32 // 4.  The string is then parsed into a vector<CGUIString>.
33 // 5.  Each item in the vector is length-calculated, and then layout occurs governed by alignment and wrapping rules.
34 // 6.  A new vector<CGUIString> is constructed
35 
36 typedef uint32_t character_t;
37 typedef std::vector<character_t> vecText;
38 
39 class CGUIString
40 {
41 public:
42   typedef vecText::const_iterator iString;
43 
44   CGUIString(iString start, iString end, bool carriageReturn);
45 
46   std::string GetAsString() const;
47 
48   vecText m_text;
49   bool m_carriageReturn; // true if we have a carriage return here
50 };
51 
52 class CGUITextLayout
53 {
54 public:
55   CGUITextLayout(CGUIFont *font, bool wrap, float fHeight=0.0f, CGUIFont *borderFont = NULL);  // this may need changing - we may just use this class to replace CLabelInfo completely
56 
57   bool UpdateScrollinfo(CScrollInfo &scrollInfo);
58 
59   // main function to render strings
60   void Render(float x, float y, float angle, UTILS::Color color, UTILS::Color shadowColor, uint32_t alignment, float maxWidth, bool solid = false);
61   void RenderScrolling(float x, float y, float angle, UTILS::Color color, UTILS::Color shadowColor, uint32_t alignment, float maxWidth, const CScrollInfo &scrollInfo);
62   void RenderOutline(float x, float y, UTILS::Color color, UTILS::Color outlineColor, uint32_t alignment, float maxWidth);
63 
64   /*! \brief Returns the precalculated width and height of the text to be rendered (in constant time).
65    \param width [out] width of text
66    \param height [out] height of text
67    \sa GetTextWidth, CalcTextExtent
68    */
69   void GetTextExtent(float &width, float &height) const;
70 
71   /*! \brief Returns the precalculated width of the text to be rendered (in constant time).
72    \return width of text
73    \sa GetTextExtent, CalcTextExtent
74    */
GetTextWidth()75   float GetTextWidth() const { return m_textWidth; };
76 
77   float GetTextWidth(const std::wstring &text) const;
78 
79   /*! \brief Returns the precalculated height of the text to be rendered (in constant time).
80    \return height of text
81   */
GetTextHeight()82   float GetTextHeight() const { return m_textHeight; };
83 
84   bool Update(const std::string &text, float maxWidth = 0, bool forceUpdate = false, bool forceLTRReadingOrder = false);
85   bool UpdateW(const std::wstring &text, float maxWidth = 0, bool forceUpdate = false, bool forceLTRReadingOrder = false);
86 
87   /*! \brief Update text from a pre-styled vecText/std::vector<UTILS::Color> combination
88    Allows styled text to be passed directly to the text layout.
89    \param text the styled text to set.
90    \param colors the colors used on the text.
91    \param maxWidth the maximum width for wrapping text, defaults to 0 (no max width).
92    \param forceLTRReadingOrder whether to force left to right reading order, defaults to false.
93    */
94   void UpdateStyled(const vecText &text, const std::vector<UTILS::Color> &colors, float maxWidth = 0, bool forceLTRReadingOrder = false);
95 
96   unsigned int GetTextLength() const;
97   void GetFirstText(vecText &text) const;
98   void Reset();
99 
100   void SetWrap(bool bWrap=true);
101   void SetMaxHeight(float fHeight);
102 
103 
104   static void DrawText(CGUIFont *font, float x, float y, UTILS::Color color, UTILS::Color shadowColor, const std::string &text, uint32_t align);
105   static void Filter(std::string &text);
106 
107 protected:
108   void LineBreakText(const vecText &text, std::vector<CGUIString> &lines);
109   void WrapText(const vecText &text, float maxWidth);
110   static void BidiTransform(std::vector<CGUIString> &lines, bool forceLTRReadingOrder);
111   static std::wstring BidiFlip(const std::wstring& text,
112                                bool forceLTRReadingOrder,
113                                int* visualToLogicalMap = nullptr);
114   void CalcTextExtent();
115   void UpdateCommon(const std::wstring &text, float maxWidth, bool forceLTRReadingOrder);
116 
117   /*! \brief Returns the text, utf8 encoded
118    \return utf8 text
119    */
120   std::string GetText() const;
121 
122   //! \brief Set the monospaced font to use
SetMonoFont(CGUIFont * font)123   void SetMonoFont(CGUIFont* font) { m_monoFont = font; }
124 
125   //! \brief Set whether or not to use the monospace font
UseMonoFont(bool use)126   void UseMonoFont(bool use) { m_font = use && m_monoFont ? m_monoFont : m_varFont; }
127 
128   // our text to render
129   std::vector<UTILS::Color> m_colors;
130   std::vector<CGUIString> m_lines;
131   typedef std::vector<CGUIString>::iterator iLine;
132 
133   // the layout and font details
134   CGUIFont *m_font;        // has style, colour info
135   CGUIFont *m_borderFont;  // only used for outlined text
136   CGUIFont* m_monoFont = nullptr; //!< Mono-space font to use
137   CGUIFont* m_varFont;    //!< Varible-space font to use
138 
139   bool  m_wrap;            // wrapping (true if justify is enabled!)
140   float m_maxHeight;
141   // the default color (may differ from the font objects defaults)
142   UTILS::Color m_textColor;
143 
144   std::string m_lastUtf8Text;
145   std::wstring m_lastText;
146   bool        m_lastUpdateW; ///< true if the last string we updated was the wstring version
147   float m_textWidth;
148   float m_textHeight;
149 private:
IsSpace(character_t letter)150   inline bool IsSpace(character_t letter) const XBMC_FORCE_INLINE
151   {
152     return (letter & 0xffff) == L' ';
153   };
CanWrapAtLetter(character_t letter)154   inline bool CanWrapAtLetter(character_t letter) const XBMC_FORCE_INLINE
155   {
156     character_t ch = letter & 0xffff;
157     return ch == L' ' || (ch >=0x4e00 && ch <= 0x9fff);
158   };
159   static void AppendToUTF32(const std::string &utf8, character_t colStyle, vecText &utf32);
160   static void AppendToUTF32(const std::wstring &utf16, character_t colStyle, vecText &utf32);
161   static void ParseText(const std::wstring &text, uint32_t defaultStyle, UTILS::Color defaultColor, std::vector<UTILS::Color> &colors, vecText &parsedText);
162 };
163 
164