7#include "otype_utilities.hpp"
9#include "../macros.hpp"
11hi_export_module(hikogui.font.otype_cmap);
13hi_export
namespace hi {
inline namespace v1 {
15[[nodiscard]]
inline std::span<std::byte const>
16otype_cmap_find(std::span<std::byte const> bytes, uint16_t platform_id, uint16_t platform_specific_id)
19 big_uint16_buf_t version;
20 big_uint16_buf_t num_tables;
24 big_uint16_buf_t platform_id;
25 big_uint16_buf_t platform_specific_id;
26 big_uint32_buf_t offset;
31 auto const& header = implicit_cast<header_type>(offset, bytes);
32 hi_check(*header.version == 0,
"CMAP version is not 0");
34 auto const entries = implicit_cast<entry_type>(offset, bytes, *header.num_tables);
36 auto key = (truncate<uint32_t>(platform_id) << 16) | truncate<uint32_t>(platform_specific_id);
37 if (
auto const entry = fast_binary_search_eq<std::endian::big>(entries, key)) {
38 return hi_check_subspan(bytes, *entry->offset);
44[[nodiscard]]
inline font_char_map otype_cmap_parse_map_4(std::span<std::byte const> over_sized_bytes)
47 big_uint16_buf_t format;
48 big_uint16_buf_t length;
49 big_uint16_buf_t language;
50 big_uint16_buf_t seg_count_x2;
51 big_uint16_buf_t search_range;
52 big_uint16_buf_t entry_selector;
53 big_uint16_buf_t range_shift;
57 auto const& header = implicit_cast<header_type>(offset, over_sized_bytes);
58 hi_axiom(*header.format == 4);
59 auto const length = *header.length;
60 auto const bytes = hi_check_subspan(over_sized_bytes, 0, length);
62 auto const seg_count = *header.seg_count_x2 / 2;
64 auto const end_codes = implicit_cast<big_uint16_buf_t>(offset, bytes, seg_count);
65 offset +=
sizeof(uint16_t);
66 auto const start_codes = implicit_cast<big_uint16_buf_t>(offset, bytes, seg_count);
68 auto const id_deltas = implicit_cast<big_uint16_buf_t>(offset, bytes, seg_count);
70 auto const id_range_offsets = implicit_cast<big_uint16_buf_t>(offset, bytes, seg_count);
72 auto const glyph_id_array_count = (bytes.size() - offset) /
sizeof(big_uint16_buf_t);
73 auto const glyph_id_array = implicit_cast<big_uint16_buf_t>(offset, bytes, glyph_id_array_count);
75 auto r = font_char_map{};
77 auto prev_end_code_point =
char32_t{0};
78 for (
auto i = 0_uz; i != seg_count; ++i) {
79 auto const end_code_point = char_cast<char32_t>(*end_codes[i]);
80 auto const start_code_point = char_cast<char32_t>(*start_codes[i]);
82 hi_check(start_code_point <= end_code_point,
"'cmap' subtable 4, start code-point must come before end code-point.");
84 i == 0 or prev_end_code_point < start_code_point,
85 "'cmap' subtable 4, all entries must be non-overlapping and ordered.");
87 if (start_code_point == 0xffff and end_code_point == 0xffff) {
92 auto id_range_offset = wide_cast<size_t>(*id_range_offsets[i]);
93 if (id_range_offset == 0) {
95 auto start_glyph_id = *id_deltas[i];
96 start_glyph_id += char_cast<uint16_t>(start_code_point);
99 start_glyph_id + (end_code_point - start_code_point) + 1_uz < 0xffff,
100 "'cmap' subtable 4, glyph_id must be in range 0 to 0xfffe.");
101 r.add(start_code_point, end_code_point, start_glyph_id);
108 id_range_offset /=
sizeof(big_uint16_buf_t);
110 id_range_offset -= seg_count - i;
113 auto const code_point_count = end_code_point - start_code_point + 1;
114 for (
auto j = 0_uz; j != code_point_count; ++j) {
115 auto const code_point = char_cast<char32_t>(start_code_point + j);
117 auto const glyph_id = *hi_check_at(glyph_id_array, id_range_offset + j);
118 hi_check(glyph_id < 0xfffe,
"'cmap' subtable 4, glyph_id must be in range 0 to 0xfffe.");
119 r.add(code_point, code_point, glyph_id);
123 prev_end_code_point = end_code_point;
130[[nodiscard]]
inline font_char_map otype_cmap_parse_map_6(std::span<std::byte const> over_sized_bytes)
133 big_uint16_buf_t format;
134 big_uint16_buf_t length;
135 big_uint16_buf_t language;
136 big_uint16_buf_t first_code;
137 big_uint16_buf_t entry_count;
141 auto const& header = implicit_cast<header_type>(offset, over_sized_bytes);
142 hi_axiom(*header.format == 6);
143 auto const bytes = hi_check_subspan(over_sized_bytes, 0, *header.length);
145 auto const entry_count = *header.entry_count;
146 auto const entries = implicit_cast<big_uint16_buf_t>(offset, bytes, entry_count);
148 auto r = font_char_map{};
149 r.reserve(entry_count);
150 auto code_point = char_cast<char32_t>(*header.first_code);
151 for (
auto i = 0_uz; i != entry_count; ++i, ++code_point) {
152 auto const glyph_id = *entries[i];
153 hi_check(glyph_id < 0xfffe,
"'cmap' subtable 6, glyph_id must be in range 0 to 0xfffe.");
154 r.add(code_point, code_point, glyph_id);
162[[nodiscard]]
inline font_char_map otype_cmap_parse_map_12(std::span<std::byte const> over_sized_bytes)
165 big_uint16_buf_t format;
166 big_uint16_buf_t reserved;
167 big_uint32_buf_t length;
168 big_uint32_buf_t language;
169 big_uint32_buf_t num_groups;
173 big_uint32_buf_t start_char_code;
174 big_uint32_buf_t end_char_code;
175 big_uint32_buf_t start_glyph_id;
179 auto const& header = implicit_cast<header_type>(offset, over_sized_bytes);
180 hi_axiom(*header.format == 12);
181 auto const bytes = hi_check_subspan(over_sized_bytes, 0, *header.length);
183 auto const entries = implicit_cast<entry_type>(offset, bytes, *header.num_groups);
185 auto r = font_char_map{};
186 r.reserve(*header.num_groups);
187 for (
auto const& entry : entries) {
188 auto const start_code_point = char_cast<char32_t>(*entry.start_char_code);
189 auto const end_code_point = char_cast<char32_t>(*entry.end_char_code);
190 hi_check(start_code_point <= end_code_point,
"'cmap' subtable 12, has invalid code-point range.");
192 auto const start_glyph_id = *entry.start_glyph_id;
194 start_glyph_id + (end_code_point - start_code_point) + 1_uz < 0xffff,
195 "'cmap' subtable 12, glyph_id must be in range 0 to 0xfffe.");
196 r.add(start_code_point, end_code_point, narrow_cast<uint16_t>(start_glyph_id));
204[[nodiscard]]
inline font_char_map otype_cmap_parse_map(std::span<std::byte const> bytes)
207 auto const format = *implicit_cast<big_uint16_buf_t>(bytes);
211 return otype_cmap_parse_map_4(bytes);
213 return otype_cmap_parse_map_6(bytes);
215 return otype_cmap_parse_map_12(bytes);
222[[nodiscard]]
inline font_char_map otype_cmap_parse(std::span<std::byte const> bytes)
234 for (
auto const[platform_id, platform_specific_id] : search_order) {
235 if (
auto const map_bytes = otype_cmap_find(bytes, platform_id, platform_specific_id); not map_bytes.empty()) {
236 if (
auto r = otype_cmap_parse_map(map_bytes); not r.empty()) {
242 throw parse_error(
"'cmap' no compatible character map found.");
Defined font_char_map type.
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20