7#include "font_font.hpp"
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/geometry.hpp"
14#include "../utility/utility.hpp"
15#include "../path/path.hpp"
22hi_export_module(hikogui.font.font_book);
24hi_export
namespace hi::inline
v1 {
35 hi::font
const *
font =
nullptr;
45 hi_axiom_not_null(
font);
51 hi_axiom_not_null(
font);
55 [[nodiscard]] aarectangle get_bounding_rectangle()
const noexcept
62 hi::font
const *
font =
nullptr;
63 lean_vector<glyph_id> ids = {};
74 hi_axiom_not_null(
font);
78 [[nodiscard]]
glyph_metrics get_starter_metrics()
const noexcept
80 hi_axiom(not ids.empty());
81 hi_axiom_not_null(
font);
106 font& register_font_file(
std::filesystem::path const& path,
bool post_process = true)
108 auto font = std::make_unique<true_type_font>(path);
109 auto font_ptr =
font.get();
111 hi_log_info(
"Parsed font {}: {}", path.string(), to_string(*
font));
117 _font_ptrs.push_back(font_ptr);
120 this->post_process();
132 auto const font_directory_glob = path /
"**" /
"*.ttf";
133 for (
auto const& font_path : glob(font_directory_glob)) {
134 auto const t =
trace<
"font_scan">{};
140 hi_log_error(
"Failed parsing font at {}: \"{}\"", font_path.string(), e.
what());
145 this->post_process();
156 std::sort(begin(_font_ptrs), end(_font_ptrs), [](
auto const& lhs,
auto const& rhs) {
157 return lhs->char_map.count() > rhs->char_map.count();
160 auto const regular_fallback_chain = make_fallback_chain(font_weight::regular, font_style::normal);
161 auto const bold_fallback_chain = make_fallback_chain(font_weight::bold, font_style::normal);
162 auto const italic_fallback_chain = make_fallback_chain(font_weight::regular, font_style::italic);
165 "Post processing fonts number={}, regular-fallback={}, bold-fallback={}, italic-fallback={}",
167 size(regular_fallback_chain),
168 size(bold_fallback_chain),
169 size(italic_fallback_chain));
172 for (
auto const&
font : _font_ptrs) {
176 for (
auto const& fallback : _font_ptrs) {
179 (fallback !=
font) and
181 (fallback->style ==
font->style) and
182 almost_equal(fallback->weight,
font->weight)
189 if (almost_equal(
font->weight, font_weight::bold)) {
191 }
else if (
font->style == font_style::italic) {
206 auto it = _family_names.find(to_lower(family_name));
207 if (it == _family_names.end()) {
219 auto name = to_lower(family_name);
221 auto it = _family_names.find(name);
222 if (it == _family_names.end()) {
224 _font_variants.emplace_back();
225 _family_names[name] = family_id;
241 hi_assert(family_id);
242 hi_assert_bounds(*family_id, _font_variants);
244 auto const& variants = _font_variants[*family_id];
245 for (
auto alternative_variant : alternatives(variant)) {
246 if (
auto font = variants[alternative_variant]) {
265 if (
auto const family_id = find_family(family_name)) {
289 hi_axiom_not_null(fallback);
290 if (
auto const glyph_ids = fallback->find_glyph(
grapheme); not glyph_ids.empty()) {
291 return {*fallback,
std::move(glyph_ids)};
316 hi_axiom_not_null(fallback);
317 if (
auto const glyph_id = fallback->find_glyph(code_point)) {
343 return (item->style == style) and almost_equal(item->weight, weight);
347 for (
auto& font : r) {
348 if (font->char_map.update_mask(char_mask) == 0) {
354 std::erase(r,
nullptr);
363inline font_book& font_book::global() noexcept
365 if (not detail::font_book_global) {
366 detail::font_book_global = std::make_unique<font_book>();
368 return *detail::font_book_global;
383 return font_book::global().register_font_file(path);
386hi_export
inline void register_font_directory(std::filesystem::path
const& path)
388 return font_book::global().register_font_directory(path);
391hi_export
template<
typename Range>
392inline void register_font_directories(Range&& range)
noexcept
394 for (
auto const& path : range) {
395 font_book::global().register_font_directory(path,
false);
397 font_book::global().post_process();
405 return font_book::global().find_family(family_name);
417 return font_book::global().find_font(family_id, variant);
429 return font_book::global().find_font(family_name, variant);
455 return font_book::global().find_glyph(
font, code_point);
458hi_export [[nodiscard]]
inline auto find_glyph(elusive_icon rhs)
noexcept
460 auto const *font = find_font(
"elusiveicons", font_variant{font_weight::medium, font_style::normal});
461 hi_assert_not_null(font,
"Could not find Elusive icon font");
462 return find_glyph(*font, std::to_underlying(rhs));
465hi_export [[nodiscard]]
inline auto find_glyph(hikogui_icon rhs)
noexcept
467 auto const *font =
find_font(
"Hikogui Icons", font_variant{font_weight::regular, font_style::normal});
468 hi_assert_not_null(font,
"Could not find HikoGUI icon font");
469 return find_glyph(*font, std::to_underlying(rhs));
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
font_weight
Definition font_weight.hpp:21
hi_export font & register_font_file(std::filesystem::path const &path)
Register a font.
Definition font_book.hpp:381
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:415
hi_export font_family_id find_font_family(std::string const &family_name) noexcept
Find font family id.
Definition font_book.hpp:403
hi_export auto find_glyph(font const &font, grapheme grapheme) noexcept
Find a glyph using the given code-point.
Definition font_book.hpp:440
font_book keeps track of multiple fonts.
Definition font_book.hpp:32
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:153
void register_font_directory(std::filesystem::path const &path, bool post_process=true)
Register all fonts found in a directory.
Definition font_book.hpp:130
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:239
font_family_id register_family(std::string_view family_name) noexcept
Register font family id.
Definition font_book.hpp:217
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:263
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:307
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:280
font_family_id find_family(std::string const &family_name) const noexcept
Find font family id.
Definition font_book.hpp:204
Definition font_book.hpp:34
Definition font_book.hpp:61
Definition font_font.hpp:31
virtual glyph_metrics get_metrics(hi::glyph_id glyph_id) const =0
Load a glyph into a path.
font_metrics_em metrics
The metrics of a font.
Definition font_font.hpp:65
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:69
glyph_id find_glyph(char32_t c) const noexcept
Get the glyph for a code-point.
Definition font_font.hpp:87
A font variant is one of 16 different fonts that can be part of a family.
Definition font_variant.hpp:27
Definition glyph_metrics.hpp:20
aarectangle bounding_rectangle
Definition glyph_metrics.hpp:23
A grapheme-cluster, what a user thinks a character is.
Definition grapheme.hpp:167
Definition tagged_id.hpp:26
T back_inserter(T... args)
T stable_partition(T... args)