7#include "otype_utilities.hpp"
9#include "../macros.hpp"
13hi_export_module(hikogui.font.otype_glyf);
15hi_export
namespace hi {
inline namespace v1 {
17constexpr uint16_t otype_glyf_flag_arg1_and_arg2_are_words = 0x0001;
18constexpr uint16_t otype_glyf_flag_args_are_xy_values = 0x0002;
19constexpr uint16_t otype_glyf_flag_round_xy_to_grid = 0x0004;
20constexpr uint16_t otype_glyf_flag_has_scale = 0x0008;
21constexpr uint16_t otype_glyf_flag_more_components = 0x0020;
22constexpr uint16_t otype_glyf_flag_has_xy_scale = 0x0040;
23constexpr uint16_t otype_glyf_flag_has_2x2 = 0x0080;
24constexpr uint16_t otype_glyf_flag_instructions = 0x0100;
25constexpr uint16_t otype_glyf_flag_use_this_glyph_metrics = 0x0200;
26constexpr uint16_t otype_glyf_flag_overlap_compound = 0x0400;
27constexpr uint16_t otype_glyf_flag_scaled_component_offset = 0x0800;
28constexpr uint16_t otype_glyf_flag_unscaled_component_offset = 0x1000;
30constexpr uint8_t otype_glyf_flag_on_curve = 0x01;
31constexpr uint8_t otype_glyf_flag_x_short = 0x02;
32constexpr uint8_t otype_glyf_flag_y_short = 0x04;
33constexpr uint8_t otype_glyf_flag_repeat = 0x08;
34constexpr uint8_t otype_glyf_flag_x_same = 0x10;
35constexpr uint8_t otype_glyf_flag_y_same = 0x20;
63 auto const& header = implicit_cast<detail::otype_glyf_header>(offset, bytes);
64 auto const num_contours = *header.num_contours;
66 hi_check(num_contours >= 0,
"'glyph' path requested on a compound glyph.");
69 auto const end_points = implicit_cast<big_uint16_buf_t>(offset, bytes, num_contours);
71 r.contourEndPoints.reserve(end_points.size());
72 uint16_t max_end_point = 0;
73 for (
auto const end_point : end_points) {
74 auto const end_point_ = *end_point;
76 hi_check(end_point_ >= max_end_point,
"'glyf' end-point indices must be increasing");
77 max_end_point = end_point_;
79 r.contourEndPoints.push_back(end_point_);
82 auto const num_points = wide_cast<size_t>(max_end_point) + 1;
85 auto const instruction_size = *implicit_cast<big_uint16_buf_t>(offset, bytes);
86 offset += instruction_size;
90 for (
auto i = 0_uz; i != num_points; ++i) {
91 auto const flag = implicit_cast<uint8_t>(offset, bytes);
94 if (to_bool(flag & detail::otype_glyf_flag_repeat)) {
95 auto const repeat = implicit_cast<uint8_t>(offset, bytes);
97 hi_check(i + repeat <= num_points,
"'glyf' repeating flags out-of-bound");
106 for (
auto i = 0_uz; i != num_points; ++i) {
107 auto const flag = flags[i];
109 if (to_bool(flag & detail::otype_glyf_flag_x_short)) {
110 if (to_bool(flag & detail::otype_glyf_flag_x_same)) {
111 x_deltas[i] = wide_cast<int16_t>(implicit_cast<uint8_t>(offset, bytes));
114 x_deltas[i] = -wide_cast<int16_t>(implicit_cast<uint8_t>(offset, bytes));
117 if (to_bool(flag & detail::otype_glyf_flag_x_same)) {
121 x_deltas[i] = *implicit_cast<big_int16_buf_t>(offset, bytes);
128 for (
auto i = 0_uz; i != num_points; ++i) {
129 auto const flag = flags[i];
131 if (to_bool(flag & detail::otype_glyf_flag_y_short)) {
132 if (to_bool(flag & detail::otype_glyf_flag_y_same)) {
133 y_deltas[i] = wide_cast<int16_t>(implicit_cast<uint8_t>(offset, bytes));
136 y_deltas[i] = -wide_cast<int16_t>(implicit_cast<uint8_t>(offset, bytes));
139 if (to_bool(flag & detail::otype_glyf_flag_y_same)) {
143 y_deltas[i] = *implicit_cast<big_int16_buf_t>(offset, bytes);
151 r.points.reserve(num_points);
152 for (
auto i = 0_uz; i != num_points; ++i) {
153 auto const flag = flags[i];
158 to_bool(flag & detail::otype_glyf_flag_on_curve) ? bezier_point::Type::Anchor : bezier_point::Type::QuadraticControl;
160 r.points.emplace_back(x * em_scale, y * em_scale, type);
167 hi::glyph_id glyph_id = {};
201 auto const& header = implicit_cast<detail::otype_glyf_header>(offset, bytes);
203 hi_check(*header.num_contours < 0,
"'glyph' compound requested on a simple glyph.");
207 flags = *implicit_cast<big_uint16_buf_t>(offset, bytes);
210 component.glyph_id = glyph_id{*implicit_cast<big_uint16_buf_t>(offset, bytes)};
212 if (to_bool(flags & detail::otype_glyf_flag_args_are_xy_values)) {
213 if (to_bool(flags & detail::otype_glyf_flag_arg1_and_arg2_are_words)) {
214 auto const tmp = implicit_cast<otype_fword_buf_t>(offset, bytes, 2);
215 component.offset =
vector2{tmp[0] * em_scale, tmp[1] * em_scale};
217 auto const tmp = implicit_cast<otype_fbyte_buf_t>(offset, bytes, 2);
218 component.offset =
vector2{tmp[0] * em_scale, tmp[1] * em_scale};
221 component.use_points =
true;
222 if (to_bool(flags & detail::otype_glyf_flag_arg1_and_arg2_are_words)) {
223 auto const tmp = implicit_cast<big_uint16_buf_t>(offset, bytes, 2);
224 component.compound_point_index = *tmp[0];
225 component.component_point_index = *tmp[1];
227 auto const tmp = implicit_cast<uint8_t>(offset, bytes, 2);
228 component.compound_point_index = tmp[0];
229 component.component_point_index = tmp[1];
234 if (to_bool(flags & detail::otype_glyf_flag_has_scale)) {
235 component.scale =
scale2(*implicit_cast<otype_fixed1_14_buf_t>(offset, bytes));
237 }
else if (to_bool(flags & detail::otype_glyf_flag_has_xy_scale)) {
238 auto const tmp = implicit_cast<otype_fixed1_14_buf_t>(offset, bytes, 2);
239 component.scale =
scale2(*tmp[0], *tmp[1]);
241 }
else if (to_bool(flags & detail::otype_glyf_flag_has_2x2)) {
242 auto const tmp = implicit_cast<otype_fixed1_14_buf_t>(offset, bytes, 4);
246 if (to_bool(flags & detail::otype_glyf_flag_scaled_component_offset)) {
247 component.offset = component.scale * component.offset;
250 if (to_bool(flags & detail::otype_glyf_flag_use_this_glyph_metrics)) {
251 component.use_for_metrics =
true;
256 }
while (to_bool(flags & detail::otype_glyf_flag_more_components));
278 auto const& header = implicit_cast<detail::otype_glyf_header>(bytes);
279 return *header.num_contours < 0;
302 auto const& header = implicit_cast<detail::otype_glyf_header>(bytes);
304 auto const x_min = header.x_min * em_scale;
305 auto const y_min = header.y_min * em_scale;
306 auto const x_max = header.x_max * em_scale;
307 auto const y_max = header.y_max * em_scale;
309 hi_check(x_min <= x_max,
"'glyf' bounding box is invalid.");
310 hi_check(y_min <= y_max,
"'glyf' bounding box is invalid.");
312 return aarectangle{point2{x_min, y_min}, point2{x_max, y_max}};
Defined font_char_map type.
The HikoGUI namespace.
Definition array_generic.hpp:20
bool otype_glyf_is_compound(std::span< std::byte const > bytes)
Check if this glyph is a compound or simple glyph.
Definition otype_glyf.hpp:263
aarectangle otype_glyf_get_bounding_box(std::span< std::byte const > bytes, float em_scale)
Get the bounding box of a simple glyph.
Definition otype_glyf.hpp:287
graphic_path otype_glyf_get_path(std::span< std::byte const > bytes, float em_scale)
Get the graphic-path of a simple glyph.
Definition otype_glyf.hpp:53
generator< otype_glyf_component > otype_glyf_get_compound(std::span< std::byte const > bytes, float em_scale)
Get the components of a compound glyph.
Definition otype_glyf.hpp:193
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition otype_glyf.hpp:37
Definition otype_glyf.hpp:166
bool use_points
The component is positioned using anchor points.
Definition otype_glyf.hpp:181
size_t component_point_index
The point in the current component being added to the compound.
Definition otype_glyf.hpp:177
bool use_for_metrics
Use this glyph for the metrics of the compound.
Definition otype_glyf.hpp:185
size_t compound_point_index
The point-nr in the compound being assembled.
Definition otype_glyf.hpp:173
Open-type for 16 signed integer that must be scaled by the EM-scale.
Definition otype_utilities.hpp:40
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:33
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix2.hpp:39
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector2.hpp:27
A path is a vector graphics object.
Definition graphic_path.hpp:29