8#include "font_family_id.hpp"
9#include "true_type_font.hpp"
10#include "elusive_icon.hpp"
11#include "hikogui_icon.hpp"
12#include "../unicode/unicode.hpp"
13#include "../geometry/module.hpp"
14#include "../utility/utility.hpp"
15#include "../coroutine/module.hpp"
16#include "../path/path.hpp"
23hi_export_module(hikogui.font.font_book);
25namespace hi::inline
v1 {
33hi_export
class font_book {
35 struct font_glyph_type {
36 hi::font
const *font =
nullptr;
39 constexpr font_glyph_type()
noexcept =
default;
40 constexpr font_glyph_type(hi::font
const& font, glyph_id
id) noexcept : font(
std::addressof(font)), id(
id) {}
42 [[nodiscard]]
constexpr friend bool operator==(font_glyph_type
const&, font_glyph_type
const&)
noexcept =
default;
44 [[nodiscard]]
font_metrics const& get_font_metrics()
const noexcept
46 hi_axiom_not_null(font);
52 hi_axiom_not_null(font);
53 return font->get_metrics(
id);
56 [[nodiscard]] aarectangle get_bounding_rectangle()
const noexcept
58 return get_metrics().bounding_rectangle;
62 struct font_glyphs_type {
63 hi::font
const *font =
nullptr;
64 lean_vector<glyph_id> ids = {};
66 constexpr font_glyphs_type()
noexcept =
default;
67 font_glyphs_type(hi::font
const& font, lean_vector<glyph_id> ids) noexcept :
71 font_glyphs_type(hi::font
const& font, glyph_id
id) noexcept : font(
std::addressof(font)), ids{
id} {}
73 [[nodiscard]]
font_metrics const& get_font_metrics()
const noexcept
75 hi_axiom_not_null(font);
79 [[nodiscard]]
glyph_metrics get_starter_metrics()
const noexcept
81 hi_axiom(not ids.empty());
82 hi_axiom_not_null(font);
83 return font->get_metrics(ids.front());
87 static font_book& global() noexcept
90 _global = std::make_unique<font_book>();
95 ~font_book() =
default;
96 font_book(font_book
const&) =
delete;
97 font_book(font_book&&) =
delete;
98 font_book& operator=(font_book
const&) =
delete;
99 font_book& operator=(font_book&&) =
delete;
100 font_book() =
default;
115 auto font = std::make_unique<true_type_font>(path);
116 auto font_ptr =
font.get();
118 hi_log_info(
"Parsed font {}: {}", path.string(), to_string(*
font));
121 _font_variants[*font_family_id][
font->font_variant()] = font_ptr;
124 _font_ptrs.push_back(font_ptr);
139 hilet font_directory_glob = path /
"**" /
"*.ttf";
140 for (hilet& font_path : glob(font_directory_glob)) {
141 hilet t =
trace<
"font_scan">{};
147 hi_log_error(
"Failed parsing font at {}: \"{}\"", font_path.string(), e.
what());
163 std::sort(begin(_font_ptrs), end(_font_ptrs), [](hilet& lhs, hilet& rhs) {
164 return lhs->char_map.count() > rhs->char_map.count();
168 hilet bold_fallback_chain = make_fallback_chain(
font_weight::bold, font_style::normal);
172 "Post processing fonts number={}, regular-fallback={}, bold-fallback={}, italic-fallback={}",
174 size(regular_fallback_chain),
175 size(bold_fallback_chain),
176 size(italic_fallback_chain));
179 for (hilet&
font : _font_ptrs) {
183 for (hilet& fallback : _font_ptrs) {
186 (fallback !=
font) and
188 (fallback->style ==
font->style) and
189 almost_equal(fallback->weight,
font->weight)
191 fallback_chain.push_back(fallback);
198 }
else if (
font->style == font_style::italic) {
213 auto it = _family_names.find(to_lower(family_name));
214 if (it == _family_names.end()) {
226 auto name = to_lower(family_name);
228 auto it = _family_names.find(name);
229 if (it == _family_names.end()) {
230 hilet family_id = font_family_id(_font_variants.size());
231 _font_variants.emplace_back();
232 _family_names[name] = family_id;
248 hi_assert(family_id);
249 hi_assert_bounds(*family_id, _font_variants);
251 hilet& variants = _font_variants[*family_id];
252 for (
auto alternative_variant :
alternatives(variant)) {
253 if (
auto font = variants[alternative_variant]) {
296 hi_axiom_not_null(fallback);
297 if (hilet glyph_ids = fallback->find_glyph(
grapheme); not glyph_ids.empty()) {
298 return {*fallback,
std::move(glyph_ids)};
303 return {
font, {glyph_id{0}}};
318 return {
font, glyph_id};
323 hi_axiom_not_null(fallback);
324 if (hilet glyph_id = fallback->find_glyph(code_point)) {
325 return {*fallback, glyph_id};
330 return {
font, glyph_id{0}};
352 return (item->style == style) and almost_equal(item->weight, weight);
356 for (
auto& font : r) {
357 if (font->char_map.update_mask(char_mask) == 0) {
363 std::erase(r,
nullptr);
380 return font_book::global().register_font_file(path);
383hi_export
inline void register_font_directory(std::filesystem::path
const& path)
385 return font_book::global().register_font_directory(path);
388hi_export
template<
typename Range>
389inline void register_font_directories(Range&& range)
noexcept
391 for (
auto const& path : range) {
392 font_book::global().register_font_directory(path,
false);
394 font_book::global().post_process();
402 return font_book::global().find_family(family_name);
414 return font_book::global().find_font(family_id, variant);
426 return font_book::global().find_font(family_name, variant);
452 return font_book::global().find_glyph(
font, code_point);
455hi_export [[nodiscard]]
inline auto find_glyph(elusive_icon rhs)
noexcept
457 hilet *font = find_font(
"elusiveicons", font_variant{font_weight::medium, font_style::normal});
458 hi_assert_not_null(font,
"Could not find Elusive icon font");
459 return find_glyph(*font, std::to_underlying(rhs));
462hi_export [[nodiscard]]
inline auto find_glyph(hikogui_icon rhs)
noexcept
464 hilet *font =
find_font(
"Hikogui Icons", font_variant{font_weight::regular, font_style::normal});
465 hi_assert_not_null(font,
"Could not find HikoGUI icon font");
466 return find_glyph(*font, std::to_underlying(rhs));
DOXYGEN BUG.
Definition algorithm.hpp:16
font_weight
Definition font_weight.hpp:18
@ bold
700: Bold
Definition font_weight.hpp:25
@ regular
400: Normal / Regular
Definition font_weight.hpp:22
hi_export font & register_font_file(std::filesystem::path const &path)
Register a font.
Definition font_book.hpp:378
hi_export generator< font_weight > alternatives(font_weight start) noexcept
Generate alternatives for the font_weight.
Definition font_weight.hpp:116
hi_export font const & find_font(font_family_id family_id, font_variant variant=font_variant{}) noexcept
Find a font closest to the variant.
Definition font_book.hpp:412
hi_export font_family_id find_font_family(std::string const &family_name) noexcept
Find font family id.
Definition font_book.hpp:400
hi_export auto find_glyph(font const &font, grapheme grapheme) noexcept
Find a glyph using the given code-point.
Definition font_book.hpp:437
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:160
void register_font_directory(std::filesystem::path const &path, bool post_process=true)
Register all fonts found in a directory.
Definition font_book.hpp:137
font const & find_font(font_family_id family_id, font_variant variant) const noexcept
Find a font closest to the variant.
Definition font_book.hpp:246
font_family_id register_family(std::string_view family_name) noexcept
Register font family id.
Definition font_book.hpp:224
font & register_font_file(std::filesystem::path const &path, bool post_process=true)
Register a font.
Definition font_book.hpp:113
font const * find_font(std::string const &family_name, font_variant variant) const noexcept
Find a font closest to the variant.
Definition font_book.hpp:270
font_glyph_type find_glyph(font const &font, char32_t code_point) const noexcept
Find a glyph using the given code-point.
Definition font_book.hpp:314
font_glyphs_type find_glyph(font const &font, hi::grapheme grapheme) const noexcept
Find a glyph using the given code-point.
Definition font_book.hpp:287
font_family_id find_family(std::string const &family_name) const noexcept
Find font family id.
Definition font_book.hpp:211
Definition font_book.hpp:35
Definition font_book.hpp:62
Definition font_font.hpp:31
std::string family_name
The family name as parsed from the font file.
Definition font_font.hpp:37
std::vector< hi::font * > fallback_chain
List of fonts to use as a fallback for this font.
Definition font_font.hpp:71
glyph_id find_glyph(char32_t c) const noexcept
Get the glyph for a code-point.
Definition font_font.hpp:89
The metrics of a font.
Definition font_metrics.hpp:19
A font variant is one of 16 different fonts that can be part of a family.
Definition font_variant.hpp:19
Definition glyph_metrics.hpp:19
A grapheme-cluster, what a user thinks a character is.
Definition grapheme.hpp:160
T back_inserter(T... args)
T stable_partition(T... args)