mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-22 05:16:21 +00:00
Handle multiple spaces at row break
In order to work around the Qt row breaking algorithm, which considers multiple spaces as one at QTextLine break, we insert word_joiner unicode characters beteween each pair of spaces. The TextLayoutHelper class makes it easy to handle that. Update Row::Element::rtrim() to only remove one space at row end. Update support::countExpanders() to count all spaces, without special handling for consecutive ones. Fixes bug #10117.
This commit is contained in:
parent
a48efa03b1
commit
201c95a76e
10
src/Row.cpp
10
src/Row.cpp
@ -27,6 +27,7 @@
|
||||
#include "support/lassert.h"
|
||||
#include "support/lstrings.h"
|
||||
#include "support/lyxlib.h"
|
||||
#include "support/textutils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
@ -203,14 +204,13 @@ bool Row::Element::splitAt(int const width, int next_width, bool force,
|
||||
|
||||
void Row::Element::rtrim()
|
||||
{
|
||||
if (type != STRING)
|
||||
if (type != STRING || str.empty() || !isSpace(str.back()))
|
||||
return;
|
||||
/* This is intended for strings that have been created by splitAt.
|
||||
* They may have trailing spaces, but they are not counted in the
|
||||
* string length (QTextLayout feature, actually). We remove them,
|
||||
* and decrease endpos, since spaces at row break are invisible.
|
||||
* If There is a trailing space, we remove it and decrease endpos,
|
||||
* since spaces at row break are invisible.
|
||||
*/
|
||||
str = support::rtrim(str);
|
||||
str.pop_back();
|
||||
endpos = pos + str.length();
|
||||
dim.wid = nspc_wid;
|
||||
}
|
||||
|
@ -20,8 +20,8 @@
|
||||
#include "support/convert.h"
|
||||
#include "support/debug.h"
|
||||
#include "support/lassert.h"
|
||||
#include "support/lstrings.h" // for breakString_helper with qt4
|
||||
#include "support/lyxlib.h"
|
||||
#include "support/textutils.h"
|
||||
|
||||
#define DISABLE_PMPROF
|
||||
#include "support/pmprof.h"
|
||||
@ -411,7 +411,13 @@ TextLayoutHelper::TextLayoutHelper(docstring const & s, bool isrtl, bool naked)
|
||||
#endif
|
||||
|
||||
// Now translate the string character-by-character.
|
||||
bool was_space = false;
|
||||
for (char_type const c : s) {
|
||||
// insert a word joiner character between consecutive spaces
|
||||
bool const is_space = isSpace(c);
|
||||
if (!naked && is_space && was_space)
|
||||
qstr += word_joiner;
|
||||
was_space = is_space;
|
||||
// Remember the QString index at this point
|
||||
pos2qpos_.push_back(qstr.size());
|
||||
// Performance: UTF-16 characters are easier
|
||||
@ -599,27 +605,19 @@ GuiFontMetrics::breakString_helper(docstring const & s, int first_wid, int wid,
|
||||
// If the line is not the last one, trailing space is always omitted.
|
||||
int nspc_wid = wid;
|
||||
// For the last line, compute the width without trailing space
|
||||
if (i + 1 == tl.lineCount()) {
|
||||
// trim_pos points to the last character that is not a space
|
||||
auto trim_pos = s.find_last_not_of(from_ascii(" "));
|
||||
if (trim_pos == docstring::npos)
|
||||
nspc_wid = 0;
|
||||
else if (trim_pos + 1 < s.length()) {
|
||||
int const num_spaces = s.length() - trim_pos - 1;
|
||||
// find the position on the line before trailing
|
||||
// spaces. Remove 1 to account for the ending
|
||||
// non-breaking space of qs.
|
||||
nspc_wid = iround(line.cursorToX(line_epos - num_spaces - 1));
|
||||
}
|
||||
}
|
||||
if (i + 1 == tl.lineCount() && !s.empty() && isSpace(s.back())
|
||||
&& line.textStart() <= tlh.pos2qpos(s.size() - 1))
|
||||
nspc_wid = iround(line.cursorToX(tlh.pos2qpos(s.size() - 1)));
|
||||
#else
|
||||
// With some monospace fonts, the value of horizontalAdvance()
|
||||
// can be wrong with Qt4. One hypothesis is that the invisible
|
||||
// characters that we use are given a non-null width.
|
||||
// FIXME: this is slower than it could be but we'll get rid of Qt4 anyway
|
||||
docstring const ss = s.substr(pos, epos - pos);
|
||||
docstring ss = s.substr(pos, epos - pos);
|
||||
int const wid = width(ss);
|
||||
int const nspc_wid = i + 1 < tl.lineCount() ? width(rtrim(ss)) : wid;
|
||||
if (!ss.empty() && isSpace(ss.back()))
|
||||
ss.pop_back();
|
||||
int const nspc_wid = i + 1 < tl.lineCount() ? width(ss) : wid;
|
||||
#endif
|
||||
breaks.emplace_back(epos - pos, wid, nspc_wid);
|
||||
pos = epos;
|
||||
|
@ -1507,18 +1507,11 @@ int countExpanders(docstring const & str)
|
||||
// Numbers of characters that are expanded by inter-word spacing. These
|
||||
// characters are spaces, except for characters 09-0D which are treated
|
||||
// specially. (From a combination of testing with the notepad found in qt's
|
||||
// examples, and reading the source code.) In addition, consecutive spaces
|
||||
// only count as one expander.
|
||||
bool wasspace = false;
|
||||
// examples, and reading the source code.)
|
||||
int nexp = 0;
|
||||
for (char_type c : str)
|
||||
if (c > 0x0d && isSpace(c)) {
|
||||
if (!wasspace) {
|
||||
++nexp;
|
||||
wasspace = true;
|
||||
}
|
||||
} else
|
||||
wasspace = false;
|
||||
if (c > 0x0d && isSpace(c))
|
||||
++nexp;
|
||||
return nexp;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user