This commit fixes the singlePar optimization which was disabled due to the ParagraphMetrics cleanup.

* rowpainter.C::paintPar(): don't calculate row signature here. Use ParagraphMetrics::rowChangeStatus() instead.

* RowList_fwd.h: RowSignature is now a vector.

* ParagraphMetrics
  - rowChangeStatus(), updateRowChangeStatus(), calculateRowSignature(): new methods.
  - row_signature_: new member
  - rowSignature_: renamed to row_signature_

* TextMetrics::redoParagraph(): call ParagraphMetrics::updateRowChangeStatus()

* BufferView::updateMetrics(): simplify the singlePar case.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@16543 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Abdelrazak Younes 2007-01-06 09:15:59 +00:00
parent a01209bee8
commit 063fdd118b
6 changed files with 72 additions and 39 deletions

View File

@ -1345,23 +1345,22 @@ void BufferView::updateMetrics(bool singlepar)
// If the paragraph metrics has changed, we can not
// use the singlepar optimisation.
if (singlepar && tm.redoParagraph(cursor_.bottom().pit()))
singlepar = false;
if (singlepar
// In Single Paragraph mode, rebreak only
// the (main text, not inset!) paragraph containing the cursor.
// (if this paragraph contains insets etc., rebreaking will
// recursively descend)
&& tm.redoParagraph(cursor_.bottom().pit()))
singlepar = false;
pit_type const pit = anchor_ref_;
int pit1 = pit;
int pit2 = pit;
size_t const npit = buftext.paragraphs().size();
// Rebreak anchor paragraph. In Single Paragraph mode, rebreak only
// the (main text, not inset!) paragraph containing the cursor.
// (if this paragraph contains insets etc., rebreaking will
// recursively descend)
if (!singlepar || pit == cursor_.bottom().pit())
// If the paragraph metrics has changed, we can not
// use the singlepar optimisation.
if (tm.redoParagraph(pit))
singlepar = false;
// Rebreak anchor paragraph.
if (!singlepar)
tm.redoParagraph(pit);
// Clear out the position cache in case of full screen redraw.
if (!singlepar)
@ -1369,13 +1368,12 @@ void BufferView::updateMetrics(bool singlepar)
int y0 = tm.parMetrics(pit).ascent() - offset_ref_;
// Redo paragraphs above anchor if necessary; again, in Single Par
// mode, only if we encounter the (main text) one having the cursor.
// Redo paragraphs above anchor if necessary.
int y1 = y0;
while (y1 > 0 && pit1 > 0) {
y1 -= tm.parMetrics(pit1).ascent();
--pit1;
if (!singlepar || pit1 == cursor_.bottom().pit())
if (!singlepar)
tm.redoParagraph(pit1);
y1 -= tm.parMetrics(pit1).descent();
}
@ -1395,13 +1393,12 @@ void BufferView::updateMetrics(bool singlepar)
anchor_ref_ = 0;
}
// Redo paragraphs below the anchor if necessary. Single par mode:
// only the one containing the cursor if encountered.
// Redo paragraphs below the anchor if necessary.
int y2 = y0;
while (y2 < height_ && pit2 < int(npit) - 1) {
y2 += tm.parMetrics(pit2).descent();
++pit2;
if (!singlepar || pit2 == cursor_.bottom().pit())
if (!singlepar)
tm.redoParagraph(pit2);
y2 += tm.parMetrics(pit2).ascent();
}

View File

