| 1 | /* |
| 2 | * LegacyClonk |
| 3 | * |
| 4 | * Copyright (c) RedWolf Design |
| 5 | * Copyright (c) 2003, Sven2 |
| 6 | * Copyright (c) 2017-2021, The LegacyClonk Team and contributors |
| 7 | * |
| 8 | * Distributed under the terms of the ISC license; see accompanying file |
| 9 | * "COPYING" for details. |
| 10 | * |
| 11 | * "Clonk" is a registered trademark of Matthes Bender, used with permission. |
| 12 | * See accompanying file "TRADEMARK" for details. |
| 13 | * |
| 14 | * To redistribute this file separately, substitute the full license texts |
| 15 | * for the above references. |
| 16 | */ |
| 17 | |
| 18 | // text drawing facility for CStdDDraw |
| 19 | |
| 20 | #pragma once |
| 21 | |
| 22 | #include "C4Facet.h" |
| 23 | #include "C4ForwardDeclarations.h" |
| 24 | #include "C4Strings.h" |
| 25 | |
| 26 | #include <cstdint> |
| 27 | #include <map> |
| 28 | |
| 29 | // Font rendering flags |
| 30 | #define STDFONT_CENTERED 0x0001 |
| 31 | #define STDFONT_RIGHTALGN 0x0008 |
| 32 | #define STDFONT_NOMARKUP 0x0020 |
| 33 | |
| 34 | #ifndef FW_NORMAL |
| 35 | #define FW_NORMAL 400 |
| 36 | #define FW_BOLD 700 |
| 37 | #endif |
| 38 | |
| 39 | class CStdFont |
| 40 | { |
| 41 | public: |
| 42 | // callback class to allow custom images |
| 43 | class CustomImages |
| 44 | { |
| 45 | protected: |
| 46 | virtual bool GetFontImage(const char *szImageTag, C4Facet &rOutImgFacet) = 0; |
| 47 | |
| 48 | friend class CStdFont; |
| 49 | |
| 50 | public: |
| 51 | virtual ~CustomImages() {} |
| 52 | }; |
| 53 | static CStdVectorFont *CreateFont(const StdBuf &Data); |
| 54 | static CStdVectorFont *CreateFont(const char *szFaceName); |
| 55 | static void DestroyFont(CStdVectorFont *pFont); |
| 56 | |
| 57 | public: |
| 58 | int id; // used by the engine to keep track of where the font came from |
| 59 | |
| 60 | protected: |
| 61 | uint32_t dwDefFontHeight; // configured font size (in points) |
| 62 | char szFontName[80 + 1]; // used font name (or surface file name) |
| 63 | |
| 64 | bool fPrerenderedFont; // true for fonts that came from a prerendered bitmap surface - no runtime adding of characters |
| 65 | C4Surface **psfcFontData; // font recource surfaces - additional surfaces created as needed |
| 66 | int iNumFontSfcs; // number of created font surfaces |
| 67 | int iSfcSizes; // size for font surfaces |
| 68 | int iFontZoom; // zoom of font in texture |
| 69 | |
| 70 | bool fUTF8; // if set, UTF8-characters are decoded |
| 71 | |
| 72 | C4Surface *sfcCurrent; // current surface font data can be written to at runtime |
| 73 | int32_t iCurrentSfcX, iCurrentSfcY; // current character rendering position |
| 74 | |
| 75 | int iHSpace; // horizontal space to be added betwen two characters |
| 76 | int iGfxLineHgt; // height of chaacters; may be larger than line height |
| 77 | uint32_t dwWeight; // font weight (usually FW_NORMAL or FW_BOLD) |
| 78 | bool fDoShadow; // if the font is shadowed |
| 79 | |
| 80 | C4Facet fctAsciiTexCoords[256 - ' ']; // texture coordinates of ASCII letters |
| 81 | std::map<uint32_t, C4Facet> fctUnicodeMap; // texture coordinates of Unicode letters |
| 82 | |
| 83 | CustomImages *pCustomImages; // callback class for custom images |
| 84 | |
| 85 | #ifdef HAVE_FREETYPE |
| 86 | CStdVectorFont *pVectorFont; // class assumed to be held externally! |
| 87 | #endif |
| 88 | |
| 89 | bool AddSurface(); |
| 90 | bool CheckRenderedCharSpace(uint32_t iCharWdt, uint32_t iCharHgt); |
| 91 | bool AddRenderedChar(uint32_t dwChar, C4Facet *pfctTarget); |
| 92 | |
| 93 | // get a character at the current string pos and advance pos by that character |
| 94 | inline uint32_t GetNextCharacter(const char **pszString) |
| 95 | { |
| 96 | unsigned char c = **pszString; |
| 97 | if (!fUTF8 || c < 128) { ++*pszString; return c; } |
| 98 | else return GetNextUTF8Character(pszString); |
| 99 | } |
| 100 | |
| 101 | uint32_t GetNextUTF8Character(const char **pszString); |
| 102 | |
| 103 | C4Facet &GetCharacterFacet(uint32_t c) |
| 104 | { |
| 105 | if (!fUTF8 || c < 128) return fctAsciiTexCoords[c - ' ']; else return GetUnicodeCharacterFacet(c); |
| 106 | } |
| 107 | |
| 108 | C4Facet &GetUnicodeCharacterFacet(uint32_t c); |
| 109 | int iLineHgt; // height of one line of font (in pixels) |
| 110 | float scale = 1.f; |
| 111 | |
| 112 | public: |
| 113 | // draw ine line of text |
| 114 | void DrawText(C4Surface *sfcDest, int iX, int iY, uint32_t dwColor, const char *szText, uint32_t dwFlags, CMarkup &Markup, float fZoom); |
| 115 | |
| 116 | // get text size |
| 117 | bool GetTextExtent(const char *szText, int32_t &rsx, int32_t &rsy, bool fCheckMarkup = true, bool ignoreScale = false); |
| 118 | // get height of a line |
| 119 | int GetLineHeight() const; |
| 120 | // Sometimes, only the width of a text is needed |
| 121 | int32_t GetTextWidth(const char *szText, bool fCheckMarkup = true) { int32_t x, y; GetTextExtent(szText, rsx&: x, rsy&: y, fCheckMarkup); return x; } |
| 122 | // insert line breaks into a message and return overall height - uses and regards '|' as line breaks; maxLines = 0 means unlimited |
| 123 | int BreakMessage(const char *szMsg, int iWdt, StdStrBuf *pOut, bool fCheckMarkup, float fZoom = 1.0f, size_t maxLines = 0); |
| 124 | |
| 125 | CStdFont(); |
| 126 | ~CStdFont() { Clear(); } |
| 127 | |
| 128 | // function throws std::runtime_error in case of failure |
| 129 | // font initialization - writes the surface data |
| 130 | void Init(CStdVectorFont &VectorFont, uint32_t dwHeight, uint32_t dwFontWeight = FW_NORMAL, const char *szCharset = "" , bool fDoShadow = true, float scale = 1.f); |
| 131 | |
| 132 | // font initialization - grabs the given surface data and extracts character sizes from it |
| 133 | void Init(const char *szFontName, C4Surface *psfcFontSfc, int iIndent); |
| 134 | |
| 135 | void Clear(); // clear font |
| 136 | |
| 137 | // query whether font is initialized |
| 138 | bool IsInitialized() { return !!*szFontName; } |
| 139 | |
| 140 | // query whether font is already initialized with certain data |
| 141 | bool IsSameAsID(const char *szCFontName, int iCID, int iCIndent) |
| 142 | { |
| 143 | return SEqual(szStr1: szCFontName, szStr2: szFontName) && iCID == id && iCIndent == -iHSpace; |
| 144 | } |
| 145 | |
| 146 | bool IsSameAs(const char *szCFontName, uint32_t iCHeight, uint32_t dwCWeight) |
| 147 | { |
| 148 | return SEqual(szStr1: szCFontName, szStr2: szFontName) && !id && iCHeight == dwDefFontHeight && dwCWeight == dwWeight; |
| 149 | } |
| 150 | |
| 151 | // set custom image request handler |
| 152 | void SetCustomImages(CustomImages *pHandler) |
| 153 | { |
| 154 | pCustomImages = pHandler; |
| 155 | } |
| 156 | }; |
| 157 | |