X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FTextMetrics.cpp;h=874cb17607f716e9551e53720237300f57c1f699;hb=449c766e03d94ddf6c823cfcae845f76f83c0e1c;hp=12a42e2d99d8e0517d82119112c921844dc4ef15;hpb=b0543270a9055dcd43df3d72e2a5584895c77ac4;p=lyx.git diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 12a42e2d99..874cb17607 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -32,7 +32,7 @@ #include "LyXRC.h" #include "MetricsInfo.h" #include "ParagraphParameters.h" -#include "rowpainter.h" +#include "RowPainter.h" #include "Text.h" #include "TextClass.h" #include "VSpace.h" @@ -290,7 +290,7 @@ Font TextMetrics::displayFont(pit_type pit, pos_type pos) const bool TextMetrics::isRTL(CursorSlice const & sl, bool boundary) const { - if (!lyxrc.rtl_support || !sl.text()) + if (!sl.text()) return false; int correction = 0; @@ -304,7 +304,7 @@ bool TextMetrics::isRTL(CursorSlice const & sl, bool boundary) const bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos) const { // no RTL boundary at paragraph start - if (!lyxrc.rtl_support || pos == 0) + if (pos == 0) return false; Font const & left_font = displayFont(pit, pos - 1); @@ -319,9 +319,8 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos) const bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos, Font const & font) const { - if (!lyxrc.rtl_support - // no RTL boundary at paragraph start - || pos == 0 + if (// no RTL boundary at paragraph start + pos == 0 // if the metrics have not been calculated, then we are not // on screen and can safely ignore issues about boundaries. || !contains(pit)) @@ -346,6 +345,7 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos, // FED FED| FED ) if (startpos == pos && endpos == pos && endpos != par.size() && (par.isNewline(pos - 1) + || par.isEnvSeparator(pos - 1) || par.isLineSeparator(pos - 1) || par.isSeparator(pos - 1))) return false; @@ -506,11 +506,11 @@ bool TextMetrics::redoParagraph(pit_type const pit) } -int TextMetrics::getAlign(Paragraph const & par, pos_type const pos) const +LyXAlignment TextMetrics::getAlign(Paragraph const & par, pos_type const pos) const { Layout const & layout = par.layout(); - int align; + LyXAlignment align; if (par.params().align() == LYX_ALIGN_LAYOUT) align = layout.align; else @@ -565,15 +565,15 @@ void TextMetrics::computeRowMetrics(pit_type const pit, Paragraph const & par = text_->getPar(pit); - double w = width - row.right_margin - row.width(); + double const w = width - row.right_margin - row.width(); // FIXME: put back this assertion when the crash on new doc is solved. //LASSERT(w >= 0, /**/); bool const is_rtl = text_->isRTL(par); if (is_rtl) - row.x = rightMargin(pit); + row.left_margin = rightMargin(pit); else - row.x = leftMargin(max_width_, pit, row.pos()); + row.left_margin = leftMargin(max_width_, pit, row.pos()); // is there a manual margin with a manual label Layout const & layout = par.layout(); @@ -607,62 +607,51 @@ void TextMetrics::computeRowMetrics(pit_type const pit, } else if (int(row.width()) < max_width_) { // is it block, flushleft or flushright? // set x how you need it - int const align = getAlign(par, row.pos()); - - switch (align) { + switch (getAlign(par, row.pos())) { case LYX_ALIGN_BLOCK: { int const ns = numberOfSeparators(row); /** If we have separators, and this row has * not be broken abruptly by a display inset * or newline, then stretch it */ - if (ns && !row.right_boundary() + if (ns && !row.right_boundary() && row.endpos() != par.size()) { setSeparatorWidth(row, w / ns); row.dimension().wid = width; } else if (is_rtl) { row.dimension().wid = width; - row.x += w; + row.left_margin += w; } break; } case LYX_ALIGN_RIGHT: - row.x += w; + row.left_margin += w; break; case LYX_ALIGN_CENTER: - row.dimension().wid = width - w / 2; - row.x += w / 2; + row.dimension().wid = width - int(w / 2); + row.left_margin += w / 2; + break; + case LYX_ALIGN_LEFT: + case LYX_ALIGN_NONE: + case LYX_ALIGN_LAYOUT: + case LYX_ALIGN_SPECIAL: + case LYX_ALIGN_DECIMAL: break; } } -#if 0 - if (is_rtl) { - pos_type body_pos = par.beginOfBody(); - pos_type end = row.endpos(); - - if (body_pos > 0 - && (body_pos > end || !par.isLineSeparator(body_pos - 1))) { - row.x += theFontMetrics(text_->labelFont(par)). - width(layout.labelsep); - if (body_pos <= end) - row.x += row.label_hfill; - } - } -#endif - + // Finally, handle hfill insets pos_type const endpos = row.endpos(); pos_type body_pos = par.beginOfBody(); if (body_pos > 0 && (body_pos > endpos || !par.isLineSeparator(body_pos - 1))) body_pos = 0; - ParagraphMetrics & pm = par_metrics_[pit]; Row::iterator cit = row.begin(); Row::iterator const cend = row.end(); for ( ; cit != cend; ++cit) { if (row.label_hfill && cit->endpos == body_pos && cit->type == Row::SPACE) - cit->dim.wid -= row.label_hfill * (nlh - 1); + cit->dim.wid -= int(row.label_hfill * (nlh - 1)); if (!cit->inset || !cit->inset->isHfill()) continue; if (pm.hfillExpansion(row, cit->pos)) @@ -680,7 +669,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit, int TextMetrics::labelFill(pit_type const pit, Row const & row) const { Paragraph const & par = text_->getPar(pit); - LBUFERR(par.beginOfBody() > 0); + LBUFERR(par.beginOfBody() > 0 || par.isEnvSeparator(0)); int w = 0; Row::const_iterator cit = row.begin(); @@ -688,7 +677,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const // iterate over elements before main body (except the last one, // which is extra space). while (cit!= end && cit->endpos < par.beginOfBody()) { - w += cit->width(); + w += cit->dim.wid; ++cit; } @@ -798,12 +787,12 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit int const width = max_width_ - right_margin; pos_type const body_pos = par.beginOfBody(); row.clear(); - row.x = leftMargin(max_width_, pit, pos); - row.dimension().wid = row.x; + // This make get changed in computeRowMetrics depending on RTL + row.left_margin = leftMargin(max_width_, pit, pos); + row.dimension().wid = row.left_margin; row.right_margin = right_margin; if (pos >= end || row.width() > width) { - row.dimension().wid += right_margin; row.endpos(end); return; } @@ -846,6 +835,8 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit // before body_pos. Instead, insert some spacing to // align text FontMetrics const & fm = theFontMetrics(text_->labelFont(par)); + // this is needed to make sure that the row width is correct + row.finalizeLast(); int const add = max(fm.width(par.layout().labelsep), labelEnd(pit) - row.width()); row.addSpace(i, add, *fi, par.lookupChange(i)); @@ -876,7 +867,7 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit // - Before a display inset // - After a display inset Inset const * inset = 0; - if (par.isNewline(i) + if (par.isNewline(i) || par.isEnvSeparator(i) || (i + 1 < end && (inset = par.getInset(i + 1)) && inset->display()) || (!row.empty() && row.back().inset @@ -889,6 +880,8 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit ++i; ++fi; } + row.finalizeLast(); + row.endpos(i); // End of paragraph marker if (lyxrc.paragraph_markers @@ -904,10 +897,8 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit row.addVirtual(end, docstring(1, char_type(0x00B6)), f, Change()); } - row.finalizeLast(); - row.endpos(i); // if the row is too large, try to cut at last separator. - row.shorten_if_needed(body_pos, width); + row.shortenIfNeeded(body_pos, width); // if the row ends with a separator that is not at end of // paragraph, remove it @@ -1111,29 +1102,29 @@ pos_type TextMetrics::getPosNearX(Row const & row, int & x, pos_type pos = row.pos(); boundary = false; if (row.empty()) - x = row.x; - else if (x <= row.x) { + x = row.left_margin; + else if (x <= row.left_margin) { pos = row.front().left_pos(); - x = row.x; - } else if (x >= row.width() - row.right_margin) { + x = row.left_margin; + } else if (x >= row.width()) { pos = row.back().right_pos(); - x = row.width() - row.right_margin; + x = row.width(); } else { - double w = row.x; + double w = row.left_margin; Row::const_iterator cit = row.begin(); Row::const_iterator cend = row.end(); for ( ; cit != cend; ++cit) { - if (w <= x && w + cit->width() > x) { - double x_offset = x - w; + if (w <= x && w + cit->full_width() > x) { + int x_offset = int(x - w); pos = cit->x2pos(x_offset); - x = x_offset + w; + x = int(x_offset + w); break; } - w += cit->width(); + w += cit->full_width(); } if (cit == row.end()) { pos = row.back().right_pos(); - x = row.width() - row.right_margin; + x = row.width(); } /** This tests for the case where the cursor is placed * just before a font direction change. See comment on @@ -1147,12 +1138,14 @@ pos_type TextMetrics::getPosNearX(Row const & row, int & x, } /** This tests for the case where the cursor is set at the end - * of a row which has been broken due to a display inset on - * next row. This is indicated by Row::right_boundary. + * of a row which has been broken due something else than a + * separator (a display inset or a forced breaking of the + * row). We know that there is a separator when the end of the + * row is larger than the end of its last element. */ if (!row.empty() && pos == row.back().endpos && row.back().endpos == row.endpos()) - boundary = row.right_boundary(); + boundary = true; x += xo; return pos; @@ -1476,10 +1469,10 @@ int TextMetrics::cursorX(CursorSlice const & sl, if (row.empty() || (pos == row.begin()->left_pos() && pos != row.begin()->right_pos())) - return int(row.x); + return row.left_margin; Row::const_iterator cit = row.begin(); - double x = row.x; + double x = row.left_margin; for ( ; cit != row.end() ; ++cit) { /** Look whether the cursor is inside the element's * span. Note that it is necessary to take the @@ -1492,7 +1485,7 @@ int TextMetrics::cursorX(CursorSlice const & sl, x += cit->pos2x(pos); break; } - x += cit->width(); + x += cit->full_width(); } return int(x); @@ -1547,7 +1540,8 @@ bool TextMetrics::cursorEnd(Cursor & cur) bool boundary = false; if (end != cur.lastpos()) { if (!cur.paragraph().isLineSeparator(end-1) - && !cur.paragraph().isNewline(end-1)) + && !cur.paragraph().isNewline(end-1) + && !cur.paragraph().isEnvSeparator(end-1)) boundary = true; else --end; @@ -1630,7 +1624,9 @@ int TextMetrics::leftMargin(int max_width, l_margin = leftMargin(max_width, newpar); // Remove the parindent that has been added // if the paragraph was empty. - if (pars[newpar].empty()) { + if (pars[newpar].empty() && + buffer.params().paragraph_separation == + BufferParams::ParagraphIndentSeparation) { docstring pi = pars[newpar].layout().parindent; l_margin -= theFontMetrics( buffer.params().getFont()).signedWidth(pi); @@ -1648,10 +1644,16 @@ int TextMetrics::leftMargin(int max_width, // This happens after sections or environments in standard classes. // We have to check the previous layout at same depth. - if (tclass.isDefaultLayout(par.layout()) && pit > 0 - && pars[pit - 1].getDepth() >= par.getDepth()) { + if (buffer.params().paragraph_separation == + BufferParams::ParagraphSkipSeparation) + parindent.erase(); + else if (pit > 0 && pars[pit - 1].getDepth() >= par.getDepth()) { pit_type prev = text_->depthHook(pit, par.getDepth()); - if (pars[prev < pit ? prev : pit - 1].layout().nextnoindent) + if (par.layout() == pars[prev].layout()) { + if (prev != pit - 1 + && pars[pit - 1].layout().nextnoindent) + parindent.erase(); + } else if (pars[prev].layout().nextnoindent) parindent.erase(); }