Reduce use of double variables in Row

All the code that is run before row metrics have been computed should use int arithmetic. After metrics have been computed, we still need doubles because fully justified rows use double for Row::Element::extra.

Rename Row::x to Row::left_margin and change its type to int.

Rename Row::Element::width() to full_width(). In some places of the code, use dim.wid (the int version without the extra separator) because metrics have not been computed.

Let Row::Element::x2pos take a int& argument instead of double&

Let Row::Element::breakAt take a int argument instead of double
This commit is contained in:
Jean-Marc Lasgouttes 2014-12-22 10:36:53 +01:00
parent 8bab23384a
commit e32a3e7f57
4 changed files with 52 additions and 70 deletions

View File

@ -48,9 +48,9 @@ double Row::Element::pos2x(pos_type const i) const
double w = 0; double w = 0;
//handle first the two bounds of the element //handle first the two bounds of the element
if (i == endpos && !(inset && inset->lyxCode() == SEPARATOR_CODE)) if (i == endpos && !(inset && inset->lyxCode() == SEPARATOR_CODE))
w = rtl ? 0 : width(); w = rtl ? 0 : full_width();
else if (i == pos || type != STRING) else if (i == pos || type != STRING)
w = rtl ? width() : 0; w = rtl ? full_width() : 0;
else { else {
FontMetrics const & fm = theFontMetrics(font); FontMetrics const & fm = theFontMetrics(font);
w = fm.pos2x(str, i - pos, font.isVisibleRightToLeft()); w = fm.pos2x(str, i - pos, font.isVisibleRightToLeft());
@ -60,7 +60,7 @@ double Row::Element::pos2x(pos_type const i) const
} }
pos_type Row::Element::x2pos(double &x) const pos_type Row::Element::x2pos(int &x) const
{ {
//lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this; //lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this;
bool const rtl = font.isVisibleRightToLeft(); bool const rtl = font.isVisibleRightToLeft();
@ -69,24 +69,21 @@ pos_type Row::Element::x2pos(double &x) const
switch (type) { switch (type) {
case STRING: { case STRING: {
FontMetrics const & fm = theFontMetrics(font); FontMetrics const & fm = theFontMetrics(font);
// FIXME: is it really necessary for x to be a double? i = fm.x2pos(str, x, rtl);
int xx = int(x);
i = fm.x2pos(str, xx, rtl);
x = xx;
break; break;
} }
case VIRTUAL: case VIRTUAL:
// those elements are actually empty (but they have a width) // those elements are actually empty (but they have a width)
i = 0; i = 0;
x = rtl ? width() : 0; x = rtl ? int(full_width()) : 0;
break; break;
case SEPARATOR: case SEPARATOR:
case INSET: case INSET:
case SPACE: case SPACE:
// those elements contain only one position. Round to // those elements contain only one position. Round to
// the closest side. // the closest side.
if (x > width()) { if (x > full_width()) {
x = width(); x = int(full_width());
i = !rtl; i = !rtl;
} else { } else {
x = 0; x = 0;
@ -100,22 +97,22 @@ pos_type Row::Element::x2pos(double &x) const
} }
bool Row::Element::breakAt(double w) bool Row::Element::breakAt(int w)
{ {
if (type != STRING || width() <= w) if (type != STRING || dim.wid <= w)
return false; return false;
bool const rtl = font.isVisibleRightToLeft(); bool const rtl = font.isVisibleRightToLeft();
if (rtl) if (rtl)
w = width() - w; w = dim.wid - w;
pos_type new_pos = x2pos(w); pos_type new_pos = x2pos(w);
if (new_pos == pos) if (new_pos == pos)
return false; return false;
str = str.substr(0, new_pos - pos); str = str.substr(0, new_pos - pos);
if (rtl) if (rtl)
dim.wid -= int(w); dim.wid -= w;
else else
dim.wid = int(w); dim.wid = w;
endpos = new_pos; endpos = new_pos;
return true; return true;
} }
@ -134,7 +131,7 @@ pos_type Row::Element::right_pos() const
Row::Row() Row::Row()
: separator(0), label_hfill(0), x(0), right_margin(0), : separator(0), label_hfill(0), left_margin(0), right_margin(0),
sel_beg(-1), sel_end(-1), sel_beg(-1), sel_end(-1),
begin_margin_sel(false), end_margin_sel(false), begin_margin_sel(false), end_margin_sel(false),
changed_(false), crc_(0), pos_(0), end_(0), right_boundary_(false) changed_(false), crc_(0), pos_(0), end_(0), right_boundary_(false)
@ -236,7 +233,7 @@ ostream & operator<<(ostream & os, Row::Element const & e)
os << "SPACE: "; os << "SPACE: ";
break; break;
} }
os << "width=" << e.width(); os << "width=" << e.full_width();
return os; return os;
} }
@ -244,7 +241,7 @@ ostream & operator<<(ostream & os, Row::Element const & e)
ostream & operator<<(ostream & os, Row const & row) ostream & operator<<(ostream & os, Row const & row)
{ {
os << " pos: " << row.pos_ << " end: " << row.end_ os << " pos: " << row.pos_ << " end: " << row.end_
<< " x: " << row.x << " left_margin: " << row.left_margin
<< " width: " << row.dim_.wid << " width: " << row.dim_.wid
<< " right_margin: " << row.right_margin << " right_margin: " << row.right_margin
<< " ascent: " << row.dim_.asc << " ascent: " << row.dim_.asc
@ -252,11 +249,11 @@ ostream & operator<<(ostream & os, Row const & row)
<< " separator: " << row.separator << " separator: " << row.separator
<< " label_hfill: " << row.label_hfill << " label_hfill: " << row.label_hfill
<< " row_boundary: " << row.right_boundary() << "\n"; << " row_boundary: " << row.right_boundary() << "\n";
double x = row.x; double x = row.left_margin;
Row::Elements::const_iterator it = row.elements_.begin(); Row::Elements::const_iterator it = row.elements_.begin();
for ( ; it != row.elements_.end() ; ++it) { for ( ; it != row.elements_.end() ; ++it) {
os << "x=" << x << " => " << *it << endl; os << "x=" << x << " => " << *it << endl;
x += it->width(); x += it->full_width();
} }
return os; return os;
} }
@ -365,8 +362,8 @@ void Row::shortenIfNeeded(pos_type const keep, int const w)
Elements::iterator const beg = elements_.begin(); Elements::iterator const beg = elements_.begin();
Elements::iterator const end = elements_.end(); Elements::iterator const end = elements_.end();
Elements::iterator last_sep = elements_.end(); Elements::iterator last_sep = elements_.end();
double last_width = 0; int last_width = 0;
double wid = x; int wid = left_margin;
Elements::iterator cit = beg; Elements::iterator cit = beg;
for ( ; cit != end ; ++cit) { for ( ; cit != end ; ++cit) {
@ -374,16 +371,16 @@ void Row::shortenIfNeeded(pos_type const keep, int const w)
last_sep = cit; last_sep = cit;
last_width = wid; last_width = wid;
} }
if (wid + cit->width() > w) if (wid + cit->dim.wid > w)
break; break;
wid += cit->width(); wid += cit->dim.wid;
} }
if (last_sep != end) { if (last_sep != end) {
// We have found a suitable separator. This is the // We have found a suitable separator. This is the
// common case. // common case.
end_ = last_sep->endpos; end_ = last_sep->endpos;
dim_.wid = int(last_width); dim_.wid = last_width;
elements_.erase(last_sep, end); elements_.erase(last_sep, end);
return; return;
} }
@ -398,14 +395,14 @@ void Row::shortenIfNeeded(pos_type const keep, int const w)
// 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.
--cit; --cit;
wid -= cit->width(); wid -= cit->dim.wid;
} }
if (cit != beg) { if (cit != beg) {
// There is no separator, but several elements (probably // There is no separator, but several elements (probably
// insets) have been added. We can cut at this place. // insets) have been added. We can cut at this place.
end_ = cit->pos; end_ = cit->pos;
dim_.wid = int(wid); dim_.wid = wid;
elements_.erase(cit, end); elements_.erase(cit, end);
return; return;
} }
@ -415,9 +412,9 @@ void Row::shortenIfNeeded(pos_type const keep, int const w)
* something: when we have one big string, maybe with some * something: when we have one big string, maybe with some
* other things after it. * other things after it.
*/ */
if (cit->breakAt(w - x)) { if (cit->breakAt(w - left_margin)) {
end_ = cit->endpos; end_ = cit->endpos;
dim_.wid = int(x + cit->width()); dim_.wid = left_margin + cit->dim.wid;
// If there are other elements, they should be removed. // If there are other elements, they should be removed.
elements_.erase(boost::next(cit), end); elements_.erase(boost::next(cit), end);
} }

