On Sun, Oct 02, 2005 at 01:26:06PM +0200, Andre' Poenitz wrote: > So we should try hard to pass through the critical path just once. I'll > send later today a preliminary patch that folds rowBreakPoint() and > setRowWidth(), i.e. reduces this by a factor of two and gives an overall > gain of 8-12% when typing into a single long paragraph of about 1200 > chars. I won't be able to take care of this patch after I send it to the > list, so I wouldn't mind if somebody took over.
Promised patch attached. Andre'
--- text.C.orig 2005-09-27 23:30:41.000000000 +0200 +++ text.C 2005-09-27 23:39:38.000000000 +0200 @@ -654,28 +654,32 @@ }; -void LyXText::rowBreakPoint(pit_type const pit, Row & row) const +int LyXText::rowBreakPoint(pit_type const pit, Row & row) const { Paragraph const & par = pars_[pit]; pos_type const end = par.size(); pos_type const pos = row.pos(); if (pos == end) { row.endpos(end); - return; + return 0; } // maximum pixel width of a row int width = maxwidth_ - rightMargin(par); // - leftMargin(pit, row); if (width < 0) { row.endpos(end); - return; + return 0; } LyXLayout_ptr const & layout = par.layout(); if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) { row.endpos(addressBreakPoint(pos, par)); - return; + // FIXME: Correct? + int v = 0; + for (int i = pos; i < row.endpos(); ++i) + v += singleWidth(par, i); + return v; } pos_type const body_pos = par.beginOfBody(); @@ -687,6 +691,8 @@ int const left = leftMargin(pit, pos); int x = left; + int w = left; + int v = w; // pixel width since last breakpoint int chunkwidth = 0; @@ -703,12 +709,14 @@ int add = font_metrics::width(layout->labelsep, getLabelFont(par)); if (par.isLineSeparator(i - 1)) add -= singleWidth(par, i - 1); - + w += add; + w = max(w, labelEnd(pit)); add = std::max(add, labelEnd(pit) - x); thiswidth += add; } x += thiswidth; + w += thiswidth; chunkwidth += thiswidth; // break before a character that will fall off @@ -716,11 +724,14 @@ if (x >= width) { // if no break before, break here if (point == end || chunkwidth >= width - left) { - if (i > pos) + if (i > pos) { point = i; - else + v = w - thiswidth; + } + else { point = i + 1; - + v = w; + } } // exit on last registered breakpoint: break; @@ -728,17 +739,20 @@ if (par.isNewline(i)) { point = i + 1; + v = w; break; } // Break before... if (i + 1 < end) { if (par.isInset(i + 1) && par.getInset(i + 1)->display()) { point = i + 1; + v = w; break; } // ...and after. if (par.isInset(i) && par.getInset(i)->display()) { point = i + 1; + v = w; break; } } @@ -748,58 +762,43 @@ if (par.isLineSeparator(i)) { // register breakpoint: point = i + 1; + v = w; + lyxerr << "case 6" << endl; chunkwidth = 0; } } } // maybe found one, but the par is short enough. - if (i == end && x < width) + if (i == end && x < width) { point = end; + v = x; + } // manual labels cannot be broken in LaTeX. But we // want to make our on-screen rendering of footnotes // etc. still break - if (body_pos && point < body_pos) + if (body_pos && point < body_pos) { + lyxerr << "case 8" << endl; point = body_pos; - - row.endpos(point); -} - - -void LyXText::setRowWidth(pit_type const pit, Row & row) const -{ - // get the pure distance - pos_type const end = row.endpos(); - - Paragraph const & par = pars_[pit]; - string const & labelsep = par.layout()->labelsep; - int w = leftMargin(pit, row.pos()); - - pos_type const body_pos = par.beginOfBody(); - pos_type i = row.pos(); - - if (i < end) { - FontIterator fi = FontIterator(*this, par, i); - for ( ; i < end; ++i, ++fi) { - if (body_pos > 0 && i == body_pos) { - w += font_metrics::width(labelsep, getLabelFont(par)); - if (par.isLineSeparator(i - 1)) - w -= singleWidth(par, i - 1); - w = max(w, labelEnd(pit)); - } - char const c = par.getChar(i); - w += singleWidth(par, i, c, *fi); - } } +#if 0 if (body_pos > 0 && body_pos >= end) { - w += font_metrics::width(labelsep, getLabelFont(par)); + w += font_metrics::width(layout->labelsep, getLabelFont(par)); if (end > 0 && par.isLineSeparator(end - 1)) w -= singleWidth(par, end - 1); w = max(w, labelEnd(pit)); } +#endif + row.endpos(point); + return v; +} + +void LyXText::setRowWidth(pit_type const pit, Row & row, int w) const +{ + Paragraph const & par = pars_[pit]; row.width(w + rightMargin(par)); } @@ -1705,8 +1704,8 @@ pos_type z = 0; do { Row row(z); - rowBreakPoint(pit, row); - setRowWidth(pit, row); + int const w = rowBreakPoint(pit, row); + setRowWidth(pit, row, w); setHeightOfRow(pit, row); par.rows().push_back(row); dim.wid = std::max(dim.wid, row.width()); --- lyxtext.h.orig 2005-09-27 23:30:56.000000000 +0200 +++ lyxtext.h 2005-09-27 23:39:59.000000000 +0200 @@ -384,9 +384,9 @@ /// sets row.end to the pos value *after* which a row should break. /// for example, the pos after which isNewLine(pos) == true - void rowBreakPoint(pit_type pit, Row & row) const; + int rowBreakPoint(pit_type pit, Row & row) const; /// sets row.width to the minimum space a row needs on the screen in pixel - void setRowWidth(pit_type pit, Row & row) const; + void setRowWidth(pit_type pit, Row & row, int w) const; /// the minimum space a manual label needs on the screen in pixels int labelFill(Paragraph const & par, Row const & row) const; /// FIXME