39 tt_axiom(nr_glyphs >= 0);
40 tt_axiom(nr_glyphs < std::ssize(glyph_ids));
41 glyph_ids[nr_glyphs++] = rhs;
45 [[nodiscard]]
size_t hash()
const noexcept {
46 tt_axiom(nr_glyphs > 3);
47 tt_axiom(nr_glyphs < std::ssize(glyph_ids));
50 for (int8_t i = 0; i != nr_glyphs; ++i) {
58 tt_axiom(lhs.nr_glyphs > 3);
59 tt_axiom(rhs.nr_glyphs > 3);
60 tt_axiom(lhs.nr_glyphs < std::ssize(lhs.glyph_ids));
61 tt_axiom(rhs.nr_glyphs < std::ssize(rhs.glyph_ids));
63 if (lhs.nr_glyphs == rhs.nr_glyphs) {
64 for (int8_t i = 0; i != lhs.nr_glyphs; ++i) {
65 if (lhs.glyph_ids[i] != rhs.glyph_ids[i]) {
79 constexpr static uint64_t empty = 0xffff'ffff'ffff'ffff;
100 if (rhs.has_pointer()) {
101 value = new_pointer(*(rhs.get_pointer()));
113 if (rhs.has_pointer()) {
114 value = new_pointer(*(rhs.get_pointer()));
123 swap(value, rhs.value);
132 void clear()
noexcept {
137 operator bool ()
const noexcept {
148 value = (value & ~static_cast<uint64_t>(font_id::mask)) |
static_cast<uint64_t
>(
font_id);
153 case 0: value = (value & 0xffff'ffff'0000'ffff) | (
static_cast<uint64_t
>(rhs) << 16);
break;
154 case 1: value = (value & 0xffff'0000'ffff'ffff) | (
static_cast<uint64_t
>(rhs) << 32);
break;
155 case 2: value = (value & 0x0000'ffff'ffff'ffff) | (
static_cast<uint64_t
>(rhs) << 48);
break;
157 value = (value & font_id::mask) | new_pointer((*
this)[0], (*this)[1], (*this)[2]);
160 *(get_pointer()) += rhs;
165 [[nodiscard]]
glyph_id front()
const noexcept {
173 [[nodiscard]]
glyph_id operator[](
size_t index)
const noexcept {
175 tt_axiom(index < 18);
176 return get_pointer()->glyph_ids[index];
179 case 0:
return glyph_id{(value >> 16) & glyph_id::mask};
180 case 1:
return glyph_id{(value >> 32) & glyph_id::mask};
181 case 2:
return glyph_id{(value >> 48) & glyph_id::mask};
182 default: tt_no_default();
187 [[nodiscard]]
size_t size()
const noexcept {
189 return get_pointer()->nr_glyphs;
190 }
else if (!(*
this)[0]) {
192 }
else if (!(*
this)[1]) {
194 }
else if (!(*
this)[2]) {
201 [[nodiscard]]
size_t hash()
const noexcept {
203 return get_pointer()->hash();
210 [[nodiscard]]
aarectangle getBoundingBox()
const noexcept;
213 [[nodiscard]]
bool has_pointer()
const noexcept {
214 return (value & 0x8000) == 0;
218 tt_axiom(has_pointer());
219 return std::launder(
reinterpret_cast<font_glyph_ids_long const *
>(
static_cast<ptrdiff_t
>(value) >> 16));
223 tt_axiom(has_pointer());
224 return std::launder(
reinterpret_cast<font_glyph_ids_long *
>(
static_cast<ptrdiff_t
>(value) >> 16));
227 void delete_pointer()
noexcept {
229 delete get_pointer();
234 template<
typename... Args>
235 [[nodiscard]]
static uint64_t new_pointer(Args &&... args)
noexcept {
237 return static_cast<uint64_t
>(
reinterpret_cast<ptrdiff_t
>(ptr) << 16);
242 if (lhs.has_pointer() == rhs.has_pointer()) {
243 if (lhs.has_pointer()) {
244 return *(lhs.get_pointer()) == *(rhs.get_pointer());
246 return lhs.value == rhs.value;
249 tt_axiom(lhs.size() != rhs.size());