Fix alignment of rows when text width is variable

When several lines of text are in the same variable-width tabular
cell, it is not possible to align properly the rows until the cell
width is known.

Therefore a parameter is added to redoParagraph to skip this
computation, so that it can be done later in TextMetrics::metrics.
Other calls to redoParagraph in the code are not affected. It is not
clear at this point whether they may create artefacts.

computeRowMetrics has been renamed to setRowAlignment to better
reflect its use.

Fixes bug #11447.
This commit is contained in:
Jean-Marc Lasgouttes 2019-01-11 15:55:17 +01:00
parent 64901b41b6
commit edb46d2a94
3 changed files with 19 additions and 12 deletions

View File

@ -182,13 +182,21 @@ bool TextMetrics::metrics(MetricsInfo & mi, Dimension & dim, int min_width,
bool changed = false;
unsigned int h = 0;
for (pit_type pit = 0; pit != npar; ++pit) {
changed |= redoParagraph(pit);
// create rows, but do not set alignment yet
changed |= redoParagraph(pit, false);
ParagraphMetrics const & pm = par_metrics_[pit];
h += pm.height();
if (dim_.wid < pm.width())
dim_.wid = pm.width();
}
// Now set alignment for all rows (the width might not have been known before).
for (pit_type pit = 0; pit != npar; ++pit) {
ParagraphMetrics & pm = par_metrics_[pit];
for (Row & row : pm.rows())
setRowAlignment(row, dim_.wid);
}
dim_.asc = par_metrics_[0].ascent();
dim_.des = h - dim_.asc;
//lyxerr << "dim_.wid " << dim_.wid << endl;
@ -354,7 +362,7 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos,
}
bool TextMetrics::redoParagraph(pit_type const pit)
bool TextMetrics::redoParagraph(pit_type const pit, bool const align_rows)
{
Paragraph & par = text_->getPar(pit);
// IMPORTANT NOTE: We pass 'false' explicitly in order to not call
@ -474,14 +482,14 @@ bool TextMetrics::redoParagraph(pit_type const pit)
/* If there is more than one row or the row has been
* broken by a display inset or a newline, expand the text
* to the full allowable width. This setting here is
* needed for the computeRowMetrics() below.
* needed for the setRowAlignment() below.
* We do nothing when inside a table cell.
*/
if (dim_.wid < max_width_)
dim_.wid = max_width_;
}
int const max_row_width = max(dim_.wid, row.width());
computeRowMetrics(row, max_row_width);
if (align_rows)
setRowAlignment(row, max(dim_.wid, row.width()));
first = row.endpos();
++row_index;
@ -588,7 +596,7 @@ LyXAlignment TextMetrics::getAlign(Paragraph const & par, Row const & row) const
}
void TextMetrics::computeRowMetrics(Row & row, int width) const
void TextMetrics::setRowAlignment(Row & row, int width) const
{
row.label_hfill = 0;
row.separator = 0;

View File

@ -97,7 +97,7 @@ public:
/// Rebreaks the given paragraph.
/// \retval true if a full screen redraw is needed.
/// \retval false if a single paragraph redraw is enough.
bool redoParagraph(pit_type const pit);
bool redoParagraph(pit_type const pit, bool align_rows = true);
/// Clear cache of paragraph metrics
void clear() { par_metrics_.clear(); }
/// Is cache of paragraph metrics empty ?
@ -145,11 +145,10 @@ private:
/// \return true when another row is required (after a newline)
bool breakRow(Row & row, int right_margin) const;
// Expand the alignment of row \param row in paragraph \param par
// Expands the alignment of row \param row in paragraph \param par
LyXAlignment getAlign(Paragraph const & par, Row const & row) const;
/** this calculates the specified parameters. needed when setting
* the cursor and when creating a visible row */
void computeRowMetrics(Row & row, int width) const;
/// Aligns properly the row contents (computes spaces and fills)
void setRowAlignment(Row & row, int width) const;
/// Set the height of the row (without space above/below paragraph)
void setRowHeight(Row & row) const;

View File

@ -202,7 +202,7 @@ void InsetSpace::metrics(MetricsInfo & mi, Dimension & dim) const
{
if (isHfill()) {
// The width for hfills is calculated externally in
// TextMetrics::computeRowMetrics. The value of 5 is the
// TextMetrics::setRowAlignment. The value of 5 is the
// minimal value when the hfill is not active.
dim = Dimension(5, 10, 10);
return;