[LyX/master] Fix display of a math hull inset in a tight inset

Jean-Marc Lasgouttes lasgouttes at lyx.org
Fri Jul 14 14:06:16 UTC 2023


commit 4bbd4a45e7494363903801540102150886fa2c6b
Author: Jean-Marc Lasgouttes <lasgouttes at lyx.org>
Date:   Fri Jul 14 02:13:18 2023 +0200

    Fix display of a math hull inset in a tight inset
    
    This is a kind of hack. This allows InsetMathHull to state that it
    needs some elbow room beyond its width, in order to fit the numbering
    and/or the left margin (with left alignment), which are outside of the
    inset itself.
    
    To this end, InsetMathHull::metrics() sets a value in
    MetricsInfo::extrawidth and this value is recorded later in the
    corresponding row element's `extra' field.
    
    The code could be reorganized to be simpler, in particular by
    computing metrics in tokenizeRow, or after tokenizeRow. However the
    choice here is to produce a simple patch, fit for 2.4.0.
    
    Fixes bug #12320.
---
 src/MetricsInfo.cpp          |    3 ++-
 src/MetricsInfo.h            |    2 ++
 src/Row.cpp                  |    5 +++--
 src/RowPainter.cpp           |    9 +++++++--
 src/TextMetrics.cpp          |   18 +++++++++++++++++-
 src/mathed/InsetMathHull.cpp |    9 +++++++--
 6 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/src/MetricsInfo.cpp b/src/MetricsInfo.cpp
index 89196f3..8fe03ba 100644
--- a/src/MetricsInfo.cpp
+++ b/src/MetricsInfo.cpp
@@ -123,7 +123,8 @@ int MetricsBase::inPixels(Length const & len) const
 
 MetricsInfo::MetricsInfo(BufferView * bv, FontInfo font, int textwidth,
                          MacroContext const & mc, bool vm, bool tight)
-	: base(bv, font, textwidth), macrocontext(mc), vmode(vm), tight_insets(tight)
+	: base(bv, font, textwidth), macrocontext(mc), vmode(vm), tight_insets(tight),
+	  extrawidth(0)
 {}
 
 
diff --git a/src/MetricsInfo.h b/src/MetricsInfo.h
index 94f8670..09c5b63 100644
--- a/src/MetricsInfo.h
+++ b/src/MetricsInfo.h
@@ -105,6 +105,8 @@ public:
 	bool vmode;
 	/// if true, do not expand insets to max width artificially
 	bool tight_insets;
+	/// Extra width required by an inset, in addition to its dimension
+	int extrawidth;
 };
 
 
diff --git a/src/Row.cpp b/src/Row.cpp
index c39d63b..7e70ca2 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -509,14 +509,15 @@ void Row::addMarginSpace(pos_type const pos, int const width,
 
 void Row::push_back(Row::Element const & e)
 {
-	dim_.wid += e.dim.wid;
+	dim_.wid += e.dim.wid + ((e.type == INSET) ? e.extra : 0);
 	elements_.push_back(e);
 }
 
 
 void Row::pop_back()
 {
-	dim_.wid -= elements_.back().dim.wid;
+	Element const & e = elements_.back();
+	dim_.wid -= e.dim.wid + ((e.type == INSET) ? e.extra : 0);
 	elements_.pop_back();
 }
 
diff --git a/src/RowPainter.cpp b/src/RowPainter.cpp
index b8db1aa..6798d91 100644
--- a/src/RowPainter.cpp
+++ b/src/RowPainter.cpp
@@ -100,12 +100,14 @@ void RowPainter::paintInset(Row::Element const & e) const
 	bool const pi_full_repaint = pi_.full_repaint;
 	bool const pi_do_spellcheck = pi_.do_spellcheck;
 	Change const pi_change = pi_.change;
+	int const pi_textwidth = pi_.base.textwidth;
 
 	pi_.base.font = e.inset->inheritFont() ? e.font.fontInfo() :
 		pi_.base.bv->buffer().params().getFont().fontInfo();
 	pi_.ltr_pos = !e.font.isVisibleRightToLeft();
 	pi_.change = pi_.change.changed() ? pi_.change : e.change;
 	pi_.do_spellcheck &= e.inset->allowSpellCheck();
+	pi_.base.textwidth += e.extra;
 
 	int const x1 = int(x_);
 	pi_.base.bv->coordCache().insets().add(e.inset, x1, yo_);
@@ -122,6 +124,7 @@ void RowPainter::paintInset(Row::Element const & e) const
 	pi_.change = pi_change;
 	pi_.do_spellcheck = pi_do_spellcheck;
 	pi_.selected = pi_selected;
+	pi_.base.textwidth = pi_textwidth;
 
 #ifdef DEBUG_METRICS
 	Dimension const & dim = pi_.base.bv->coordCache().insets().dim(e.inset);
@@ -555,7 +558,8 @@ void RowPainter::paintOnlyInsets()
 				paintChange(e);
 		}
 
