From e32a3e7f57fa0823a16caad64b4273c4a3c30cce Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Mon, 22 Dec 2014 10:36:53 +0100 Subject: [PATCH] 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 --- src/Row.cpp | 55 +++++++++++++++++++++------------------------ src/Row.h | 10 ++++----- src/RowPainter.cpp | 2 +- src/TextMetrics.cpp | 55 +++++++++++++++++---------------------------- 4 files changed, 52 insertions(+), 70 deletions(-) diff --git a/src/Row.cpp b/src/Row.cpp index 7052aa025c..9d94451684 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -48,9 +48,9 @@ double Row::Element::pos2x(pos_type const i) const double w = 0; //handle first the two bounds of the element if (i == endpos && !(inset && inset->lyxCode() == SEPARATOR_CODE)) - w = rtl ? 0 : width(); + w = rtl ? 0 : full_width(); else if (i == pos || type != STRING) - w = rtl ? width() : 0; + w = rtl ? full_width() : 0; else { FontMetrics const & fm = theFontMetrics(font); 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; bool const rtl = font.isVisibleRightToLeft(); @@ -69,24 +69,21 @@ pos_type Row::Element::x2pos(double &x) const switch (type) { case STRING: { FontMetrics const & fm = theFontMetrics(font); - // FIXME: is it really necessary for x to be a double? - int xx = int(x); - i = fm.x2pos(str, xx, rtl); - x = xx; + i = fm.x2pos(str, x, rtl); break; } case VIRTUAL: // those elements are actually empty (but they have a width) i = 0; - x = rtl ? width() : 0; + x = rtl ? int(full_width()) : 0; break; case SEPARATOR: case INSET: case SPACE: // those elements contain only one position. Round to // the closest side. - if (x > width()) { - x = width(); + if (x > full_width()) { + x = int(full_width()); i = !rtl; } else { 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; bool const rtl = font.isVisibleRightToLeft(); if (rtl) - w = width() - w; + w = dim.wid - w; pos_type new_pos = x2pos(w); if (new_pos == pos) return false; str = str.substr(0, new_pos - pos); if (rtl) - dim.wid -= int(w); + dim.wid -= w; else - dim.wid = int(w); + dim.wid = w; endpos = new_pos; return true; } @@ -134,7 +131,7 @@ pos_type Row::Element::right_pos() const 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), begin_margin_sel(false), end_margin_sel(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: "; break; } - os << "width=" << e.width(); + os << "width=" << e.full_width(); return os; } @@ -244,7 +241,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 + << " left_margin: " << row.left_margin << " width: " << row.dim_.wid << " right_margin: " << row.right_margin << " ascent: " << row.dim_.asc @@ -252,11 +249,11 @@ ostream & operator<<(ostream & os, Row const & row) << " separator: " << row.separator << " label_hfill: " << row.label_hfill << " row_boundary: " << row.right_boundary() << "\n"; - double x = row.x; + double x = row.left_margin; Row::Elements::const_iterator it = row.elements_.begin(); for ( ; it != row.elements_.end() ; ++it) { os << "x=" << x << " => " << *it << endl; - x += it->width(); + x += it->full_width(); } 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 end = elements_.end(); Elements::iterator last_sep = elements_.end(); - double last_width = 0; - double wid = x; + int last_width = 0; + int wid = left_margin; Elements::iterator cit = beg; for ( ; cit != end ; ++cit) { @@ -374,16 +371,16 @@ void Row::shortenIfNeeded(pos_type const keep, int const w) last_sep = cit; last_width = wid; } - if (wid + cit->width() > w) + if (wid + cit->dim.wid > w) break; - wid += cit->width(); + wid += cit->dim.wid; } if (last_sep != end) { // We have found a suitable separator. This is the // common case. end_ = last_sep->endpos; - dim_.wid = int(last_width); + dim_.wid = last_width; elements_.erase(last_sep, end); 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 // previous one. --cit; - wid -= cit->width(); + wid -= cit->dim.wid; } if (cit != beg) { // There is no separator, but several elements (probably // insets) have been added. We can cut at this place. end_ = cit->pos; - dim_.wid = int(wid); + dim_.wid = wid; elements_.erase(cit, end); 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 * other things after it. */ - if (cit->breakAt(w - x)) { + if (cit->breakAt(w - left_margin)) { 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. elements_.erase(boost::next(cit), end); } diff --git a/src/Row.h b/src/Row.h index 13a11b4870..9039ff8860 100644 --- a/src/Row.h +++ b/src/Row.h @@ -76,7 +76,7 @@ public: extra(0), font(f), change(ch), final(false) {} // 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 * \param i in the row element. */ @@ -85,11 +85,11 @@ public: * pixel position \param x. The value \param x is * 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 * 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. pos_type left_pos() const; @@ -243,8 +243,8 @@ public: double separator; /// width of hfills in the label double label_hfill; - /// the x position of the row (left margin) - double x; + /// the left margin position of the row + int left_margin; /// the right margin of the row int right_margin; /// diff --git a/src/RowPainter.cpp b/src/RowPainter.cpp index c42e82c207..ab42e675b4 100644 --- a/src/RowPainter.cpp +++ b/src/RowPainter.cpp @@ -83,7 +83,7 @@ RowPainter::RowPainter(PainterInfo & pi, 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; //row_.dump(); diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index ce31435b7f..874cb17607 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -571,9 +571,9 @@ void TextMetrics::computeRowMetrics(pit_type const pit, bool const is_rtl = text_->isRTL(par); if (is_rtl) - row.x = rightMargin(pit); + row.left_margin = rightMargin(pit); 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 Layout const & layout = par.layout(); @@ -619,16 +619,16 @@ void TextMetrics::computeRowMetrics(pit_type const pit, row.dimension().wid = width; } else if (is_rtl) { row.dimension().wid = width; - row.x += w; + row.left_margin += w; } break; } case LYX_ALIGN_RIGHT: - row.x += w; + row.left_margin += w; break; case LYX_ALIGN_CENTER: row.dimension().wid = width - int(w / 2); - row.x += w / 2; + row.left_margin += w / 2; break; case LYX_ALIGN_LEFT: 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 pos_type const endpos = row.endpos(); 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); LBUFERR(par.beginOfBody() > 0 || par.isEnvSeparator(0)); - double w = 0; + int w = 0; Row::const_iterator cit = row.begin(); Row::const_iterator const end = row.end(); // iterate over elements before main body (except the last one, // which is extra space). while (cit!= end && cit->endpos < par.beginOfBody()) { - w += cit->width(); + w += cit->dim.wid; ++cit; } @@ -703,7 +688,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const FontMetrics const & fm = 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(); row.clear(); // This make get changed in computeRowMetrics depending on RTL - row.x = leftMargin(max_width_, pit, pos); - row.dimension().wid = int(row.x); + row.left_margin = leftMargin(max_width_, pit, pos); + row.dimension().wid = row.left_margin; row.right_margin = right_margin; if (pos >= end || row.width() > width) { @@ -1117,25 +1102,25 @@ pos_type TextMetrics::getPosNearX(Row const & row, int & x, pos_type pos = row.pos(); boundary = false; if (row.empty()) - x = int(row.x); - else if (x <= row.x) { + x = row.left_margin; + else if (x <= row.left_margin) { pos = row.front().left_pos(); - x = int(row.x); + x = row.left_margin; } else if (x >= row.width()) { pos = row.back().right_pos(); x = row.width(); } else { - double w = row.x; + double w = row.left_margin; 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; + if (w <= x && w + cit->full_width() > x) { + int x_offset = int(x - w); pos = cit->x2pos(x_offset); x = int(x_offset + w); break; } - w += cit->width(); + w += cit->full_width(); } if (cit == row.end()) { pos = row.back().right_pos(); @@ -1484,10 +1469,10 @@ int TextMetrics::cursorX(CursorSlice const & sl, if (row.empty() || (pos == row.begin()->left_pos() && pos != row.begin()->right_pos())) - return int(row.x); + return row.left_margin; Row::const_iterator cit = row.begin(); - double x = row.x; + double x = row.left_margin; for ( ; cit != row.end() ; ++cit) { /** Look whether the cursor is inside the element's * span. Note that it is necessary to take the @@ -1500,7 +1485,7 @@ int TextMetrics::cursorX(CursorSlice const & sl, x += cit->pos2x(pos); break; } - x += cit->width(); + x += cit->full_width(); } return int(x); -- 2.39.5