Adapt caret height to context in mathed.

Compute a height from current font and current cell vertical
dimensions in MathData::metrics(), because this is where current font
is known.

Introduce BufferView::setCaretAscentDescent to remember this value.

This mechanism is not used for text because Cursor::current_font is
restored by undo, and the caret height would not be changed then. But
in principle it is doable.
This commit is contained in:
Jean-Marc Lasgouttes 2018-04-27 00:03:48 +02:00
parent 2f1eb35b86
commit 90cfe4ec3b
3 changed files with 40 additions and 9 deletions

View File

@ -230,7 +230,8 @@ enum ScreenUpdateStrategy {
struct BufferView::Private struct BufferView::Private
{ {
Private(BufferView & bv) : update_strategy_(FullScreenUpdate), Private(BufferView & bv) :
update_strategy_(FullScreenUpdate),
update_flags_(Update::Force), update_flags_(Update::Force),
wh_(0), cursor_(bv), wh_(0), cursor_(bv),
anchor_pit_(0), anchor_ypos_(0), anchor_pit_(0), anchor_ypos_(0),
@ -238,7 +239,8 @@ struct BufferView::Private
last_inset_(0), clickable_inset_(false), last_inset_(0), clickable_inset_(false),
mouse_position_cache_(), mouse_position_cache_(),
bookmark_edit_position_(-1), gui_(0), bookmark_edit_position_(-1), gui_(0),
horiz_scroll_offset_(0) horiz_scroll_offset_(0),
caret_ascent_(0), caret_descent_(0)
{ {
xsel_cache_.set = false; xsel_cache_.set = false;
} }
@ -317,6 +319,12 @@ struct BufferView::Private
/// a slice pointing to the start of the row where cursor was /// a slice pointing to the start of the row where cursor was
/// at previous draw event /// at previous draw event
CursorSlice last_row_slice_; CursorSlice last_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_;
}; };
@ -2982,13 +2990,26 @@ 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 void BufferView::caretPosAndHeight(Point & p, int & h) const
{ {
int asc, des;
Cursor const & cur = cursor(); Cursor const & cur = cursor();
if (cur.inMathed()) {
asc = d->caret_ascent_;
des = d->caret_descent_;
} else {
Font const font = cur.real_current_font; Font const font = cur.real_current_font;
frontend::FontMetrics const & fm = theFontMetrics(font); frontend::FontMetrics const & fm = theFontMetrics(font);
int const asc = fm.maxAscent(); asc = fm.maxAscent();
int const des = fm.maxDescent(); des = fm.maxDescent();
}
h = asc + des; h = asc + des;
p = getPos(cur); p = getPos(cur);
p.y_ -= asc; p.y_ -= asc;

View File

@ -307,6 +307,8 @@ public:
bool paragraphVisible(DocIterator const & dit) const; bool paragraphVisible(DocIterator const & dit) const;
/// is the cursor currently visible in the view /// is the cursor currently visible in the view
bool cursorInView(Point const & p, int h) const; 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 /// get the position and height of the caret
void caretPosAndHeight(Point & p, int & h) const; void caretPosAndHeight(Point & p, int & h) const;

View File

@ -262,6 +262,7 @@ bool isInside(DocIterator const & it, MathData const & ar,
void MathData::metrics(MetricsInfo & mi, Dimension & dim, bool tight) const void MathData::metrics(MetricsInfo & mi, Dimension & dim, bool tight) const
{ {
frontend::FontMetrics const & fm = theFontMetrics(mi.base.font); frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
BufferView * bv = mi.base.bv;
int const Iascent = fm.dimension('I').ascent(); int const Iascent = fm.dimension('I').ascent();
int xascent = fm.dimension('x').ascent(); int xascent = fm.dimension('x').ascent();
if (xascent >= Iascent) if (xascent >= Iascent)
@ -273,8 +274,8 @@ void MathData::metrics(MetricsInfo & mi, Dimension & dim, bool tight) const
MathRow mrow(mi, this); MathRow mrow(mi, this);
mrow.metrics(mi, dim); mrow.metrics(mi, dim);
mrow_cache_[mi.base.bv] = mrow; mrow_cache_[bv] = mrow;
kerning_ = mrow.kerning(mi.base.bv); kerning_ = mrow.kerning(bv);
// Set a minimal ascent/descent for the cell // Set a minimal ascent/descent for the cell
if (tight) if (tight)
@ -286,8 +287,15 @@ void MathData::metrics(MetricsInfo & mi, Dimension & dim, bool tight) const
dim.des = max(dim.des, fm.maxDescent()); dim.des = max(dim.des, fm.maxDescent());
} }
// This is one of the the few points where the drawing font is known,
// so that we can set the caret vertical dimensions.
Cursor & cur = bv->cursor();
if (cur.inMathed() && &cur.cell() == this)
bv->setCaretAscentDescent(min(dim.asc, fm.maxAscent()),
min(dim.des, fm.maxDescent()));
// Cache the dimension. // Cache the dimension.
mi.base.bv->coordCache().arrays().add(this, dim); bv->coordCache().arrays().add(this, dim);
} }