From a214c970420df5944b7299055bdce956af1ecd3a Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Thu, 2 Sep 2021 15:16:28 +0200 Subject: [PATCH] Fix setting of row pos/endpos (overlapping rows) In TextMetrics::breakParagraph, get rid of the fragile `pos' local variable, which was not correctly updated. Rely on the endpos of the last element in row instead. Rewrite cleanupRow to rely on the endpos of last the row element to set row endpos, instead of a `pos' parameter. --- src/Row.cpp | 4 ++-- src/TextMetrics.cpp | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Row.cpp b/src/Row.cpp index 7b74694f77..8233a965a7 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -463,8 +463,8 @@ void Row::pop_back() namespace { -// Remove stuff after it from elts, and return it. -// if init is provided, it will be in front of the rest +// Remove stuff after \c it from \c elts, and return it. +// if \c init is provided, it will prepended to the rest Row::Elements splitFrom(Row::Elements & elts, Row::Elements::iterator const & it, Row::Element const & init = Row::Element()) { diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 8812daf399..d681a63356 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -1059,15 +1059,19 @@ Row newRow(TextMetrics const & tm, pit_type pit, pos_type pos, bool is_rtl) } -void cleanupRow(Row & row, pos_type pos, pos_type real_endpos, bool is_rtl) +void cleanupRow(Row & row, pos_type real_endpos, bool is_rtl) { - row.endpos(pos); + if (row.empty()) { + row.endpos(0); + return; + } + + row.endpos(row.back().endpos); // remove trailing spaces on row break - if (pos < real_endpos && !row.empty()) + if (row.endpos() < real_endpos) row.back().rtrim(); // boundary exists when there was no space at the end of row - row.right_boundary(!row.empty() && pos < real_endpos - && row.back().endpos == pos); + row.right_boundary(row.endpos() < real_endpos && row.back().endpos == row.endpos()); // make sure that the RTL elements are in reverse ordering row.reverseRTL(is_rtl); } @@ -1095,7 +1099,6 @@ RowList TextMetrics::breakParagraph(Row const & bigrow) const bool const is_rtl = text_->isRTL(bigrow.pit()); bool const end_label = text_->getEndLabel(bigrow.pit()) != END_LABEL_NO_LABEL; - pos_type pos = 0; int width = 0; flexible_const_iterator fcit = flexible_begin(bigrow); flexible_const_iterator const end = flexible_end(bigrow); @@ -1112,7 +1115,8 @@ RowList TextMetrics::breakParagraph(Row const & bigrow) const : fcit->row_flags; if (rows.empty() || needsRowBreak(f1, f2)) { if (!rows.empty()) - cleanupRow(rows.back(), pos, bigrow.endpos(), is_rtl); + cleanupRow(rows.back(), bigrow.endpos(), is_rtl); + pos_type pos = rows.empty() ? 0 : rows.back().endpos(); rows.push_back(newRow(*this, bigrow.pit(), pos, is_rtl)); // the width available for the row. width = max_width_ - rows.back().right_margin; @@ -1150,7 +1154,6 @@ RowList TextMetrics::breakParagraph(Row const & bigrow) const // a new element in the row rows.back().push_back(elt); rows.back().finalizeLast(); - pos = elt.endpos; // Go to next element ++fcit; @@ -1165,7 +1168,7 @@ RowList TextMetrics::breakParagraph(Row const & bigrow) const } if (!rows.empty()) { - cleanupRow(rows.back(), pos, bigrow.endpos(), is_rtl); + cleanupRow(rows.back(), bigrow.endpos(), is_rtl); // Last row in paragraph is flushed rows.back().flushed(true); } -- 2.39.5