Rewrite the code that sets caret height in mathed

Instead of remembering the caret ascent and descent for the cell that contains the cursor, the new code remembers caret dimension for each MathRow object. This makes the code much less fragile (ans slightly smaller).

This fixes caret size issues when the Update::SinglePar flag is active.

Fixes bug #11541.
This commit is contained in:
Jean-Marc Lasgouttes 2019-04-16 15:58:51 +02:00
parent f7a11ca711
commit 048f9ee08e
6 changed files with 30 additions and 42 deletions

View File

@ -239,8 +239,7 @@ struct BufferView::Private
last_inset_(0), clickable_inset_(false),
mouse_position_cache_(),
bookmark_edit_position_(-1), gui_(0),
horiz_scroll_offset_(0),
caret_ascent_(0), caret_descent_(0)
horiz_scroll_offset_(0)
{
xsel_cache_.set = false;
}
@ -316,12 +315,6 @@ struct BufferView::Private
/// a slice pointing to the start of the row where the cursor
/// is (at last draw time)
CursorSlice current_row_slice_;
// The vertical size of the blinking caret. Only used for math
// Using it for text could be bad when undo restores the cursor
// current font, since the caret size could become wrong.
int caret_ascent_;
int caret_descent_;
};
@ -3013,20 +3006,13 @@ bool BufferView::paragraphVisible(DocIterator const & dit) const
}
void BufferView::setCaretAscentDescent(int asc, int des)
{
d->caret_ascent_ = asc;
d->caret_descent_ = des;
}
void BufferView::caretPosAndHeight(Point & p, int & h) const
{
int asc, des;
Cursor const & cur = cursor();
if (cur.inMathed()) {
asc = d->caret_ascent_;
des = d->caret_descent_;
asc = cur.cell().caretAscent(this);
des = cur.cell().caretDescent(this);
} else {
Font const font = cur.real_current_font;
frontend::FontMetrics const & fm = theFontMetrics(font);

View File

@ -302,8 +302,6 @@ public:
bool paragraphVisible(DocIterator const & dit) const;
/// is the cursor currently visible in the view
bool cursorInView(Point const & p, int h) const;
/// set the ascent and descent of the caret
void setCaretAscentDescent(int asc, int des);
/// get the position and height of the caret
void caretPosAndHeight(Point & p, int & h) const;

View File

@ -267,10 +267,15 @@ bool isInside(DocIterator const & it, MathData const & ar,
#endif
bool MathData::hasCaret(BufferView * bv) const
int MathData::caretAscent(BufferView const * bv) const
{
Cursor & cur = bv->cursor();
return cur.inMathed() && &cur.cell() == this;
return mrow_cache_[bv].caret_ascent;
}
int MathData::caretDescent(BufferView const * bv) const
{
return mrow_cache_[bv].caret_descent;
}
@ -288,8 +293,7 @@ void MathData::metrics(MetricsInfo & mi, Dimension & dim, bool tight) const
sshift_ = xascent / 4;
MathRow mrow(mi, this);
bool has_caret = mrow.metrics(mi, dim);
mrow_cache_[bv] = mrow;
mrow.metrics(mi, dim);
kerning_ = mrow.kerning(bv);
// Set a minimal ascent/descent for the cell
@ -304,12 +308,11 @@ void MathData::metrics(MetricsInfo & mi, Dimension & dim, bool tight) const
// This is one of the the few points where the drawing font is known,
// so that we can set the caret vertical dimensions.
has_caret |= hasCaret(bv);
if (has_caret)
bv->setCaretAscentDescent(min(dim.asc, fm.maxAscent()),
min(dim.des, fm.maxDescent()));
mrow.caret_ascent = min(dim.asc, fm.maxAscent());
mrow.caret_descent = min(dim.des, fm.maxDescent());
// Cache the dimension.
// Cache row and dimension.
mrow_cache_[bv] = mrow;
bv->coordCache().arrays().add(this, dim);
}

View File

@ -124,8 +124,10 @@ public:
/// Add this array to a math row. Return true if contents got added
bool addToMathRow(MathRow &, MetricsInfo & mi) const;
// return true if caret is in this cell in this buffer view
bool hasCaret(BufferView * bv) const;
// ascent of caret in this cell
int caretAscent(BufferView const * bv) const;
/// descent of caret in this cell
int caretDescent(BufferView const * bv) const;
/// rebuild cached metrics information
/** When \c tight is true, the height of the cell will be at least
@ -196,7 +198,7 @@ protected:
Buffer * buffer_;
/// cached object that describes typeset data
mutable std::map<BufferView*, MathRow> mrow_cache_;
mutable std::map<BufferView const *, MathRow> mrow_cache_;
private:
/// is this an exact match at this position?

View File

@ -234,10 +234,8 @@ int MathRow::after(int i) const
}
bool MathRow::metrics(MetricsInfo & mi, Dimension & dim)
void MathRow::metrics(MetricsInfo & mi, Dimension & dim)
{
bool has_caret = false;
dim.wid = 0;
// In order to compute the dimension of macros and their
// arguments, it is necessary to keep track of them.
@ -262,10 +260,8 @@ bool MathRow::metrics(MetricsInfo & mi, Dimension & dim)
d.wid = e.before + e.after;
e.inset->beforeMetrics();
}
if (e.ar) {
if (e.ar)
dim_arrays.push_back(make_pair(e.ar, Dimension()));
has_caret |= e.ar->hasCaret(mi.base.bv);
}
break;
case END:
if (e.inset) {
@ -314,7 +310,6 @@ bool MathRow::metrics(MetricsInfo & mi, Dimension & dim)
dim.wid += mathed_string_width(font, e.compl_text);
}
LATTEST(dim_insets.empty() && dim_arrays.empty());
return has_caret;
}

View File

@ -86,7 +86,7 @@ public:
};
///
MathRow() {};
MathRow() : caret_ascent(0), caret_descent(0) {};
///
typedef std::vector<Element> Elements;
///
@ -110,14 +110,18 @@ public:
// compute the spacings.
MathRow(MetricsInfo & mi, MathData const * ar);
// this returns true if the caret is here
bool metrics(MetricsInfo & mi, Dimension & dim);
//
void metrics(MetricsInfo & mi, Dimension & dim);
//
void draw(PainterInfo & pi, int const x, int const y) const;
/// superscript kerning
int kerning(BufferView const *) const;
/// useful when the caret visits this cell
int caret_ascent, caret_descent;
private:
// Index of the first inset element before position i
int before(int i) const;