1 #include <stdarg.h>
2 #include "HImage.h"
3 #include "Local.h"
4 #include "Types.h"
5 #include "MemMan.h"
6 #include "Font.h"
7 #include "Debug.h"
8 #include "TranslationTable.h"
9 #include "VSurface.h"
10 #include "VObject.h"
11 #include "VObject_Blitters.h"
12 #include "UILayout.h"
13 #include "GameRes.h"
14 #include "Logger.h"
15
16 typedef UINT8 GlyphIdx;
17
18
19 // Destination printing parameters
20 SGPFont FontDefault = 0;
21 static SGPVSurface* FontDestBuffer;
22 static SGPRect FontDestRegion = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
23 static UINT16 FontForeground16 = 0;
24 static UINT16 FontBackground16 = 0;
25 static UINT16 FontShadow16 = DEFAULT_SHADOW;
26
27 // Temp, for saving printing parameters
28 static SGPFont SaveFontDefault = 0;
29 static SGPVSurface* SaveFontDestBuffer = NULL;
30 static SGPRect SaveFontDestRegion = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
31 static UINT16 SaveFontForeground16 = 0;
32 static UINT16 SaveFontShadow16 = 0;
33 static UINT16 SaveFontBackground16 = 0;
34
35
36 /* Sets both the foreground and the background colors of the current font. The
37 * top byte of the parameter word is the background color, and the bottom byte
38 * is the foreground. */
SetFontColors(UINT16 usColors)39 void SetFontColors(UINT16 usColors)
40 {
41 UINT8 ubForeground = usColors & 0xFF;
42 UINT8 ubBackground = (usColors >> 8) & 0xFF;
43
44 SetFontForeground(ubForeground);
45 SetFontBackground(ubBackground);
46 }
47
48
49 /* Sets the foreground color of the currently selected font. The parameter is
50 * the index into the 8-bit palette. In 16BPP mode, the RGB values from the
51 * palette are used to create the pixel color. Note that if you change fonts,
52 * the selected foreground/background colors will stay at what they are
53 * currently set to. */
SetFontForeground(UINT8 ubForeground)54 void SetFontForeground(UINT8 ubForeground)
55 {
56 if (!FontDefault) return;
57 const SGPPaletteEntry* const c = &FontDefault->Palette()[ubForeground];
58 FontForeground16 = Get16BPPColor(FROMRGB(c->r, c->g, c->b));
59 }
60
61
SetFontShadow(UINT8 ubShadow)62 void SetFontShadow(UINT8 ubShadow)
63 {
64 if (!FontDefault) return;
65 const SGPPaletteEntry* const c = &FontDefault->Palette()[ubShadow];
66 FontShadow16 = Get16BPPColor(FROMRGB(c->r, c->g, c->b));
67
68 if (ubShadow != 0 && FontShadow16 == 0) FontShadow16 = 1;
69 }
70
71
72 /* Sets the Background color of the currently selected font. The parameter is
73 * the index into the 8-bit palette. In 16BPP mode, the RGB values from the
74 * palette are used to create the pixel color. If the background value is zero,
75 * the background of the font will be transparent. Note that if you change
76 * fonts, the selected foreground/background colors will stay at what they are
77 * currently set to. */
SetFontBackground(UINT8 ubBackground)78 void SetFontBackground(UINT8 ubBackground)
79 {
80 if (!FontDefault) return;
81 const SGPPaletteEntry* const c = &FontDefault->Palette()[ubBackground];
82 FontBackground16 = Get16BPPColor(FROMRGB(c->r, c->g, c->b));
83 }
84
85
86 /* Loads a font from an ETRLE file */
LoadFontFile(const char * filename)87 SGPFont LoadFontFile(const char *filename)
88 {
89 SGPFont const font = AddVideoObjectFromFile(filename);
90 if (!FontDefault) FontDefault = font;
91 return font;
92 }
93
94
95 /* Deletes the video object of a particular font. Frees up the memory and
96 * resources allocated for it. */
UnloadFont(SGPFont const font)97 void UnloadFont(SGPFont const font)
98 {
99 Assert(font);
100 DeleteVideoObject(font);
101 }
102
103
104 /* Returns the width of a given character in the font. */
GetWidth(HVOBJECT const hSrcVObject,GlyphIdx const ssIndex)105 static UINT32 GetWidth(HVOBJECT const hSrcVObject, GlyphIdx const ssIndex)
106 {
107 // Get Offsets from Index into structure
108 ETRLEObject const& pTrav = hSrcVObject->SubregionProperties(ssIndex);
109 return pTrav.usWidth + pTrav.sOffsetX;
110 }
111
112
113 /* Returns the length of a string in pixels, depending on the font given. */
StringPixLength(const ST::utf32_buffer & codepoints,SGPFont font)114 INT16 StringPixLength(const ST::utf32_buffer& codepoints, SGPFont font)
115 {
116 UINT32 w = 0;
117 for (char32_t c : codepoints)
118 {
119 w += GetCharWidth(font, c);
120 }
121 return w;
122 }
123
124
125 /* Saves the current font printing settings into temporary locations. */
SaveFontSettings(void)126 void SaveFontSettings(void)
127 {
128 SaveFontDefault = FontDefault;
129 SaveFontDestBuffer = FontDestBuffer;
130 SaveFontDestRegion = FontDestRegion;
131 SaveFontForeground16 = FontForeground16;
132 SaveFontShadow16 = FontShadow16;
133 SaveFontBackground16 = FontBackground16;
134 }
135
136
137 /* Restores the last saved font printing settings from the temporary lactions */
RestoreFontSettings(void)138 void RestoreFontSettings(void)
139 {
140 FontDefault = SaveFontDefault;
141 FontDestBuffer = SaveFontDestBuffer;
142 FontDestRegion = SaveFontDestRegion;
143 FontForeground16 = SaveFontForeground16;
144 FontShadow16 = SaveFontShadow16;
145 FontBackground16 = SaveFontBackground16;
146 }
147
148
149 /* Returns the height of a given character in the font. */
GetHeight(HVOBJECT hSrcVObject,INT16 ssIndex)150 static UINT32 GetHeight(HVOBJECT hSrcVObject, INT16 ssIndex)
151 {
152 // Get Offsets from Index into structure
153 ETRLEObject const& pTrav = hSrcVObject->SubregionProperties(ssIndex);
154 return pTrav.usHeight + pTrav.sOffsetY;
155 }
156
157
158 /* Returns the height of the first character in a font. */
GetFontHeight(SGPFont const font)159 UINT16 GetFontHeight(SGPFont const font)
160 {
161 return GetHeight(font, 0);
162 }
163
164
IsPrintableChar(char32_t c)165 bool IsPrintableChar(char32_t c)
166 {
167 if (TRANSLATION_TABLE_SIZE <= c) return false;
168 return TranslationTable[c] != 0 || c == getZeroGlyphChar();
169 }
170
171
172 /* Given a unicode codepoint, this function returns the index of the glyph. If no glyph
173 * exists for the requested codepoint, the glyph index of '?' is returned. */
GetGlyphIndex(char32_t c)174 static GlyphIdx GetGlyphIndex(char32_t c)
175 {
176 if (c < TRANSLATION_TABLE_SIZE)
177 {
178 GlyphIdx const idx = TranslationTable[c];
179 if (idx != 0 || c == getZeroGlyphChar()) return idx;
180 }
181 SLOGE("Invalid character given U+%04X", c);
182 return TranslationTable[L'?'];
183 }
184
185
GetCharWidth(HVOBJECT SGPFont,char32_t c)186 UINT32 GetCharWidth(HVOBJECT SGPFont, char32_t c)
187 {
188 return GetWidth(SGPFont, GetGlyphIndex(c));
189 }
190
191
192 /* Sets the current font number. */
SetFont(SGPFont const font)193 void SetFont(SGPFont const font)
194 {
195 Assert(font);
196 FontDefault = font;
197 }
198
199
SetFontAttributes(SGPFont const font,UINT8 const foreground,UINT8 const shadow,UINT8 const background)200 void SetFontAttributes(SGPFont const font, UINT8 const foreground, UINT8 const shadow, UINT8 const background)
201 {
202 SetFont(font);
203 SetFontForeground(foreground);
204 SetFontShadow(shadow);
205 SetFontBackground(background);
206 }
207
208
SetFontDestBuffer(SGPVSurface * const dst,const INT32 x1,const INT32 y1,const INT32 x2,const INT32 y2)209 void SetFontDestBuffer(SGPVSurface* const dst, const INT32 x1, const INT32 y1, const INT32 x2, const INT32 y2)
210 {
211 Assert(x2 > x1);
212 Assert(y2 > y1);
213
214 FontDestBuffer = dst;
215 FontDestRegion.iLeft = x1;
216 FontDestRegion.iTop = y1;
217 FontDestRegion.iRight = x2;
218 FontDestRegion.iBottom = y2;
219 }
220
221
SetFontDestBuffer(SGPVSurface * const dst)222 void SetFontDestBuffer(SGPVSurface* const dst)
223 {
224 SetFontDestBuffer(dst, 0, 0, dst->Width(), dst->Height());
225 }
226
227
228 /** Replace backbuffer if it is used by the font system. */
ReplaceFontBackBuffer(SGPVSurface * oldBackbuffer,SGPVSurface * newBackbuffer)229 void ReplaceFontBackBuffer(SGPVSurface* oldBackbuffer, SGPVSurface* newBackbuffer)
230 {
231 if(FontDestBuffer == oldBackbuffer)
232 {
233 FontDestBuffer = newBackbuffer;
234 }
235
236 if(SaveFontDestBuffer == oldBackbuffer)
237 {
238 SaveFontDestBuffer = newBackbuffer;
239 }
240 }
241
242
FindFontRightCoordinates(INT16 sLeft,INT16 sTop,INT16 sWidth,INT16 sHeight,const ST::utf32_buffer & codepoints,SGPFont font,INT16 * psNewX,INT16 * psNewY)243 void FindFontRightCoordinates(INT16 sLeft, INT16 sTop, INT16 sWidth, INT16 sHeight, const ST::utf32_buffer& codepoints, SGPFont font, INT16* psNewX, INT16* psNewY)
244 {
245 // Compute the coordinates to right justify the text
246 INT16 xp = sWidth - StringPixLength(codepoints, font) + sLeft;
247 INT16 yp = (sHeight - GetFontHeight(font)) / 2 + sTop;
248
249 *psNewX = xp;
250 *psNewY = yp;
251 }
252
253
FindFontCenterCoordinates(INT16 sLeft,INT16 sTop,INT16 sWidth,INT16 sHeight,const ST::utf32_buffer & codepoints,SGPFont font,INT16 * psNewX,INT16 * psNewY)254 void FindFontCenterCoordinates(INT16 sLeft, INT16 sTop, INT16 sWidth, INT16 sHeight, const ST::utf32_buffer& codepoints, SGPFont font, INT16* psNewX, INT16* psNewY)
255 {
256 // Compute the coordinates to center the text
257 INT16 xp = (sWidth - StringPixLength(codepoints, font) + 1) / 2 + sLeft;
258 INT16 yp = (sHeight - GetFontHeight(font)) / 2 + sTop;
259
260 *psNewX = xp;
261 *psNewY = yp;
262 }
263
264
GPrint(INT32 x,INT32 y,const ST::utf32_buffer & codepoints)265 void GPrint(INT32 x, INT32 y, const ST::utf32_buffer& codepoints)
266 {
267 SGPVSurface::Lock l(FontDestBuffer);
268 UINT16* const buf = l.Buffer<UINT16>();
269 UINT32 const pitch = l.Pitch();
270 SGPFont const font = FontDefault;
271 for (char32_t c : codepoints)
272 {
273 GlyphIdx const glyph = GetGlyphIndex(c);
274 Blt8BPPDataTo16BPPBufferTransparentClip(buf, pitch, font, x, y, glyph, &FontDestRegion);
275 x += GetWidth(font, glyph);
276 }
277 }
278
279
MPrintChar(INT32 x,INT32 y,char32_t c)280 UINT32 MPrintChar(INT32 x, INT32 y, char32_t c)
281 {
282 GlyphIdx const glyph = GetGlyphIndex(c);
283 SGPFont const font = FontDefault;
284 { SGPVSurface::Lock l(FontDestBuffer);
285 Blt8BPPDataTo16BPPBufferMonoShadowClip(l.Buffer<UINT16>(), l.Pitch(), font, x, y, glyph, &FontDestRegion, FontForeground16, FontBackground16, FontShadow16);
286 }
287 return GetWidth(font, glyph);
288 }
289
290
MPrintBuffer(UINT16 * pDestBuf,UINT32 uiDestPitchBYTES,INT32 x,INT32 y,const ST::utf32_buffer & codepoints)291 void MPrintBuffer(UINT16* pDestBuf, UINT32 uiDestPitchBYTES, INT32 x, INT32 y, const ST::utf32_buffer& codepoints)
292 {
293 SGPFont const font = FontDefault;
294 for (char32_t c : codepoints)
295 {
296 GlyphIdx const glyph = GetGlyphIndex(c);
297 Blt8BPPDataTo16BPPBufferMonoShadowClip(pDestBuf, uiDestPitchBYTES, font, x, y, glyph, &FontDestRegion, FontForeground16, FontBackground16, FontShadow16);
298 x += GetWidth(font, glyph);
299 }
300 }
301
302
MPrint(INT32 x,INT32 y,const ST::utf32_buffer & codepoints)303 void MPrint(INT32 x, INT32 y, const ST::utf32_buffer& codepoints)
304 {
305 SGPVSurface::Lock l(FontDestBuffer);
306 MPrintBuffer(l.Buffer<UINT16>(), l.Pitch(), x, y, codepoints);
307 }
308
309
InitializeFontManager(void)310 void InitializeFontManager(void)
311 {
312 FontDefault = 0;
313 SetFontDestBuffer(BACKBUFFER);
314 }
315