7#include "font_font.hpp"
9#include "font_glyph_ids.hpp"
10#include "font_family_id.hpp"
11#include "true_type_font.hpp"
12#include "elusive_icon.hpp"
13#include "hikogui_icon.hpp"
14#include "../unicode/unicode.hpp"
15#include "../geometry/geometry.hpp"
16#include "../utility/utility.hpp"
17#include "../path/path.hpp"
25hi_export_module(hikogui.font : font_book);
27hi_export
namespace hi::inline
v1 {
37 static font_book& global()
noexcept;
39 ~font_book() =
default;
40 font_book(font_book
const&) =
delete;
41 font_book(font_book&&) =
delete;
42 font_book& operator=(font_book
const&) =
delete;
43 font_book& operator=(font_book&&) =
delete;
44 font_book() =
default;
59 if (_fonts.size() >= font_id::empty_value) {
63 auto const font_id =
hi::font_id{gsl::narrow_cast<font_id::value_type>(_fonts.size())};
64 auto const &
font = *_fonts.emplace_back(std::make_unique<true_type_font>(path));
65 _fallback_chain.push_back(font_id);
67 hi_log_info(
"Parsed font id={} {}: {}", *font_id, path.string(), to_string(
font));
70 _font_variants[*font_family_id][
font.font_variant()] = font_id;
85 auto const font_directory_glob = path /
"**" /
"*.ttf";
86 for (
auto const& font_path : glob(font_directory_glob)) {
87 auto const t =
trace<
"font_scan">{};
93 hi_log_error(
"Failed parsing font at {}: \"{}\"", font_path.string(), e.
what());
109 std::sort(begin(_fallback_chain), end(_fallback_chain), [](
auto const& lhs,
auto const& rhs) {
110 return lhs->char_map.count() > rhs->char_map.count();
113 auto const regular_fallback_chain = make_fallback_chain(
font_weight::regular, font_style::normal);
114 auto const bold_fallback_chain = make_fallback_chain(
font_weight::bold, font_style::normal);
115 auto const italic_fallback_chain = make_fallback_chain(
font_weight::regular, font_style::italic);
118 "Post processing fonts number={}, regular-fallback={}, bold-fallback={}, italic-fallback={}",
120 size(regular_fallback_chain),
121 size(bold_fallback_chain),
122 size(italic_fallback_chain));
125 for (
auto const&
font : _fallback_chain) {
129 for (
auto const& fallback : _fallback_chain) {
132 (fallback !=
font) and
134 (fallback->style ==
font->style) and
135 almost_equal(fallback->weight,
font->weight)
137 fallback_chain.push_back(fallback);
144 }
else if (
font->style == font_style::italic) {
159 auto it = _family_names.find(to_lower(family_name));
160 if (it == _family_names.end()) {
172 auto name = to_lower(family_name);
174 auto it = _family_names.find(name);
175 if (it == _family_names.end()) {
176 if (_font_variants.size() >= font_family_id::empty_value) {
180 auto const family_id = font_family_id{gsl::narrow_cast<font_family_id::value_type>(_font_variants.size())};
181 _font_variants.emplace_back();
182 _family_names[name] = family_id;
198 hi_assert(family_id);
199 hi_assert_bounds(*family_id, _font_variants);
201 auto const& variants = _font_variants[*family_id];
203 if (
auto id = variants[i]) {
212 [[nodiscard]]
font &get_font(font_id
id)
const
214 return *_fonts.at(*
id);
234 hi_axiom(not fallback.empty());
235 if (
auto const glyph_ids = fallback->find_glyph(
grapheme); not glyph_ids.empty()) {
236 return {*fallback,
std::move(glyph_ids)};
241 return {
font, {glyph_id{0}}};
258 auto r = _fallback_chain;
261 return (item->style == style) and almost_equal(item->weight, weight);
265 for (
auto& font : r) {
266 if (font->char_map.update_mask(char_mask) == 0) {
272 std::erase(r, std::nullopt);
278inline std::unique_ptr<font_book> font_book_global =
nullptr;
281inline font_book& font_book::global() noexcept
283 if (not detail::font_book_global) {
284 detail::font_book_global = std::make_unique<font_book>();
286 return *detail::font_book_global;
301 return font_book::global().register_font_file(path);
304inline void register_font_directory(std::filesystem::path
const& path)
306 return font_book::global().register_font_directory(path);
309template<
typename Range>
310inline void register_font_directories(Range&& range)
noexcept
312 for (
auto const& path : range) {
313 font_book::global().register_font_directory(path,
false);
315 font_book::global().post_process();
323 return font_book::global().find_family(family_name);
335 return font_book::global().find_font(family_id, variant);
347 if (
auto family_id = find_font_family(family_name)) {
348 return find_font(family_id, variant);
367[[nodiscard]]
inline font_glyph_ids find_glyph(elusive_icon rhs)
noexcept
369 auto const id = find_font(
"elusiveicons", font_variant{font_weight::medium, font_style::normal});
370 hi_assert(not
id.empty(),
"Could not find Elusive icon font");
371 return find_glyph(
id, std::to_underlying(rhs));
374[[nodiscard]]
inline font_glyph_ids
find_glyph(hikogui_icon rhs)
noexcept
376 auto const id =
find_font(
"Hikogui Icons", font_variant{font_weight::regular, font_style::normal});
377 hi_assert(not
id.empty(),
"Could not find HikoGUI icon font");
378 return find_glyph(
id, std::to_underlying(rhs));
381[[nodiscard]]
inline font &get_font(font_id
id)
383 return font_book::global().get_font(
id);
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
font_weight
Definition font_weight.hpp:21
@ bold
700: Bold
Definition font_weight.hpp:28
@ regular
400: Normal / Regular
Definition font_weight.hpp:25
font_id find_font(font_family_id family_id, font_variant variant=font_variant{}) noexcept
Find a font closest to the variant.
Definition font_book.hpp:333
font_id register_font_file(std::filesystem::path const &path)
Register a font.
Definition font_book.hpp:299
font_glyph_ids find_glyph(font_id font, grapheme grapheme) noexcept
Find a glyph using the given code-point.
Definition font_book.hpp:362
generator< font_weight > alternatives(font_weight start) noexcept
Generate alternatives for the font_weight.
Definition font_weight.hpp:119
font_family_id find_font_family(std::string const &family_name) noexcept
Find font family id.
Definition font_book.hpp:321
font_id register_font_file(std::filesystem::path const &path, bool post_process=true)
Register a font.
Definition font_book.hpp:57
void post_process() noexcept
Post process font_book Should be called after a set of register_font() calls This calculates font fal...
Definition font_book.hpp:106
void register_font_directory(std::filesystem::path const &path, bool post_process=true)
Register all fonts found in a directory.
Definition font_book.hpp:83
font_glyph_ids find_glyph(font_id font, hi::grapheme grapheme) const noexcept
Find a combination of glyphs matching the given grapheme.
Definition font_book.hpp:225
font_family_id register_family(std::string_view family_name)
Register font family id.
Definition font_book.hpp:170
font_id find_font(font_family_id family_id, font_variant variant) const noexcept
Find a font closest to the variant.
Definition font_book.hpp:196
font_family_id find_family(std::string const &family_name) const noexcept
Find font family id.
Definition font_book.hpp:157
Definition font_font.hpp:32
std::string family_name
The family name as parsed from the font file.
Definition font_font.hpp:38
glyph_id find_glyph(char32_t c) const noexcept
Get the glyph for a code-point.
Definition font_font.hpp:88
std::vector< hi::font_id > fallback_chain
List of fonts to use as a fallback for this font.
Definition font_font.hpp:70
An identifier for a font-family that was registered with HikoGUI.
Definition font_id.hpp:23
font * operator->() const
Dereference to a font-object.
Definition font_book.hpp:386
A font variant is one of 16 different fonts that can be part of a family.
Definition font_variant.hpp:27
A grapheme-cluster, what a user thinks a character is.
Definition grapheme.hpp:168
T back_inserter(T... args)
T stable_partition(T... args)