commit fe8c3b4348b47099171957ea76daf9ccc019a5d1 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Jun 14 00:01:49 2013 +0200
Cleanup TextMetrics::rowBreakPoint. Collect properly all strings to compute string metrics Some changes with respect to existing code - end of paragraph font is now the one of the text - words longer than a line are not broken anymore. I think this is not useful if we have horizontal scrollbar Other than that, the code is still compatible with rowWidth and friends. diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 66771d4..3026367 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -27,6 +27,7 @@ #include "CoordCache.h" #include "Cursor.h" #include "CutAndPaste.h" +#include "Encoding.h" #include "HSpace.h" #include "InsetList.h" #include "Layout.h" @@ -800,26 +801,25 @@ private: } // anon namespace -pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit, - pos_type pos) const +pos_type TextMetrics::rowBreakPoint(int const width, pit_type const pit, + pos_type const pos) const { - ParagraphMetrics const & pm = par_metrics_[pit]; Paragraph const & par = text_->getPar(pit); pos_type const end = par.size(); if (pos == end || width < 0) return end; - Layout const & layout = par.layout(); + ParagraphMetrics const & pm = par_metrics_[pit]; + ParagraphList const & pars = text_->paragraphs(); #if 0 //FIXME: As long as leftMargin() is not correctly implemented for // MARGIN_RIGHT_ADDRESS_BOX, we should also not do this here. // Otherwise, long rows will be painted off the screen. - if (layout.margintype == MARGIN_RIGHT_ADDRESS_BOX) + if (par.layout().margintype == MARGIN_RIGHT_ADDRESS_BOX) return addressBreakPoint(pos, par); #endif - pos_type const body_pos = par.beginOfBody(); // check for possible inline completion DocIterator const & inlineCompletionPos = bv_->inlineCompletionPos(); @@ -831,70 +831,69 @@ pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit, inlineCompletionLPos = inlineCompletionPos.pos() - 1; } - // Now we iterate through until we reach the right margin - // or the end of the par, then choose the possible break - // nearest that. - - int label_end = labelEnd(pit); int const left = leftMargin(max_width_, pit, pos); + pos_type const body_pos = par.beginOfBody(); int x = left; - - // pixel width since last breakpoint - int chunkwidth = 0; - - docstring const s(1, char_type(0x00B6)); - Font f; - int par_marker_width = theFontMetrics(f).width(s); + pos_type point = end; FontIterator fi = FontIterator(*this, par, pit, pos); - pos_type point = end; - pos_type i = pos; + // Accumulator for character strings + docstring chunkstr; + Font chunkfont = *fi; - ParagraphList const & pars_ = text_->paragraphs(); - bool const draw_par_end_marker = lyxrc.paragraph_markers - && size_type(pit + 1) < pars_.size(); + // Now we iterate through until we reach the right margin + // or the end of the par, then choose the possible break + // nearest that. + pos_type i = pos; for ( ; i < end; ++i, ++fi) { - int thiswidth = pm.singleWidth(i, *fi); + // Add the chunk width when it is finished + if (par.isInset(i) || *fi != chunkfont + || (body_pos && i == body_pos)) { + x += theFontMetrics(chunkfont).width(chunkstr); + chunkstr.clear(); + chunkfont = *fi; + } + + char_type c = par.getChar(i); + Language const * language = fi->language(); + // The most special cases are handled first. + if (par.isInset(i)) { + x += pm.insetDimension(par.getInset(i)).wid; + } else if (c == '\t') + chunkstr += " "; + else if (language->rightToLeft()) { + if (language->lang() == "arabic_arabtex" || + language->lang() == "arabic_arabi" || + language->lang() == "farsi") { + if (!Encodings::isArabicComposeChar(c)) + chunkstr += par.transformChar(c, i); + } else if (language->lang() == "hebrew" && + !Encodings::isHebrewComposeChar(c)) { + chunkstr+= c; + } + } else + chunkstr += c; - if (draw_par_end_marker && i == end - 1) + if (lyxrc.paragraph_markers + && i == end - 1 && size_type(pit + 1) < pars.size()) // enlarge the last character to hold the end-of-par marker - thiswidth += par_marker_width; + chunkstr += char_type(0x00B6); // add inline completion width - if (inlineCompletionLPos == i) { - docstring const & completion = bv_->inlineCompletion(); - if (completion.length() > 0) - thiswidth += theFontMetrics(*fi).width(completion); - } + if (inlineCompletionLPos == i) + chunkstr += bv_->inlineCompletion(); // add the auto-hfill from label end to the body if (body_pos && i == body_pos) { FontMetrics const & fm = theFontMetrics( text_->labelFont(par)); - int add = fm.width(layout.labelsep); - if (par.isLineSeparator(i - 1)) - add -= singleWidth(pit, i - 1); + int add = fm.width(par.layout().labelsep); + //if (par.isLineSeparator(i - 1)) + // add -= singleWidth(pit, i - 1); - add = max(add, label_end - x); - thiswidth += add; - } - - x += thiswidth; - chunkwidth += thiswidth; - - // break before a character that will fall off - // the right of the row - if (x >= width) { - // if no break before, break here - if (point == end || chunkwidth >= width - left) { - if (i > pos) - point = i; - else - point = i + 1; - } - // exit on last registered breakpoint: - break; + add = max(add, labelEnd(pit) - x); + x += add; } if (par.isNewline(i)) { @@ -915,20 +914,25 @@ pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit, } } - inset = par.getInset(i); - if (!inset || inset->isChar()) { - // some insets are line separators too - if (par.isLineSeparator(i)) { - // register breakpoint: - point = i + 1; - chunkwidth = 0; + if (par.isLineSeparator(i)) { + x += theFontMetrics(chunkfont).width(chunkstr); + chunkstr.clear(); + chunkfont = *fi; + if (x >= width) { + // exit on last registered breakpoint: + break; } + // register breakpoint: + point = i + 1; } } - // maybe found one, but the par is short enough. - if (i == end && x < width) - point = end; + if (i == end) { + x += theFontMetrics(chunkfont).width(chunkstr); + // maybe found one, but the par is short enough. + if (x < width) + point = end; + } // manual labels cannot be broken in LaTeX. But we // want to make our on-screen rendering of footnotes