1 // Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3 
4 #include "FontConfig.h"
5 #include "FileSystem.h"
6 #include "JsonUtils.h"
7 #include "utils.h"
8 
9 namespace Text {
10 
FontConfig(const std::string & name,float scaleX,float scaleY)11 	FontConfig::FontConfig(const std::string &name, float scaleX, float scaleY)
12 	{
13 		const std::string path("fonts/" + name + ".json");
14 		Json data = JsonUtils::LoadJsonFile(path, FileSystem::gameDataFiles);
15 		if (data.is_null()) {
16 			Output("couldn't read font file '%s'\n", path.c_str());
17 			abort();
18 		}
19 
20 		m_name = data.value("name", "unknown");
21 		m_outline = data.value("outline", false);
22 
23 		Json faces = data.value("faces", Json::array());
24 		for (auto &i : faces) {
25 			const std::string &fontFile = i.value("fontFile", "");
26 			const int pixelWidth = 1.0f / scaleX * i.value("pixelWidth", 14);
27 			const int pixelHeight = 1.0f / scaleY * i.value("pixelWidth", 14);
28 			const float advanceXAdjustment = i.value("advanceXAdjustment", 0.0f);
29 
30 			Json ranges = i.value("ranges", Json::array());
31 			if (ranges.empty())
32 				m_faces.push_back(Face(fontFile, pixelWidth, pixelHeight, advanceXAdjustment, 0x000000, 0x1fffff));
33 			else {
34 				for (auto &j : ranges) {
35 					Uint32 rangeMin = 0x000000, rangeMax = 0x1fffff;
36 					const std::string rangeMinStr = j[0].is_string() ? j[0] : "0x000000";
37 					const std::string rangeMaxStr = j[1].is_string() ? j[1] : "0x1fffff";
38 					sscanf(rangeMinStr.c_str(), "%x", &rangeMin);
39 					sscanf(rangeMaxStr.c_str(), "%x", &rangeMax);
40 					m_faces.push_back(Face(fontFile, pixelWidth, pixelHeight, advanceXAdjustment, rangeMin, rangeMax));
41 				}
42 			}
43 		}
44 	}
45 
GetFaceForCodePoint(Uint32 cp)46 	const FontConfig::Face &FontConfig::GetFaceForCodePoint(Uint32 cp)
47 	{
48 		// XXX naive. map and custom comparator would be better
49 		auto best = m_faces.end();
50 		for (auto i = m_faces.begin(); i != m_faces.end(); ++i) {
51 			if (cp < (*i).rangeMin || cp > (*i).rangeMax)
52 				continue;
53 			if (best == m_faces.end()) {
54 				best = i;
55 				continue;
56 			}
57 			if ((*i).rangeMax - (*i).rangeMin < (*best).rangeMax - (*best).rangeMin) {
58 				best = i;
59 				continue;
60 			}
61 		}
62 		return *best;
63 	}
64 
65 } // namespace Text
66