1 /* 2 * This file is part of the Colobot: Gold Edition source code 3 * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam 4 * http://epsitec.ch; http://colobot.info; http://github.com/colobot 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 * See the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see http://gnu.org/licenses 18 */ 19 20 /** 21 * \file graphics/engine/text.h 22 * \brief Text rendering - CText class 23 */ 24 25 #pragma once 26 27 28 #include "graphics/core/color.h" 29 30 #include "math/intpoint.h" 31 #include "math/point.h" 32 33 #include <map> 34 #include <memory> 35 #include <vector> 36 37 38 // Graphics module namespace 39 namespace Gfx 40 { 41 42 class CEngine; 43 class CDevice; 44 45 //! Standard small font size 46 const float FONT_SIZE_SMALL = 12.0f; 47 //! Standard big font size 48 const float FONT_SIZE_BIG = 18.0f; 49 50 /** 51 * \enum TextAlign 52 * \brief Type of text alignment 53 */ 54 enum TextAlign 55 { 56 TEXT_ALIGN_RIGHT, 57 TEXT_ALIGN_LEFT, 58 TEXT_ALIGN_CENTER 59 }; 60 61 /* Font meta char constants */ 62 63 //! Type used for font character metainfo 64 typedef short FontMetaChar; 65 66 /** 67 * \enum FontType 68 * \brief Type of font 69 * 70 * Bitmask in lower 4 bits (mask 0x00f) 71 */ 72 enum FontType 73 { 74 //! Flag for bold font subtype 75 FONT_BOLD = 0x04, 76 //! Flag for italic font subtype 77 FONT_ITALIC = 0x08, 78 79 //! Default colobot font used for interface 80 FONT_COMMON = 0x00, 81 //! Alias for bold colobot font 82 FONT_COMMON_BOLD = FONT_COMMON | FONT_BOLD, 83 //! Alias for italic colobot font 84 FONT_COMMON_ITALIC = FONT_COMMON | FONT_ITALIC, 85 86 //! Studio font used mainly in code editor 87 FONT_STUDIO = 0x01, 88 //! Alias for bold studio font 89 FONT_STUDIO_BOLD = FONT_STUDIO | FONT_BOLD, 90 //! Alias for italic studio font (at this point not used anywhere) 91 FONT_STUDIO_ITALIC = FONT_STUDIO | FONT_ITALIC, 92 93 //! SatCom font used for interface (currently bold and italic wariants aren't used anywhere) 94 FONT_SATCOM = 0x02, 95 //! Alias for bold satcom font 96 FONT_SATCOM_BOLD = FONT_SATCOM | FONT_BOLD, 97 //! Alias for italic satcom font 98 FONT_SATCOM_ITALIC = FONT_SATCOM | FONT_ITALIC, 99 100 //! Pseudo-font loaded from textures for buttons, icons, etc. 101 FONT_BUTTON = 0x03, 102 }; 103 104 /** 105 * \enum FontTitle 106 * \brief Size of font title 107 * 108 * Used internally by CEdit 109 * 110 * Bitmask in 2 bits left shifted 4 (mask 0x030) 111 */ 112 enum FontTitle 113 { 114 FONT_TITLE_BIG = 0x01 << 4, 115 FONT_TITLE_NORM = 0x02 << 4, 116 FONT_TITLE_LITTLE = 0x03 << 4, 117 }; 118 119 /** 120 * \enum FontHighlight 121 * \brief Type of color highlight for text 122 * 123 * Bitmask in 4 bits left shifted 6 (mask 0x3c0) 124 */ 125 enum FontHighlight 126 { 127 FONT_HIGHLIGHT_NONE = 0x00 << 6, 128 FONT_HIGHLIGHT_TABLE = 0x02 << 6, //!< code background in SatCom 129 FONT_HIGHLIGHT_KEY = 0x03 << 6, //!< background for keys in documentation in SatCom 130 FONT_HIGHLIGHT_TOKEN = 0x04 << 6, //!< keywords in CBot scripts 131 FONT_HIGHLIGHT_TYPE = 0x05 << 6, //!< types in CBot scripts 132 FONT_HIGHLIGHT_CONST = 0x06 << 6, //!< constants in CBot scripts 133 FONT_HIGHLIGHT_THIS = 0x07 << 6, //!< "this" keyword in CBot scripts 134 FONT_HIGHLIGHT_COMMENT = 0x08 << 6, //!< comments in CBot scripts 135 FONT_HIGHLIGHT_KEYWORD = 0x09 << 6, //!< builtin keywords in CBot scripts 136 FONT_HIGHLIGHT_STRING = 0x0A << 6, //!< string literals in CBot scripts 137 }; 138 139 /** 140 * \enum FontMask 141 * \brief Masks in FontMetaChar for different attributes 142 */ 143 enum FontMask 144 { 145 //! Mask for FontType 146 FONT_MASK_FONT = 0x00f, 147 //! Mask for FontTitle 148 FONT_MASK_TITLE = 0x030, 149 //! Mask for FontHighlight 150 FONT_MASK_HIGHLIGHT = 0x3c0, 151 //! Mask for links 152 FONT_MASK_LINK = 0x400, 153 //! Mask for image bit (TODO: not used?) 154 FONT_MASK_IMAGE = 0x800 155 }; 156 157 158 /** 159 * \struct UTF8Char 160 * \brief UTF-8 character in font cache 161 * 162 * Only 3-byte chars are supported 163 */ 164 struct UTF8Char 165 { 166 char c1, c2, c3; 167 // Padding for 4-byte alignment 168 // It also seems to fix some problems reported by valgrind 169 char pad; 170 171 explicit UTF8Char(char ch1 = '\0', char ch2 = '\0', char ch3 = '\0') c1UTF8Char172 : c1(ch1), c2(ch2), c3(ch3), pad('\0') {} 173 174 inline bool operator<(const UTF8Char &other) const 175 { 176 if (c1 < other.c1) 177 return true; 178 else if (c1 > other.c1) 179 return false; 180 181 if (c2 < other.c2) 182 return true; 183 else if (c2 > other.c2) 184 return false; 185 186 return c3 < other.c3; 187 } 188 189 inline bool operator==(const UTF8Char &other) const 190 { 191 return c1 == other.c1 && c2 == other.c2 && c3 == other.c3; 192 } 193 }; 194 195 /** 196 * \struct CharTexture 197 * \brief Texture of font character 198 */ 199 struct CharTexture 200 { 201 unsigned int id = 0; 202 Math::IntPoint charPos; 203 Math::IntPoint charSize; 204 }; 205 206 // Definition is private - in text.cpp 207 struct CachedFont; 208 struct MultisizeFont; 209 struct FontTexture; 210 211 /** 212 * \enum SpecialChar 213 * \brief Special codes for certain characters 214 */ 215 enum SpecialChar 216 { 217 CHAR_TAB = '\t', //! Tab character - : 218 CHAR_NEWLINE = '\n', //! Newline character - arrow pointing down and left 219 CHAR_DOT = 1, //! Single dot in the middle 220 CHAR_SQUARE = 2, //! Square 221 CHAR_SKIP_RIGHT = 5, //! Filled triangle pointing right 222 CHAR_SKIP_LEFT = 6 //! Filled triangle pointing left 223 }; 224 225 /** 226 * \class CText 227 * \brief Text rendering engine 228 * 229 * CText is responsible for drawing text in 2D interface. Font rendering is done using 230 * textures generated by SDL_ttf from TTF font files. 231 * 232 * All functions rendering text are divided into two types: 233 * - single font - function takes a single FontType argument that (along with size) 234 * determines the font to be used for all characters, 235 * - multi-font - function takes the text as one argument and a std::vector of FontMetaChar 236 * with per-character formatting information (font, highlights and some other info used by CEdit) 237 * 238 * All font rendering is done in UTF-8. 239 */ 240 class CText 241 { 242 public: 243 CText(CEngine* engine); 244 virtual ~CText(); 245 246 //! Sets the device to be used 247 void SetDevice(CDevice *device); 248 249 //! Returns the last encountered error 250 std::string GetError(); 251 252 //! Initializes the font engine; must be called after SetDevice() 253 bool Create(); 254 //! Frees resources before exit 255 void Destroy(); 256 257 //! Flushes cached textures 258 void FlushCache(); 259 //! Try to load new font files 260 bool ReloadFonts(); 261 262 //@{ 263 //! Tab size management 264 void SetTabSize(int tabSize); 265 int GetTabSize(); 266 //@} 267 268 //! Draws text (multi-format) 269 void DrawText(const std::string &text, std::vector<FontMetaChar>::iterator format, 270 std::vector<FontMetaChar>::iterator end, 271 float size, Math::Point pos, float width, TextAlign align, 272 int eol, Color color = Color(0.0f, 0.0f, 0.0f, 1.0f)); 273 //! Draws text (one font) 274 void DrawText(const std::string &text, FontType font, 275 float size, Math::Point pos, float width, TextAlign align, 276 int eol, Color color = Color(0.0f, 0.0f, 0.0f, 1.0f)); 277 278 //! Calculates dimensions for text (multi-format) 279 void SizeText(const std::string &text, std::vector<FontMetaChar>::iterator format, 280 std::vector<FontMetaChar>::iterator endFormat, 281 float size, Math::Point pos, TextAlign align, 282 Math::Point &start, Math::Point &end); 283 //! Calculates dimensions for text (one font) 284 void SizeText(const std::string &text, FontType font, 285 float size, Math::Point pos, TextAlign align, 286 Math::Point &start, Math::Point &end); 287 288 //! Returns the ascent font metric 289 float GetAscent(FontType font, float size); 290 //! Returns the descent font metric 291 float GetDescent(FontType font, float size); 292 //! Returns the height font metric 293 float GetHeight(FontType font, float size); 294 int GetHeightInt(FontType font, float size); 295 296 //! Returns width of string (multi-format) 297 TEST_VIRTUAL float GetStringWidth(const std::string& text, 298 std::vector<FontMetaChar>::iterator format, 299 std::vector<FontMetaChar>::iterator end, float size); 300 //! Returns width of string (single font) 301 TEST_VIRTUAL float GetStringWidth(std::string text, FontType font, float size); 302 //! Returns width of single character 303 TEST_VIRTUAL float GetCharWidth(UTF8Char ch, FontType font, float size, float offset); 304 int GetCharWidthInt(UTF8Char ch, FontType font, float size, float offset); 305 306 //! Justifies a line of text (multi-format) 307 int Justify(const std::string &text, std::vector<FontMetaChar>::iterator format, 308 std::vector<FontMetaChar>::iterator end, 309 float size, float width); 310 //! Justifies a line of text (one font) 311 int Justify(const std::string &text, FontType font, float size, float width); 312 313 //! Returns the most suitable position to a given offset (multi-format) 314 int Detect(const std::string &text, std::vector<FontMetaChar>::iterator format, 315 std::vector<FontMetaChar>::iterator end, 316 float size, float offset); 317 //! Returns the most suitable position to a given offset (one font) 318 int Detect(const std::string &text, FontType font, float size, float offset); 319 320 UTF8Char TranslateSpecialChar(int specialChar); 321 322 CharTexture GetCharTexture(UTF8Char ch, FontType font, float size); 323 Math::IntPoint GetFontTextureSize(); 324 325 protected: 326 CachedFont* GetOrOpenFont(FontType font, float size); 327 CharTexture CreateCharTexture(UTF8Char ch, CachedFont* font); 328 FontTexture* GetOrCreateFontTexture(Math::IntPoint tileSize); 329 FontTexture CreateFontTexture(Math::IntPoint tileSize); 330 Math::IntPoint GetNextTilePos(const FontTexture& fontTexture); 331 332 void DrawString(const std::string &text, std::vector<FontMetaChar>::iterator format, 333 std::vector<FontMetaChar>::iterator end, 334 float size, Math::IntPoint pos, int width, int eol, Color color); 335 void DrawString(const std::string &text, FontType font, 336 float size, Math::IntPoint pos, int width, int eol, Color color); 337 void DrawHighlight(FontMetaChar hl, Math::IntPoint pos, Math::IntPoint size); 338 void DrawCharAndAdjustPos(UTF8Char ch, FontType font, float size, Math::IntPoint &pos, Color color); 339 void StringToUTFCharList(const std::string &text, std::vector<UTF8Char> &chars); 340 void StringToUTFCharList(const std::string &text, std::vector<UTF8Char> &chars, std::vector<FontMetaChar>::iterator format, std::vector<FontMetaChar>::iterator end); 341 342 int GetCharSizeAt(Gfx::FontType font, const std::string& text, unsigned int index) const; 343 344 protected: 345 CEngine* m_engine; 346 CDevice* m_device; 347 348 std::string m_error; 349 float m_defaultSize; 350 int m_tabSize; 351 352 std::map<FontType, std::unique_ptr<MultisizeFont>> m_fonts; 353 std::vector<FontTexture> m_fontTextures; 354 355 FontType m_lastFontType; 356 int m_lastFontSize; 357 CachedFont* m_lastCachedFont; 358 359 class CQuadBatch; 360 std::unique_ptr<CQuadBatch> m_quadBatch; 361 }; 362 363 364 } // namespace Gfx 365