X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FRow.cpp;h=9df572441cae0e735f0f6f9678c9f5c4c2d2467c;hb=2de30c62f8d671a8c8d4d52a6a7310e2c5ca84de;hp=2bfe55a1b80d46d00b1aad0fbd6253d9910a4e74;hpb=7137826896beed3590f8dce6e6b7ce3c422ceea2;p=lyx.git diff --git a/src/Row.cpp b/src/Row.cpp index 2bfe55a1b8..9df572441c 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -37,23 +37,39 @@ using support::rtrim; using frontend::FontMetrics; +// Maximum length that a space can be stretched when justifying text +static double const MAX_SPACE_STRETCH = 1.5; //em + + int Row::Element::countSeparators() const { if (type != STRING) return 0; - // Consecutive spaces count as only one separator. - bool wasspace = false; - int nsep = 0; - for (size_t i = 0 ; i < str.size() ; ++i) { - if (str[i] == ' ') { - if (!wasspace) { - ++nsep; - wasspace = true; - } - } else - wasspace = false; - } - return nsep; + return count(str.begin(), str.end(), ' '); +} + + +int Row::Element::countExpanders() const +{ + if (type != STRING) + return 0; + return theFontMetrics(font).countExpanders(str); +} + + +int Row::Element::expansionAmount() const +{ + if (type != STRING) + return 0; + return countExpanders() * theFontMetrics(font).em(); +} + + +void Row::Element::setExtra(double extra_per_em) +{ + if (type != STRING) + return; + extra = extra_per_em * theFontMetrics(font).em(); } @@ -66,8 +82,7 @@ double Row::Element::pos2x(pos_type const i) const double w = 0; //handle first the two bounds of the element - if (i == endpos && type != VIRTUAL - && !(inset && inset->lyxCode() == SEPARATOR_CODE)) + if (i == endpos && type != VIRTUAL) w = isRTL() ? 0 : full_width(); else if (i == pos || type != STRING) w = isRTL() ? full_width() : 0; @@ -129,17 +144,6 @@ bool Row::Element::breakAt(int w, bool force) return true; } - // Qt will not break at a leading space, and we need that sometimes, see - // http://www.lyx.org/trac/ticket/9921. - // It would be nice to fix this properly, but for now do it by hand. - // FIXME: figure out what to do for RtL text. - if (!isRTL() && !str.empty() && str[0] == ' ') { - dim.wid = 0; - str = ' '; - endpos = pos + 1; - return true; - } - return false; } @@ -160,7 +164,8 @@ Row::Row() : separator(0), label_hfill(0), left_margin(0), right_margin(0), sel_beg(-1), sel_end(-1), begin_margin_sel(false), end_margin_sel(false), - changed_(false), crc_(0), pos_(0), end_(0), right_boundary_(false) + changed_(false), crc_(0), + pit_(0), pos_(0), end_(0), right_boundary_(false) {} @@ -245,7 +250,7 @@ ostream & operator<<(ostream & os, Row::Element const & e) switch (e.type) { case Row::STRING: os << "STRING: `" << to_utf8(e.str) << "' (" - << e.countSeparators() << " sep.), "; + << e.countExpanders() << " expanders.), "; break; case Row::VIRTUAL: os << "VIRTUAL: `" << to_utf8(e.str) << "', "; @@ -322,13 +327,30 @@ int Row::countSeparators() const } -void Row::setSeparatorExtraWidth(double w) +bool Row::setExtraWidth(int w) { - separator = w; - iterator const end = elements_.end(); - for (iterator it = elements_.begin() ; it != end ; ++it) - if (it->type == Row::STRING) - it->extra = w; + if (w < 0) + // this is not expected to happen (but it does) + return false; + // amount of expansion: number of expanders time the em value for each + // string element + int exp_amount = 0; + for (Row::Element const & e : elements_) + exp_amount += e.expansionAmount(); + if (!exp_amount) + return false; + // extra length per expander per em + double extra_per_em = double(w) / exp_amount; + if (extra_per_em > MAX_SPACE_STRETCH) + // do not stretch more than MAX_SPACE_STRETCH em per expander + return false; + // add extra length to each element proportionally to its em. + for (Row::Element & e : elements_) + if (e.type == Row::STRING) + e.setExtra(extra_per_em); + // update row dimension + dim_.wid += w; + return true; } @@ -424,10 +446,10 @@ void Row::pop_back() } -void Row::shortenIfNeeded(pos_type const keep, int const w) +bool Row::shortenIfNeeded(pos_type const keep, int const w) { if (empty() || width() <= w) - return; + return false; Elements::iterator const beg = elements_.begin(); Elements::iterator const end = elements_.end(); @@ -444,7 +466,7 @@ void Row::shortenIfNeeded(pos_type const keep, int const w) if (cit == end) { // This should not happen since the row is too long. LYXERR0("Something is wrong cannot shorten row: " << *this); - return; + return false; } // Iterate backwards over breakable elements and try to break them @@ -487,7 +509,7 @@ void Row::shortenIfNeeded(pos_type const keep, int const w) dim_.wid = wid_brk + brk.dim.wid; // If there are other elements, they should be removed. elements_.erase(cit_brk + 1, end); - return; + return true; } } @@ -504,7 +526,7 @@ void Row::shortenIfNeeded(pos_type const keep, int const w) end_ = cit->pos; dim_.wid = wid; elements_.erase(cit, end); - return; + return true; } /* If we are here, it means that we have not found a separator to @@ -519,7 +541,9 @@ void Row::shortenIfNeeded(pos_type const keep, int const w) dim_.wid = wid + cit->dim.wid; // If there are other elements, they should be removed. elements_.erase(next(cit, 1), end); + return true; } + return false; }