View File

@ -76,7 +76,7 @@ public:
extra(0), font(f), change(ch), final(false) {} extra(0), font(f), change(ch), final(false) {}
// Return total width of element, including separator overhead // Return total width of element, including separator overhead
double width() const { return dim.wid + extra; }; double full_width() const { return dim.wid + extra; };
/** Return position in pixels (from the left) of position /** Return position in pixels (from the left) of position
* \param i in the row element. * \param i in the row element.
*/ */
@ -85,11 +85,11 @@ public:
* pixel position \param x. The value \param x is * pixel position \param x. The value \param x is
* adjusted to the actual pixel position. * adjusted to the actual pixel position.
*/ */
pos_type x2pos(double &x) const; pos_type x2pos(int &x) const;
/** Break the element if possible, so that its width is /** Break the element if possible, so that its width is
* less then \param w. Returns true on success. * less then \param w. Returns true on success.
*/ */
bool breakAt(double w); bool breakAt(int w);
// Returns the position on left side of the element. // Returns the position on left side of the element.
pos_type left_pos() const; pos_type left_pos() const;
@ -243,8 +243,8 @@ public:
double separator; double separator;
/// width of hfills in the label /// width of hfills in the label
double label_hfill; double label_hfill;
/// the x position of the row (left margin) /// the left margin position of the row
double x; int left_margin;
/// the right margin of the row /// the right margin of the row
int right_margin; int right_margin;
/// ///

