#include "TextClass.h"
#include "VSpace.h"
+#include "insets/InsetSeparator.h"
#include "insets/InsetText.h"
#include "mathed/MacroTable.h"
}
+// This is an arbitrary magic value
+static const pos_type force_label = -12345;
+
+// if pos == force_label, this function will return the label font instead.
+// This undocumented and only for use by labelDisplayFont()
Font TextMetrics::displayFont(pit_type pit, pos_type pos) const
{
- LASSERT(pos >= 0, { static Font f; return f; });
+ LASSERT(pos >= 0 || pos == force_label, { static Font f; return f; });
ParagraphList const & pars = text_->paragraphs();
Paragraph const & par = pars[pit];
Layout const & layout = par.layout();
Buffer const & buffer = bv_->buffer();
// FIXME: broken?
- BufferParams const & params = buffer.params();
- pos_type const body_pos = par.beginOfBody();
+ BufferParams const & bparams = buffer.params();
+ bool const label = pos < par.beginOfBody() || pos == force_label;
+
+ Font f = (pos == force_label) ? Font(inherit_font, bparams.language)
+ : par.getFontSettings(bparams, pos);
+ FontInfo const & lf = label ? layout.labelfont : layout.font;
// We specialize the 95% common case:
if (!par.getDepth()) {
- Font f = par.getFontSettings(params, pos);
if (!text_->isMainText())
applyOuterFont(f);
- bool lab = layout.labeltype == LABEL_MANUAL && pos < body_pos;
- FontInfo const & lf = lab ? layout.labelfont : layout.font;
- FontInfo rlf = lab ? layout.reslabelfont : layout.resfont;
+ FontInfo rlf = label ? layout.reslabelfont : layout.resfont;
// In case the default family has been customized
if (lf.family() == INHERIT_FAMILY)
- rlf.setFamily(params.getFont().fontInfo().family());
+ rlf.setFamily(bparams.getFont().fontInfo().family());
f.fontInfo().realize(rlf);
return f;
}
- // The uncommon case need not be optimized as much
- FontInfo const & layoutfont = pos < body_pos ?
- layout.labelfont : layout.font;
-
- Font font = par.getFontSettings(params, pos);
- font.fontInfo().realize(layoutfont);
+ // The uncommon case need not be optimized as much.
+ // FIXME : the two code paths seem different in function.
+ f.fontInfo().realize(lf);
if (!text_->isMainText())
- applyOuterFont(font);
+ applyOuterFont(f);
// Realize against environment font information
// NOTE: the cast to pit_type should be removed when pit_type
// changes to a unsigned integer.
if (pit < pit_type(pars.size()))
- font.fontInfo().realize(text_->outerFont(pit).fontInfo());
+ f.fontInfo().realize(text_->outerFont(pit).fontInfo());
// Realize with the fonts of lesser depth.
- font.fontInfo().realize(params.getFont().fontInfo());
+ f.fontInfo().realize(bparams.getFont().fontInfo());
- return font;
+ return f;
+}
+
+
+Font TextMetrics::labelDisplayFont(pit_type pit) const
+{
+ return displayFont(pit, force_label);
}
displayFont(pit, e.pos) : bufferfont;
MacroContext mc(&buffer, parPos);
MetricsInfo mi(bv_, font.fontInfo(), w, mc, e.pos == 0, tight_);
+ mi.base.outer_font = displayFont(pit, e.pos).fontInfo();
e.inset->metrics(mi, dim);
if (!insetCache.has(e.inset) || insetCache.dim(e.inset) != dim) {
insetCache.add(e.inset, dim);
if (Inset const * inset = par.getInset(row.pos())) {
if (inset->rowFlags() & Display) {
if (inset->rowFlags() & AlignLeft)
- align = LYX_ALIGN_BLOCK;
+ align = LYX_ALIGN_LEFT;
else if (inset->rowFlags() & AlignRight)
align = LYX_ALIGN_RIGHT;
else
public:
//
- flexible_const_iterator operator++() {
+ flexible_const_iterator & operator++() {
if (pile_.empty())
++cit_;
else
// pile, or the place when we were in main row
Row::Element elt = *fcit;
Row::Elements tail;
- elt.splitAt(width - rows.back().width(), next_width, false, tail);
+ elt.splitAt(width - rows.back().width(), next_width, Row::FIT, tail);
Row & rb = rows.back();
if (elt.type == Row::MARGINSPACE)
elt.dim.wid = max(elt.dim.wid, leftMargin(bigrow.pit()) - rb.width());
rb.push_back(elt);
rb.finalizeLast();
if (rb.width() > width) {
- LATTEST(tail.empty());
+ // Keep the tail for later; this ought to be rare, but play safe.
+ if (!tail.empty())
+ fcit.put(tail);
// if the row is too large, try to cut at last separator.
tail = rb.shortenIfNeeded(width, next_width);
}
// Last row in paragraph is flushed
rows.back().flushed(true);
cleanupRow(rows.back(), true);
+ // Is there an end-of-paragraph change?
+ if (bigrow.needsChangeBar())
+ rows.back().needsChangeBar(true);
}
return rows;
{
Paragraph const & par = text_->getPar(row.pit());
Layout const & layout = par.layout();
- double const spacing_val = layout.spacing.getValue() * text_->spacing(par);
+ // leading space (line spacing) factor based on current paragraph
+ double spacing_val = layout.spacing.getValue() * text_->spacing(par);
+
+ // if this is the first row but not the first paragraph, take into
+ // account the spacing of the previous paragraph.
+ if (row.pos() == 0 && row.pit() > 0) {
+ // for the first row in the paragraph,
+ // use previous paragraphs line spacing if it is larger
+ Paragraph const & previousPar = text_->getPar(row.pit() - 1);
+ Layout const & previousLayout = previousPar.layout();
+ // leading space factor based on previous paragraph
+ double const previous_spacing_val
+ = previousLayout.spacing.getValue() * text_->spacing(previousPar);
+ if (previous_spacing_val > spacing_val)
+ spacing_val = previous_spacing_val;
+ }
// Initial value for ascent (useful if row is empty).
Font const font = displayFont(row.pit(), row.pos());
FontMetrics const & fm = theFontMetrics(font);
- int maxasc = int(fm.maxAscent() * spacing_val);
- int maxdes = int(fm.maxDescent() * spacing_val);
+ int maxasc = int(fm.maxAscent()
+ // add leading space
+ + fm.maxHeight() * (spacing_val - 1));
+ int maxdes = int(fm.maxDescent());
// Take label string into account (useful if labelfont is large)
if (row.pos() == 0 && layout.labelIsInline()) {
FontInfo const labelfont = text_->labelFont(par);
FontMetrics const & lfm = theFontMetrics(labelfont);
- maxasc = max(maxasc, int(lfm.maxAscent() * spacing_val));
- maxdes = max(maxdes, int(lfm.maxDescent() * spacing_val));
+ maxasc = max(maxasc, int(lfm.maxAscent()
+ // add leading space
+ + lfm.maxHeight() * (spacing_val - 1)));
+ maxdes = max(maxdes, int(lfm.maxDescent()));
}
// Find the ascent/descent of the row contents
maxdes = max(maxdes, e.dim.descent());
} else {
FontMetrics const & fm2 = theFontMetrics(e.font);
- maxasc = max(maxasc, int(fm2.maxAscent() * spacing_val));
- maxdes = max(maxdes, int(fm2.maxDescent() * spacing_val));
+ maxasc = max(maxasc, int(fm2.maxAscent()
+ // add leading space
+ + fm2.maxHeight() * (spacing_val - 1)));
+ maxdes = max(maxdes, int(fm2.maxDescent()));
}
}
{
LASSERT(!text_->paragraphs().empty(), return -1);
LASSERT(!par_metrics_.empty(), return -1);
- LYXERR(Debug::DEBUG, "y: " << y << " cache size: " << par_metrics_.size());
+ LYXERR(Debug::PAINTING, "y: " << y << " cache size: " << par_metrics_.size());
// look for highest numbered paragraph with y coordinate less than given y
pit_type pit = -1;
}
for (; it != et; ++it) {
- LYXERR(Debug::DEBUG, "examining: pit: " << it->first
+ LYXERR(Debug::PAINTING, "examining: pit: " << it->first
<< " y: " << it->second.position());
ParagraphMetrics const & pm2 = par_metrics_[it->first];
}
}
- LYXERR(Debug::DEBUG, "found best y: " << yy << " for pit: " << pit);
+ LYXERR(Debug::PAINTING, "found best y: " << yy << " for pit: " << pit);
return pit;
}
ParagraphMetrics const & pm = par_metrics_[pit];
int yy = pm.position() - pm.rows().front().ascent();
- LYXERR(Debug::DEBUG, "x: " << x << " y: " << y <<
+ LYXERR(Debug::PAINTING, "x: " << x << " y: " << y <<
" pit: " << pit << " yy: " << yy);
int r = 0;
Row const & row = pm.rows()[r];
- LYXERR(Debug::DEBUG, "row " << r << " from pos: " << row.pos());
+ LYXERR(Debug::PAINTING, "row " << r << " from pos: " << row.pos());
bool bound = false;
int xx = x;
pos_type const pos = getPosNearX(row, xx, bound);
- LYXERR(Debug::DEBUG, "setting cursor pit: " << pit << " pos: " << pos);
+ LYXERR(Debug::PAINTING, "setting cursor pit: " << pit << " pos: " << pos);
text_->setCursor(cur, pit, pos, true, bound);
// remember new position.
Paragraph const & par = text_->paragraphs()[pit];
CoordCache::Insets const & insetCache = bv_->coordCache().getInsets();
- LYXERR(Debug::DEBUG, "x: " << x << " y: " << y << " pit: " << pit);
+ LYXERR(Debug::PAINTING, "x: " << x << " y: " << y << " pit: " << pit);
for (InsetList::Element const & e : par.insetList()) {
- LYXERR(Debug::DEBUG, "examining inset " << e.inset);
+ LYXERR(Debug::PAINTING, "examining inset " << e.inset);
if (insetCache.covers(e.inset, x, y)) {
- LYXERR(Debug::DEBUG, "Hit inset: " << e.inset);
+ LYXERR(Debug::PAINTING, "Hit inset: " << e.inset);
return const_cast<InsetList::Element *>(&e);
}
}
- LYXERR(Debug::DEBUG, "No inset hit. ");
+ LYXERR(Debug::PAINTING, "No inset hit. ");
return nullptr;
}
}
}
- // This happens after sections or environments in standard classes.
- // We have to check the previous layout at same depth.
+ // Check for reasons to remove indentation.
+ // First, at document level.
if (buffer.params().paragraph_separation ==
BufferParams::ParagraphSkipSeparation)
parindent.erase();
+ // This happens after sections or environments in standard classes.
+ // We have to check the previous layout at same depth.
else if (pit > 0 && pars[pit - 1].getDepth() >= par.getDepth()) {
pit_type prev = text_->depthHook(pit, par.getDepth());
if (par.layout() == pars[prev].layout()) {
} else if (pars[prev].layout().nextnoindent)
parindent.erase();
}
+ // The previous paragraph may have ended with a separator inset.
+ if (pit > 0) {
+ Paragraph const & ppar = pars[pit - 1];
+ if (ppar.size() > 0) {
+ auto * in = dynamic_cast<InsetSeparator const *>(ppar.getInset(ppar.size() - 1));
+ if (in != nullptr && in->nextnoindent())
+ parindent.erase();
+ }
+ }
FontInfo const labelfont = text_->labelFont(par);
FontMetrics const & lfm = theFontMetrics(labelfont);
swap(pi.leftx, pi.rightx);
BookmarksSection::BookmarkPosList bpl =
- theSession().bookmarks().bookmarksInPar(bv_->buffer().fileName(), pm.par().id());
+ theSession().bookmarks().bookmarksInPar(bv_->buffer().fileName(), pm.id());
for (size_t i = 0; i != nrows; ++i) {