commit ef88e31a1fb00d16d6d56e63b671d128ef43ad12
Author: Jean-Marc Lasgouttes <[email protected]>
Date:   Wed Jul 14 00:47:42 2021 +0200

    Break the paragraph's big row according to margins
    
    Still many features missing:
    - handle insets that break rows (display math, newline, ...)
    - handle rows that are too long by replacing the single call to
      breakAt with a call to a reworked Row::shortenIfNeeded.
    - some easy things at the end of breakRow (bidi text, etc.).
---
 src/TextMetrics.cpp |   91 ++++++++++++++++++++++++++++++++++++++++++++++-----
 src/TextMetrics.h   |    2 +
 2 files changed, 84 insertions(+), 9 deletions(-)

diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index cc380cc..fb6574d 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -990,6 +990,79 @@ Row TextMetrics::tokenizeParagraph(pit_type const pit) 
const
 }
 
 
+namespace {
+
+Row newRow(TextMetrics const & tm, pit_type pit, pos_type pos, bool is_rtl)
+{
+       Row nrow;
+       nrow.pit(pit);
+       nrow.pos(pos);
+       nrow.left_margin = tm.leftMargin(pit, pos);
+       nrow.right_margin = tm.rightMargin(pit);
+       if (is_rtl)
+               swap(nrow.left_margin, nrow.right_margin);
+       // Remember that the row width takes into account the left_margin
+       // but not the right_margin.
+       nrow.dim().wid = nrow.left_margin;
+       return nrow;
+}
+
+}
+
+
+RowList TextMetrics::breakParagraph(Row const & row) const
+{
+       RowList rows;
+       bool const is_rtl = text_->isRTL(row.pit());
+
+       bool need_new_row = true;
+       pos_type pos = 0;
+       int width = 0;
+       Row::const_iterator cit = row.begin();
+       Row::const_iterator const end = row.end();
+       // This is a vector, but we use it like a pile putting and taking
+       // stuff at the back.
+       Row::Elements pile;
+       while (true) {
+               if (need_new_row) {
+                       if (!rows.empty())
+                               rows.back().endpos(pos);
+                       rows.push_back(newRow(*this, row.pit(), pos, is_rtl));
+                       // the width available for the row.
+                       width = max_width_ - rows.back().right_margin;
+                       need_new_row = false;
+               }
+
+               // The stopping condition is here because we may need a new
+               // empty row at the end.
+               if (cit == end && pile.empty())
+                       break;
+
+               // Next element to consider is either the top of the temporary
+               // pile, or the place when we were in main row
+               Row::Element elt = pile.empty() ? *cit : pile.back();
+               //LYXERR0("elt=" << elt);
+               Row::Element next_elt = elt.splitAt(width - rows.back().width(),
+                                                   
!elt.font.language()->wordWrap());
+               //LYXERR0("next_elt=" << next_elt);
+               // a new element in the row
+               rows.back().push_back(elt);
+               pos = elt.endpos;
+               // Go to next element
+               if (pile.empty())
+                       ++cit;
+               else
+                       pile.pop_back();
+               // Add a new next element on the pile
+               if (next_elt.isValid()) {
+                       pile.push_back(next_elt);
+                       need_new_row = true;
+               }
+       }
+
+       return rows;
+}
+
 /** This is the function where the hard work is done. The code here is
  * very sensitive to small changes :) Note that part of the
  * intelligence is also in Row::shortenIfNeeded.
@@ -1003,20 +1076,20 @@ bool TextMetrics::breakRow(Row & row, int const 
right_margin) const
                theSession().bookmarks().bookmarksInPar(buf.fileName(), 
par.id());//
 
        pos_type const end = par.size();//
-       pos_type const pos = row.pos();
+       pos_type const pos = row.pos();//
        pos_type const body_pos = par.beginOfBody();//
-       bool const is_rtl = text_->isRTL(row.pit());
-       bool need_new_row = false;
+       bool const is_rtl = text_->isRTL(row.pit());//
+       bool need_new_row = false;//
 
-       row.left_margin = leftMargin(row.pit(), pos);
-       row.right_margin = right_margin;
-       if (is_rtl)
-               swap(row.left_margin, row.right_margin);
+       row.left_margin = leftMargin(row.pit(), pos);//
+       row.right_margin = right_margin;//
+       if (is_rtl)//
+               swap(row.left_margin, row.right_margin);//
        // Remember that the row width takes into account the left_margin
        // but not the right_margin.
-       row.dim().wid = row.left_margin;
+       row.dim().wid = row.left_margin;//
        // the width available for the row.
-       int const width = max_width_ - row.right_margin;
+       int const width = max_width_ - row.right_margin;//
 
        // check for possible inline completion
        DocIterator const & ic_it = bv_->inlineCompletionPos();//
diff --git a/src/TextMetrics.h b/src/TextMetrics.h
index 1666cd0..3ff1161 100644
--- a/src/TextMetrics.h
+++ b/src/TextMetrics.h
@@ -153,6 +153,8 @@ private:
 
        Row tokenizeParagraph(pit_type pit) const;
 
+       RowList breakParagraph(Row const & row) const;
+
        /// sets row.end to the pos value *after* which a row should break.
        /// for example, the pos after which isNewLine(pos) == true
        /// \return true when another row is required (after a newline)
-- 
lyx-cvs mailing list
[email protected]
http://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to