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 added later to the width of
the row that contains the inset (when this row is tight or shorter
than the max allowed width).

Fixes bug #12320.
This commit is contained in:
Jean-Marc Lasgouttes 2023-07-14 02:13:18 +02:00
parent 6d62d8009f
commit 4dfebbe9da
4 changed files with 32 additions and 3 deletions

View File

@ -152,7 +152,8 @@ int MetricsBase::inPixels(Length const & len) const
MetricsInfo::MetricsInfo(BufferView * bv, FontInfo font, int textwidth, MetricsInfo::MetricsInfo(BufferView * bv, FontInfo font, int textwidth,
MacroContext const & mc, bool vm, bool tight) 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)
{} {}

View File

@ -109,6 +109,8 @@ public:
bool vmode; bool vmode;
/// if true, do not expand insets to max width artificially /// if true, do not expand insets to max width artificially
bool tight_insets; bool tight_insets;
/// Extra width required by an inset, in addition to its dimension
int extrawidth;
}; };

View File

@ -485,6 +485,7 @@ bool TextMetrics::redoParagraph(pit_type const pit, bool const align_rows)
par.setBeginOfBody(); par.setBeginOfBody();
Font const bufferfont = buffer.params().getFont(); Font const bufferfont = buffer.params().getFont();
CoordCache::Insets & insetCache = bv_->coordCache().insets(); CoordCache::Insets & insetCache = bv_->coordCache().insets();
map <Inset const *, int> extrawidths;
for (auto const & e : par.insetList()) { for (auto const & e : par.insetList()) {
// FIXME Doesn't this HAVE to be non-empty? // FIXME Doesn't this HAVE to be non-empty?
// position already initialized? // position already initialized?
@ -521,6 +522,20 @@ bool TextMetrics::redoParagraph(pit_type const pit, bool const align_rows)
MetricsInfo mi(bv_, font.fontInfo(), w, mc, e.pos == 0, tight_); MetricsInfo mi(bv_, font.fontInfo(), w, mc, e.pos == 0, tight_);
mi.base.outer_font = displayFont(pit, e.pos).fontInfo(); mi.base.outer_font = displayFont(pit, e.pos).fontInfo();
e.inset->metrics(mi, dim); e.inset->metrics(mi, dim);
/* FIXME: This is a 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 added later to
* the width of the row that contains the inset (when this row
* is tight or shorter than the max allowed width).
*
* See ticket #12320 for details.
*/
extrawidths[e.inset] = mi.extrawidth;
if (!insetCache.has(e.inset) || insetCache.dim(e.inset) != dim) { if (!insetCache.has(e.inset) || insetCache.dim(e.inset) != dim) {
insetCache.add(e.inset, dim); insetCache.add(e.inset, dim);
changed = true; changed = true;
@ -532,6 +547,12 @@ bool TextMetrics::redoParagraph(pit_type const pit, bool const align_rows)
// Split the row in several rows fitting in available width // Split the row in several rows fitting in available width
pm.rows() = breakParagraph(bigrow); pm.rows() = breakParagraph(bigrow);
// Add the needed extra width to the rows that contain the insets that request it
for (Row & row : pm.rows())
for (Row::Element & e : row)
if (e.type == Row::INSET && (row.width() < max_width_ || tight_))
row.dim().wid += extrawidths[e.inset];
/* If there is more than one row, expand the text to the full /* If there is more than one row, expand the text to the full
* allowable width. This setting here is needed for the * allowable width. This setting here is needed for the
* setRowAlignment() below. We do nothing when tight insets are * setRowAlignment() below. We do nothing when tight insets are

View File

@ -523,6 +523,9 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
if (mi.vmode) if (mi.vmode)
top_display_margin += theFontMetrics(mi.base.font).maxHeight() + 2; top_display_margin += theFontMetrics(mi.base.font).maxHeight() + 2;
int const ind = indent(*mi.base.bv);
mi.extrawidth = ind;
if (previewState(mi.base.bv)) { if (previewState(mi.base.bv)) {
preview_->metrics(mi, dim); preview_->metrics(mi, dim);
if (previewTooSmall(dim)) { if (previewTooSmall(dim)) {
@ -554,6 +557,7 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
if (numberedType()) { if (numberedType()) {
BufferParams::MathNumber const math_number = buffer().params().getMathNumber(); BufferParams::MathNumber const math_number = buffer().params().getMathNumber();
int extra_offset = 0; int extra_offset = 0;
int max_nlwid = 0;
for (row_type row = 0; row < nrows(); ++row) { for (row_type row = 0; row < nrows(); ++row) {
rowinfo(row).offset[mi.base.bv] += extra_offset; rowinfo(row).offset[mi.base.bv] += extra_offset;
docstring const nl = nicelabel(row); docstring const nl = nicelabel(row);
@ -561,7 +565,6 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
continue; continue;
Dimension dimnl; Dimension dimnl;
mathed_string_dim(mi.base.font, nl, 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; int const x = ind ? ind : (mi.base.textwidth - dim.wid) / 2;
// for some reason metrics does not trigger at the // for some reason metrics does not trigger at the
// same point as draw, and therefore we use >= instead of > // same point as draw, and therefore we use >= instead of >
@ -569,8 +572,10 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const
|| (math_number == BufferParams::RIGHT || (math_number == BufferParams::RIGHT
&& dimnl.wid >= mi.base.textwidth - x - dim.wid)) { && dimnl.wid >= mi.base.textwidth - x - dim.wid)) {
extra_offset += dimnl.height(); extra_offset += dimnl.height();
} else if (dimnl.wid > max_nlwid)
max_nlwid = dimnl.wid;
} }
} mi.extrawidth += max_nlwid;
dim.des += extra_offset; dim.des += extra_offset;
} }