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 "../cast.hpp"
13#include <memory>
14
15namespace hi::inline v1 {
16
17class true_type_font final : public font {
18private:
21 std::optional<URL> url;
22
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:
41 {
42 parse_font_directory();
43 }
44
45 true_type_font(URL const &url) : url(url), view(url.loadView())
46 {
47 ++global_counter<"ttf:map">;
48 try {
49 parse_font_directory();
50
51 // Clear the view to reclaim resources.
52 view = {};
53 ++global_counter<"ttf:unmap">;
54
55 } catch (std::exception const &e) {
56 throw parse_error(std::format("{}: Could not parse font directory.\n{}", to_string(url), e.what()));
57 }
58 }
59
60 true_type_font() = delete;
61 true_type_font(true_type_font const &other) = delete;
62 true_type_font &operator=(true_type_font const &other) = delete;
63 true_type_font(true_type_font &&other) = delete;
64 true_type_font &operator=(true_type_font &&other) = delete;
65 ~true_type_font() = default;
66
67 [[nodiscard]] bool loaded() const noexcept override
68 {
69 return to_bool(view);
70 }
71
75 [[nodiscard]] hi::glyph_id find_glyph(char32_t c) const noexcept override;
76
84 std::optional<hi::glyph_id> load_glyph(hi::glyph_id glyph_id, graphic_path &path) const noexcept override;
85
94 bool load_glyph_metrics(hi::glyph_id glyph_id, glyph_metrics &metrics, hi::glyph_id lookahead_glyph_id = hi::glyph_id{})
95 const noexcept override;
96
97 [[nodiscard]] vector2 get_kerning(hi::glyph_id current_glyph, hi::glyph_id next_glyph) const noexcept override;
98
100 const noexcept override
101 {
102 }
103
104private:
105 mutable std::span<std::byte const> _cmap_table_bytes;
106 mutable std::span<std::byte const> _cmap_bytes;
107 mutable std::span<std::byte const> _loca_table_bytes;
108 mutable std::span<std::byte const> _glyf_table_bytes;
109 mutable std::span<std::byte const> _hmtx_table_bytes;
110 mutable std::span<std::byte const> _kern_table_bytes;
111 mutable std::span<std::byte const> _GSUB_table_bytes;
112 bool _loca_table_is_offset32;
113
114 void cache_tables() const noexcept
115 {
116 _cmap_table_bytes = get_table_bytes("cmap");
117 _cmap_bytes = parse_cmap_table_directory();
118 _loca_table_bytes = get_table_bytes("loca");
119 _glyf_table_bytes = get_table_bytes("glyf");
120 _hmtx_table_bytes = get_table_bytes("hmtx");
121
122 // Optional tables.
123 _kern_table_bytes = get_table_bytes("kern");
124 _GSUB_table_bytes = get_table_bytes("GSUB");
125 }
126
127 void load_view() const noexcept
128 {
129 if (view) {
130 [[likely]] return;
131 }
132
133 hi_axiom(url);
134 view = url->loadView();
135 ++global_counter<"ttf:map">;
136 cache_tables();
137 }
138
143 [[nodiscard]] std::span<std::byte const> get_table_bytes(char const *table_name) const;
144
150 void parse_font_directory();
151
152 void parse_head_table(std::span<std::byte const> headTableBytes);
153 void parse_hhea_table(std::span<std::byte const> bytes);
154 void parse_name_table(std::span<std::byte const> bytes);
155 void parse_OS2_table(std::span<std::byte const> bytes);
156 void parse_maxp_table(std::span<std::byte const> bytes);
157
158 [[nodiscard]] std::span<std::byte const> parse_cmap_table_directory() const;
159
162 [[nodiscard]] hi::unicode_mask parse_cmap_table_mask() const;
163
167 bool get_glyf_bytes(hi::glyph_id glyph_id, std::span<std::byte const> &bytes) const noexcept;
168
172 bool update_glyph_metrics(
173 hi::glyph_id glyph_id,
174 glyph_metrics &metrics,
175 hi::glyph_id kern_glyph1_id = hi::glyph_id{},
176 hi::glyph_id kern_glyph2_id = hi::glyph_id{}) const noexcept;
177
178 bool load_simple_glyph(std::span<std::byte const> bytes, graphic_path &glyph) const noexcept;
179
188 bool
189 load_compound_glyph(std::span<std::byte const> bytes, graphic_path &glyph, hi::glyph_id &metrics_glyph_id) const noexcept;
190
198 bool load_compound_glyph_metrics(std::span<std::byte const> bytes, hi::glyph_id &metrics_glyph_id) const noexcept;
199
206 [[nodiscard]] std::ptrdiff_t get_coverage_index(std::span<std::byte const> bytes, hi::glyph_id glyph) noexcept;
207};
208
209} // 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: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:67
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:99
Definition URL.hpp:47
T move(T... args)
T what(T... args)