mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-22 05:16:21 +00:00
Re-implement getColumNearX using row elements
The code is now so much shorter that it is scary... Expect that further changes will be necessary Cursor boundary is not handled yet.
This commit is contained in:
parent
01c9bcb432
commit
f215bb3b92
@ -13,15 +13,17 @@ What is done:
|
||||
|
||||
* re-implement cursorX using row elements
|
||||
|
||||
* re-implement getColumnNearX using row elements (boundary is not
|
||||
considered yet).
|
||||
|
||||
* Implement proper string metrics computation (with cache), when
|
||||
lyxrc.force_paint_single_char is false.
|
||||
lyxrc.force_paint_single_char is false. In this case, remove also
|
||||
useless workarounds which disable kerning and ligatures.
|
||||
|
||||
Next steps:
|
||||
|
||||
* re-implement getColumnNearX using row elements
|
||||
|
||||
* get rid of old code of cursorX and getColumnNearX (which have been
|
||||
kept for comparison purpose).
|
||||
kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE).
|
||||
|
||||
* re-implement row painting using row elements (can it be done?)
|
||||
|
||||
@ -41,3 +43,5 @@ Other differences that should be considered as bugs
|
||||
* words longer than the screen are no monger broken at an arbitrary
|
||||
point. This is a problem for languages like chinese that do not use
|
||||
separators.
|
||||
|
||||
* Boundary is not taken in account properly in getColumnNearX
|
||||
|
89
src/Row.cpp
89
src/Row.cpp
@ -54,8 +54,58 @@ double Row::Element::pos2x(pos_type const i) const
|
||||
}
|
||||
|
||||
|
||||
pos_type Row::Element::x2pos(double &x) const
|
||||
{
|
||||
//lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this;
|
||||
// if element is rtl, flip x value
|
||||
bool const rtl = font.isVisibleRightToLeft();
|
||||
double x2 = rtl ? (width() - x) : x;
|
||||
|
||||
FontMetrics const & fm = theFontMetrics(font);
|
||||
double last_w = 0;
|
||||
double w = 0;
|
||||
size_t i = 1;
|
||||
// non-STRING element only contain one position
|
||||
if (type != STRING) {
|
||||
i = 0;
|
||||
w = width();
|
||||
} else {
|
||||
// FIXME: implement dichotomy search?
|
||||
for ( ; i <= str.size() ; ++i) {
|
||||
last_w = w;
|
||||
w = fm.width(str.substr(0,i));
|
||||
if (w > x2) {
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if (i == str.size())
|
||||
// lyxerr << " NOT FOUND ";
|
||||
}
|
||||
|
||||
// round to the closest side
|
||||
if (x2 - last_w > w - x2) {
|
||||
x2 = w;
|
||||
++i;
|
||||
} else
|
||||
x2 = last_w;
|
||||
|
||||
// is element is rtl, flip values
|
||||
if (rtl) {
|
||||
x = last_w - x2;
|
||||
i = endpos - i;
|
||||
} else {
|
||||
x = x2;
|
||||
i = pos + i;
|
||||
}
|
||||
|
||||
//lyxerr << "=> p=" << i << " x=" << x << endl;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
Row::Row()
|
||||
: separator(0), label_hfill(0), x(0),
|
||||
: separator(0), label_hfill(0), x(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)
|
||||
@ -153,19 +203,19 @@ ostream & operator<<(ostream & os, Row::Element const & e)
|
||||
os << e.pos << ">>" << e.endpos << " ";
|
||||
|
||||
switch (e.type) {
|
||||
case Row::Element::STRING:
|
||||
os << "STRING: `" << to_utf8(e.str) << "'";
|
||||
case Row::STRING:
|
||||
os << "STRING: `" << to_utf8(e.str) << "' " << e.dim.wid;
|
||||
break;
|
||||
case Row::Element::COMPLETION:
|
||||
os << "COMPLETION: `" << to_utf8(e.str) << "'";
|
||||
case Row::VIRTUAL:
|
||||
os << "VIRTUAL: `" << to_utf8(e.str) << "'";
|
||||
break;
|
||||
case Row::Element::INSET:
|
||||
case Row::INSET:
|
||||
os << "INSET: " << to_utf8(e.inset->layoutName());
|
||||
break;
|
||||
case Row::Element::SEPARATOR:
|
||||
case Row::SEPARATOR:
|
||||
os << "SEPARATOR: " << e.dim.wid << "+" << e.extra;
|
||||
break;
|
||||
case Row::Element::SPACE:
|
||||
case Row::SPACE:
|
||||
os << "SPACE: " << e.dim.wid;
|
||||
break;
|
||||
}
|
||||
@ -176,6 +226,7 @@ ostream & operator<<(ostream & os, Row::Element const & e)
|
||||
ostream & operator<<(ostream & os, Row const & row)
|
||||
{
|
||||
os << " pos: " << row.pos_ << " end: " << row.end_
|
||||
<< " x: " << row.x
|
||||
<< " width: " << row.dim_.wid
|
||||
<< " ascent: " << row.dim_.asc
|
||||
<< " descent: " << row.dim_.des
|
||||
@ -194,7 +245,7 @@ bool Row::sameString(Font const & f, Change const & ch) const
|
||||
if (elements_.empty())
|
||||
return false;
|
||||
Element const & elt = elements_.back();
|
||||
return elt.type == Element::STRING && !elt.final
|
||||
return elt.type == STRING && !elt.final
|
||||
&& elt.font == f && elt.change == ch;
|
||||
}
|
||||
|
||||
@ -208,7 +259,7 @@ void Row::finalizeLast()
|
||||
return;
|
||||
elt.final = true;
|
||||
|
||||
if (elt.type == Element::STRING) {
|
||||
if (elt.type == STRING) {
|
||||
elt.dim.wid = theFontMetrics(elt.font).width(elt.str);
|
||||
dim_.wid += elt.dim.wid;
|
||||
}
|
||||
@ -219,7 +270,7 @@ void Row::add(pos_type const pos, Inset const * ins, Dimension const & dim,
|
||||
Font const & f, Change const & ch)
|
||||
{
|
||||
finalizeLast();
|
||||
Element e(Element::INSET, pos, f, ch);
|
||||
Element e(INSET, pos, f, ch);
|
||||
e.inset = ins;
|
||||
e.dim = dim;
|
||||
elements_.push_back(e);
|
||||
@ -232,7 +283,7 @@ void Row::add(pos_type const pos, char_type const c,
|
||||
{
|
||||
if (!sameString(f, ch)) {
|
||||
finalizeLast();
|
||||
Element e(Element::STRING, pos, f, ch);
|
||||
Element e(STRING, pos, f, ch);
|
||||
elements_.push_back(e);
|
||||
}
|
||||
//lyxerr << "FONT " <<back().font.language() << endl;
|
||||
@ -241,11 +292,11 @@ void Row::add(pos_type const pos, char_type const c,
|
||||
}
|
||||
|
||||
|
||||
void Row::addCompletion(pos_type const pos, docstring const & s,
|
||||
Font const & f, Change const & ch)
|
||||
void Row::addVirtual(pos_type const pos, docstring const & s,
|
||||
Font const & f, Change const & ch)
|
||||
{
|
||||
finalizeLast();
|
||||
Element e(Element::COMPLETION, pos, f, ch);
|
||||
Element e(VIRTUAL, pos, f, ch);
|
||||
e.str = s;
|
||||
// A completion has no size
|
||||
e.endpos = pos;
|
||||
@ -258,7 +309,7 @@ void Row::addSeparator(pos_type const pos, char_type const c,
|
||||
Font const & f, Change const & ch)
|
||||
{
|
||||
finalizeLast();
|
||||
Element e(Element::SEPARATOR, pos, f, ch);
|
||||
Element e(SEPARATOR, pos, f, ch);
|
||||
e.str += c;
|
||||
e.dim.wid = theFontMetrics(f).width(c);
|
||||
elements_.push_back(e);
|
||||
@ -270,7 +321,7 @@ void Row::addSpace(pos_type const pos, int const width,
|
||||
Font const & f, Change const & ch)
|
||||
{
|
||||
finalizeLast();
|
||||
Element e(Element::SPACE, pos, f, ch);
|
||||
Element e(SPACE, pos, f, ch);
|
||||
e.dim.wid = width;
|
||||
elements_.push_back(e);
|
||||
dim_.wid += e.dim.wid;
|
||||
@ -291,13 +342,13 @@ void Row::separate_back(pos_type const keep)
|
||||
int i = elements_.size();
|
||||
int new_end = end_;
|
||||
int new_wid = dim_.wid;
|
||||
if (i > 0 && elements_[i - 1].isSeparator() && new_end > keep) {
|
||||
if (i > 0 && elements_[i - 1].type == SEPARATOR && new_end > keep) {
|
||||
--i;
|
||||
new_end = elements_[i].pos;
|
||||
new_wid -= elements_[i].dim.wid;
|
||||
}
|
||||
|
||||
while (i > 0 && !elements_[i - 1].isSeparator() && new_end > keep) {
|
||||
while (i > 0 && elements_[i - 1].type != SEPARATOR && new_end > keep) {
|
||||
--i;
|
||||
new_end = elements_[i].pos;
|
||||
new_wid -= elements_[i].dim.wid;
|
||||
|
47
src/Row.h
47
src/Row.h
@ -30,37 +30,50 @@ class DocIterator;
|
||||
class Inset;
|
||||
|
||||
/**
|
||||
* An on-screen row of text. A paragraph is broken into a
|
||||
* RowList for display. Each Row contains position pointers
|
||||
* into the first and last character positions of that row.
|
||||
* An on-screen row of text. A paragraph is broken into a RowList for
|
||||
* display. Each Row contains a tokenized description of the contents
|
||||
* of the line.
|
||||
*/
|
||||
class Row {
|
||||
public:
|
||||
// Possible types of row elements
|
||||
enum Type {
|
||||
// a string of character
|
||||
STRING,
|
||||
/**
|
||||
* Something (completion, end-of-par marker)
|
||||
* that occupies space one screen but does not
|
||||
* correspond to any paragraph contents
|
||||
*/
|
||||
VIRTUAL,
|
||||
// A stretchable space, basically
|
||||
SEPARATOR,
|
||||
// An inset
|
||||
INSET,
|
||||
// Some spacing described by its width, not a string
|
||||
SPACE
|
||||
};
|
||||
|
||||
/**
|
||||
* One element of a Row. It has a set of attributes that can be used
|
||||
* by other methods that need to parse the Row contents.
|
||||
*/
|
||||
struct Element {
|
||||
enum Type {
|
||||
STRING,
|
||||
COMPLETION,
|
||||
SEPARATOR,
|
||||
INSET,
|
||||
SPACE
|
||||
};
|
||||
|
||||
Element(Type const t, pos_type p, Font const & f, Change const & ch)
|
||||
: type(t), pos(p), endpos(p + 1), inset(0),
|
||||
extra(0), font(f), change(ch), final(false) {}
|
||||
|
||||
//
|
||||
bool isSeparator() const { return type == SEPARATOR; }
|
||||
// returns total width of element, including separator overhead
|
||||
double width() const { return dim.wid + extra; };
|
||||
// returns position in pixels (from the left) of position
|
||||
// \param i in the row element
|
||||
double pos2x(pos_type const i) const;
|
||||
|
||||
// Return character position that is the closest to
|
||||
// pixel position \param x. The value \param x is
|
||||
// rounded to the actual pixel position.
|
||||
pos_type x2pos(double &x) const;
|
||||
|
||||
// The kind of row element
|
||||
Type type;
|
||||
// position of the element in the paragraph
|
||||
@ -139,8 +152,8 @@ public:
|
||||
void add(pos_type pos, char_type const c,
|
||||
Font const & f, Change const & ch);
|
||||
///
|
||||
void addCompletion(pos_type pos, docstring const & s,
|
||||
Font const & f, Change const & ch);
|
||||
void addVirtual(pos_type pos, docstring const & s,
|
||||
Font const & f, Change const & ch);
|
||||
///
|
||||
void addSeparator(pos_type pos, char_type const c,
|
||||
Font const & f, Change const & ch);
|
||||
@ -197,8 +210,10 @@ public:
|
||||
double separator;
|
||||
/// width of hfills in the label
|
||||
double label_hfill;
|
||||
/// the x position of the row
|
||||
/// the x position of the row (left margin)
|
||||
double x;
|
||||
/// the right margin of the row
|
||||
int right_margin;
|
||||
///
|
||||
mutable pos_type sel_beg;
|
||||
///
|
||||
|
@ -15,6 +15,8 @@
|
||||
* Full author contact details are available in file CREDITS.
|
||||
*/
|
||||
|
||||
//#define KEEP_OLD_METRICS_CODE 1
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "TextMetrics.h"
|
||||
@ -48,7 +50,7 @@
|
||||
#include "support/debug.h"
|
||||
#include "support/lassert.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -65,7 +67,7 @@ int numberOfSeparators(Row const & row)
|
||||
Row::const_iterator cit = row.begin();
|
||||
Row::const_iterator const end = row.end();
|
||||
for ( ; cit != end ; ++cit)
|
||||
if (cit->isSeparator())
|
||||
if (cit->type == Row::SEPARATOR)
|
||||
++n;
|
||||
return n;
|
||||
}
|
||||
@ -77,7 +79,7 @@ void setSeparatorWidth(Row & row, double w)
|
||||
Row::iterator it = row.begin();
|
||||
Row::iterator const end = row.end();
|
||||
for ( ; it != end ; ++it)
|
||||
if (it->isSeparator())
|
||||
if (it->type == Row::SEPARATOR)
|
||||
it->extra = w;
|
||||
}
|
||||
|
||||
@ -630,6 +632,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
|
||||
&& !par.isNewline(row.endpos() - 1)
|
||||
&& !disp_inset) {
|
||||
setSeparatorWidth(row, w / ns);
|
||||
row.dimension().wid = width;
|
||||
//lyxerr << "row.separator " << row.separator << endl;
|
||||
//lyxerr << "ns " << ns << endl;
|
||||
} else if (is_rtl) {
|
||||
@ -672,7 +675,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
|
||||
Row::iterator const cend = row.end();
|
||||
for ( ; cit != cend; ++cit) {
|
||||
if (row.label_hfill && cit->endpos == body_pos
|
||||
&& cit->type == Row::Element::SPACE)
|
||||
&& cit->type == Row::SPACE)
|
||||
cit->dim.wid -= row.label_hfill * (nlh - 1);
|
||||
if (!cit->inset || !cit->inset->isHfill())
|
||||
continue;
|
||||
@ -806,6 +809,7 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit
|
||||
pos_type const body_pos = par.beginOfBody();
|
||||
row.clear();
|
||||
row.dimension().wid = leftMargin(max_width_, pit, pos);
|
||||
row.right_margin = right_margin;
|
||||
|
||||
if (pos >= end || row.width() > width) {
|
||||
row.dimension().wid += right_margin;
|
||||
@ -864,7 +868,7 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit
|
||||
// enlarge the last character to hold the end-of-par marker
|
||||
Font f(text_->layoutFont(pit));
|
||||
f.fontInfo().setColor(Color_paragraphmarker);
|
||||
row.add(i, char_type(0x00B6), f, Change());
|
||||
row.addVirtual(i, docstring(1, char_type(0x00B6)), f, Change());
|
||||
}
|
||||
|
||||
// add inline completion width
|
||||
@ -872,7 +876,7 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit
|
||||
!bv_->inlineCompletion().empty()) {
|
||||
Font f = *fi;
|
||||
f.fontInfo().setColor(Color_inlinecompletion);
|
||||
row.addCompletion(i + 1, bv_->inlineCompletion(),
|
||||
row.addVirtual(i + 1, bv_->inlineCompletion(),
|
||||
f, Change());
|
||||
}
|
||||
|
||||
@ -897,7 +901,8 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit
|
||||
if (body_pos && i == body_pos) {
|
||||
FontMetrics const & fm = theFontMetrics(text_->labelFont(par));
|
||||
pos_type j = i;
|
||||
if (!row.empty() && row.back().isSeparator()) {
|
||||
if (!row.empty()
|
||||
&& row.back().type == Row::SEPARATOR) {
|
||||
row.pop_back();
|
||||
--j;
|
||||
}
|
||||
@ -916,7 +921,7 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit
|
||||
|
||||
// if the row ends with a separator that is not at end of
|
||||
// paragraph, remove it
|
||||
if (!row.empty() && row.back().isSeparator()
|
||||
if (!row.empty() && row.back().type == Row::SEPARATOR
|
||||
&& row.endpos() < par.size())
|
||||
row.pop_back();
|
||||
|
||||
@ -966,11 +971,11 @@ void TextMetrics::setRowHeight(Row & row, pit_type const pit,
|
||||
|
||||
// insets may be taller
|
||||
ParagraphMetrics const & pm = par_metrics_[pit];
|
||||
InsetList::const_iterator ii = par.insetList().begin();
|
||||
InsetList::const_iterator iend = par.insetList().end();
|
||||
for ( ; ii != iend; ++ii) {
|
||||
if (ii->pos >= row.pos() && ii->pos < row.endpos()) {
|
||||
Dimension const & dim = pm.insetDimension(ii->inset);
|
||||
Row::const_iterator cit = row.begin();
|
||||
Row::const_iterator cend = row.end();
|
||||
for ( ; cit != cend; ++cit) {
|
||||
if (cit->inset) {
|
||||
Dimension const & dim = pm.insetDimension(cit->inset);
|
||||
maxasc = max(maxasc, dim.ascent());
|
||||
maxdesc = max(maxdesc, dim.descent());
|
||||
}
|
||||
@ -1109,13 +1114,40 @@ void TextMetrics::setRowHeight(Row & row, pit_type const pit,
|
||||
pos_type TextMetrics::getColumnNearX(pit_type const pit,
|
||||
Row const & row, int & x, bool & boundary) const
|
||||
{
|
||||
// FIXME: handle properly boundary (not done now)
|
||||
pos_type pos = row.pos();
|
||||
if (row.x >= x || row.empty())
|
||||
x = row.x;
|
||||
else if (x >= row.width() - row.right_margin) {
|
||||
x = row.width() - row.right_margin;
|
||||
pos = row.back().endpos;
|
||||
} else {
|
||||
double w = row.x;
|
||||
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;
|
||||
pos = cit->x2pos(x_offset);
|
||||
x = x_offset + w;
|
||||
break;
|
||||
}
|
||||
w += cit->width();
|
||||
}
|
||||
if (cit == row.end())
|
||||
lyxerr << "NOT FOUND!! x=" << x << ", wid=" << row.width() << endl;
|
||||
}
|
||||
|
||||
#if !defined(KEEP_OLD_METRICS_CODE)
|
||||
return pos - row.pos();
|
||||
#else
|
||||
Buffer const & buffer = bv_->buffer();
|
||||
|
||||
/// For the main Text, it is possible that this pit is not
|
||||
/// yet in the CoordCache when moving cursor up.
|
||||
/// x Paragraph coordinate is always 0 for main text anyway.
|
||||
int const xo = origin_.x_;
|
||||
x -= xo;
|
||||
int x2 = x - xo;
|
||||
Paragraph const & par = text_->getPar(pit);
|
||||
Bidi bidi;
|
||||
bidi.computeTables(par, buffer, row);
|
||||
@ -1138,7 +1170,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
|
||||
|
||||
// check for empty row
|
||||
if (vc == end) {
|
||||
x = int(tmpx) + xo;
|
||||
x2 = int(tmpx) + xo;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1150,7 +1182,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
|
||||
// the value of rtl.
|
||||
bool const rtl_on_lastrow = lastrow ? text_->isRTL(par) : false;
|
||||
|
||||
while (vc < end && tmpx <= x) {
|
||||
while (vc < end && tmpx <= x2) {
|
||||
c = bidi.vis2log(vc);
|
||||
last_tmpx = tmpx;
|
||||
if (body_pos > 0 && c == body_pos - 1) {
|
||||
@ -1167,7 +1199,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
|
||||
++vc;
|
||||
}
|
||||
|
||||
if ((tmpx + last_tmpx) / 2 > x) {
|
||||
if ((tmpx + last_tmpx) / 2 > x2) {
|
||||
tmpx = last_tmpx;
|
||||
left_side = true;
|
||||
}
|
||||
@ -1175,11 +1207,11 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
|
||||
// This shouldn't happen. But we can reset and try to continue.
|
||||
LASSERT(vc <= end, vc = end);
|
||||
|
||||
boundary = false;
|
||||
bool boundary2 = false;
|
||||
|
||||
if (lastrow &&
|
||||
((rtl_on_lastrow && left_side && vc == row.pos() && x < tmpx - 5) ||
|
||||
(!rtl_on_lastrow && !left_side && vc == end && x > tmpx + 5))) {
|
||||
((rtl_on_lastrow && left_side && vc == row.pos() && x2 < tmpx - 5) ||
|
||||
(!rtl_on_lastrow && !left_side && vc == end && x2 > tmpx + 5))) {
|
||||
if (!par.isNewline(end - 1))
|
||||
c = end;
|
||||
} else if (vc == row.pos()) {
|
||||
@ -1191,7 +1223,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
|
||||
bool const rtl = (bidi.level(c) % 2 == 1);
|
||||
if (left_side == rtl) {
|
||||
++c;
|
||||
boundary = isRTLBoundary(pit, c);
|
||||
boundary2 = isRTLBoundary(pit, c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1223,18 +1255,25 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
|
||||
}
|
||||
#endif
|
||||
|
||||
x = int(tmpx) + xo;
|
||||
x2 = int(tmpx) + xo;
|
||||
pos_type const col = c - row.pos();
|
||||
|
||||
if (abs(x2 - x) > 0.1 || boundary != boundary
|
||||
|| c != pos) {
|
||||
lyxerr << "new=(x=" << x << ", b=" << boundary << ", p=" << pos << "), "
|
||||
<< "old=(x=" << x2 << ", b=" << boundary2 << ", p=" << c << "), " << row;
|
||||
}
|
||||
|
||||
if (!c || end == par.size())
|
||||
return col;
|
||||
|
||||
if (c==end && !par.isLineSeparator(c-1) && !par.isNewline(c-1)) {
|
||||
boundary = true;
|
||||
boundary2 = true;
|
||||
return col;
|
||||
}
|
||||
|
||||
return min(col, end - 1 - row.pos());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1530,9 +1569,8 @@ int TextMetrics::cursorX(CursorSlice const & sl,
|
||||
{
|
||||
LASSERT(sl.text() == text_, return 0);
|
||||
pit_type const pit = sl.pit();
|
||||
pos_type ppos = sl.pos();
|
||||
pos_type pos = sl.pos();
|
||||
|
||||
Paragraph const & par = text_->paragraphs()[pit];
|
||||
ParagraphMetrics const & pm = par_metrics_[pit];
|
||||
if (pm.rows().empty())
|
||||
return 0;
|
||||
@ -1543,42 +1581,41 @@ int TextMetrics::cursorX(CursorSlice const & sl,
|
||||
/**
|
||||
* When boundary is true, position is on the row element (pos, endpos)
|
||||
* if
|
||||
* pos < ppos <= endpos
|
||||
* pos < pos <= endpos
|
||||
* whereas, when boundary is false, the test is
|
||||
* pos <= ppos < endpos
|
||||
* pos <= pos < endpos
|
||||
* The correction below allows to handle both cases.
|
||||
*/
|
||||
int const boundary_corr = (boundary && ppos) ? -1 : 0;
|
||||
int const boundary_corr = (boundary && pos) ? -1 : 0;
|
||||
|
||||
if (row.empty()
|
||||
if (row.empty()
|
||||
|| (row.begin()->font.isRightToLeft()
|
||||
&& ppos == row.begin()->endpos))
|
||||
&& pos == row.begin()->endpos))
|
||||
return int(x);
|
||||
|
||||
Row::const_iterator cit = row.begin();
|
||||
for ( ; cit != row.end() ; ++cit) {
|
||||
// lyxerr << "ppos=" << ppos << "(" << boundary_corr << ")"
|
||||
// << ", x=" << x << " " << *cit << endl;
|
||||
// lyxerr << "test1=" << (ppos + boundary_corr >= cit->pos)
|
||||
// << " test2=" << ( ppos + boundary_corr < best->endpos) <<endl;
|
||||
if (ppos + boundary_corr >= cit->pos
|
||||
&& ppos + boundary_corr < cit->endpos) {
|
||||
x += cit->pos2x(ppos);
|
||||
if (pos + boundary_corr >= cit->pos
|
||||
&& pos + boundary_corr < cit->endpos) {
|
||||
x += cit->pos2x(pos);
|
||||
break;
|
||||
}
|
||||
x += cit->width();
|
||||
}
|
||||
|
||||
if (cit == row.end()
|
||||
&& (row.back().font.isRightToLeft() || ppos != row.back().endpos))
|
||||
&& (row.back().font.isRightToLeft() || pos != row.back().endpos))
|
||||
lyxerr << "NOT FOUND!"
|
||||
<< "ppos=" << ppos << "(" << boundary_corr << ")" << "\n"
|
||||
<< "pos=" << pos << "(" << boundary_corr << ")" << "\n"
|
||||
<< row;
|
||||
|
||||
#ifdef KEEP_OLD_METRICS_CODE
|
||||
Paragraph const & par = text_->paragraphs()[pit];
|
||||
|
||||
// Correct position in front of big insets
|
||||
bool const boundary_correction = ppos != 0 && boundary;
|
||||
bool const boundary_correction = pos != 0 && boundary;
|
||||
if (boundary_correction)
|
||||
--ppos;
|
||||
--pos;
|
||||
|
||||
pos_type cursor_vpos = 0;
|
||||
|
||||
@ -1598,18 +1635,18 @@ int TextMetrics::cursorX(CursorSlice const & sl,
|
||||
|
||||
if (end <= row_pos)
|
||||
cursor_vpos = row_pos;
|
||||
else if (ppos >= end)
|
||||
else if (pos >= end)
|
||||
cursor_vpos = text_->isRTL(par) ? row_pos : end;
|
||||
else if (ppos > row_pos && ppos >= end)
|
||||
else if (pos > row_pos && pos >= end)
|
||||
//FIXME: this code is never reached!
|
||||
// (see http://www.lyx.org/trac/changeset/8251)
|
||||
// Place cursor after char at (logical) position pos - 1
|
||||
cursor_vpos = (bidi.level(ppos - 1) % 2 == 0)
|
||||
? bidi.log2vis(ppos - 1) + 1 : bidi.log2vis(ppos - 1);
|
||||
cursor_vpos = (bidi.level(pos - 1) % 2 == 0)
|
||||
? bidi.log2vis(pos - 1) + 1 : bidi.log2vis(pos - 1);
|
||||
else
|
||||
// Place cursor before char at (logical) position ppos
|
||||
cursor_vpos = (bidi.level(ppos) % 2 == 0)
|
||||
? bidi.log2vis(ppos) : bidi.log2vis(ppos) + 1;
|
||||
// Place cursor before char at (logical) position pos
|
||||
cursor_vpos = (bidi.level(pos) % 2 == 0)
|
||||
? bidi.log2vis(pos) : bidi.log2vis(pos) + 1;
|
||||
|
||||
pos_type body_pos = par.beginOfBody();
|
||||
if (body_pos > 0 &&
|
||||
@ -1703,23 +1740,23 @@ int TextMetrics::cursorX(CursorSlice const & sl,
|
||||
// see correction above
|
||||
if (boundary_correction) {
|
||||
if (isRTL(sl, boundary))
|
||||
x2 -= singleWidth(pit, ppos);
|
||||
x2 -= singleWidth(pit, pos);
|
||||
else
|
||||
x2 += singleWidth(pit, ppos);
|
||||
x2 += singleWidth(pit, pos);
|
||||
}
|
||||
|
||||
if (x2 != x) {
|
||||
if (abs(x2 - x) > 0.01) {
|
||||
lyxerr << "cursorX: x2=" << x2 << ", x=" << x;
|
||||
if (cit == row.end())
|
||||
lyxerr << "Element not found for "
|
||||
<< ppos - boundary_corr << "(" << boundary_corr << ")";
|
||||
<< pos - boundary_corr << "(" << boundary_corr << ")";
|
||||
else
|
||||
lyxerr << " in [" << cit->pos << "/"
|
||||
<< ppos - boundary_corr << "(" << boundary_corr << ")"
|
||||
<< pos - boundary_corr << "(" << boundary_corr << ")"
|
||||
<< "/" << cit->endpos << "] of " << *cit << "\n";
|
||||
lyxerr << row <<endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return int(x);
|
||||
}
|
||||
@ -2004,13 +2041,14 @@ int TextMetrics::leftMargin(int max_width,
|
||||
}
|
||||
|
||||
|
||||
#ifdef KEEP_OLD_METRICS_CODE
|
||||
int TextMetrics::singleWidth(pit_type pit, pos_type pos) const
|
||||
{
|
||||
ParagraphMetrics const & pm = par_metrics_[pit];
|
||||
|
||||
return pm.singleWidth(pos, displayFont(pit, pos));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void TextMetrics::draw(PainterInfo & pi, int x, int y) const
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user