On Wed, Dec 21, 2005 at 01:46:53PM -0500, Bennett Helm wrote: > On Dec 21, 2005, at 9:01 AM, Bennett Helm wrote: > > >I haven't noticed any strange drawing issues. > > I take that back. On occasion, when typing text into the middle of a > paragraph should result in the last word of that line being bumped to > the next line, it doesn't happen on screen, even though the next line > and subsequent lines are properly redrawn. A similar problem happens > (and not always in the same cases) with deleting: when deleting text > in a line should result in a word from the next line being brought > up, that word does appear in the current line, though the next line > still contains that word. > > I hope that's clear. I haven't been able to see a pattern as to when > the problem occurs and when not. But it's frequent enough that you > should be able to reproduce it without much effort.
Clear enough. Jean-Marc has been expecting that the 'row signature' we are using isn't discriminating enough, and now you seem to have run into that. Our row signature is rit->endpos() - rit->pos() + 1000 * y which means: end-of-row - beginning-of-row + 1000 * vertical position of row. The row beginning and end positions in characters from start-of-paragraph, y in pixels from top of screen. I expect that the pattern you see is: the word that gets pushed to the next line is the same length as the word getting pushed to the 'next next' line. I can reproduce that. (endpos - pos) remains unchanged. A good signature has the following properties: 1) it _never_ changes when the row does not change. (e.g., not when you add characters above it in the paragraph.) 2) it _always_ changes when the row changes. On this, the current signature is weak. The best signature would be a checksum computed over the row content, but designed such that, e.g., changing the order of the characters will produce a different checksum. Such a checksum would be rather expensive to compute. We should think of a signature that is simple and cheap, but better than this one. BTW I did manage to extend the patch to include text inside insets. Attached. You will see that there are still some rendering 'warts', but I live in hope. The logic seems to be correct. Please let me know if you get the intended speed-up, and if so, we'll start ironing out the warts. Hopefully. - Martin PS I'll be out of the scenery over the extended Christmas weekend.
Index: RowList_fwd.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/RowList_fwd.h,v retrieving revision 1.6 diff -u -p -r1.6 RowList_fwd.h --- RowList_fwd.h 31 Jan 2005 16:29:38 -0000 1.6 +++ RowList_fwd.h 21 Dec 2005 20:34:02 -0000 @@ -15,6 +15,7 @@ #include "lyxrow.h" #include <vector> +#include <map> /** * Each paragraph is broken up into a number of rows on the screen. @@ -22,5 +23,7 @@ * downwards. */ typedef std::vector<Row> RowList; +/// +typedef std::map<lyx::size_type, lyx::size_type> RowSignature; #endif 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 21 Dec 2005 20:34:03 -0000 @@ -81,7 +81,8 @@ Paragraph::Paragraph() Paragraph::Paragraph(Paragraph const & par) : itemdepth(par.itemdepth), insetlist(par.insetlist), dim_(par.dim_), - rows_(par.rows_), layout_(par.layout_), + rows_(par.rows_), rowSignature_(par.rowSignature_), + layout_(par.layout_), text_(par.text_), begin_of_body_(par.begin_of_body_), pimpl_(new Paragraph::Pimpl(*par.pimpl_, this)) { @@ -107,6 +108,7 @@ Paragraph & Paragraph::operator=(Paragra rows_ = par.rows_; dim_ = par.dim_; + rowSignature_ = par.rowSignature_; layout_ = par.layout(); text_ = par.text_; begin_of_body_ = par.begin_of_body_; 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 21 Dec 2005 20:34:03 -0000 @@ -391,7 +391,9 @@ public: RowList & rows() { return rows_; } /// The painter and others use this RowList const & rows() const { return rows_; } - + /// + RowSignature & rowSignature() const { return rowSignature_; } + /// LyXText::redoParagraph updates this Dimension & dim() { return dim_; } @@ -408,6 +410,9 @@ private: /// mutable RowList rows_; + /// + mutable RowSignature rowSignature_; + /// LyXLayout_ptr layout_; /** 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 21 Dec 2005 20:34:03 -0000 @@ -37,6 +37,7 @@ #include "frontends/Painter.h" #include "insets/insettext.h" +#include "insets/insetcollapsable.h" #include "support/textutils.h" @@ -158,7 +159,8 @@ void RowPainter::paintInset(pos_type con pi.ltr_pos = (text_.bidi.level(pos) % 2 == 0); pi.erased_ = erased_ || isDeletedText(par_, pos); theCoords.insets().add(inset, int(x_), yo_); - inset->drawSelection(pi, int(x_), yo_); + if (bv_.refresh()) + inset->drawSelection(pi, int(x_), yo_); inset->draw(pi, int(x_), yo_); x_ += inset->width(); } @@ -719,7 +721,8 @@ void paintPar static NullPainter nop; static PainterInfo nullpi(pi.base.bv, nop); int const ww = pi.base.bv->workHeight(); - + bool repaintAll = pi.base.bv->refresh(); + Paragraph const & par = text.paragraphs()[pit]; RowList::const_iterator const rb = par.rows().begin(); @@ -734,15 +737,70 @@ 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? + lyx::size_type const row_sig + = rit->endpos() - rit->pos() + 1000 * y; + + // The following code figures out if the cursor is inside + // an inset _on this row_. + bool cur_in_inset_in_row(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->isTextInset() + && pi.base.bv->cursor().isInside(ii->inset)) { + cur_in_inset_in_row = true; + break; + } + } + + // If selection is on, the current row signature differs from + // from cache, or cursor is inside an inset _on this row_, + // then paint the row + lyx::size_type rowno = std::distance(rit, rb); + if (repaintAll || par.rowSignature()[rowno] != row_sig + || cur_in_inset_in_row) { + // Add to row signature cache + par.rowSignature()[rowno] = row_sig; + + // Signals if this row contains a single open inset + // and nothing more + bool openInsetOnly = (rit->endpos() - rit->pos() == 1) + && par.isInset(rit->pos()) + && par.getInset(rit->pos())->isTextInset(); + if (openInsetOnly) { + InsetCollapsable const * in = + static_cast<InsetCollapsable const *>(par.getInset(rit->pos())); + openInsetOnly = in->isOpen(); + } + + // Clear background of this row + // (if whole screen background was not cleared) + if (!repaintAll && !openInsetOnly) { + // Try to keep row background inside inset + // frame (how?) + int w = pi.base.bv->workWidth() - 30; + int ht = rit->ascent() + rit->descent(); + pi.pain.fillRectangle(x, y - ht, w, ht, + text.backgroundColor()); + } + + // Instrumentation for testing row cache (see also + // 12 lines lower): + //lyxerr << "#"; + rp.paintAppendix(); + rp.paintDepthBar(); + rp.paintChangeBar(); + if (rit == rb) + rp.paintFirst(); + if (rit + 1 == re) + rp.paintLast(); + rp.paintText(); + } } + //lyxerr << "." << endl; } } // namespace anon @@ -752,22 +810,28 @@ void paintText(BufferView const & bv, Vi { Painter & pain = bv.painter(); LyXText * const text = bv.text(); + bool const select = bv.cursor().selection(); - // clear background - pain.fillRectangle(0, vi.y1, bv.workWidth(), vi.y2 - vi.y1, - LColor::background); - - // draw selection PainterInfo pi(const_cast<BufferView *>(&bv), pain); - - text->drawSelection(pi, 0, 0); + // Should the whole screen, including insets, be refreshed? + bv.refresh(select || !vi.singlepar); + if (bv.refresh()) { + // Clear background + // (Delegated to rows if no forced screen refresh) + pain.fillRectangle(0, vi.y1, bv.workWidth(), vi.y2 - vi.y1, + text->backgroundColor()); + } + if (select) { + 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(); + Paragraph const & par = text->getPar(pit); + yy += par.ascent(); paintPar(pi, *bv.text(), pit, 0, yy); - yy += text->getPar(pit).descent(); + yy += par.descent(); } // Cache one paragraph above and one below Index: BufferView.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView.C,v retrieving revision 1.264 diff -u -p -r1.264 BufferView.C --- BufferView.C 1 Dec 2005 10:28:47 -0000 1.264 +++ BufferView.C 21 Dec 2005 20:34:03 -0000 @@ -369,6 +369,18 @@ void BufferView::putSelectionAt(DocItera } +bool const BufferView::refresh() const +{ + return pimpl_->refresh(); +} + + +void const BufferView::refresh(bool r) const +{ + pimpl_->refresh(r); +} + + LCursor & BufferView::cursor() { return pimpl_->cursor_; Index: BufferView.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView.h,v retrieving revision 1.189 diff -u -p -r1.189 BufferView.h --- BufferView.h 1 Dec 2005 10:28:47 -0000 1.189 +++ BufferView.h 21 Dec 2005 20:34:04 -0000 @@ -198,7 +198,10 @@ public: */ void putSelectionAt(DocIterator const & cur, int length, bool backwards); - + /// + bool const refresh() const; + /// + void const refresh(bool r) const; private: /// Index: BufferView_pimpl.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView_pimpl.h,v retrieving revision 1.129 diff -u -p -r1.129 BufferView_pimpl.h --- BufferView_pimpl.h 7 Nov 2005 15:06:42 -0000 1.129 +++ BufferView_pimpl.h 21 Dec 2005 20:34:04 -0000 @@ -103,6 +103,10 @@ public: FuncStatus getStatus(FuncRequest const & cmd); /// a function should be executed bool dispatch(FuncRequest const & ev); + /// + bool refresh() { return refresh_; } + /// + void refresh(bool r) {refresh_ = r; } private: /// An error list (replaces the error insets) ErrorList errorlist_; @@ -189,7 +193,8 @@ private: int offset_ref_; /// ViewMetricsInfo metrics(bool singlepar = false); - + /// Working variable indicating a full screen refresh + mutable bool refresh_; }; #endif // BUFFERVIEW_PIMPL_H Index: insets/insetcollapsable.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/insetcollapsable.C,v retrieving revision 1.281 diff -u -p -r1.281 insetcollapsable.C --- insets/insetcollapsable.C 16 Dec 2005 12:48:18 -0000 1.281 +++ insets/insetcollapsable.C 21 Dec 2005 20:34:05 -0000 @@ -140,15 +140,20 @@ void InsetCollapsable::metrics(MetricsIn InsetText::metrics(mi, textdim_); bool oldopeninlined = openinlined_; openinlined_ = (textdim_.wid + dim.wid <= mi.base.textwidth); - if (openinlined_ != oldopeninlined) + if (openinlined_ != oldopeninlined) { InsetText::metrics(mi, textdim_); + mi.base.bv->update(); + } if (openinlined_) { dim.wid += textdim_.wid; dim.des = max(dim.des - textdim_.asc + dim.asc, textdim_.des); dim.asc = textdim_.asc; } else { dim.des += textdim_.height() + TEXT_TO_BOTTOM_OFFSET; - dim.wid = max(dim.wid, textdim_.wid); + // Fixed width needed across refreshes, cf. + // rowpainter's selective row refresh + // mechanism + dim.wid = mi.base.textwidth; } } } Index: insets/insettext.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/insettext.C,v retrieving revision 1.622 diff -u -p -r1.622 insettext.C --- insets/insettext.C 21 Oct 2005 09:55:23 -0000 1.622 +++ insets/insettext.C 21 Dec 2005 20:34:05 -0000 @@ -192,6 +192,7 @@ void InsetText::draw(PainterInfo & pi, i // update our idea of where we are setPosCache(pi, x, y); + text_.background_color_ = backgroundColor(); text_.draw(pi, x + border_, y); if (drawFrame_) {
pgpnD7CRJ8F9U.pgp
Description: PGP signature