1 /**
2  * @file
3  */
4 
5 /*
6 Copyright (C) 2002-2013 UFO: Alien Invasion.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 
23 */
24 
25 #include "ui_main.h"
26 #include "ui_internal.h"
27 #include "ui_font.h"
28 #include "ui_parse.h"
29 
30 #include "../cl_shared.h"
31 #include "../../shared/parse.h"
32 #include "../renderer/r_font.h"
33 
34 #define MAX_FONTS 16
35 static int numFonts = 0;
36 static uiFont_t fonts[MAX_FONTS];
37 
38 static const value_t fontValues[] = {
39 	{"font", V_TRANSLATION_STRING, offsetof(uiFont_t, path), 0},
40 	{"size", V_INT, offsetof(uiFont_t, size), MEMBER_SIZEOF(uiFont_t, size)},
41 	{"style", V_HUNK_STRING, offsetof(uiFont_t, style), 0},
42 
43 	{nullptr, V_NULL, 0, 0}
44 };
45 
46 /**
47  * @brief Registers a new TTF font
48  * @note The TTF font path is translated via gettext to be able to use different
49  * fonts for every translation
50  * @param[in] font Font to register
51  */
UI_RegisterFont(const uiFont_t * font)52 static void UI_RegisterFont (const uiFont_t* font)
53 {
54 	const char* path = _(font->path);
55 
56 	if (!path)
57 		Com_Error(ERR_FATAL, "...font without path (font %s)", font->name);
58 
59 	if (FS_CheckFile("%s", path) == -1)
60 		Com_Error(ERR_FATAL, "...font file %s does not exist (font %s)", path, font->name);
61 
62 	R_FontRegister(font->name, font->size, path, font->style);
63 }
64 
65 /**
66  * @sa CL_ParseClientData
67  */
UI_ParseFont(const char * name,const char ** text)68 bool UI_ParseFont (const char* name, const char** text)
69 {
70 	uiFont_t* font;
71 	const char* errhead = "UI_ParseFont: unexpected end of file (font";
72 	const char* token;
73 	const value_t* v = nullptr;
74 
75 	/* search for font with same name */
76 	if (UI_GetFontByID(name)) {
77 		Com_Printf("UI_ParseFont: font \"%s\" with same name found, second ignored\n", name);
78 		return false;
79 	}
80 
81 	if (numFonts >= MAX_FONTS) {
82 		Com_Printf("UI_ParseFont: Max fonts reached\n");
83 		return false;
84 	}
85 
86 	/* initialize the UI */
87 	font = &fonts[numFonts];
88 	OBJZERO(*font);
89 
90 	font->name = Mem_PoolStrDup(name, ui_sysPool, 0);
91 
92 	Com_DPrintf(DEBUG_CLIENT, "...found font %s (%i)\n", font->name, numFonts);
93 
94 	/* get it's body */
95 	token = Com_Parse(text);
96 
97 	if (!*text || *token != '{') {
98 		Com_Printf("UI_ParseFont: font \"%s\" without body ignored\n", name);
99 		return false;
100 	}
101 
102 	numFonts++;
103 
104 	do {
105 		/* get the name type */
106 		token = Com_EParse(text, errhead, name);
107 		if (!*text)
108 			return false;
109 		if (*token == '}')
110 			break;
111 
112 		for (v = fontValues; v->string; v++)
113 			if (Q_streq(token, v->string)) {
114 				/* found a definition */
115 				token = Com_EParse(text, errhead, name);
116 				if (!*text)
117 					return false;
118 
119 				switch (v->type) {
120 				case V_TRANSLATION_STRING:
121 					token++;
122 				case V_HUNK_STRING:
123 					Mem_PoolStrDupTo(token, &Com_GetValue<char*>(font, v), ui_sysPool, 0);
124 					break;
125 				default:
126 					Com_EParseValue(font, token, v->type, v->ofs, v->size);
127 					break;
128 				}
129 				break;
130 			}
131 
132 		if (!v->string)
133 			Com_Printf("UI_ParseFont: unknown token \"%s\" ignored (font %s)\n", token, name);
134 	} while (*text);
135 
136 	UI_RegisterFont(font);
137 	return true;
138 }
139 
140 /**
141  * @brief Return the font for a specific node or default font
142  * @param[in] node Context node
143  * @return char pointer with font name (default is f_small)
144  */
UI_GetFontFromNode(const uiNode_t * const node)145 const char* UI_GetFontFromNode (const uiNode_t* const node)
146 {
147 	if (node && node->font) {
148 		return UI_GetReferenceString(node, node->font);
149 	}
150 	return "f_small";
151 }
152 
153 
154 /**
155  * @brief Return the font for a specific id
156  */
UI_GetFontByID(const char * name)157 const uiFont_t* UI_GetFontByID (const char* name)
158 {
159 	int i;
160 
161 	for (i = 0; i < numFonts; i++)
162 		if (Q_streq(fonts[i].name, name))
163 			return &fonts[i];
164 
165 	return nullptr;
166 }
167 
UI_FontGetHeight(const char * fontID)168 int UI_FontGetHeight (const char* fontID)
169 {
170 	font_t* font = R_GetFont(fontID);
171 	if (font != nullptr)
172 		return font->height;
173 	return -1;
174 }
175 
176 /**
177  * @brief after a video restart we have to reinitialize the fonts
178  */
UI_InitFonts(void)179 void UI_InitFonts (void)
180 {
181 	int i;
182 
183 	Com_Printf("...registering %i fonts\n", numFonts);
184 	for (i = 0; i < numFonts; i++)
185 		UI_RegisterFont(&fonts[i]);
186 }
187 
UI_FontShutdown(void)188 void UI_FontShutdown (void)
189 {
190 	numFonts = 0;
191 }
192