@ -78,6 +78,42 @@ ParagraphMetrics::ParagraphMetrics(Paragraph const & par): par_(&par)
}
ParagraphMetrics & ParagraphMetrics::operator=(
ParagraphMetrics const & pm)
{
rows_ = pm.rows_;
dim_ = pm.dim_;
par_ = pm.par_;
return *this;
}
size_type ParagraphMetrics::calculateRowSignature(Row const & row)
{
boost::crc_32_type crc;
for (pos_type i = row.pos(); i < row.endpos(); ++i) {
char_type const b[] = { par_->getChar(i) };
crc.process_bytes(b, 1);
}
return crc.checksum();
}
void ParagraphMetrics::updateRowChangeStatus()
{
size_t const size = rows_.size();
row_change_status_.resize(size);
row_signature_.resize(size);
for (size_t i = 0; i != size; ++i) {
// Row signature; has row changed since last update?
size_type const row_sig = calculateRowSignature(rows_[i]);
row_change_status_[i] = row_signature_[i] != row_sig;
row_signature_[i] = row_sig;
}
}
Row & ParagraphMetrics::getRow(pos_type pos, bool boundary)
{
BOOST_ASSERT(!rows().empty());

View File

@ -31,6 +31,13 @@ public:
ParagraphMetrics(): par_(0) {};
/// The only useful constructor.
ParagraphMetrics(Paragraph const & par);
/// Copy operator.
/// Important note: We don't copy \c row_change_status_ and
/// \c row_signature_ because those are updated externally with
/// \c updateRowChangeStatus() in TextMetrics::redoParagraph().
ParagraphMetrics & operator=(ParagraphMetrics const &);
///
Row & getRow(pos_type pos, bool boundary);
///
@ -53,8 +60,11 @@ public:
RowList & rows() { return rows_; }
/// The painter and others use this
RowList const & rows() const { return rows_; }
/// The painter and others use this
std::vector<bool> const & rowChangeStatus() const
{ return row_change_status_; }
///
RowSignature & rowSignature() const { return rowSignature_; }
void updateRowChangeStatus();
///
int rightMargin(Buffer const & buffer) const;
@ -62,10 +72,14 @@ public:
void dump() const;
private:
///
size_type ParagraphMetrics::calculateRowSignature(Row const &);
///
mutable RowList rows_;
///
mutable RowSignature rowSignature_;
RowSignature row_signature_;
///
std::vector<bool> row_change_status_;
/// cached dimensions of paragraph
Dimension dim_;
///

View File

@ -27,7 +27,7 @@ namespace lyx {
*/
typedef std::vector<Row> RowList;
///
typedef std::map<size_type, size_type> RowSignature;
typedef std::vector<size_type> RowSignature;
} // namespace lyx

View File

@ -258,6 +258,10 @@ bool TextMetrics::redoParagraph(pit_type const pit)
par_metrics_[pit] = pm;
// Update the row change statuses. The painter will need that info
// in order to know which row has to be repainted.
par_metrics_[pit].updateRowChangeStatus();
return changed;
}

View File

@ -823,20 +823,6 @@ void RowPainter::paintText()
}
size_type calculateRowSignature(Row const & row, Paragraph const & par,
int x, int y)
{
boost::crc_32_type crc;
for (pos_type i = row.pos(); i < row.endpos(); ++i) {
char_type const b[] = { par.getChar(i) };
crc.process_bytes(b, 1);
}
char_type const b[] = { x, y, row.width() };
crc.process_bytes(b, 3);
return crc.checksum();
}
bool CursorOnRow(PainterInfo & pi, pit_type const pit,
RowList::const_iterator rit, LyXText const & text)
{
@ -899,8 +885,7 @@ void paintPar
bool tmp = refreshInside;
// Row signature; has row changed since last paint?
size_type const row_sig = calculateRowSignature(*rit, par, x, y);
bool row_has_changed = pm.rowSignature()[rowno] != row_sig;
bool row_has_changed = pm.rowChangeStatus()[rowno];
bool cursor_on_row = CursorOnRow(pi, pit, rit, text);
bool in_inset_alone_on_row = innerCursorOnRow(pi, pit, rit,
@ -928,9 +913,6 @@ void paintPar
// from cache, or cursor is inside an inset _on this row_,
// then paint the row
if (repaintAll || row_has_changed || cursor_on_row) {
// Add to row signature cache
pm.rowSignature()[rowno] = row_sig;
bool const inside = (y + rit->descent() >= 0
&& y - rit->ascent() < ww);
// it is not needed to draw on screen if we are not inside.