7#include "otype_utilities.hpp"
9#include "../generator.hpp"
12namespace hi {
inline namespace v1 {
14constexpr uint16_t otype_glyf_flag_arg1_and_arg2_are_words = 0x0001;
15constexpr uint16_t otype_glyf_flag_args_are_xy_values = 0x0002;
16constexpr uint16_t otype_glyf_flag_round_xy_to_grid = 0x0004;
17constexpr uint16_t otype_glyf_flag_has_scale = 0x0008;
18constexpr uint16_t otype_glyf_flag_more_components = 0x0020;
19constexpr uint16_t otype_glyf_flag_has_xy_scale = 0x0040;
20constexpr uint16_t otype_glyf_flag_has_2x2 = 0x0080;
21constexpr uint16_t otype_glyf_flag_instructions = 0x0100;
22constexpr uint16_t otype_glyf_flag_use_this_glyph_metrics = 0x0200;
23constexpr uint16_t otype_glyf_flag_overlap_compound = 0x0400;
24constexpr uint16_t otype_glyf_flag_scaled_component_offset = 0x0800;
25constexpr uint16_t otype_glyf_flag_unscaled_component_offset = 0x1000;
27constexpr uint8_t otype_glyf_flag_on_curve = 0x01;
28constexpr uint8_t otype_glyf_flag_x_short = 0x02;
29constexpr uint8_t otype_glyf_flag_y_short = 0x04;
30constexpr uint8_t otype_glyf_flag_repeat = 0x08;
31constexpr uint8_t otype_glyf_flag_x_same = 0x10;
32constexpr uint8_t otype_glyf_flag_y_same = 0x20;
35 big_int16_buf_t num_contours;
49[[nodiscard]]
inline graphic_path
52 auto r = graphic_path{};
60 hilet& header = implicit_cast<detail::otype_glyf_header>(offset, bytes);
61 hilet num_contours = *header.num_contours;
63 hi_check(num_contours >= 0,
"'glyph' path requested on a compound glyph.");
66 hilet end_points = implicit_cast<big_uint16_buf_t>(offset, bytes, num_contours);
68 r.contourEndPoints.reserve(end_points.size());
69 uint16_t max_end_point = 0;
70 for (
hilet end_point : end_points) {
71 hilet end_point_ = *end_point;
73 hi_check(end_point_ >= max_end_point,
"'glyf' end-point indices must be increasing");
74 max_end_point = end_point_;
76 r.contourEndPoints.push_back(end_point_);
79 hilet num_points = wide_cast<size_t>(max_end_point) + 1;
82 hilet instruction_size = *implicit_cast<big_uint16_buf_t>(offset, bytes);
83 offset += instruction_size;
87 for (
auto i = 0_uz; i != num_points; ++i) {
88 hilet flag = implicit_cast<uint8_t>(offset, bytes);
91 if (to_bool(flag & detail::otype_glyf_flag_repeat)) {
92 hilet repeat = implicit_cast<uint8_t>(offset, bytes);
94 hi_check(i + repeat <= num_points,
"'glyf' repeating flags out-of-bound");
103 for (
auto i = 0_uz; i != num_points; ++i) {
104 hilet flag = flags[i];
106 if (to_bool(flag & detail::otype_glyf_flag_x_short)) {
107 if (to_bool(flag & detail::otype_glyf_flag_x_same)) {
108 x_deltas[i] = wide_cast<int16_t>(implicit_cast<uint8_t>(offset, bytes));
111 x_deltas[i] = -wide_cast<int16_t>(implicit_cast<uint8_t>(offset, bytes));
114 if (to_bool(flag & detail::otype_glyf_flag_x_same)) {
118 x_deltas[i] = *implicit_cast<big_int16_buf_t>(offset, bytes);
125 for (
auto i = 0_uz; i != num_points; ++i) {
126 hilet flag = flags[i];
128 if (to_bool(flag & detail::otype_glyf_flag_y_short)) {
129 if (to_bool(flag & detail::otype_glyf_flag_y_same)) {
130 y_deltas[i] = wide_cast<int16_t>(implicit_cast<uint8_t>(offset, bytes));
133 y_deltas[i] = -wide_cast<int16_t>(implicit_cast<uint8_t>(offset, bytes));
136 if (to_bool(flag & detail::otype_glyf_flag_y_same)) {
140 y_deltas[i] = *implicit_cast<big_int16_buf_t>(offset, bytes);
148 r.points.reserve(num_points);
149 for (
auto i = 0_uz; i != num_points; ++i) {
150 hilet flag = flags[i];
155 to_bool(flag & detail::otype_glyf_flag_on_curve) ? bezier_point::Type::Anchor : bezier_point::Type::QuadraticControl;
157 r.points.emplace_back(x * em_scale, y * em_scale, type);
164 hi::glyph_id glyph_id = {};
198 hilet& header = implicit_cast<detail::otype_glyf_header>(offset, bytes);
200 hi_check(*header.num_contours < 0,
"'glyph' compound requested on a simple glyph.");
204 flags = *implicit_cast<big_uint16_buf_t>(offset, bytes);
207 component.glyph_id = glyph_id{*implicit_cast<big_uint16_buf_t>(offset, bytes)};
209 if (to_bool(flags & detail::otype_glyf_flag_args_are_xy_values)) {
210 if (to_bool(flags & detail::otype_glyf_flag_arg1_and_arg2_are_words)) {
211 hilet tmp = implicit_cast<otype_fword_buf_t>(offset, bytes, 2);
212 component.offset = vector2{tmp[0] * em_scale, tmp[1] * em_scale};
214 hilet tmp = implicit_cast<otype_fbyte_buf_t>(offset, bytes, 2);
215 component.offset = vector2{tmp[0] * em_scale, tmp[1] * em_scale};
218 component.use_points =
true;
219 if (to_bool(flags & detail::otype_glyf_flag_arg1_and_arg2_are_words)) {
220 hilet tmp = implicit_cast<big_uint16_buf_t>(offset, bytes, 2);
221 component.compound_point_index = *tmp[0];
222 component.component_point_index = *tmp[1];
224 hilet tmp = implicit_cast<uint8_t>(offset, bytes, 2);
225 component.compound_point_index = tmp[0];
226 component.component_point_index = tmp[1];
231 if (to_bool(flags & detail::otype_glyf_flag_has_scale)) {
232 component.scale = scale2(*implicit_cast<otype_fixed1_14_buf_t>(offset, bytes));
234 }
else if (to_bool(flags & detail::otype_glyf_flag_has_xy_scale)) {
235 hilet tmp = implicit_cast<otype_fixed1_14_buf_t>(offset, bytes, 2);
236 component.scale = scale2(*tmp[0], *tmp[1]);
238 }
else if (to_bool(flags & detail::otype_glyf_flag_has_2x2)) {
239 hilet tmp = implicit_cast<otype_fixed1_14_buf_t>(offset, bytes, 4);
240 component.scale =
matrix2{vector2{*tmp[0], *tmp[1]}, vector2{*tmp[2], *tmp[3]}};
243 if (to_bool(flags & detail::otype_glyf_flag_scaled_component_offset)) {
244 component.offset = component.scale * component.offset;
247 if (to_bool(flags & detail::otype_glyf_flag_use_this_glyph_metrics)) {
248 component.use_for_metrics =
true;
253 }
while (to_bool(flags & detail::otype_glyf_flag_more_components));
263 big_int16_buf_t num_contours;
275 hilet& header = implicit_cast<detail::otype_glyf_header>(bytes);
276 return *header.num_contours < 0;
287 big_int16_buf_t num_contours;
299 hilet& header = implicit_cast<detail::otype_glyf_header>(bytes);
301 hilet x_min = header.x_min * em_scale;
302 hilet y_min = header.y_min * em_scale;
303 hilet x_max = header.x_max * em_scale;
304 hilet y_max = header.y_max * em_scale;
306 hi_check(x_min <= x_max,
"'glyf' bounding box is invalid.");
307 hi_check(y_min <= y_max,
"'glyf' bounding box is invalid.");
309 return aarectangle{point2{x_min, y_min}, point2{x_max, y_max}};
Defined font_char_map type.
#define hi_check(expression, message,...)
Check if the expression is valid, or throw a parse_error.
Definition assert.hpp:110
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
geo::matrix< 2 > matrix2
A 2D homogenious transformation matrix.
Definition matrix.hpp:610
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:260
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:284
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:50
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:190
Definition otype_glyf.hpp:34
Definition otype_glyf.hpp:163
bool use_points
The component is positioned using anchor points.
Definition otype_glyf.hpp:178
size_t component_point_index
The point in the current component being added to the compound.
Definition otype_glyf.hpp:174
bool use_for_metrics
Use this glyph for the metrics of the compound.
Definition otype_glyf.hpp:182
size_t compound_point_index
The point-nr in the compound being assembled.
Definition otype_glyf.hpp:170
Open-type for 16 signed integer that must be scaled by the EM-scale.
Definition otype_utilities.hpp:37
Class which represents an axis-aligned rectangle.
Definition axis_aligned_rectangle.hpp:27