The Battle for Wesnoth  1.17.12+dev
font_config.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2016 - 2022
3  by Chris Beck<render787@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #include "font/font_config.hpp"
18 #include "font/error.hpp"
19 
20 #include "config.hpp"
21 #include "log.hpp"
22 #include "tstring.hpp"
23 
24 #include "filesystem.hpp"
25 #include "game_config.hpp"
26 
27 #include "serialization/parser.hpp"
31 #include "preferences/general.hpp"
32 
33 #include <list>
34 #include <set>
35 #include <stack>
36 #include <sstream>
37 #include <vector>
38 
39 #include <cairo-features.h>
40 
41 #include <fontconfig/fontconfig.h>
42 
43 static lg::log_domain log_font("font");
44 #define DBG_FT LOG_STREAM(debug, log_font)
45 #define LOG_FT LOG_STREAM(info, log_font)
46 #define WRN_FT LOG_STREAM(warn, log_font)
47 #define ERR_FT LOG_STREAM(err, log_font)
48 
49 namespace font {
50 
51 
52 bool check_font_file(std::string name) {
53  if(game_config::path.empty() == false) {
54  if(!filesystem::file_exists(game_config::path + "/fonts/" + name)) {
55  if(!filesystem::file_exists("fonts/" + name)) {
56  if(!filesystem::file_exists(name)) {
57  WRN_FT << "Failed opening font file '" << name << "': No such file or directory";
58  return false;
59  }
60  }
61  }
62  } else {
63  if(!filesystem::file_exists("fonts/" + name)) {
64  if(!filesystem::file_exists(name)) {
65  WRN_FT << "Failed opening font file '" << name << "': No such file or directory";
66  return false;
67  }
68  }
69  }
70  return true;
71 }
72 
73 namespace
74 {
75 
76 // Current font family for sanserif and monospace fonts in the game
77 
78 t_string family_order_sans;
79 t_string family_order_mono;
80 t_string family_order_light;
81 t_string family_order_script;
82 
83 } // end anon namespace
84 
85 /***
86  * Public interface
87  */
88 
90 {
91  config cfg;
92  try {
93  const std::string& cfg_path = filesystem::get_wml_location("hardwired/fonts.cfg");
94  if(cfg_path.empty()) {
95  ERR_FT << "could not resolve path to fonts.cfg, file not found";
96  return false;
97  }
98 
100  read(cfg, *stream);
101  } catch(const config::error &e) {
102  ERR_FT << "could not read fonts.cfg:\n" << e.message;
103  return false;
104  }
105 
106  const config &fonts_config = cfg.child("fonts");
107  if (!fonts_config)
108  return false;
109 
110  family_order_sans = fonts_config["family_order"];
111  family_order_mono = fonts_config["family_order_monospace"];
112  family_order_light = fonts_config["family_order_light"];
113  family_order_script = fonts_config["family_order_script"];
114 
115  if(family_order_mono.empty()) {
116  ERR_FT << "No monospace font family order defined, falling back to sans serif order";
117  family_order_mono = family_order_sans;
118  }
119 
120  if(family_order_light.empty()) {
121  ERR_FT << "No light font family order defined, falling back to sans serif order";
122  family_order_light = family_order_sans;
123  }
124 
125  if(family_order_script.empty()) {
126  ERR_FT << "No script font family order defined, falling back to sans serif order";
127  family_order_script = family_order_sans;
128  }
129 
130  return true;
131 }
132 
134 {
135  switch(fclass) {
136  case FONT_MONOSPACE:
137  return family_order_mono;
138  case FONT_LIGHT:
139  return family_order_light;
140  case FONT_SCRIPT:
141  return family_order_script;
142  default:
143  return family_order_sans;
144  }
145 }
146 
147 /***
148  * Manager member functions
149  */
150 
152 {
153  std::string font_path = game_config::path + "/fonts";
154  if (!FcConfigAppFontAddDir(FcConfigGetCurrent(),
155  reinterpret_cast<const FcChar8 *>(font_path.c_str())))
156  {
157  ERR_FT << "Could not load the true type fonts";
158  throw font::error("font config lib failed to add the font path: '" + font_path + "'");
159  }
160 
161  std::string font_file = font_path + "/fonts.conf";
162  if(!FcConfigParseAndLoad(FcConfigGetCurrent(),
163  reinterpret_cast<const FcChar8*>(font_file.c_str()),
164  FcFalse))
165  {
166  ERR_FT << "Could not load local font configuration";
167  throw font::error("font config lib failed to find font.conf: '" + font_file + "'");
168  }
169  else
170  {
171  LOG_FT << "Local font configuration loaded";
172  }
173 }
174 
176 {
177  FcConfigAppFontClear(FcConfigGetCurrent());
178 }
179 
180 } // end namespace font
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:402
family_class
Font classes for get_font_families().
bool check_font_file(std::string name)
Test if a font file exists.
Definition: font_config.cpp:52
Collection of helper functions relating to Pango formatting.
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:264
#define WRN_FT
Definition: font_config.cpp:46
#define LOG_FT
Definition: font_config.cpp:45
Definitions for the interface to Wesnoth Markup Language (WML).
const t_string & get_font_families(family_class fclass)
Returns the currently defined fonts.
void read(config &cfg, std::istream &in, abstract_validator *validator)
Definition: parser.cpp:627
std::unique_ptr< std::istream > scoped_istream
Definition: filesystem.hpp:39
std::string path
Definition: game_config.cpp:39
static lg::log_domain log_font("font")
bool load_font_config()
Definition: font_config.cpp:89
std::string get_wml_location(const std::string &filename, const std::string &current_dir)
Returns a complete path to the actual WML file or directory or an empty string if the file isn&#39;t pres...
Declarations for File-IO.
#define ERR_FT
Definition: font_config.cpp:47
Standard logging facilities (interface).
std::string message
Definition: exceptions.hpp:30
#define e
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:60
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
Function to use the WML preprocessor on a file.