1 /////////////////////////////////////////////////////////////////////////////// 2 // Copyright (C) 2004-2011 by The Allacrost Project 3 // Copyright (C) 2012-2016 by Bertram (Valyria Tear) 4 // All Rights Reserved 5 // 6 // This code is licensed under the GNU GPL version 2. It is free software 7 // and you may modify it and/or redistribute it under the terms of this license. 8 // See http://www.gnu.org/copyleft/gpl.html for details. 9 /////////////////////////////////////////////////////////////////////////////// 10 11 /** **************************************************************************** 12 *** \file text.h 13 *** \author Lindsay Roberts, linds@allacrost.org 14 *** \author Yohann Ferreira, yohann ferreira orange fr 15 *** \brief Header file for text rendering 16 *** 17 *** This code makes use of the SDL_ttf font library for representing fonts, 18 *** font glyphs, and text. 19 *** ***************************************************************************/ 20 21 #ifndef __TEXT_HEADER__ 22 #define __TEXT_HEADER__ 23 24 #include "engine/video/image.h" 25 26 #include "utils/singleton.h" 27 #include "utils/ustring.h" 28 29 #include <map> 30 31 typedef struct _TTF_Font TTF_Font; 32 33 namespace vt_video 34 { 35 36 class TextSupervisor; 37 38 //! \brief The singleton pointer for the instance of the text supervisor 39 extern TextSupervisor *TextManager; 40 41 42 //! \brief Styles for setting the type of text shadows. 43 enum TEXT_SHADOW_STYLE { 44 VIDEO_TEXT_SHADOW_INVALID = -1, 45 46 //! \brief No text shadow is drawn, even if shadows are enabled. 47 VIDEO_TEXT_SHADOW_NONE = 0, 48 //! \brief Shadowed area is darkened (this is the default). 49 VIDEO_TEXT_SHADOW_DARK = 1, 50 //! \brief Shadowed area is lightened. 51 VIDEO_TEXT_SHADOW_LIGHT = 2, 52 //! \brief Shadowed area is completely black. 53 VIDEO_TEXT_SHADOW_BLACK = 3, 54 //! \brief Shadowed area is the same color of the text, but has less alpha. 55 VIDEO_TEXT_SHADOW_COLOR = 4, 56 //! \brief Shadowed area is the inverse of the text's color (e.g. white text, black shadow). 57 VIDEO_TEXT_SHADOW_INVCOLOR = 5, 58 59 VIDEO_TEXT_SHADOW_TOTAL = 6 60 }; 61 62 /** **************************************************************************** 63 *** \brief A class which holds properties about fonts 64 *** ***************************************************************************/ 65 class FontProperties 66 { 67 public: 68 FontProperties(); 69 ~FontProperties(); 70 71 //! \brief Clears out the font object. 72 //! Useful when changing a TextStyle font without deleting 73 //! the font properties object. 74 void ClearFont(); 75 76 //! \brief The maximum height of all of the glyphs for this font. 77 int32_t height; 78 79 //! \brief SDL_ttf's recommended amount of spacing between lines. 80 int32_t line_skip; 81 82 //! \brief The height above and below baseline of font 83 int32_t ascent, descent; 84 85 //! \brief A pointer to SDL_TTF's font structure. 86 TTF_Font* ttf_font; 87 88 //! \brief Used to know the font currently used. 89 std::string font_filename; 90 91 //! \brief Used to know the font size currently used. 92 uint32_t font_size; 93 94 private: 95 //! \brief The copy constructor and assignment operator are hidden by design 96 //! to cause compilation errors when attempting to copy or assign this class. 97 FontProperties(const FontProperties& font_properties); 98 FontProperties& operator=(const FontProperties& font_properties); 99 }; 100 101 /** **************************************************************************** 102 *** \brief A class encompassing all properties that define a text style 103 *** 104 *** The TextSupervisor class maintains a TextStyle object that serves as the 105 *** default style. The various constructors for the TextStyle class will use the 106 *** properties of the default text style when they are not provided with the 107 *** information to initialize all of the class members. 108 *** ***************************************************************************/ 109 class TextStyle 110 { 111 public: 112 //! \brief No-arg constructor will set all members to the same value as the current default text style. 113 //! Special empty TextStyle to permit a default initialization in the TextSupervisor. TextStyle()114 TextStyle(): 115 _shadow_style(VIDEO_TEXT_SHADOW_NONE), 116 _shadow_offset_x(0), 117 _shadow_offset_y(0), 118 _font_property(nullptr) 119 { 120 } 121 122 //! \brief Constructor requiring a font name only. 123 explicit TextStyle(const std::string& font); 124 125 //! \brief Constructor requiring a text color only. 126 explicit TextStyle(const Color& color); 127 128 //! \brief Constructor requiring a shadow style only. 129 explicit TextStyle(TEXT_SHADOW_STYLE style); 130 131 //! \brief Constructor requiring a font name and text color. 132 TextStyle(const std::string& font, const Color& color); 133 134 //! \brief Constructor requiring a font name and shadow style. 135 TextStyle(const std::string& font, TEXT_SHADOW_STYLE style); 136 137 //! \brief Constructor requiring a text color and shadow style. 138 TextStyle(const Color& color, TEXT_SHADOW_STYLE style); 139 140 //! \brief Constructor requiring a font name, color, and shadow style. 141 TextStyle(const std::string& font, const Color& color, TEXT_SHADOW_STYLE style); 142 143 //! \brief Full constructor requiring initialization data arguments for all class members. 144 TextStyle(const std::string& font, const Color& color, TEXT_SHADOW_STYLE style, int32_t shadow_x, int32_t shadow_y); 145 146 //! \brief Sets the font name and updates the font properties. 147 void SetFont(const std::string& font); 148 149 //! \brief Sets the font name and updates the font properties. SetColor(const Color & color)150 void SetColor(const Color& color) { 151 _color = color; 152 _UpdateTextShadowColor(); 153 } 154 155 //! \brief Sets the shadow style. SetShadowStyle(TEXT_SHADOW_STYLE shadow_style)156 void SetShadowStyle(TEXT_SHADOW_STYLE shadow_style) { 157 _shadow_style = shadow_style; 158 _UpdateTextShadowColor(); 159 } 160 161 //! \brief Sets the shadow offsets from the given text. SetShadowOffsets(int32_t xoffset,int32_t yoffset)162 void SetShadowOffsets(int32_t xoffset, int32_t yoffset) { 163 _shadow_offset_x = xoffset; 164 _shadow_offset_y = yoffset; 165 } 166 167 //! \brief Returns the font property pointer value. GetFontProperties()168 FontProperties* GetFontProperties() const { 169 return _font_property; 170 } 171 GetFontName()172 const std::string& GetFontName() const { 173 return _font; 174 } 175 GetColor()176 const Color& GetColor() const { 177 return _color; 178 } 179 GetShadowColor()180 const Color& GetShadowColor() const { 181 return _shadow_color; 182 } 183 GetShadowStyle()184 TEXT_SHADOW_STYLE GetShadowStyle() const { 185 return _shadow_style; 186 } 187 GetShadowOffsetX()188 int32_t GetShadowOffsetX() const { 189 return _shadow_offset_x; 190 } 191 GetShadowOffsetY()192 int32_t GetShadowOffsetY() const { 193 return _shadow_offset_y; 194 } 195 196 private: 197 //! \brief The string font name 198 std::string _font; 199 200 //! \brief The color of the text 201 Color _color; 202 203 //! \brief The enum representing the shadow style. 204 TEXT_SHADOW_STYLE _shadow_style; 205 //! \brief The shadow color corresponding to the current color and shadow style. 206 Color _shadow_color; 207 208 //! \brief The x and y offsets of the shadow. 209 int32_t _shadow_offset_x; 210 int32_t _shadow_offset_y; 211 212 //! \brief A pointer to the FontProperty object. 213 //! This acts as reference cache, thus it must not be deleted here! 214 FontProperties* _font_property; 215 216 //! \brief Updates the shadow color to correspond to the current color and shadow style. 217 void _UpdateTextShadowColor(); 218 }; 219 220 namespace private_video 221 { 222 223 /** **************************************************************************** 224 *** \brief Represents an image of rendered text stored in a texture sheet 225 *** 226 *** A text specific class derived from the BaseImage class, it contains a 227 *** unicode string and text style needed to render a piece of text. 228 *** ***************************************************************************/ 229 class TextTexture : public private_video::BaseTexture 230 { 231 public: 232 /** \brief Constructor defaults image as the first one in a texture sheet. 233 *** \note The actual sheet where the image is located will be determined later. 234 **/ 235 TextTexture(const vt_utils::ustring &string_, const TextStyle &style_); 236 237 ~TextTexture(); 238 239 // ---------- Public members 240 241 //! \brief The string represented 242 vt_utils::ustring string; 243 244 //! \brief The text style of the rendered string 245 TextStyle style; 246 247 // ---------- Public methods 248 249 //! \brief Generate a text texture and add to a texture sheet 250 bool Regenerate(); 251 252 //! \brief Reload texture to an already assigned texture sheet 253 bool Reload(); 254 255 private: 256 TextTexture(const TextTexture ©); 257 TextTexture &operator=(const TextTexture ©); 258 }; // class TextTexture : public private_video::BaseImage 259 260 261 /** **************************************************************************** 262 *** \brief An element used as a portion of a full rendered block of text. 263 *** 264 *** This class represents a block (usually a single line) of rendered text that 265 *** is stored by the TextImage class as a portion, or element, that makes up 266 *** a rendered block of text. This class managed a pointer to a TextTexture 267 *** object that refers to the rendered line of text as it is stored in texture 268 *** memory. 269 *** ***************************************************************************/ 270 class TextElement : public ImageDescriptor 271 { 272 public: 273 TextElement(); 274 275 explicit TextElement(TextTexture* texture); 276 277 virtual ~TextElement() override; 278 279 // ---------- Public members 280 281 //! \brief The image that is being referenced by this object. 282 TextTexture *text_texture; 283 284 // ---------- Public methods 285 286 void Clear() override; 287 288 void Draw() const; 289 290 void Draw(const Color& draw_color) const override; 291 292 /** \brief Sets the texture used by the class and modifies the width and height members 293 *** \param texture A pointer to the TextTexture object that this class object should manage 294 *** 295 *** Because it is rare that the user needs to define a custom width/height for the text (since 296 *** scaled text looks so poor), this function also automatically sets the _width and _height members 297 *** to the translated value of the width and height of the TextTexture in the current coordinate system 298 *** (current context) in which this function call is made. Passing a nullptr argument will deallocate any 299 *** texture resources and set the width/height to zero. 300 *** 301 *** \note This function will invoke the AddReference() method for the argument object if it is not nullptr. 302 **/ 303 void SetTexture(TextTexture *texture); 304 SetStatic(bool is_static)305 void SetStatic(bool is_static) override { 306 _is_static = is_static; 307 } 308 SetWidth(float width)309 void SetWidth(float width) override { 310 _width = width; 311 } 312 SetHeight(float height)313 void SetHeight(float height) override { 314 _height = height; 315 } 316 SetDimensions(float width,float height)317 void SetDimensions(float width, float height) override { 318 SetWidth(width); 319 SetHeight(height); 320 } 321 322 private: _EnableGrayscale()323 void _EnableGrayscale() override 324 {} 325 _DisableGrayscale()326 void _DisableGrayscale() override 327 {} 328 }; 329 330 } // namespace private_video 331 332 /** **************************************************************************** 333 *** \brief Represents a rendered text string 334 *** TextImage is a compound image containing each line of a text string. 335 *** ***************************************************************************/ 336 class TextImage : public ImageDescriptor 337 { 338 friend class VideoEngine; 339 public: 340 //! \brief Construct empty text object 341 TextImage(); 342 343 //! \brief Constructs rendered string of specified ustring 344 explicit TextImage(const vt_utils::ustring& text, const TextStyle& style = TextStyle()); 345 346 //! \brief Constructs rendered string of specified std::string 347 explicit TextImage(const std::string& text, const TextStyle& style = TextStyle()); 348 349 //! \brief Destructs TextImage, lowering reference counts on all contained timages. ~TextImage()350 virtual ~TextImage() override { 351 Clear(); 352 } 353 354 TextImage(const TextImage ©); 355 TextImage &operator=(const TextImage ©); 356 357 // ---------- Public methods 358 359 //! \brief Clears the image by resetting its properties 360 void Clear() override; 361 362 /** \brief Draws the rendered text to the screen with a color modulation 363 *** \param draw_color The color to modulate the text by 364 **/ 365 void Draw(const Color &draw_color = vt_video::Color::white) const override; 366 367 //! \brief Sets image to static/animated SetStatic(bool is_static)368 virtual void SetStatic(bool is_static) override { 369 _is_static = is_static; 370 } 371 372 //! \brief Sets width of the image SetWidth(float width)373 virtual void SetWidth(float width) override { 374 _width = width; 375 } 376 377 //! \brief Sets height of the image SetHeight(float height)378 virtual void SetHeight(float height) override { 379 _height = height; 380 } 381 382 //! \brief Sets the dimensions (width + height) of the image. SetDimensions(float width,float height)383 virtual void SetDimensions(float width, float height) override { 384 _width = width; 385 _height = height; 386 } 387 388 //! \brief Sets the color for the image (for all four verteces). SetColor(const Color & color)389 void SetColor(const Color &color) override { 390 _color[0] = _color[1] = _color[2] = _color[3] = color; 391 } 392 393 /** \brief Sets individual vertex colors in the image. 394 *** \param tl top left vertex color 395 *** \param tr top right vertex color 396 *** \param bl bottom left vertex color 397 *** \param br bottom right vertex color 398 **/ SetVertexColors(const Color & tl,const Color & tr,const Color & bl,const Color & br)399 void SetVertexColors(const Color& tl, const Color& tr, const Color& bl, const Color& br) override { 400 _color[0] = tl; 401 _color[1] = tr; 402 _color[2] = bl; 403 _color[3] = br; 404 } 405 406 //! \brief Sets the text contained SetText(const vt_utils::ustring & text)407 void SetText(const vt_utils::ustring& text) { 408 // Don't do anything if it's the same text 409 if (_text == text) 410 return; 411 412 _text = text; 413 _Regenerate(); 414 } 415 SetText(const vt_utils::ustring & text,const TextStyle & text_style)416 void SetText(const vt_utils::ustring& text, const TextStyle& text_style) { 417 _text = text; 418 _style = text_style; 419 _Regenerate(); 420 } 421 422 //! \brief Sets the text (std::string version) SetText(const std::string & text)423 void SetText(const std::string& text) { 424 SetText(vt_utils::MakeUnicodeString(text)); 425 } 426 427 //! \brief Sets the texts style - regenerating text if present. SetStyle(const TextStyle & style)428 void SetStyle(const TextStyle& style) { 429 _style = style; 430 _Regenerate(); 431 } 432 SetText(const std::string & text,const TextStyle & text_style)433 void SetText(const std::string& text, const TextStyle& text_style) { 434 SetText(vt_utils::MakeUnicodeString(text), text_style); 435 } 436 437 //! \brief Set the maximum permitted width to the text image 438 //! It will auto wrap and use more height intead when modified. 439 void SetWordWrapWidth(uint32_t width); 440 441 //! \name Class Member Access Functions 442 //@{ GetString()443 const vt_utils::ustring& GetString() const { 444 return _text; 445 } 446 GetStyle()447 TextStyle GetStyle() const { 448 return _style; 449 } 450 GetWidth()451 virtual float GetWidth() const override { 452 return _width; 453 } 454 GetWordWrapWidth()455 uint32_t GetWordWrapWidth() const { 456 return _max_width; 457 } 458 //@} 459 460 private: 461 //! \brief The unicode string of the text to render 462 vt_utils::ustring _text; 463 464 //! \brief The style to render the text in 465 TextStyle _style; 466 467 //! \brief The text max width, used for word wrapping 468 uint32_t _max_width; 469 470 //! \brief The TextTexture elements representing rendered text portions, usually lines. 471 std::vector<private_video::TextElement *> _text_sections; 472 473 // ---------- Private methods 474 475 //! \brief Regenerates the texture images for the text 476 void _Regenerate(); 477 478 //! \brief Dervied from ImageDescriptor, this method is not used by TextImage _EnableGrayscale()479 void _EnableGrayscale() override 480 {} 481 482 //! \brief Dervied from ImageDescriptor, this method is not used by TextImage _DisableGrayscale()483 void _DisableGrayscale() override 484 {} 485 }; 486 487 488 /** **************************************************************************** 489 *** \brief A helper class to the video engine to manage all text rendering 490 *** 491 *** This class is a singleton and it is both created and destroyed by the VideoEngine 492 *** class. TextSupervisor is essentially an extension of the VideoEngine singleton 493 *** class which handles all font and text related operations. 494 *** 495 *** \note The singleton name of this class is "TextManager" 496 *** 497 *** \note When the API user needs to access methods of this class, the recommended 498 *** way for doing so is to call "VideoManager->Text()->MethodName()". 499 *** VideoManager->Text() returns the singleton pointer to this class. 500 *** ***************************************************************************/ 501 class TextSupervisor : public vt_utils::Singleton<TextSupervisor> 502 { 503 friend class vt_utils::Singleton<TextSupervisor>; 504 friend class VideoEngine; 505 friend class TextureController; 506 friend class private_video::TextTexture; 507 friend class TextImage; 508 friend class TextStyle; 509 510 public: 511 ~TextSupervisor(); 512 513 /** \brief Initializes the SDL_ttf library 514 *** \return True if all initializations were successful, or false if there was an error 515 **/ 516 bool SingletonInitialize(); 517 518 /** \brief Loads or reloads font needed by the given locale (ex: fr, it, ru, ...) 519 *** using the font script filename: "data/config/fonts.lua" 520 *** \return false in case of an error. 521 **/ 522 bool LoadFonts(const std::string& locale_name); 523 //@} 524 525 //! \name Text methods 526 //@{ 527 /** \brief Renders and draws a unicode string of text to the screen in the default text style 528 *** \param text The text string to draw in unicode format 529 **/ Draw(const vt_utils::ustring & text)530 inline void Draw(const vt_utils::ustring &text) { 531 Draw(text, _default_style); 532 } 533 534 /** \brief Renders and draws a string of text to the screen in a desired text style 535 *** \param text The text string to draw in unicode format 536 *** \param style A reference to the TextStyle to use for drawing the string 537 **/ 538 void Draw(const vt_utils::ustring &text, const TextStyle &style); 539 540 /** \brief Renders and draws a standard string of text to the screen in the default text style 541 *** \param text The text string to draw in standard format 542 **/ Draw(const std::string & text)543 inline void Draw(const std::string &text) { 544 Draw(vt_utils::MakeUnicodeString(text)); 545 } 546 547 /** \brief Renders and draws a standard string of text to the screen in a desired text style 548 *** \param text The text string to draw in standard format 549 *** \param style A reference to the TextStyle to use for drawing the string 550 **/ Draw(const std::string & text,const TextStyle & style)551 inline void Draw(const std::string &text, const TextStyle &style) { 552 Draw(vt_utils::MakeUnicodeString(text), style); 553 } 554 555 /** \brief Calculates what the width would be for a unicode string of text if it were rendered 556 *** \param ttf_font The True Type SDL font object 557 *** \param text The text string in unicode format 558 *** \return The width of the text as it would be rendered, or -1 if there was an error 559 **/ 560 int32_t CalculateTextWidth(TTF_Font* ttf_font, const vt_utils::ustring& text); 561 562 /** \brief Calculates what the width would be for a standard string of text if it were rendered 563 *** \param ttf_font The True Type SDL font object 564 *** \param text The text string in standard format 565 *** \return The width of the text as it would be rendered, or -1 if there was an error 566 **/ 567 int32_t CalculateTextWidth(TTF_Font* ttf_font, const std::string& text); 568 569 /** \brief Returns the text as a vector of lines which text width is inferior or equal to the given pixel max width. 570 *** \param text The ustring text 571 *** \param ttf_font The True Type SDL font object 572 **/ 573 std::vector<vt_utils::ustring> WrapText(const vt_utils::ustring& text, TTF_Font* ttf_font, uint32_t max_width); 574 //@} 575 576 //! \name Class member access methods 577 //@{ GetDefaultStyle()578 const TextStyle &GetDefaultStyle() const { 579 return _default_style; 580 } 581 SetDefaultStyle(const TextStyle & style)582 void SetDefaultStyle(const TextStyle& style) { 583 _default_style = style; 584 } 585 //@} 586 587 private: 588 TextSupervisor(); 589 590 // ---------- Private members 591 592 //! \brief A texture used to draw text to the screen. 593 GLuint _text_texture; 594 595 //! \brief The text texture's width. 596 GLuint _text_texture_width; 597 598 //! \brief The text texture's height. 599 GLuint _text_texture_height; 600 601 //! \brief The default text style 602 TextStyle _default_style; 603 604 /** \brief A container for properties for each font which has been loaded 605 *** The key to the map is the font name. 606 **/ 607 std::map<std::string, FontProperties *> _font_map; 608 609 /** \brief Loads or Reloads a font file from disk with a specific size and name 610 *** \param Text style name The name which to refer to the text style after it is loaded 611 *** \param font_filename The filename of the TTF font filename to load 612 *** \param size The point size to set the font after it is loaded 613 *** \return True if the font was successfully loaded, or false if there was an error 614 **/ 615 bool _LoadFont(const std::string& textstyle_name, const std::string& font_filename, uint32_t size); 616 617 /** \brief Removes a loaded font from memory and frees up associated resources 618 *** \param font_name The reference name of the font to unload 619 *** 620 *** If the argument name is invalid (i.e. no font with that reference name exists), this method will do 621 *** nothing more than print out a warning message if running in debug mode. 622 *** 623 *** \todo Implement this function. Its not available yet because of potential problems with lingering references to the 624 *** font (in TextStyle objects, or elswhere) 625 **/ 626 void _FreeFont(const std::string &font_name); 627 628 /** \brief Renders a unicode string to the screen. 629 *** \param text A pointer to a unicode string to draw. 630 *** \param font_properties A pointer to the properties of the font to use in drawing the text. 631 *** \param color The color to render the text in. 632 *** 633 *** This method is intended for drawing only a single line of text. 634 **/ 635 void _RenderText(const uint16_t* text, FontProperties* font_properties, const Color& color); 636 637 /** \brief Renders a unicode, shadowed string to the screen. 638 *** \param text A pointer to a unicode string to draw. 639 *** \param font_properties A pointer to the properties of the font to use in drawing the text. 640 *** \param color The color to render the text in. 641 *** \param shadow_offset_x The X offset for the text's shadow. 642 *** \param shadow_offset_y The Y offset for the text's shadow. 643 *** \param color_shadow The color to render the text's shadow in. 644 *** 645 *** This method is intended for drawing only a single line of text. 646 **/ 647 void _RenderText(const uint16_t* text, FontProperties* font_properties, 648 const Color& color, 649 float shadow_offset_x, float shadow_offset_y, 650 const Color& color_shadow); 651 652 /** \brief Renders a unicode string to a pixel array. 653 *** \param text The unicdoe string to render. 654 *** \param style The text style to render the string in. 655 *** \param buffer A reference to the pixel array where to place the rendered string into. 656 *** \return True if the string was rendered successfully, or false if it was not. 657 **/ 658 bool _RenderText(const vt_utils::ustring& text, TextStyle& style, private_video::ImageMemory& buffer); 659 660 /** \brief Returns true if a font of a certain reference name exists 661 *** \param font_name The reference name of the font to check 662 *** \return True if font name is valid, false if it is not. 663 **/ _IsFontValid(const std::string & font_name)664 bool _IsFontValid(const std::string& font_name) { 665 return (_font_map.find(font_name) != _font_map.end()); 666 } 667 668 /** \brief Get the font properties for a loaded font 669 *** \param font_name The name reference of the loaded font 670 *** \return A pointer to the FontProperties object with the requested data, or nullptr if the properties could not be fetched 671 **/ 672 FontProperties* _GetFontProperties(const std::string& font_name); 673 }; // class TextSupervisor : public vt_utils::Singleton 674 675 } // namespace vt_video 676 677 #endif // __TEXT_HEADER__ 678