Make caret visible inside math macros arguments

The first step is to move the MathRow cache to BufferView, alongside
coordCache. This was on the todo list anyway, since it allows to let
go the math row information when the math equation is not on the
screen anymore. With the old scheme, it would always remain in memory.

Then, when computing caret size in MathData::metrics, make sure that
the mathrow of the elements that are linearized in the MathRow object
get their caret size information initialized too.

Fixes bug #11587.
This commit is contained in:
Jean-Marc Lasgouttes 2019-06-03 16:22:44 +02:00
parent 18ebcab403
commit d02244c8fb
5 changed files with 36 additions and 26 deletions

View File

@ -252,6 +252,9 @@ struct BufferView::Private
Update::flags update_flags_; Update::flags update_flags_;
/// ///
CoordCache coord_cache_; CoordCache coord_cache_;
///
typedef map<MathData const *, MathRow> MathRows;
MathRows math_rows_;
/// Estimated average par height for scrollbar. /// Estimated average par height for scrollbar.
int wh_; int wh_;
@ -430,6 +433,20 @@ CoordCache const & BufferView::coordCache() const
} }
MathRow const & BufferView::mathRow(MathData const * cell) const
{
auto it = d->math_rows_.find(cell);
LATTEST(it != d->math_rows_.end());
return it->second;
}
void BufferView::setMathRow(MathData const * cell, MathRow const & mrow)
{
d->math_rows_[cell] = mrow;
}
Buffer & BufferView::buffer() Buffer & BufferView::buffer()
{ {
return buffer_; return buffer_;
@ -2771,6 +2788,7 @@ void BufferView::updateMetrics(Update::flags & update_flags)
// Clear out the position cache in case of full screen redraw, // Clear out the position cache in case of full screen redraw,
d->coord_cache_.clear(); d->coord_cache_.clear();
d->math_rows_.clear();
// Clear out paragraph metrics to avoid having invalid metrics // Clear out paragraph metrics to avoid having invalid metrics
// in the cache from paragraphs not relayouted below // in the cache from paragraphs not relayouted below
@ -3011,8 +3029,9 @@ void BufferView::caretPosAndHeight(Point & p, int & h) const
int asc, des; int asc, des;
Cursor const & cur = cursor(); Cursor const & cur = cursor();
if (cur.inMathed()) { if (cur.inMathed()) {
asc = cur.cell().caretAscent(this); MathRow const & mrow = mathRow(&cur.cell());
des = cur.cell().caretDescent(this); asc = mrow.caret_ascent;
des = mrow.caret_descent;
} else { } 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);

View File

@ -42,6 +42,8 @@ class FuncStatus;
class Intl; class Intl;
class Inset; class Inset;
class Length; class Length;
class MathData;
class MathRow;
class ParIterator; class ParIterator;
class ParagraphMetrics; class ParagraphMetrics;
class Point; class Point;
@ -296,6 +298,11 @@ public:
/// ///
CoordCache const & coordCache() const; CoordCache const & coordCache() const;
///
MathRow const & mathRow(MathData const * cell) const;
///
void setMathRow(MathData const * cell, MathRow const & mrow);
/// ///
Point getPos(DocIterator const & dit) const; Point getPos(DocIterator const & dit) const;
/// is the paragraph of the cursor visible ? /// is the paragraph of the cursor visible ?

View File

@ -267,18 +267,6 @@ bool isInside(DocIterator const & it, MathData const & ar,
#endif #endif
int MathData::caretAscent(BufferView const * bv) const
{
return mrow_cache_[bv].caret_ascent;
}
int MathData::caretDescent(BufferView const * bv) const
{
return mrow_cache_[bv].caret_descent;
}
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);
@ -310,9 +298,14 @@ void MathData::metrics(MetricsInfo & mi, Dimension & dim, bool tight) const
// so that we can set the caret vertical dimensions. // so that we can set the caret vertical dimensions.
mrow.caret_ascent = min(dim.asc, fm.maxAscent()); mrow.caret_ascent = min(dim.asc, fm.maxAscent());
mrow.caret_descent = min(dim.des, fm.maxDescent()); mrow.caret_descent = min(dim.des, fm.maxDescent());
/// do the same for math cells linearized in the row
MathRow caret_row = MathRow(mrow.caret_ascent, mrow.caret_descent);
for (auto const & e : mrow)
if (e.type == MathRow::BEGIN && e.ar)
bv->setMathRow(e.ar, caret_row);
// Cache row and dimension. // Cache row and dimension.
mrow_cache_[bv] = mrow; bv->setMathRow(this, mrow);
bv->coordCache().arrays().add(this, dim); bv->coordCache().arrays().add(this, dim);
} }
@ -357,7 +350,7 @@ void MathData::draw(PainterInfo & pi, int const x, int const y) const
setXY(*pi.base.bv, x, y); setXY(*pi.base.bv, x, y);
drawSelection(pi, x, y); drawSelection(pi, x, y);
MathRow const & mrow = mrow_cache_[pi.base.bv]; MathRow const & mrow = pi.base.bv->mathRow(this);
mrow.draw(pi, x, y); mrow.draw(pi, x, y);
} }

View File

@ -26,7 +26,6 @@
#include <cstddef> #include <cstddef>
#include <vector> #include <vector>
#include <map>
namespace lyx { namespace lyx {
@ -124,11 +123,6 @@ public:
/// Add this array to a math row. Return true if contents got added /// Add this array to a math row. Return true if contents got added
bool addToMathRow(MathRow &, MetricsInfo & mi) const; bool addToMathRow(MathRow &, MetricsInfo & mi) 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 /// rebuild cached metrics information
/** When \c tight is true, the height of the cell will be at least /** When \c tight is true, the height of the cell will be at least
* the x height of the font. Otherwise, it will be the max height * the x height of the font. Otherwise, it will be the max height
@ -197,9 +191,6 @@ protected:
mutable int kerning_; mutable int kerning_;
Buffer * buffer_; Buffer * buffer_;
/// cached object that describes typeset data
mutable std::map<BufferView const *, MathRow> mrow_cache_;
private: private:
/// is this an exact match at this position? /// is this an exact match at this position?
bool find1(MathData const & ar, size_type pos) const; bool find1(MathData const & ar, size_type pos) const;

View File

@ -86,7 +86,7 @@ public:
}; };
/// ///
MathRow() : caret_ascent(0), caret_descent(0) {}; MathRow(int asc = 0, int des = 0) : caret_ascent(asc), caret_descent(des) {};
/// ///
typedef std::vector<Element> Elements; typedef std::vector<Element> Elements;
/// ///