-		x_ += e.full_width();
+		// extra is the extrawidth band-aid described in redoParagraphs
+		x_ +=  e.full_width() + ((e.type == Row::INSET) ? e.extra : 0);
 	}
 }
 
@@ -590,7 +594,8 @@ void RowPainter::paintText()
 		if (e.type != Row::INSET || ! e.inset->canPaintChange(*pi_.base.bv))
 			paintChange(e);
 
-		x_ += e.full_width();
+		// extra is the extrawidth band-aid described in redoParagraphs
+		x_ +=  e.full_width() + ((e.type == Row::INSET) ? e.extra : 0);
 	}
 }
 
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 88c8e81..6fdcfe5 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -485,6 +485,7 @@ bool TextMetrics::redoParagraph(pit_type const pit, bool const align_rows)
 	par.setBeginOfBody();
 	Font const bufferfont = buffer.params().getFont();
 	CoordCache::Insets & insetCache = bv_->coordCache().insets();
+	map <Inset const *, int> extrawidths;
 	for (auto const & e : par.insetList()) {
 		// FIXME Doesn't this HAVE to be non-empty?
 		// position already initialized?
@@ -520,6 +521,17 @@ bool TextMetrics::redoParagraph(pit_type const pit, bool const align_rows)
 		MacroContext mc(&buffer, parPos);
 		MetricsInfo mi(bv_, font.fontInfo(), w, mc, e.pos == 0, tight_);
 		e.inset->metrics(mi, dim);
+		/* FIXME: This is a kind of hack. This allows InsetMathHull to
+		 * state that it needs some elbow room beyond its width, in
+		 * order to fit the numbering and/or the left margin (with
+		 * left alignment), which are outside of the inset itself.
+		 *
+		 * To this end, InsetMathHull::metrics() sets a value in
+		 * MetricsInfo::extrawidth and this value is recorded later in
+		 * the corresponding row element's `extra' field. See ticket
+		 * #12320 for details.
+		*/
+		extrawidths[e.inset] = mi.extrawidth;
 		if (!insetCache.has(e.inset) || insetCache.dim(e.inset) != dim) {
 			insetCache.add(e.inset, dim);
 			changed = true;
@@ -527,7 +539,11 @@ bool TextMetrics::redoParagraph(pit_type const pit, bool const align_rows)
 	}
 
 	// Transform the paragraph into a single row containing all the elements.
-	Row const bigrow = tokenizeParagraph(pit);
+	Row bigrow = tokenizeParagraph(pit);
+	// Add the needed extra width to the row elements of the insets
+	for (auto & e : bigrow)
+		if (e.type == Row::INSET)
+			e.extra = extrawidths[e.inset];
 	// Split the row in several rows fitting in available width
 	pm.rows() = breakParagraph(bigrow);
 
diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp
index bdac94f..b33bb0d 100644
--- a/src/mathed/InsetMathHull.cpp
+++ b/src/mathed/InsetMathHull.cpp
@@ -476,6 +476,9 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
 	if (mi.vmode)
 		top_display_margin += theFontMetrics(mi.base.font).maxHeight() + 2;
 
+	int const ind = indent(*mi.base.bv);
+	mi.extrawidth = ind;
+
 	if (previewState(mi.base.bv)) {
 		preview_->metrics(mi, dim);
 		if (previewTooSmall(dim)) {
@@ -507,6 +510,7 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
 	if (numberedType()) {
 		BufferParams::MathNumber const math_number = buffer().params().getMathNumber();
 		int extra_offset = 0;
+		int max_nlwid = 0;
 		for (row_type row = 0; row < nrows(); ++row) {
 			rowinfo(row).offset[mi.base.bv] += extra_offset;
 			docstring const nl = nicelabel(row);
@@ -514,7 +518,6 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
 				continue;
 			Dimension dimnl;
 			mathed_string_dim(mi.base.font, nl, dimnl);
-			int const ind = indent(*mi.base.bv);
 			int const x = ind ? ind : (mi.base.textwidth - dim.wid) / 2;
 			// for some reason metrics does not trigger at the
 			// same point as draw, and therefore we use >= instead of >
@@ -522,8 +525,10 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
 			    || (math_number == BufferParams::RIGHT
 			        && dimnl.wid >= mi.base.textwidth - x - dim.wid)) {
 				extra_offset += dimnl.height();
-			}
+			} else if (dimnl.wid > max_nlwid)
+				max_nlwid = dimnl.wid;
 		}
+		mi.extrawidth += max_nlwid;
 		dim.des += extra_offset;
 	}
 


More information about the lyx-cvs mailing list