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
39class CStdFont
40{
41public:
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
57public:
58 int id; // used by the engine to keep track of where the font came from
59
60protected:
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
112public:
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