mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-11 05:33:33 +00:00
Another go at improving row shortening
Instead of remembering the last breakable element in the row, search backward in the row and consider all string elements one by one until a correct place to break is found. This fixes the case where the row ends with a string, but there is no space soon enough in the string to break it here. In this case, we need to consider the previous row.
This commit is contained in:
parent
2b8ebe9f0d
commit
d893400f93
73
src/Row.cpp
73
src/Row.cpp
@ -224,7 +224,8 @@ ostream & operator<<(ostream & os, Row::Element const & e)
|
|||||||
|
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case Row::STRING:
|
case Row::STRING:
|
||||||
os << "STRING: `" << to_utf8(e.str) << "', ";
|
os << "STRING: `" << to_utf8(e.str) << "' ("
|
||||||
|
<< e.countSeparators() << " sep.), ";
|
||||||
break;
|
break;
|
||||||
case Row::VIRTUAL:
|
case Row::VIRTUAL:
|
||||||
os << "VIRTUAL: `" << to_utf8(e.str) << "', ";
|
os << "VIRTUAL: `" << to_utf8(e.str) << "', ";
|
||||||
@ -378,54 +379,58 @@ void Row::shortenIfNeeded(pos_type const keep, int const w)
|
|||||||
{
|
{
|
||||||
if (empty() || width() <= w)
|
if (empty() || width() <= w)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Elements::iterator const beg = elements_.begin();
|
Elements::iterator const beg = elements_.begin();
|
||||||
Elements::iterator const end = elements_.end();
|
Elements::iterator const end = elements_.end();
|
||||||
int wid = left_margin;
|
int wid = left_margin;
|
||||||
|
|
||||||
// The last breakable element that has been found and its x position.
|
// Search for the first element that goes beyond right margin
|
||||||
Elements::iterator last_brk = elements_.end();
|
|
||||||
int last_wid = 0;
|
|
||||||
|
|
||||||
Elements::iterator cit = beg;
|
Elements::iterator cit = beg;
|
||||||
for ( ; cit != end ; ++cit) {
|
for ( ; cit != end ; ++cit) {
|
||||||
if (cit->countSeparators() && cit->pos >= keep) {
|
|
||||||
last_brk = cit;
|
|
||||||
last_wid = wid;
|
|
||||||
}
|
|
||||||
if (wid + cit->dim.wid > w)
|
if (wid + cit->dim.wid > w)
|
||||||
break;
|
break;
|
||||||
wid += cit->dim.wid;
|
wid += cit->dim.wid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have found a suitable separable element. This is the common case.
|
|
||||||
* Try to break it cleanly (at word boundary) at a length that is both
|
|
||||||
* - less than the available space on the row
|
|
||||||
* - shorter than the natural width of the element, in order to enforce
|
|
||||||
* break-up.
|
|
||||||
*/
|
|
||||||
if (last_brk != end
|
|
||||||
&& last_brk->breakAt(min(w - last_wid, last_brk->dim.wid - 2), false)) {
|
|
||||||
end_ = last_brk->endpos;
|
|
||||||
/* after breakAt, there may be spaces at the end of the
|
|
||||||
* string, but they are not counted in the string length
|
|
||||||
* (QTextLayout feature, actually). We remove them, but do not
|
|
||||||
* change the endo of the row, since the spaces at row break
|
|
||||||
* are invisible.
|
|
||||||
*/
|
|
||||||
last_brk->str = rtrim(last_brk->str);
|
|
||||||
last_brk->endpos = last_brk->pos + last_brk->str.length();
|
|
||||||
dim_.wid = last_wid + last_brk->dim.wid;
|
|
||||||
// If there are other elements, they should be removed.
|
|
||||||
elements_.erase(next(last_brk, 1), end);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cit == end) {
|
if (cit == end) {
|
||||||
// This should not happen since the row is too long.
|
// This should not happen since the row is too long.
|
||||||
LYXERR0("Something is wrong cannot shorten row: " << *this);
|
LYXERR0("Something is wrong cannot shorten row: " << *this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iterate backwards over breakable elements and try to break them
|
||||||
|
Elements::iterator cit_brk = cit;
|
||||||
|
int wid_brk = wid + cit_brk->dim.wid;
|
||||||
|
++cit_brk;
|
||||||
|
while (cit_brk != beg) {
|
||||||
|
--cit_brk;
|
||||||
|
Element & brk = *cit_brk;
|
||||||
|
wid_brk -= brk.dim.wid;
|
||||||
|
if (brk.countSeparators() == 0 || brk.pos < keep)
|
||||||
|
continue;
|
||||||
|
/* We have found a suitable separable element. This is the common case.
|
||||||
|
* Try to break it cleanly (at word boundary) at a length that is both
|
||||||
|
* - less than the available space on the row
|
||||||
|
* - shorter than the natural width of the element, in order to enforce
|
||||||
|
* break-up.
|
||||||
|
*/
|
||||||
|
if (brk.breakAt(min(w - wid_brk, brk.dim.wid - 2), false)) {
|
||||||
|
end_ = brk.endpos;
|
||||||
|
/* after breakAt, there may be spaces at the end of the
|
||||||
|
* string, but they are not counted in the string length
|
||||||
|
* (QTextLayout feature, actually). We remove them, but do
|
||||||
|
* not change the endo of the row, since the spaces at row
|
||||||
|
* break are invisible.
|
||||||
|
*/
|
||||||
|
brk.str = rtrim(brk.str);
|
||||||
|
brk.endpos = brk.pos + brk.str.length();
|
||||||
|
dim_.wid = wid_brk + brk.dim.wid;
|
||||||
|
// If there are other elements, they should be removed.
|
||||||
|
elements_.erase(cit_brk + 1, end);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cit != beg && cit->type == VIRTUAL) {
|
if (cit != beg && cit->type == VIRTUAL) {
|
||||||
// It is not possible to separate a virtual element from the
|
// It is not possible to separate a virtual element from the
|
||||||
// previous one.
|
// previous one.
|
||||||
@ -434,8 +439,8 @@ void Row::shortenIfNeeded(pos_type const keep, int const w)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cit != beg) {
|
if (cit != beg) {
|
||||||
// There is no separator, but several elements have been
|
// There is no usable separator, but several elements have
|
||||||
// added. We can cut right here.
|
// been added. We can cut right here.
|
||||||
end_ = cit->pos;
|
end_ = cit->pos;
|
||||||
dim_.wid = wid;
|
dim_.wid = wid;
|
||||||
elements_.erase(cit, end);
|
elements_.erase(cit, end);
|
||||||
|
Loading…
Reference in New Issue
Block a user