8#include "glyph_atlas_info.hpp"
9#include "../graphic_path.hpp"
10#include "../geometry/axis_aligned_rectangle.hpp"
23hi_warning_ignore_msvc(26401)
26hi_warning_ignore_msvc(26409)
28namespace hi::inline v1 {
35 constexpr glyph_ids_long(glyph_ids_long
const &)
noexcept =
default;
36 constexpr glyph_ids_long(glyph_ids_long &&) noexcept = default;
37 constexpr glyph_ids_long &operator=(glyph_ids_long const &) noexcept = default;
38 constexpr glyph_ids_long &operator=(glyph_ids_long &&) noexcept = default;
45 constexpr glyph_ids_long(
std::
size_t value, glyph_id new_id) noexcept : _num_glyphs(), _num_graphemes(), _glyphs()
49 _num_graphemes = (value >> 4) & 0xf;
50 std::get<0>(_glyphs) = glyph_id{(value >> 16) & 0xffff};
51 std::get<1>(_glyphs) = new_id;
54 _num_graphemes = (value >> 4) & 0xf;
55 std::get<0>(_glyphs) = glyph_id{(value >> 16) & 0xffff};
56 std::get<1>(_glyphs) = glyph_id{(value >> 32) & 0xffff};
57 std::get<2>(_glyphs) = glyph_id{(value >> 48) & 0xffff};
58 std::get<3>(_glyphs) = new_id;
62 [[nodiscard]]
constexpr std::size_t num_glyphs() const noexcept
67 [[nodiscard]]
constexpr std::size_t num_graphemes() const noexcept
69 return _num_graphemes;
72 constexpr void set_num_graphemes(
std::size_t num_graphemes)
noexcept
74 hi_axiom(num_graphemes <= 0xf);
75 _num_graphemes = narrow_cast<uint8_t>(num_graphemes);
78 [[nodiscard]]
constexpr std::size_t hash() const noexcept
82 for (
auto i = 0_uz; i != _num_glyphs; ++i) {
84 r ^= std::rotl(r, 16);
90 constexpr glyph_ids_long &operator+=(glyph_id
id)
noexcept
93 if (_num_glyphs < _glyphs.size()) {
94 _glyphs[_num_glyphs++] = id;
99 [[nodiscard]]
constexpr glyph_id
const &operator[](
std::size_t i)
const noexcept
101 hi_axiom(i < _num_glyphs);
105 template<std::
size_t I>
106 [[nodiscard]]
constexpr friend glyph_id get(glyph_ids_long
const &rhs)
noexcept
108 hi_axiom(I < rhs._num_glyphs);
109 return std::get<I>(rhs._glyphs);
112 [[nodiscard]]
constexpr friend bool operator==(glyph_ids_long
const &, glyph_ids_long
const &)
noexcept =
default;
116 uint8_t _num_graphemes;
137 constexpr ~glyph_ids()
144 constexpr glyph_ids(glyph_ids
const &other) noexcept : _font(other._font), _ptr(other._ptr)
147 _ptr =
new detail::glyph_ids_long(*_ptr);
151 constexpr glyph_ids &operator=(glyph_ids
const &other)
noexcept
153 hi_return_on_self_assignment(other);
161 _ptr =
new detail::glyph_ids_long(*_ptr);
166 constexpr glyph_ids(glyph_ids &&other) noexcept : _font(other._font), _ptr(std::exchange(other._ptr, make_ptr(1))) {}
168 constexpr glyph_ids &operator=(glyph_ids &&other)
noexcept
180 constexpr glyph_ids() noexcept : _font(
nullptr), _ptr(make_ptr(1)) {}
188 constexpr glyph_ids(hi::font
const &font) noexcept : _font(&font), _ptr(make_ptr(1)) {}
192 [[nodiscard]]
constexpr font
const &font() const noexcept
200 void set_font(hi::font
const &font)
noexcept
209 constexpr void clear() noexcept
219 [[nodiscard]]
constexpr bool empty() const noexcept
221 return _ptr == make_ptr(1);
226 constexpr operator bool() const noexcept
238 template<std::
size_t N>
239 [[nodiscard]]
constexpr bool has_num_glyphs() const noexcept
241 static_assert(N <= num_glyphs_mask);
243 constexpr std::size_t mask = (num_glyphs_mask << num_glyphs_shift) | 1;
244 constexpr std::size_t value = (N << num_glyphs_shift) | 1;
245 return (make_value(_ptr) & mask) == value;
250 [[nodiscard]]
constexpr glyph_id get_single() const noexcept
252 hi_axiom(has_num_glyphs<1>());
258 [[nodiscard]]
constexpr std::size_t num_glyphs() const noexcept
260 return is_long() ? _ptr->num_glyphs() : (make_value(_ptr) >> 1) & num_glyphs_mask;
263 [[nodiscard]]
constexpr std::size_t num_graphemes() const noexcept
265 return is_long() ? _ptr->num_graphemes() : (make_value(_ptr) >> 4) & 0xf;
268 constexpr void set_num_graphemes(
std::size_t num_graphemes)
noexcept
271 _ptr->set_num_graphemes(num_graphemes);
273 hi_axiom(num_graphemes <= num_graphemes_mask);
275 (make_value(_ptr) & ~(num_graphemes_mask << num_graphemes_shift)) | (num_graphemes << num_graphemes_shift));
281 [[nodiscard]]
constexpr std::size_t hash() const noexcept
283 return is_long() ? _ptr->hash() : make_value(_ptr);
290 constexpr glyph_ids &operator+=(glyph_id
id)
noexcept
295 }
else if (
hilet index = short_num_glyphs(); index < num_glyphs_mask) {
296 increment_num_glyphs();
297 set_glyph(index,
id);
300 _ptr =
new detail::glyph_ids_long(make_value(_ptr),
id);
309 [[nodiscard]]
constexpr glyph_id operator[](
std::size_t index)
const noexcept
311 hi_axiom(index < num_glyphs());
314 return (*_ptr)[index];
316 return get_glyph(index);
320 template<std::
size_t I>
321 [[nodiscard]]
constexpr friend glyph_id get(glyph_ids
const &rhs)
noexcept
324 return get<I>(*rhs._ptr);
327 return glyph_id{(make_value(rhs._ptr) >> shift) & 0xffff};
331 [[nodiscard]]
constexpr friend bool operator==(glyph_ids
const &lhs, glyph_ids
const &rhs)
noexcept
333 hilet lhs_value = make_value(lhs._ptr);
334 hilet rhs_value = make_value(rhs._ptr);
336 if (lhs._font != rhs._font) {
338 }
else if (lhs_value == rhs_value) {
341 return ((lhs_value | rhs_value) & 1) == 0 and *lhs._ptr == *rhs._ptr;
347 [[nodiscard]] glyph_atlas_info &atlas_info() const noexcept;
353 [[nodiscard]]
std::pair<graphic_path, aarectangle> get_path_and_bounding_box() const noexcept;
359 [[nodiscard]] aarectangle get_bounding_box() const noexcept;
362 static_assert(sizeof(
std::
size_t) == sizeof(detail::glyph_ids_long *));
364 static constexpr
std::
size_t num_glyphs_shift = 1;
365 static constexpr
std::
size_t num_glyphs_mask = sizeof(
std::
size_t) == 4 ? 1 : 3;
366 static constexpr
std::
size_t num_graphemes_shift = 4;
367 static constexpr
std::
size_t num_graphemes_mask = 15;
369 hi::font const *_font;
382 detail::glyph_ids_long *_ptr;
384 constexpr
void increment_num_glyphs() noexcept
386 hi_axiom(is_short());
387 hi_axiom(short_num_glyphs() < num_glyphs_mask);
389 _ptr = make_ptr(make_value(_ptr) + (1 << num_glyphs_shift));
392 [[nodiscard]]
constexpr glyph_id get_glyph(
std::size_t index)
const noexcept
394 hi_axiom(is_short());
396 hilet shift = (index + 1) * 16;
397 return glyph_id{(make_value(_ptr) >> shift) & 0xffff};
400 constexpr void set_glyph(
std::size_t i, glyph_id
id)
noexcept
402 hi_axiom(is_short());
404 hilet shift = (i + 1) * 16;
406 _ptr = make_ptr((make_value(_ptr) & ~mask) | (
static_cast<std::size_t>(
id) << shift));
409 [[nodiscard]]
constexpr std::size_t short_num_glyphs() const noexcept
411 hi_axiom(is_short());
412 return (make_value(_ptr) >> num_glyphs_shift) & num_glyphs_mask;
415 [[nodiscard]]
constexpr bool is_short() const noexcept
417 return to_bool(make_value(_ptr) & 1);
420 [[nodiscard]]
constexpr bool is_long() const noexcept
422 return not is_short();
425 [[nodiscard]]
static constexpr detail::glyph_ids_long *make_ptr(
std::size_t value)
noexcept
427 return std::bit_cast<detail::glyph_ids_long *>(value);
430 [[nodiscard]]
static constexpr std::size_t make_value(detail::glyph_ids_long *ptr)
noexcept
432 return std::bit_cast<std::size_t>(ptr);
This file includes required definitions.
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
T operator()(T... args)
Definition datum.hpp:2458