15 using iterator = vector_type::iterator;
16 using const_iterator = vector_type::const_iterator;
17 using value_type = vector_type::value_type;
31 line(), width(0.0f), ascender(0.0f), descender(0.0f), lineGap(0.0f), capHeight(0.0f), xHeight(0.0f)
37 calculateLineMetrics();
40 [[nodiscard]]
bool shouldWrap(
float maximum_width)
noexcept {
41 tt_axiom(std::ssize(line) >= 1);
43 width > maximum_width &&
44 std::ssize(line) >= (line.
back().isParagraphSeparator() ? 3 : 2);
48 tt_axiom(shouldWrap(maximum_width));
50 auto word_end = line.
begin();
51 auto line_width = 0.0f;
52 auto line_valid_width = 0.0f;
54 auto i = line.
begin();
55 for (; i != line.
end(); ++i) {
56 line_width += i->metrics.advance.x();
58 line_valid_width = line_width;
61 if (line_valid_width > maximum_width) {
65 }
else if (i->isWhiteSpace()) {
72 (word_end != line.
begin()) ? word_end :
73 (i != line.begin()) ? i :
78 calculateLineMetrics();
82 [[nodiscard]] aarect boundingBox() const noexcept {
83 tt_axiom(std::ssize(line) >= 1);
86 line.
front().position.x(),
87 line.
front().position.y() - descender
91 line.
back().position.x() + line.
back().metrics.advance.x(),
92 line.
back().position.y() + ascender
98 [[nodiscard]]
bool contains(f32x4 coordinate)
const noexcept {
99 return boundingBox().
contains(coordinate);
102 [[nodiscard]] const_iterator find(f32x4 coordinate)
const noexcept {
103 auto bbox = boundingBox();
105 if (coordinate.y() < bbox.y() || coordinate.y() > bbox.p3().y()) {
109 if (coordinate.x() < bbox.x()) {
113 if (coordinate.x() > bbox.p3().x()) {
117 return std::lower_bound(cbegin(), cend(), coordinate.x(), [](ttlet &a, ttlet &b) {
118 return (a.position.x() + a.metrics.advance.x()) < b;
122 [[nodiscard]]
size_t size() const noexcept {
return line.
size(); }
124 [[nodiscard]] iterator begin() noexcept {
return line.
begin(); }
125 [[nodiscard]] const_iterator begin() const noexcept {
return line.
cbegin(); }
126 [[nodiscard]] const_iterator cbegin() const noexcept {
return line.
cbegin(); }
128 [[nodiscard]] iterator end() noexcept {
return line.
end(); }
129 [[nodiscard]] const_iterator end() const noexcept {
return line.
cend(); }
130 [[nodiscard]] const_iterator cend() const noexcept {
return line.
cend(); }
132 void positionGlyphs(f32x4 position)
noexcept {
133 tt_axiom(position.is_point());
135 for (
auto &&g: line) {
136 g.position = position;
137 position += g.metrics.advance;
142 void calculateLineMetrics() noexcept {
149 auto totalWidth = 0.0f;
150 auto validWidth = 0.0f;
151 for (ttlet &g: line) {
152 totalWidth += g.metrics.advance.x();
153 ascender =
std::max(ascender, g.metrics.ascender);
154 descender =
std::max(descender, g.metrics.descender);
155 lineGap =
std::max(lineGap, g.metrics.lineGap);
156 capHeight += g.metrics.capHeight;
157 xHeight += g.metrics.xHeight;
161 validWidth = totalWidth;
164 capHeight /= narrow_cast<float>(std::ssize(line));
165 xHeight /= narrow_cast<float>(std::ssize(line));
bool contains(numeric_array< T, 4 > const &rhs) const noexcept
Check if a 2D coordinate is inside the rectangle.
Definition aarect.hpp:300
attributed_glyph_line(iterator first, iterator last) noexcept
This constructor will move the data from first to last.
Definition attributed_glyph_line.hpp:30