View File

@ -83,7 +83,7 @@ RowPainter::RowPainter(PainterInfo & pi,
dotted_line_offset_ = int(0.5 * dotted_line_thickness_) + 1; dotted_line_offset_ = int(0.5 * dotted_line_thickness_) + 1;
} }
x_ = row_.x + xo_; x_ = row_.left_margin + xo_;
//lyxerr << "RowPainter: x: " << x_ << " xo: " << xo_ << " yo: " << yo_ << endl; //lyxerr << "RowPainter: x: " << x_ << " xo: " << xo_ << " yo: " << yo_ << endl;
//row_.dump(); //row_.dump();

View File

@ -571,9 +571,9 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
bool const is_rtl = text_->isRTL(par); bool const is_rtl = text_->isRTL(par);
if (is_rtl) if (is_rtl)
row.x = rightMargin(pit); row.left_margin = rightMargin(pit);
else else
row.x = leftMargin(max_width_, pit, row.pos()); row.left_margin = leftMargin(max_width_, pit, row.pos());
// is there a manual margin with a manual label // is there a manual margin with a manual label
Layout const & layout = par.layout(); Layout const & layout = par.layout();
@ -619,16 +619,16 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
row.dimension().wid = width; row.dimension().wid = width;
} else if (is_rtl) { } else if (is_rtl) {
row.dimension().wid = width; row.dimension().wid = width;
row.x += w; row.left_margin += w;
} }
break; break;
} }
case LYX_ALIGN_RIGHT: case LYX_ALIGN_RIGHT:
row.x += w; row.left_margin += w;
break; break;
case LYX_ALIGN_CENTER: case LYX_ALIGN_CENTER:
row.dimension().wid = width - int(w / 2); row.dimension().wid = width - int(w / 2);
row.x += w / 2; row.left_margin += w / 2;
break; break;
case LYX_ALIGN_LEFT: case LYX_ALIGN_LEFT:
case LYX_ALIGN_NONE: case LYX_ALIGN_NONE:
@ -639,21 +639,6 @@ void TextMetrics::computeRowMetrics(pit_type const pit,
} }
} }
#if 0
if (is_rtl) {
pos_type body_pos = par.beginOfBody();
pos_type end = row.endpos();
if (body_pos > 0
&& (body_pos > end || !par.isLineSeparator(body_pos - 1))) {
row.x += theFontMetrics(text_->labelFont(par)).
width(layout.labelsep);
if (body_pos <= end)
row.x += row.label_hfill;
}
}
#endif
// Finally, handle hfill insets // Finally, handle hfill insets
pos_type const endpos = row.endpos(); pos_type const endpos = row.endpos();
pos_type body_pos = par.beginOfBody(); pos_type body_pos = par.beginOfBody();
@ -686,13 +671,13 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const
Paragraph const & par = text_->getPar(pit); Paragraph const & par = text_->getPar(pit);
LBUFERR(par.beginOfBody() > 0 || par.isEnvSeparator(0)); LBUFERR(par.beginOfBody() > 0 || par.isEnvSeparator(0));
double w = 0; int w = 0;
Row::const_iterator cit = row.begin(); Row::const_iterator cit = row.begin();
Row::const_iterator const end = row.end(); Row::const_iterator const end = row.end();
// iterate over elements before main body (except the last one, // iterate over elements before main body (except the last one,
// which is extra space). // which is extra space).
while (cit!= end && cit->endpos < par.beginOfBody()) { while (cit!= end && cit->endpos < par.beginOfBody()) {
w += cit->width(); w += cit->dim.wid;
++cit; ++cit;
} }
@ -703,7 +688,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const
FontMetrics const & fm FontMetrics const & fm
= theFontMetrics(text_->labelFont(par)); = theFontMetrics(text_->labelFont(par));
return max(0, fm.width(label) - int(w)); return max(0, fm.width(label) - w);
} }
@ -803,8 +788,8 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit
pos_type const body_pos = par.beginOfBody(); pos_type const body_pos = par.beginOfBody();
row.clear(); row.clear();
// This make get changed in computeRowMetrics depending on RTL // This make get changed in computeRowMetrics depending on RTL
row.x = leftMargin(max_width_, pit, pos); row.left_margin = leftMargin(max_width_, pit, pos);
row.dimension().wid = int(row.x); row.dimension().wid = row.left_margin;
row.right_margin = right_margin; row.right_margin = right_margin;
if (pos >= end || row.width() > width) { if (pos >= end || row.width() > width) {
@ -1117,25 +1102,25 @@ pos_type TextMetrics::getPosNearX(Row const & row, int & x,
pos_type pos = row.pos(); pos_type pos = row.pos();
boundary = false; boundary = false;
if (row.empty()) if (row.empty())
x = int(row.x); x = row.left_margin;
else if (x <= row.x) { else if (x <= row.left_margin) {
pos = row.front().left_pos(); pos = row.front().left_pos();
x = int(row.x); x = row.left_margin;
} else if (x >= row.width()) { } else if (x >= row.width()) {
pos = row.back().right_pos(); pos = row.back().right_pos();
x = row.width(); x = row.width();
} else { } else {
double w = row.x; double w = row.left_margin;
Row::const_iterator cit = row.begin(); Row::const_iterator cit = row.begin();
Row::const_iterator cend = row.end(); Row::const_iterator cend = row.end();
for ( ; cit != cend; ++cit) { for ( ; cit != cend; ++cit) {
if (w <= x && w + cit->width() > x) { if (w <= x && w + cit->full_width() > x) {
double x_offset = x - w; int x_offset = int(x - w);
pos = cit->x2pos(x_offset); pos = cit->x2pos(x_offset);
x = int(x_offset + w); x = int(x_offset + w);
break; break;
} }
w += cit->width(); w += cit->full_width();
} }
if (cit == row.end()) { if (cit == row.end()) {
pos = row.back().right_pos(); pos = row.back().right_pos();
@ -1484,10 +1469,10 @@ int TextMetrics::cursorX(CursorSlice const & sl,
if (row.empty() if (row.empty()
|| (pos == row.begin()->left_pos() || (pos == row.begin()->left_pos()
&& pos != row.begin()->right_pos())) && pos != row.begin()->right_pos()))
return int(row.x); return row.left_margin;
Row::const_iterator cit = row.begin(); Row::const_iterator cit = row.begin();
double x = row.x; double x = row.left_margin;
for ( ; cit != row.end() ; ++cit) { for ( ; cit != row.end() ; ++cit) {
/** Look whether the cursor is inside the element's /** Look whether the cursor is inside the element's
* span. Note that it is necessary to take the * span. Note that it is necessary to take the
@ -1500,7 +1485,7 @@ int TextMetrics::cursorX(CursorSlice const & sl,
x += cit->pos2x(pos); x += cit->pos2x(pos);
break; break;
} }
x += cit->width(); x += cit->full_width();
} }
return int(x); return int(x);