HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
true_type_font.hpp
1// Copyright Take Vos 2019-2021.
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 "../URL.hpp"
11#include "../counters.hpp"
12#include <memory>
13
14namespace hi::inline v1 {
15
16class true_type_font final : public font {
17private:
20 std::optional<URL> url;
21
27
28 uint16_t OS2_x_height = 0;
29 uint16_t OS2_cap_height = 0;
30
31 float unitsPerEm;
32 float emScale;
33
34 uint16_t numberOfHMetrics;
35
36 int num_glyphs;
37
38public:
40 {
41 parse_font_directory();
42 }
43
44 true_type_font(URL const &url) : url(url), view(url.loadView())
45 {
46 ++global_counter<"ttf:map">;
47 try {
48 parse_font_directory();
49
50 // Clear the view to reclaim resources.
51 view = {};
52 ++global_counter<"ttf:unmap">;
53
54 } catch (std::exception const &e) {
55 throw parse_error(std::format("{}: Could not parse font directory.\n{}", to_string(url), e.what()));
56 }
57 }
58
59 true_type_font() = delete;
60 true_type_font(true_type_font const &other) = delete;
61 true_type_font &operator=(true_type_font const &other) = delete;
62 true_type_font(true_type_font &&other) = delete;
63 true_type_font &operator=(true_type_font &&other) = delete;
64 ~true_type_font() = default;
65
66 [[nodiscard]] bool loaded() const noexcept override
67 {
68 return static_cast<bool>(view);
69 }
70
74 [[nodiscard]] hi::glyph_id find_glyph(char32_t c) const noexcept override;
75
83 std::optional<hi::glyph_id> load_glyph(hi::glyph_id glyph_id, graphic_path &path) const noexcept override;
84
93 bool load_glyph_metrics(hi::glyph_id glyph_id, glyph_metrics &metrics, hi::glyph_id lookahead_glyph_id = hi::glyph_id{})
94 const noexcept override;
95
96 [[nodiscard]] vector2 get_kerning(hi::glyph_id current_glyph, hi::glyph_id next_glyph) const noexcept override;
97
99 const noexcept override
100 {
101 }
102
103private:
104 mutable std::span<std::byte const> _cmap_table_bytes;
105 mutable std::span<std::byte const> _cmap_bytes;
106 mutable std::span<std::byte const> _loca_table_bytes;
107 mutable std::span<std::byte const> _glyf_table_bytes;
108 mutable std::span<std::byte const> _hmtx_table_bytes;
109 mutable std::span<std::byte const> _kern_table_bytes;
110 mutable std::span<std::byte const> _GSUB_table_bytes;
111 bool _loca_table_is_offset32;
112
113 void cache_tables() const noexcept
114 {
115 _cmap_table_bytes = get_table_bytes("cmap");
116 _cmap_bytes = parse_cmap_table_directory();
117 _loca_table_bytes = get_table_bytes("loca");
118 _glyf_table_bytes = get_table_bytes("glyf");
119 _hmtx_table_bytes = get_table_bytes("hmtx");
120
121 // Optional tables.
122 _kern_table_bytes = get_table_bytes("kern");
123 _GSUB_table_bytes = get_table_bytes("GSUB");
124 }
125
126 void load_view() const noexcept
127 {
128 if (view) {
129 [[likely]] return;
130 }
131
132 hi_axiom(url);
133 view = url->loadView();
134 ++global_counter<"ttf:map">;
135 cache_tables();
136 }
137
142 [[nodiscard]] std::span<std::byte const> get_table_bytes(char const *table_name) const;
143
149 void parse_font_directory();
150
151 void parse_head_table(std::span<std::byte const> headTableBytes);
152 void parse_hhea_table(std::span<std::byte const> bytes);
153 void parse_name_table(std::span<std::byte const> bytes);
154 void parse_OS2_table(std::span<std::byte const> bytes);
155 void parse_maxp_table(std::span<std::byte const> bytes);
156
157 [[nodiscard]] std::span<std::byte const> parse_cmap_table_directory() const;
158
161 [[nodiscard]] hi::unicode_mask parse_cmap_table_mask() const;
162
166 bool get_glyf_bytes(hi::glyph_id glyph_id, std::span<std::byte const> &bytes) const noexcept;
167
171 bool update_glyph_metrics(
172 hi::glyph_id glyph_id,
173 glyph_metrics &metrics,
174 hi::glyph_id kern_glyph1_id = hi::glyph_id{},
175 hi::glyph_id kern_glyph2_id = hi::glyph_id{}) const noexcept;
176
177 bool load_simple_glyph(std::span<std::byte const> bytes, graphic_path &glyph) const noexcept;
178
187 bool
188 load_compound_glyph(std::span<std::byte const> bytes, graphic_path &glyph, hi::glyph_id &metrics_glyph_id) const noexcept;
189
197 bool load_compound_glyph_metrics(std::span<std::byte const> bytes, hi::glyph_id &metrics_glyph_id) const noexcept;
198
205 [[nodiscard]] std::ptrdiff_t get_coverage_index(std::span<std::byte const> bytes, hi::glyph_id glyph) noexcept;
206};
207
208} // namespace hi::inline v1
Exception thrown during parsing on an error.
Definition exception.hpp:25
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:16
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:66
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:98
Definition URL.hpp:47
T move(T... args)
T what(T... args)