From 6ce171eec85dd1ed275daa1c01294e7d4f964d80 Mon Sep 17 00:00:00 2001 From: Abdelrazak Younes Date: Tue, 11 Sep 2007 16:04:10 +0000 Subject: [PATCH] Transfer the Paragraph position cache from CoordCache to ParagraphMetrics and TextMetrics. * ParagraphMetrics::position_: new private member (and associated access method). * TextMetrics: - origin_: new screen position cache. - use origin_ and ParagraphMetrics::position() instead of the parPos cache. * Cursor: - comment out buggy bruteFind() method, will work on that later. * BufferView::updateMetrics(): refactor and simplify to use new cache and to gather everything SinglePar related. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@20214 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/BufferView.cpp | 67 +++++++++++++++++----------------------- src/CoordCache.cpp | 28 ----------------- src/CoordCache.h | 8 ----- src/Cursor.cpp | 4 ++- src/ParagraphMetrics.cpp | 10 +++++- src/ParagraphMetrics.h | 7 +++++ src/TextMetrics.cpp | 54 ++++++++++++++++---------------- src/TextMetrics.h | 21 ++++++------- src/bufferview_funcs.cpp | 19 +++--------- 9 files changed, 90 insertions(+), 128 deletions(-) diff --git a/src/BufferView.cpp b/src/BufferView.cpp index ae5a4ddc5f..9a66db4014 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -1341,10 +1341,10 @@ ViewMetricsInfo const & BufferView::viewMetricsInfo() void BufferView::updateMetrics(bool singlepar) { Text & buftext = buffer_.text(); - pit_type size = int(buftext.paragraphs().size()); + pit_type const npit = int(buftext.paragraphs().size()); - if (anchor_ref_ > int(buftext.paragraphs().size() - 1)) { - anchor_ref_ = int(buftext.paragraphs().size() - 1); + if (anchor_ref_ > int(npit - 1)) { + anchor_ref_ = int(npit - 1); offset_ref_ = 0; } @@ -1360,6 +1360,7 @@ void BufferView::updateMetrics(bool singlepar) TextMetrics & tm = textMetrics(&buftext); + pit_type const bottom_pit = cursor_.bottom().pit(); // If the paragraph metrics has changed, we can not // use the singlepar optimisation. if (singlepar @@ -1367,17 +1368,31 @@ void BufferView::updateMetrics(bool singlepar) // 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; + && !tm.redoParagraph(bottom_pit)) { + + updateOffsetRef(); + // collect cursor paragraph iter bounds + ParagraphMetrics const & pm = tm.parMetrics(bottom_pit); + int y1 = pm.position() - pm.ascent(); + int y2 = pm.position() + pm.descent(); + metrics_info_ = ViewMetricsInfo(bottom_pit, bottom_pit, y1, y2, + SingleParUpdate, npit); + LYXERR(Debug::PAINTING) + << BOOST_CURRENT_FUNCTION + << "\ny1: " << y1 + << " y2: " << y2 + << " pit: " << bottom_pit + << " singlepar: " << singlepar + << endl; + return; + } pit_type const pit = anchor_ref_; int pit1 = pit; int pit2 = pit; - size_t const npit = buftext.paragraphs().size(); // Rebreak anchor paragraph. - if (!singlepar) - tm.redoParagraph(pit); + tm.redoParagraph(pit); updateOffsetRef(); @@ -1388,12 +1403,10 @@ void BufferView::updateMetrics(bool singlepar) while (y1 > 0 && pit1 > 0) { y1 -= tm.parMetrics(pit1).ascent(); --pit1; - if (!singlepar) - tm.redoParagraph(pit1); + tm.redoParagraph(pit1); y1 -= tm.parMetrics(pit1).descent(); } - // Take care of ascent of first line y1 -= tm.parMetrics(pit1).ascent(); @@ -1413,49 +1426,25 @@ void BufferView::updateMetrics(bool singlepar) while (y2 < height_ && pit2 < int(npit) - 1) { y2 += tm.parMetrics(pit2).descent(); ++pit2; - if (!singlepar) - tm.redoParagraph(pit2); + tm.redoParagraph(pit2); y2 += tm.parMetrics(pit2).ascent(); } // Take care of descent of last line y2 += tm.parMetrics(pit2).descent(); - // The coordinates of all these paragraphs are correct, cache them - int y = y1; - CoordCache::InnerParPosCache & parPos = coord_cache_.parPos()[&buftext]; - for (pit_type pit = pit1; pit <= pit2; ++pit) { - ParagraphMetrics const & pm = tm.parMetrics(pit); - y += pm.ascent(); - parPos[pit] = Point(0, y); - if (singlepar && pit == cursor_.bottom().pit()) { - // In Single Paragraph mode, collect here the - // y1 and y2 of the (one) paragraph the cursor is in - y1 = y - pm.ascent(); - y2 = y + pm.descent(); - } - y += pm.descent(); - } - - if (singlepar) { - // collect cursor paragraph iter bounds - pit1 = cursor_.bottom().pit(); - pit2 = cursor_.bottom().pit(); - } - - LYXERR(Debug::DEBUG) + LYXERR(Debug::PAINTING) << BOOST_CURRENT_FUNCTION - << " y1: " << y1 + << "\n y1: " << y1 << " y2: " << y2 << " pit1: " << pit1 << " pit2: " << pit2 << " npit: " << npit << " singlepar: " << singlepar - << "size: " << size << endl; metrics_info_ = ViewMetricsInfo(pit1, pit2, y1, y2, - singlepar? SingleParUpdate: FullScreenUpdate, size); + FullScreenUpdate, npit); if (lyxerr.debugging(Debug::WORKAREA)) { LYXERR(Debug::WORKAREA) << "BufferView::updateMetrics" << endl; diff --git a/src/CoordCache.cpp b/src/CoordCache.cpp index 8ab101ba80..38baabf805 100644 --- a/src/CoordCache.cpp +++ b/src/CoordCache.cpp @@ -43,41 +43,13 @@ void CoordCache::clear() { arrays_.clear(); insets_.clear(); - pars_.clear(); slices0_.clear(); slices1_.clear(); } -Point CoordCache::get(Text const * text, pit_type pit) const -{ - ParPosCache::const_iterator const it = pars_.find(text); - BOOST_ASSERT(it != pars_.end()); - InnerParPosCache::const_iterator const posit = it->second.find(pit); - BOOST_ASSERT(posit != it->second.end()); - return posit->second; -} - - void CoordCache::dump() const { - lyxerr << "ParPosCache contains:" << std::endl; - for (ParPosCache::const_iterator it = getParPos().begin(); it != getParPos().end(); ++it) { - Text const * lt = it->first; - InnerParPosCache const & cache = it->second; - lyxerr << "Text:" << lt << std::endl; - for (InnerParPosCache::const_iterator jt = cache.begin(); jt != cache.end(); ++jt) { - pit_type pit = jt->first; - Paragraph const & par = lt->getPar(pit); - Point p = jt->second; - lyxerr << "Paragraph " << pit << ": \""; - int const n = std::min(static_cast(10), par.size()); - for (int k = 0; k < n; ++k) - lyxerr << to_utf8(docstring(1, par.getChar(k))); - lyxerr << "\" has point " << p.x_ << "," << p.y_ << std::endl; - } - } - lyxerr << "InsetCache contains:" << std::endl; for (CoordCacheBase::cache_type::const_iterator it = getInsets().getData().begin(); it != getInsets().getData().end(); ++it) { Inset const * inset = it->first; diff --git a/src/CoordCache.h b/src/CoordCache.h index ba69f94eba..63e0aece96 100644 --- a/src/CoordCache.h +++ b/src/CoordCache.h @@ -113,12 +113,9 @@ public: class CoordCache { public: void clear(); - Point get(Text const *, pit_type) const; /// A map from paragraph index number to screen point typedef std::map InnerParPosCache; - /// A map from a Text to the map of paragraphs to screen points - typedef std::map ParPosCache; /// A map from a CursorSlice to screen points typedef std::map SliceCache; @@ -128,9 +125,6 @@ public: /// A map from insets to positions on the screen CoordCacheBase & insets() { return insets_; } CoordCacheBase const & getInsets() const { return insets_; } - /// A map from (Text, paragraph) pair to screen positions - ParPosCache & parPos() { return pars_; } - ParPosCache const & getParPos() const { return pars_; } /// SliceCache & slice(bool boundary) { @@ -148,8 +142,6 @@ private: CoordCacheBase arrays_; // All insets CoordCacheBase insets_; - /// Paragraph grouped by owning text - ParPosCache pars_; /// Used with boundary == 0 SliceCache slices0_; /// Used with boundary == 1 diff --git a/src/Cursor.cpp b/src/Cursor.cpp index f31e52fdab..95c0d71999 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -132,6 +132,7 @@ namespace { } + /* /// moves position closest to (x, y) in given box bool bruteFind(Cursor & cursor, int x, int y, int xlow, int xhigh, int ylow, int yhigh) @@ -186,6 +187,7 @@ namespace { return false; } + */ /// moves position closest to (x, y) in given box @@ -683,7 +685,7 @@ bool Cursor::openable(MathAtom const & t) const void Cursor::setScreenPos(int x, int y) { setTargetX(x); - bruteFind(*this, x, y, 0, bv().workWidth(), 0, bv().workHeight()); + //bruteFind(*this, x, y, 0, bv().workWidth(), 0, bv().workHeight()); } diff --git a/src/ParagraphMetrics.cpp b/src/ParagraphMetrics.cpp index d9272f2255..a05177831d 100644 --- a/src/ParagraphMetrics.cpp +++ b/src/ParagraphMetrics.cpp @@ -71,7 +71,7 @@ using std::ostream; using std::ostringstream; -ParagraphMetrics::ParagraphMetrics(Paragraph const & par): par_(&par) +ParagraphMetrics::ParagraphMetrics(Paragraph const & par): par_(&par), position_(-1) { } @@ -82,6 +82,7 @@ ParagraphMetrics & ParagraphMetrics::operator=( rows_ = pm.rows_; dim_ = pm.dim_; par_ = pm.par_; + position_ = pm.position_; return *this; } @@ -90,6 +91,7 @@ void ParagraphMetrics::reset(Paragraph const & par) { par_ = ∥ dim_ = Dimension(); + //position_ = -1; } @@ -110,6 +112,12 @@ void ParagraphMetrics::computeRowSignature(Row & row, } +void ParagraphMetrics::setPosition(int position) +{ + position_ = position; +} + + Row & ParagraphMetrics::getRow(pos_type pos, bool boundary) { BOOST_ASSERT(!rows().empty()); diff --git a/src/ParagraphMetrics.h b/src/ParagraphMetrics.h index 5cf587f788..69ac74df41 100644 --- a/src/ParagraphMetrics.h +++ b/src/ParagraphMetrics.h @@ -82,7 +82,14 @@ public: /// void computeRowSignature(Row &, BufferParams const & bparams); + /// + int position() const { return position_; } + void setPosition(int position); + + private: + /// + int position_; /// mutable RowList rows_; /// cached dimensions of paragraph diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index f9c533e7e3..9ea8674456 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -25,7 +25,6 @@ #include "BufferView.h" #include "bufferview_funcs.h" #include "Color.h" -#include "CoordCache.h" #include "CutAndPaste.h" #include "debug.h" #include "FontIterator.h" @@ -46,6 +45,7 @@ #include +using std::make_pair; using std::max; using std::min; using std::endl; @@ -126,6 +126,12 @@ TextMetrics::TextMetrics(BufferView * bv, Text * text) } +bool TextMetrics::has(pit_type pit) const +{ + return par_metrics_.find(pit) != par_metrics_.end(); +} + + ParagraphMetrics const & TextMetrics::parMetrics(pit_type pit) const { return const_cast(this)->parMetrics(pit, true); @@ -138,7 +144,7 @@ ParagraphMetrics & TextMetrics::parMetrics(pit_type pit, ParMetricsCache::iterator pmc_it = par_metrics_.find(pit); if (pmc_it == par_metrics_.end()) { pmc_it = par_metrics_.insert( - std::make_pair(pit, ParagraphMetrics(text_->getPar(pit)))).first; + make_pair(pit, ParagraphMetrics(text_->getPar(pit)))).first; } if (pmc_it->second.rows().empty() && redo) { redoParagraph(pit); @@ -987,7 +993,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit, /// For the main Text, it is possible that this pit is not /// yet in the CoordCache when moving cursor up. /// x Paragraph coordinate is always 0 for main text anyway. - int const xo = main_text_? 0 : bv_->coordCache().get(text_, pit).x_; + int const xo = origin_.x_; x -= xo; Paragraph const & par = text_->getPar(pit); ParagraphMetrics const & pm = par_metrics_[pit]; @@ -1137,26 +1143,24 @@ pos_type TextMetrics::x2pos(pit_type pit, int row, int x) const pit_type TextMetrics::getPitNearY(int y) { BOOST_ASSERT(!text_->paragraphs().empty()); - BOOST_ASSERT(bv_->coordCache().getParPos().find(text_) != bv_->coordCache().getParPos().end()); - CoordCache::InnerParPosCache const & cc = bv_->coordCache().getParPos().find(text_)->second; LYXERR(Debug::DEBUG) << BOOST_CURRENT_FUNCTION - << ": y: " << y << " cache size: " << cc.size() + << ": y: " << y << " cache size: " << par_metrics_.size() << endl; // look for highest numbered paragraph with y coordinate less than given y pit_type pit = 0; int yy = -1; - CoordCache::InnerParPosCache::const_iterator it = cc.begin(); - CoordCache::InnerParPosCache::const_iterator et = cc.end(); - CoordCache::InnerParPosCache::const_iterator last = et; last--; + ParMetricsCache::const_iterator it = par_metrics_.begin(); + ParMetricsCache::const_iterator et = par_metrics_.end(); + ParMetricsCache::const_iterator last = et; last--; - ParagraphMetrics const & pm = par_metrics_[it->first]; + ParagraphMetrics const & pm = it->second; // If we are off-screen (before the visible part) if (y < 0 // and even before the first paragraph in the cache. - && y < it->second.y_ - int(pm.ascent())) { + && y < it->second.position() - int(pm.ascent())) { // and we are not at the first paragraph in the inset. if (it->first == 0) return 0; @@ -1164,8 +1168,7 @@ pit_type TextMetrics::getPitNearY(int y) pit = it->first - 1; // rebreak it and update the CoordCache. redoParagraph(pit); - bv_->coordCache().parPos()[text_][pit] = - Point(0, it->second.y_ - pm.descent()); + par_metrics_[pit].setPosition(it->second.position() - pm.descent()); return pit; } @@ -1174,7 +1177,7 @@ pit_type TextMetrics::getPitNearY(int y) // If we are off-screen (after the visible part) if (y > bv_->workHeight() // and even after the first paragraph in the cache. - && y >= last->second.y_ + int(pm_last.descent())) { + && y >= last->second.position() + int(pm_last.descent())) { pit = last->first + 1; // and we are not at the last paragraph in the inset. if (pit == int(text_->paragraphs().size())) @@ -1182,8 +1185,7 @@ pit_type TextMetrics::getPitNearY(int y) // then this is the paragraph we are looking for. // rebreak it and update the CoordCache. redoParagraph(pit); - bv_->coordCache().parPos()[text_][pit] = - Point(0, last->second.y_ + pm_last.ascent()); + par_metrics_[pit].setPosition(last->second.position() + pm_last.ascent()); return pit; } @@ -1191,14 +1193,14 @@ pit_type TextMetrics::getPitNearY(int y) LYXERR(Debug::DEBUG) << BOOST_CURRENT_FUNCTION << " examining: pit: " << it->first - << " y: " << it->second.y_ + << " y: " << it->second.position() << endl; ParagraphMetrics const & pm = par_metrics_[it->first]; - if (it->first >= pit && int(it->second.y_) - int(pm.ascent()) <= y) { + if (it->first >= pit && int(it->second.position()) - int(pm.ascent()) <= y) { pit = it->first; - yy = it->second.y_; + yy = it->second.position(); } } @@ -1215,7 +1217,7 @@ Row const & TextMetrics::getRowNearY(int y, pit_type pit) const { ParagraphMetrics const & pm = par_metrics_[pit]; - int yy = bv_->coordCache().get(text_, pit).y_ - pm.ascent(); + int yy = pm.position() - pm.ascent(); BOOST_ASSERT(!pm.rows().empty()); RowList::const_iterator rit = pm.rows().begin(); RowList::const_iterator const rlast = boost::prior(pm.rows().end()); @@ -1292,7 +1294,7 @@ void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const ParagraphMetrics const & pm = par_metrics_[pit]; - int yy = bv_->coordCache().get(text_, pit).y_ - pm.ascent(); + int yy = pm.position() - pm.ascent(); LYXERR(Debug::DEBUG) << BOOST_CURRENT_FUNCTION << ": x: " << x @@ -1802,17 +1804,18 @@ void TextMetrics::draw(PainterInfo & pi, int x, int y) const if (par_metrics_.empty()) return; - CoordCache::InnerParPosCache & ppcache = bv_->coordCache().parPos()[text_]; + origin_.x_ = x; + origin_.y_ = y; - ParMetricsCache::const_iterator it = par_metrics_.begin(); - ParMetricsCache::const_iterator const pm_end = par_metrics_.end(); + ParMetricsCache::iterator it = par_metrics_.begin(); + ParMetricsCache::iterator const pm_end = par_metrics_.end(); y -= it->second.ascent(); for (; it != pm_end; ++it) { ParagraphMetrics const & pmi = it->second; y += pmi.ascent(); pit_type const pit = it->first; // Save the paragraph position in the cache. - ppcache[pit] = Point(x, y); + it->second.setPosition(y); drawParagraph(pi, pit, x, y); y += pmi.descent(); } @@ -1866,7 +1869,6 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co Color_color(Color::color(pi.background_color))); } if (row_selection) { - lyxerr << "row selected" << endl; DocIterator beg = bv_->cursor().selectionBegin(); DocIterator end = bv_->cursor().selectionEnd(); beg.pit() = pit; diff --git a/src/TextMetrics.h b/src/TextMetrics.h index 0057e837e3..44624913be 100644 --- a/src/TextMetrics.h +++ b/src/TextMetrics.h @@ -15,6 +15,9 @@ #define TEXT_METRICS_H #include "Font.h" +// FIXME: We only need Point class definition, not the full +// CoordCache. +#include "CoordCache.h" #include "ParagraphMetrics.h" #include "support/types.h" @@ -40,12 +43,17 @@ public: TextMetrics(): text_(0) {} /// The only useful constructor. TextMetrics(BufferView *, Text *); + + /// + bool has(pit_type pit) const; /// ParagraphMetrics const & parMetrics(pit_type) const; /// Dimension const & dimension() const; - Dimension const & dimension(); + + Point const & origin() const { return origin_; } + /// compute text metrics. bool metrics(MetricsInfo & mi, Dimension & dim); @@ -251,16 +259,7 @@ private: mutable ParMetricsCache par_metrics_; Dimension dim_; int max_width_; - - /// FIXME: transfer this code in CoordCache here. - /* - /// A map from paragraph index number to screen point - typedef std::map InnerParPosCache; - /// A map from a Text to the map of paragraphs to screen points - typedef std::map ParPosCache; - /// Paragraph grouped by owning text - ParPosCache pars_; - */ + mutable Point origin_; // temporary public: public: diff --git a/src/bufferview_funcs.cpp b/src/bufferview_funcs.cpp index 9130ec76e3..6c218eb53e 100644 --- a/src/bufferview_funcs.cpp +++ b/src/bufferview_funcs.cpp @@ -231,19 +231,12 @@ Point coordOffset(BufferView const & bv, DocIterator const & dit, Point getPos(BufferView const & bv, DocIterator const & dit, bool boundary) { CursorSlice const & bot = dit.bottom(); - CoordCache::ParPosCache::const_iterator cache_it = - bv.coordCache().getParPos().find(bot.text()); - if (cache_it == bv.coordCache().getParPos().end()) + TextMetrics const & tm = bv.textMetrics(bot.text()); + if (!tm.has(bot.pit())) return Point(-1, -1); - CoordCache::InnerParPosCache const & cache = cache_it->second; - CoordCache::InnerParPosCache::const_iterator it = cache.find(bot.pit()); - if (it == cache.end()) { - //lyxerr << "cursor out of view" << std::endl; - return Point(-1, -1); - } Point p = coordOffset(bv, dit, boundary); // offset from outer paragraph - p.y_ += it->second.y_; + p.y_ += tm.parMetrics(bot.pit()).position(); return p; } @@ -252,10 +245,8 @@ Point getPos(BufferView const & bv, DocIterator const & dit, bool boundary) // FIXME: This does not work within mathed! CurStatus status(BufferView const * bv, DocIterator const & dit) { - CoordCache::InnerParPosCache const & cache = - bv->coordCache().getParPos().find(dit.bottom().text())->second; - - if (cache.find(dit.bottom().pit()) != cache.end()) + TextMetrics const & tm = bv->textMetrics(dit.bottom().text()); + if (tm.has(dit.bottom().pit())) return CUR_INSIDE; else if (dit.bottom().pit() < bv->anchor_ref()) return CUR_ABOVE;