From 4bbd4a45e7494363903801540102150886fa2c6b Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Fri, 14 Jul 2023 02:13:18 +0200 Subject: [PATCH 1/1] 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 89196f3fb3..8fe03ba441 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 94f86706a7..09c5b6331b 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 c39d63bd20..7e70ca274b 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 b8db1aac2e..6798d917ec 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 88c8e81c1e..6fdcfe5aaf 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 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 bdac94fcae..b33bb0d711 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; } -- 2.39.2