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"
8#include "../graphic_path.hpp"
9#include "../resource_view.hpp"
10#include "../counters.hpp"
11#include "../cast.hpp"
12#include "../file_view.hpp"
13#include <memory>
14#include <filesystem>
15
16namespace hi::inline v1 {
17
18class true_type_font final : public font {
19private:
22 std::optional<std::filesystem::path> _path;
23
29
30 uint16_t OS2_x_height = 0;
31 uint16_t OS2_cap_height = 0;
32
33 float unitsPerEm;
34 float emScale;
35
36 uint16_t numberOfHMetrics;
37
38 int num_glyphs;
39
40public:
42 {
43 parse_font_directory();
44 }
45
46 true_type_font(std::filesystem::path const& path) : _path(path), view(std::make_unique<file_view>(path))
47 {
48 ++global_counter<"ttf:map">;
49 try {
50 parse_font_directory();
51
52 // Clear the view to reclaim resources.
53 view = {};
54 ++global_counter<"ttf:unmap">;
55
56 } catch (std::exception const &e) {
57 throw parse_error(std::format("{}: Could not parse font directory.\n{}", path.string(), e.what()));
58 }
59 }
60
61 true_type_font() = delete;
62 true_type_font(true_type_font const &other) = delete;
63 true_type_font &operator=(true_type_font const &other) = delete;
64 true_type_font(true_type_font &&other) = delete;
65 true_type_font &operator=(true_type_font &&other) = delete;
66 ~true_type_font() = default;
67
68 [[nodiscard]] bool loaded() const noexcept override
69 {
70 return to_bool(view);
71 }
72
76 [[nodiscard]] hi::glyph_id find_glyph(char32_t c) const noexcept override;
77
85 std::optional<hi::glyph_id> load_glyph(hi::glyph_id glyph_id, graphic_path &path) const noexcept override;
86
95 bool load_glyph_metrics(hi::glyph_id glyph_id, glyph_metrics &metrics, hi::glyph_id lookahead_glyph_id = hi::glyph_id{})
96 const noexcept override;
97
98 [[nodiscard]] vector2 get_kerning(hi::glyph_id current_glyph, hi::glyph_id next_glyph) const noexcept override;
99
101 const noexcept override
102 {
103 }
104
105private:
106 mutable std::span<std::byte const> _cmap_table_bytes;
107 mutable std::span<std::byte const> _cmap_bytes;
108 mutable std::span<std::byte const> _loca_table_bytes;
109 mutable std::span<std::byte const> _glyf_table_bytes;
110 mutable std::span<std::byte const> _hmtx_table_bytes;
111 mutable std::span<std::byte const> _kern_table_bytes;
112 mutable std::span<std::byte const> _GSUB_table_bytes;
113 bool _loca_table_is_offset32;
114
115 void cache_tables() const noexcept
116 {
117 _cmap_table_bytes = get_table_bytes("cmap");
118 _cmap_bytes = parse_cmap_table_directory();
119 _loca_table_bytes = get_table_bytes("loca");
120 _glyf_table_bytes = get_table_bytes("glyf");
121 _hmtx_table_bytes = get_table_bytes("hmtx");
122
123 // Optional tables.
124 _kern_table_bytes = get_table_bytes("kern");
125 _GSUB_table_bytes = get_table_bytes("GSUB");
126 }
127
128 void load_view() const noexcept
129 {
130 if (view) {
131 [[likely]] return;
132 }
133
134 hi_axiom(_path);
135 view = std::make_unique<file_view>(*_path);
136 ++global_counter<"ttf:map">;
137 cache_tables();
138 }
139
144 [[nodiscard]] std::span<std::byte const> get_table_bytes(char const *table_name) const;
145
151 void parse_font_directory();
152
153 void parse_head_table(std::span<std::byte const> headTableBytes);
154 void parse_hhea_table(std::span<std::byte const> bytes);
155 void parse_name_table(std::span<std::byte const> bytes);
156 void parse_OS2_table(std::span<std::byte const> bytes);
157 void parse_maxp_table(std::span<std::byte const> bytes);
158
159 [[nodiscard]] std::span<std::byte const> parse_cmap_table_directory() const;
160
163 [[nodiscard]] hi::unicode_mask parse_cmap_table_mask() const;
164
168 bool get_glyf_bytes(hi::glyph_id glyph_id, std::span<std::byte const> &bytes) const noexcept;
169
173 bool update_glyph_metrics(
174 hi::glyph_id glyph_id,
175 glyph_metrics &metrics,
176 hi::glyph_id kern_glyph1_id = hi::glyph_id{},
177 hi::glyph_id kern_glyph2_id = hi::glyph_id{}) const noexcept;
178
179 bool load_simple_glyph(std::span<std::byte const> bytes, graphic_path &glyph) const noexcept;
180
189 bool
190 load_compound_glyph(std::span<std::byte const> bytes, graphic_path &glyph, hi::glyph_id &metrics_glyph_id) const noexcept;
191
199 bool load_compound_glyph_metrics(std::span<std::byte const> bytes, hi::glyph_id &metrics_glyph_id) const noexcept;
200
207 [[nodiscard]] std::ptrdiff_t get_coverage_index(std::span<std::byte const> bytes, hi::glyph_id glyph) noexcept;
208};
209
210} // namespace hi::inline v1
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:18
ISO-639 language code.
Definition iso_639.hpp:25
Definition language.hpp:18
Definition font.hpp:34
Definition glyph_metrics.hpp:17
Definition true_type_font.hpp:18
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:68
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:100
T move(T... args)
T what(T... args)