X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FRow.cpp;h=7e70ca274bc640d61e5c7eabe16819cb1567702f;hb=89120ce72238077d08c52e4558d83f9d81e7d573;hp=6edde19e7548f11fa3b27122bd492a1e9e44f427;hpb=201c95a76ea69fb5c6652b657b175db12bcd5e80;p=lyx.git diff --git a/src/Row.cpp b/src/Row.cpp index 6edde19e75..7e70ca274b 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -45,7 +45,7 @@ static double const MAX_SPACE_STRETCH = 1.5; //em int Row::Element::countExpanders() const { - if (type != STRING) + if (type != STRING || font.fontInfo().family() == TYPEWRITER_FAMILY) return 0; return support::countExpanders(str); } @@ -53,7 +53,7 @@ int Row::Element::countExpanders() const int Row::Element::expansionAmount() const { - if (type != STRING) + if (type != STRING || font.fontInfo().family() == TYPEWRITER_FAMILY) return 0; return countExpanders() * theFontMetrics(font).em(); } @@ -61,7 +61,7 @@ int Row::Element::expansionAmount() const void Row::Element::setExtra(double extra_per_em) { - if (type != STRING) + if (type != STRING || font.fontInfo().family() == TYPEWRITER_FAMILY) return; extra = extra_per_em * theFontMetrics(font).em(); } @@ -144,8 +144,12 @@ bool Row::Element::splitAt(int const width, int next_width, bool force, FontMetrics::Breaks breaks = fm.breakString(str, width, next_width, isRTL(), wrap_any | force); - // if breaking did not really work, give up - if (!force && breaks.front().nspc_wid > width) { + /** if breaking did not really work, give up + * case 1: we do not force break and the first element is longer than the limit; + * case 2: the first break occurs at the front of the string + */ + if ((!force && breaks.front().nspc_wid > width) + || (breaks.size() > 1 && breaks.front().len == 0)) { if (dim.wid == 0) dim.wid = fm.width(str); return false; @@ -156,12 +160,6 @@ bool Row::Element::splitAt(int const width, int next_width, bool force, bool first = true; docstring::size_type i = 0; for (FontMetrics::Break const & brk : breaks) { - /* For some reason breakString can decide to break before the - * first character (normally we use a 0-width nbsp to prevent - * that). Skip leading empty elements, they are never wanted. - */ - if (first && brk.len == 0 && breaks.size() > 1) - continue; Element e(STRING, pos + i, font, change); e.str = str.substr(i, brk.len); e.endpos = e.pos + brk.len; @@ -191,8 +189,20 @@ bool Row::Element::splitAt(int const width, int next_width, bool force, // first_e row should be broken after the original element first_e.row_flags |= BreakAfter; } else { - // Restore the after flags of the original element. +#if 1 + // remove the BreakAfter that got added above. first_e.row_flags &= ~BreakAfter; +#else + // FIXME : the code below looks like a good idea, but I do not + // have a use case yet. The question is what happens + // when breaking at the end of a string with a + // trailing space. + // if it turns out that no breaking was necessary, remove the + // BreakAfter that got added above. + if (first_e.dim.wid <= width) + first_e.row_flags &= ~BreakAfter; +#endif + // Restore the after flags of the original element. first_e.row_flags |= row_flags & AfterFlags; } @@ -328,7 +338,7 @@ ostream & operator<<(ostream & os, Row::Elements const & elts) ostream & operator<<(ostream & os, Row const & row) { - os << " pos: " << row.pos_ << " end: " << row.end_ + os << " pit: " << row.pit_ << " pos: " << row.pos_ << " end: " << row.end_ << " left_margin: " << row.left_margin << " width: " << row.dim_.wid << " right_margin: " << row.right_margin @@ -337,7 +347,8 @@ ostream & operator<<(ostream & os, Row const & row) << " separator: " << row.separator << " label_hfill: " << row.label_hfill << " end_boundary: " << row.end_boundary() - << " flushed: " << row.flushed() << "\n"; + << " flushed: " << row.flushed_ + << " rtl=" << row.rtl_ << "\n"; // We cannot use the operator above, unfortunately double x = row.left_margin; for (Row::Element const & e : row.elements_) { @@ -498,14 +509,15 @@ void Row::addMarginSpace(pos_type const pos, int const width, void Row::push_back(Row::Element const & e) { - dim_.wid += e.dim.wid; + dim_.wid += e.dim.wid + ((e.type == INSET) ? e.extra : 0); elements_.push_back(e); } void Row::pop_back() { - dim_.wid -= elements_.back().dim.wid; + Element const & e = elements_.back(); + dim_.wid -= e.dim.wid + ((e.type == INSET) ? e.extra : 0); elements_.pop_back(); } @@ -590,12 +602,31 @@ Row::Elements Row::shortenIfNeeded(int const w, int const next_width) */ if (brk.splitAt(min(w - wid_brk, brk.dim.wid - 2), next_width, false, tail)) { /* if this element originally did not cause a row overflow - * in itself, and the remainder of the row would still be - * too large after breaking, then we will have issues in - * next row. Thus breaking does not help. + * in itself, and the next item is not breakable and would + * still be too large after breaking, then we will have + * issues in next row. Thus breaking does not help. + * + * FIXME: this is not perfect, since it is difficult to + * know whether next element in tail is too large: + * + * - next element could be a very long word, which is + * theoretically breakable, but not in practice + * (difficult to solve). + * + * - next element could be short enough, but linked to + * another one with a NoBreak bond. + * + * Basically, it is difficult to solve that in a purely + * left-to-right algorithm; implementing the TeX badness + * algorithm is more difficult and more costly, so we do + * our best in our restricted setting. */ + auto const cit_next = cit_brk + 1; + int const tail_wid = !tail.empty() ? tail.front().dim.wid : 0; if (wid_brk + cit_brk->dim.wid < w - && dim_.wid - (wid_brk + brk.dim.wid) >= next_width) { + && cit_next != elements_.end() + && tail_wid + cit_next->dim.wid > next_width + && !(cit_next->row_flags & CanBreakInside)) { tail.clear(); break; } @@ -698,10 +729,9 @@ Row::findElement(pos_type const pos, bool const boundary, double & x) const * to accept virtual elements, in which case the position * will be before the virtual element. */ - if (cit->isVirtual() && pos + boundary_corr == cit->pos) - break; - else if (pos + boundary_corr >= cit->pos - && pos + boundary_corr < cit->endpos) { + if ((pos + boundary_corr >= cit->pos && pos + boundary_corr < cit->endpos) + || (cit->isVirtual() && pos + boundary_corr == cit->pos)) { + // FIXME: shall we use `pos + boundary_corr' here? x += cit->pos2x(pos); break; }