On Wed, 2005-12-14 at 10:59 -0500, Bennett Helm wrote: > On Dec 14, 2005, at 10:51 AM, Jean-Marc Lasgouttes wrote: > > >>>>>> "Angus" == Angus Leeming <[EMAIL PROTECTED]> writes: > > > > Angus> Do I read top-down correctly as saying that one half of all > > Angus> LyX's processing time is spent in doTextTask? > > > > Yes, drawing seems to be very slow with Qt/Mac. > > But this doesn't explain why the same version of Qt/Mac together with > lyx-1.3.x is relatively speedy! With lyx-1.3.x, there's no lag *at > all* in typing into even very large paragraphs, into large insets > embedded within large paragraphs, etc. I don't think this can be the > explanation of the speed problem in lyx-1.4.0.
So I gave it another try... see attached. This is essentially based upon the 'row signature' approach mentioned by Jean-Marc in a later post. What I did wrong in the earlier singlerow patch was, that I tested for the presence of an inset in the current paragraph by seeing if insetlist was empty. (This must be done because rows containing insets containing further text _must be rendered_ in order to render the inside text through recursive descent.) Now unfortunately almost any paragraph in a typical text contains _some_ inset, if only a double quote or so. So I had to make the inset testing more refined. Now the code traverses the inset list looking for HIGHLY_EDITABLE insets, the only ones that can contain inner text. While at it, I did this test for every row separately. Testing with lyxerr-instrumented code in rowpainter showed this to be highly effective. LyX even _feels_ faster with this patch, even on Linux. Currently this is implemented only for "outer" paragraphs, not text inside an inset. If it does the job, I know precisely what to do to get also the latter working. So Bennett, if I may bother you once again to test this for a huge paragraph _not inside an inset_. If it works, I will extend it for insets, and the patch can then be included with the Mac binaries to be published, if at this point we don't want to risk it with 1.4.0. After all this is a serious regression for one platform. Oh, and you should have the earlier lyxfunc patch included as well for testing. - Martin
Index: rowpainter.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/rowpainter.C,v retrieving revision 1.159 diff -u -p -r1.159 rowpainter.C --- rowpainter.C 2 Dec 2005 13:20:26 -0000 1.159 +++ rowpainter.C 16 Dec 2005 09:29:36 -0000 @@ -713,7 +713,8 @@ void RowPainter::paintText() void paintPar - (PainterInfo & pi, LyXText const & text, pit_type pit, int x, int y) + (PainterInfo & pi, LyXText const & text, pit_type pit, int x, int y, + bool select) { // lyxerr << " paintPar: pit: " << pit << " at y: " << y << endl; static NullPainter nop; @@ -727,6 +728,7 @@ void paintPar theCoords.parPos()[&text][pit] = Point(x, y); y -= rb->ascent(); + unsigned rowno = 0; for (RowList::const_iterator rit = rb; rit != re; ++rit) { y += rit->ascent(); bool const inside = (y + rit->descent() >= 0 @@ -734,14 +736,52 @@ void paintPar RowPainter rp(inside ? pi : nullpi, text, pit, *rit, x, y); y += rit->descent(); - rp.paintAppendix(); - rp.paintDepthBar(); - rp.paintChangeBar(); - if (rit == rb) - rp.paintFirst(); - if (rit + 1 == re) - rp.paintLast(); - rp.paintText(); + + // Row signature; has row changed since last paint? + unsigned row_sig = rit->endpos() - rit->pos() + y; + + // The following code figures out if this row contains + // insets containing their own rows. + bool insetinrow(false); + InsetList::const_iterator ii = par.insetlist.begin(); + InsetList::const_iterator iend = par.insetlist.end(); + for ( ; ii != iend; ++ii) { + if (ii->pos >= rit->pos() && ii->pos < rit->endpos() + && ii->inset->editable() == InsetBase::HIGHLY_EDITABLE) + insetinrow = true; + } + + // If selection is on, the current row signature differs + // from cache (or no cache entry), or this row contains + // insets (with possibly pars), then paint this row + if (select || rowno >= par.row_sig().size() + || par.row_sig()[rowno] != row_sig + || insetinrow) { + // Add to row signature cache + if (rowno >= par.row_sig().size()) + par.row_sig().push_back(row_sig); + else + par.row_sig()[rowno] = row_sig; + + // Clear background of this row (par background was + // not cleared) + if (!select) { + int ht = rit->ascent() + rit->descent(); + pi.pain.fillRectangle(0, y - ht, + pi.base.bv->workWidth(), ht, + text.backgroundColor()); + } + + rp.paintAppendix(); + rp.paintDepthBar(); + rp.paintChangeBar(); + if (rit == rb) + rp.paintFirst(); + if (rit + 1 == re) + rp.paintLast(); + rp.paintText(); + } + ++rowno; } } @@ -752,21 +792,25 @@ void paintText(BufferView const & bv, Vi { Painter & pain = bv.painter(); LyXText * const text = bv.text(); - - // clear background - pain.fillRectangle(0, vi.y1, bv.workWidth(), vi.y2 - vi.y1, - LColor::background); - - // draw selection + bool select = bv.cursor().selection(); + PainterInfo pi(const_cast<BufferView *>(&bv), pain); - - text->drawSelection(pi, 0, 0); + if (select) { + // Clear background (Delegated to rows if no selection) + pain.fillRectangle(0, vi.y1, bv.workWidth(), vi.y2 - vi.y1, + text->backgroundColor()); + text->drawSelection(pi, 0, 0); + } int yy = vi.y1; // draw contents for (pit_type pit = vi.p1; pit <= vi.p2; ++pit) { yy += text->getPar(pit).ascent(); - paintPar(pi, *bv.text(), pit, 0, yy); + // This handles scroll page up - page down. + // Must be repainted though signature unchanged + if (!vi.singlepar) + text->getPar(pit).row_sig().clear(); + paintPar(pi, *bv.text(), pit, 0, yy, select); yy += text->getPar(pit).descent(); } @@ -805,7 +849,7 @@ void paintTextInset(LyXText const & text y -= text.getPar(0).ascent(); for (int pit = 0; pit < int(text.paragraphs().size()); ++pit) { y += text.getPar(pit).ascent(); - paintPar(pi, text, pit, x, y); + paintPar(pi, text, pit, x, y, true); y += text.getPar(pit).descent(); } } Index: paragraph.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/paragraph.C,v retrieving revision 1.417 diff -u -p -r1.417 paragraph.C --- paragraph.C 25 Nov 2005 14:40:34 -0000 1.417 +++ paragraph.C 16 Dec 2005 09:29:37 -0000 @@ -71,7 +71,7 @@ ParagraphList::ParagraphList() Paragraph::Paragraph() - : begin_of_body_(0), pimpl_(new Paragraph::Pimpl(this)) + : row_sig_(0), begin_of_body_(0), pimpl_(new Paragraph::Pimpl(this)) { itemdepth = 0; params().clear(); @@ -80,8 +80,8 @@ Paragraph::Paragraph() Paragraph::Paragraph(Paragraph const & par) : itemdepth(par.itemdepth), insetlist(par.insetlist), - dim_(par.dim_), - rows_(par.rows_), layout_(par.layout_), + dim_(par.dim_), rows_(par.rows_), + row_sig_(par.row_sig_), layout_(par.layout_), text_(par.text_), begin_of_body_(par.begin_of_body_), pimpl_(new Paragraph::Pimpl(*par.pimpl_, this)) { @@ -110,7 +110,8 @@ Paragraph & Paragraph::operator=(Paragra layout_ = par.layout(); text_ = par.text_; begin_of_body_ = par.begin_of_body_; - + row_sig_ = par.row_sig_; + delete pimpl_; pimpl_ = new Pimpl(*par.pimpl_, this); } Index: paragraph.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/paragraph.h,v retrieving revision 1.157 diff -u -p -r1.157 paragraph.h --- paragraph.h 7 Sep 2005 10:36:59 -0000 1.157 +++ paragraph.h 16 Dec 2005 09:29:37 -0000 @@ -391,7 +391,9 @@ public: RowList & rows() { return rows_; } /// The painter and others use this RowList const & rows() const { return rows_; } - + /// + std::vector<unsigned> & row_sig() const { return row_sig_; } + /// LyXText::redoParagraph updates this Dimension & dim() { return dim_; } @@ -401,6 +403,8 @@ public: public: /// InsetList insetlist; + /// + bool breakFlag; private: /// cached dimensions of paragraph @@ -408,6 +412,9 @@ private: /// mutable RowList rows_; + /// + mutable std::vector<unsigned> row_sig_; + /// LyXLayout_ptr layout_; /**
signature.asc
Description: This is a digitally signed message part