14 using iterator = vector_type::iterator;
15 using const_iterator = vector_type::const_iterator;
16 using value_type = vector_type::value_type;
30 line(), width(0.0f), ascender(0.0f), descender(0.0f), lineGap(0.0f), capHeight(0.0f), xHeight(0.0f)
36 calculateLineMetrics();
39 [[nodiscard]]
bool shouldWrap(
float maximum_width)
noexcept {
40 tt_assume(ssize(line) >= 1);
42 width > maximum_width &&
43 ssize(line) >= (line.
back().isParagraphSeparator() ? 3 : 2);
47 tt_assume(shouldWrap(maximum_width));
49 auto word_end = line.
begin();
50 auto line_width = 0.0f;
51 auto line_valid_width = 0.0f;
53 auto i = line.
begin();
54 for (; i != line.
end(); ++i) {
55 line_width += i->metrics.advance.x();
57 line_valid_width = line_width;
60 if (line_valid_width > maximum_width) {
64 }
else if (i->isWhiteSpace()) {
71 (word_end != line.
begin()) ? word_end :
72 (i != line.begin()) ? i :
77 calculateLineMetrics();
81 [[nodiscard]] aarect boundingBox() const noexcept {
82 tt_assume(ssize(line) >= 1);
85 line.
front().position.x(),
86 line.
front().position.y() - descender
90 line.
back().position.x() + line.
back().metrics.advance.x(),
91 line.
back().position.y() + ascender
97 [[nodiscard]]
bool contains(vec coordinate)
const noexcept {
98 return boundingBox().
contains(coordinate);
101 [[nodiscard]] const_iterator find(vec coordinate)
const noexcept {
102 auto bbox = boundingBox();
104 if (coordinate.y() < bbox.y() || coordinate.y() > bbox.p3().y()) {
108 if (coordinate.x() < bbox.x()) {
112 if (coordinate.x() > bbox.p3().x()) {
116 return std::lower_bound(cbegin(), cend(), coordinate.x(), [](ttlet &a, ttlet &b) {
117 return (a.position.x() + a.metrics.advance.x()) < b;
121 [[nodiscard]]
size_t size() const noexcept {
return line.
size(); }
123 [[nodiscard]] iterator begin() noexcept {
return line.
begin(); }
124 [[nodiscard]] const_iterator begin() const noexcept {
return line.
cbegin(); }
125 [[nodiscard]] const_iterator cbegin() const noexcept {
return line.
cbegin(); }
127 [[nodiscard]] iterator end() noexcept {
return line.
end(); }
128 [[nodiscard]] const_iterator end() const noexcept {
return line.
cend(); }
129 [[nodiscard]] const_iterator cend() const noexcept {
return line.
cend(); }
131 void positionGlyphs(vec position)
noexcept {
132 tt_assume(position.is_point());
134 for (
auto &&g: line) {
135 g.position = position;
136 position += g.metrics.advance;
141 void calculateLineMetrics() noexcept {
148 auto totalWidth = 0.0f;
149 auto validWidth = 0.0f;
150 for (ttlet &g: line) {
151 totalWidth += g.metrics.advance.x();
152 ascender =
std::max(ascender, g.metrics.ascender);
153 descender =
std::max(descender, g.metrics.descender);
154 lineGap =
std::max(lineGap, g.metrics.lineGap);
155 capHeight += g.metrics.capHeight;
156 xHeight += g.metrics.xHeight;
160 validWidth = totalWidth;
163 capHeight /= numeric_cast<float>(ssize(line));
164 xHeight /= numeric_cast<float>(ssize(line));
bool contains(vec const &rhs) const noexcept
Check if a 2D coordinate is inside the rectangle.
Definition aarect.hpp:221
static tt_force_inline vec point(float x=0.0f, float y=0.0f, float z=0.0f) noexcept
Create a point out of 2 to 4 values.
Definition vec.hpp:180
AttributedGlyphLine(iterator first, iterator last) noexcept
This constructor will move the data from first to last.
Definition AttributedGlyphLine.hpp:29