HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
true_type_font.hpp
1// Copyright Take Vos 2019-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "font.hpp"
9#include "../graphic_path.hpp"
10#include "../counters.hpp"
11#include "../cast.hpp"
12#include <memory>
13#include <filesystem>
14
15namespace hi::inline v1 {
16
17class true_type_font final : public font {
18private:
21 std::filesystem::path _path;
22
27 mutable file_view _view;
28
29 uint16_t OS2_x_height = 0;
30 uint16_t OS2_cap_height = 0;
31
32 float unitsPerEm;
33 float emScale;
34
35 uint16_t numberOfHMetrics;
36
37 int num_glyphs;
38
39public:
40 true_type_font(std::filesystem::path const& path) : _path(path), _view(file_view{path})
41 {
42 ++global_counter<"ttf:map">;
43 try {
44 parse_font_directory();
45
46 // Clear the view to reclaim resources.
47 _view = {};
48 ++global_counter<"ttf:unmap">;
49
50 } catch (std::exception const &e) {
51 throw parse_error(std::format("{}: Could not parse font directory.\n{}", path.string(), e.what()));
52 }
53 }
54
55 true_type_font() = delete;
56 true_type_font(true_type_font const &other) = delete;
57 true_type_font &operator=(true_type_font const &other) = delete;
58 true_type_font(true_type_font &&other) = delete;
59 true_type_font &operator=(true_type_font &&other) = delete;
60 ~true_type_font() = default;
61
62 [[nodiscard]] bool loaded() const noexcept override
63 {
64 return to_bool(_view);
65 }
66
70 [[nodiscard]] hi::glyph_id find_glyph(char32_t c) const noexcept override;
71
79 std::optional<hi::glyph_id> load_glyph(hi::glyph_id glyph_id, graphic_path &path) const noexcept override;
80
89 bool load_glyph_metrics(hi::glyph_id glyph_id, glyph_metrics &metrics, hi::glyph_id lookahead_glyph_id = hi::glyph_id{})
90 const noexcept override;
91
92 [[nodiscard]] vector2 get_kerning(hi::glyph_id current_glyph, hi::glyph_id next_glyph) const noexcept override;
93
95 const noexcept override
96 {
97 }
98
99private:
100 mutable std::span<std::byte const> _cmap_table_bytes;
101 mutable std::span<std::byte const> _cmap_bytes;
102 mutable std::span<std::byte const> _loca_table_bytes;
103 mutable std::span<std::byte const> _glyf_table_bytes;
104 mutable std::span<std::byte const> _hmtx_table_bytes;
105 mutable std::span<std::byte const> _kern_table_bytes;
106 mutable std::span<std::byte const> _GSUB_table_bytes;
107 bool _loca_table_is_offset32;
108
109 void cache_tables() const noexcept
110 {
111 _cmap_table_bytes = get_table_bytes("cmap");
112 _cmap_bytes = parse_cmap_table_directory();
113 _loca_table_bytes = get_table_bytes("loca");
114 _glyf_table_bytes = get_table_bytes("glyf");
115 _hmtx_table_bytes = get_table_bytes("hmtx");
116
117 // Optional tables.
118 _kern_table_bytes = get_table_bytes("kern");
119 _GSUB_table_bytes = get_table_bytes("GSUB");
120 }
121
122 void load_view() const noexcept
123 {
124 if (_view) {
125 [[likely]] return;
126 }
127
128 _view = file_view{_path};
129 ++global_counter<"ttf:map">;
130 cache_tables();
131 }
132
137 [[nodiscard]] std::span<std::byte const> get_table_bytes(char const *table_name) const;
138
144 void parse_font_directory();
145
146 void parse_head_table(std::span<std::byte const> headTableBytes);
147 void parse_hhea_table(std::span<std::byte const> bytes);
148 void parse_name_table(std::span<std::byte const> bytes);
149 void parse_OS2_table(std::span<std::byte const> bytes);
150 void parse_maxp_table(std::span<std::byte const> bytes);
151
152 [[nodiscard]] std::span<std::byte const> parse_cmap_table_directory() const;
153
156 [[nodiscard]] hi::unicode_mask parse_cmap_table_mask() const;
157
161 bool get_glyf_bytes(hi::glyph_id glyph_id, std::span<std::byte const> &bytes) const noexcept;
162
166 bool update_glyph_metrics(
167 hi::glyph_id glyph_id,
168 glyph_metrics &metrics,
169 hi::glyph_id kern_glyph1_id = hi::glyph_id{},
170 hi::glyph_id kern_glyph2_id = hi::glyph_id{}) const noexcept;
171
172 bool load_simple_glyph(std::span<std::byte const> bytes, graphic_path &glyph) const noexcept;
173
182 bool
183 load_compound_glyph(std::span<std::byte const> bytes, graphic_path &glyph, hi::glyph_id &metrics_glyph_id) const noexcept;
184
192 bool load_compound_glyph_metrics(std::span<std::byte const> bytes, hi::glyph_id &metrics_glyph_id) const noexcept;
193
200 [[nodiscard]] std::ptrdiff_t get_coverage_index(std::span<std::byte const> bytes, hi::glyph_id glyph) noexcept;
201};
202
203} // namespace hi::inline v1
Defines the file_view class.
DOXYGEN BUG.
Definition algorithm.hpp:15
A path is a vector graphics object.
Definition graphic_path.hpp:29
ISO-15924 script code.
Definition iso_15924.hpp:19
ISO-639 language code.
Definition iso_639.hpp:25
Definition language.hpp:17
Definition font.hpp:32
Definition glyph_metrics.hpp:17
Definition true_type_font.hpp:17
std::optional< hi::glyph_id > load_glyph(hi::glyph_id glyph_id, graphic_path &path) const noexcept override
Load a glyph into a path.
bool load_glyph_metrics(hi::glyph_id glyph_id, glyph_metrics &metrics, hi::glyph_id lookahead_glyph_id=hi::glyph_id{}) const noexcept override
Load a glyphMetrics into a path.
bool loaded() const noexcept override
Return if the font is loaded.
Definition true_type_font.hpp:62
vector2 get_kerning(hi::glyph_id current_glyph, hi::glyph_id next_glyph) const noexcept override
Get the kerning between two glyphs.
hi::glyph_id find_glyph(char32_t c) const noexcept override
Get the glyph for a code-point.
virtual void substitution_and_kerning(iso_639 language, iso_15924 script, std::vector< substitution_and_kerning_type > &word) const noexcept override
Substitute and kern a run of glyphs.
Definition true_type_font.hpp:94
T what(T... args)