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);
36 hi::font
const *
font =
nullptr;
44 [[nodiscard]]
font_metrics const& get_font_metrics()
const noexcept
46 hi_axiom_not_null(
font);
52 hi_axiom_not_null(
font);
56 [[nodiscard]] aarectangle get_bounding_rectangle()
const noexcept
63 hi::font
const *
font =
nullptr;
64 lean_vector<glyph_id> ids = {};
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);
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));
124 _font_ptrs.push_back(font_ptr);
127 this->post_process();
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());
152 this->post_process();
163 std::sort(begin(_font_ptrs), end(_font_ptrs), [](hilet& lhs, hilet& rhs) {
164 return lhs->char_map.count() > rhs->char_map.count();
167 hilet regular_fallback_chain = make_fallback_chain(font_weight::regular, font_style::normal);
168 hilet bold_fallback_chain = make_fallback_chain(font_weight::bold, font_style::normal);
169 hilet italic_fallback_chain = make_fallback_chain(font_weight::regular, font_style::italic);
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)
196 if (almost_equal(
font->weight, font_weight::bold)) {
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()) {
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]) {
272 if (hilet family_id = find_family(family_name)) {
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)};
323 hi_axiom_not_null(fallback);
324 if (hilet
glyph_id = fallback->find_glyph(code_point)) {
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));
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
hi_export font & register_font_file(std::filesystem::path const &path)
Register a font.
Definition font_book.hpp:378
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
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
font_book keeps track of multiple fonts.
Definition font_book.hpp:33
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
virtual glyph_metrics get_metrics(hi::glyph_id glyph_id) const =0
Load a glyph into a path.
hi::font_metrics metrics
The metrics of a font.
Definition font_font.hpp:67
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
aarectangle bounding_rectangle
Definition glyph_metrics.hpp:22
A grapheme-cluster, what a user thinks a character is.
Definition grapheme.hpp:160
Definition tagged_id.hpp:20
T back_inserter(T... args)
T stable_partition(T... args)