The branch, str-metrics, has been updated. - Log -----------------------------------------------------------------
commit df57a9a3f74e25e7a1e03bcdc08f7ebb33c1c76e Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Oct 18 11:42:26 2013 +0200 Some fixes related to RTL text * rewrite Row::reverseRTL so that it works in RTL paragraphs with mixed LTR/RTL text; * fix handling of boundary situations in Row::Elements::x2pos; * fix handling of boundary situations in TextMetrics::getColumnNearX; * make sure to always use Font::isVisibleRightToLeft instead of Font::isRightToLeft; * in cursorX, return the old pixel value when KEEP_OLD_METRICS_CODE is true; * Improve debug messages. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 18c68ca..e38d4b6 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -24,21 +24,26 @@ What is done: useless workarounds which disable kerning and ligatures. -Next steps needed: +Next steps: * check what happens with arabic and/or hebrew text. There may be some problems related to compose characters. I suspect that some code is needed in FontMetrics::width. -Next possible steps: - * Get rid of old code in cursorX and getColumnNearX; it has been kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in order to check computations. +* rename getColumnNearX to getPosNearX or x2pos (and change code + accordingly). It does not make sense to return a position relative + to the start of row, since nobody needs this. + * Re-implement row painting using row elements. This is not difficult in principle, but the code is intricate and needs some careful - analysis. + analysis. First thing that needs to be done is to break row elements + with the same criterions. Currently TextMetrics::breakRow does not + consider on-the-fly spellchecking and selection changes, but it is + not clear to me that it is required. * Profile and see how performance can be improved. @@ -56,4 +61,7 @@ Other differences (aka real bugs) * there are still difference in what breaks words. In particular, RowPainter breaks strings at: selection end, spellchecking - extremity. + extremities. + +* when clicking in the right margin, GetColumnNearX does not return + the same value as before. diff --git a/src/Row.cpp b/src/Row.cpp index d784979..d074d73 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -64,27 +64,26 @@ pos_type Row::Element::x2pos(double &x, bool const low) const FontMetrics const & fm = theFontMetrics(font); double last_w = 0; double w = 0; - size_t i = 1; + size_t i = 0; // non-STRING element only contain one position if (type != STRING) { - i = 0; w = width(); } else { // FIXME: implement dichotomy search? - for ( ; i <= str.size() ; ++i) { + for ( ; i < str.size() ; ++i) { last_w = w; - w = fm.width(str.substr(0,i)); - if (w > x2) { - --i; + w = fm.width(str.substr(0, i + 1)); + if (w > x2) break; - } } // if (i == str.size()) // lyxerr << " NOT FOUND "; } + if (i == str.size()) + x2 = w; // round to the closest side - if (!low && (x2 - last_w > w - x2)) { + else if (!low && (x2 - last_w > w - x2)) { x2 = w; ++i; } else @@ -214,6 +213,7 @@ ostream & operator<<(ostream & os, Row const & row) os << " pos: " << row.pos_ << " end: " << row.end_ << " x: " << row.x << " width: " << row.dim_.wid + << " right_margin: " << row.right_margin << " ascent: " << row.dim_.asc << " descent: " << row.dim_.des << " separator: " << row.separator @@ -382,24 +382,25 @@ void Row::shorten_if_needed(pos_type const keep, int const w) } -void Row::reverseRTL() +void Row::reverseRTL(bool const rtl_par) { pos_type i = 0; pos_type const end = elements_.size(); while (i < end) { - // skip LtR elements - while (i < end && !elements_[i].font.isRightToLeft()) - ++i; - if (i >= end) - break; - - // look for a RTL sequence + // gather a sequence of elements with the same direction + bool const rtl = elements_[i].font.isVisibleRightToLeft(); pos_type j = i; - while (j < end && elements_[j].font.isRightToLeft()) + while (j < end && elements_[j].font.isVisibleRightToLeft() == rtl) ++j; - reverse(elements_.begin() + i, elements_.begin() + j); + // if the direction is not the same as the paragraph + // direction, the sequence has to be reverted. + if (rtl != rtl_par) + reverse(elements_.begin() + i, elements_.begin() + j); i = j; } + // If the paragraph itself is RTL, reverse everything + if (rtl_par) + reverse(elements_.begin(), elements_.end()); } } // namespace lyx diff --git a/src/Row.h b/src/Row.h index 4f2bd74..0a45aa0 100644 --- a/src/Row.h +++ b/src/Row.h @@ -186,6 +186,10 @@ public: /// bool empty() const { return elements_.empty(); } /// + Element & front() { return elements_.front(); } + /// + Element const & front() const { return elements_.front(); } + /// Element & back() { return elements_.back(); } /// Element const & back() const { return elements_.back(); } @@ -212,7 +216,7 @@ public: * Find sequences of right-to-left elements and reverse them. * This should be called once the row is completely built. */ - void reverseRTL(); + void reverseRTL(bool rtl_par); friend std::ostream & operator<<(std::ostream & os, Row const & row); diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 8684625..7192d1e 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -15,7 +15,7 @@ * Full author contact details are available in file CREDITS. */ -//#define KEEP_OLD_METRICS_CODE 1 +#define KEEP_OLD_METRICS_CODE 1 #include <config.h> @@ -810,8 +810,8 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit int const width = max_width_ - right_margin; pos_type const body_pos = par.beginOfBody(); row.clear(); - row.dimension().wid = leftMargin(max_width_, pit, pos); - row.x = row.width(); + row.x = leftMargin(max_width_, pit, pos); + row.dimension().wid = row.x; row.right_margin = right_margin; if (pos >= end || row.width() > width) { @@ -929,7 +929,7 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit row.pop_back(); // make sure that the RTL elements are in reverse ordering - row.reverseRTL(); + row.reverseRTL(text_->isRTL(par)); row.dimension().wid += right_margin; } @@ -1130,11 +1130,16 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit, pos_type pos = row.pos(); boundary = false; - if (row.x >= x || row.empty()) + if (row.empty()) x = row.x; - else if (x >= row.width() - row.right_margin) { + else if (x < row.x) { + pos = row.front().font.isVisibleRightToLeft() ? + row.front().endpos : row.front().pos; + x = row.x; + } else if (x > row.width() - row.right_margin) { + pos = row.back().font.isVisibleRightToLeft() ? + row.back().pos : row.back().endpos; x = row.width() - row.right_margin; - pos = row.back().endpos; } else { double w = row.x; Row::const_iterator cit = row.begin(); @@ -1296,7 +1301,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit, if (abs(x2 - x) > 0.1 || boundary != boundary || c != pos) { - lyxerr << "getColumnNearX: new=(x=" << x - xo << ", b=" << boundary << ", p=" << pos << "), " + lyxerr << "getColumnNearX(" << x_orig << "): new=(x=" << x - xo << ", b=" << boundary << ", p=" << pos << "), " << "old=(x=" << x2 - xo << ", b=" << boundary2 << ", p=" << c << "), " << row; } @@ -1625,7 +1630,7 @@ int TextMetrics::cursorX(CursorSlice const & sl, int const boundary_corr = (boundary && pos) ? -1 : 0; if (row.empty() - || (row.begin()->font.isRightToLeft() + || (row.begin()->font.isVisibleRightToLeft() && pos == row.begin()->endpos)) return int(x); @@ -1640,12 +1645,13 @@ int TextMetrics::cursorX(CursorSlice const & sl, } if (cit == row.end() - && (row.back().font.isRightToLeft() || pos != row.back().endpos)) - lyxerr << "NOT FOUND!" - << "pos=" << pos << "(" << boundary_corr << ")" << "\n" - << row; + && (row.back().font.isVisibleRightToLeft() || pos != row.back().endpos)) + LYXERR0("cursorX(" << pos - boundary_corr + << ", " << boundary_corr << "): NOT FOUND! " << row); -#ifdef KEEP_OLD_METRICS_CODE +#ifndef KEEP_OLD_METRICS_CODE + return int(x); +#else Paragraph const & par = text_->paragraphs()[pit]; // Correct position in front of big insets @@ -1782,19 +1788,17 @@ int TextMetrics::cursorX(CursorSlice const & sl, } if (abs(x2 - x) > 0.01) { - lyxerr << "cursorX: x2=" << x2 << ", x=" << x; + lyxerr << "cursorX(" << pos - boundary_corr << ", " << boundary_corr + << "): old=" << x2 << ", new=" << x; if (cit == row.end()) - lyxerr << "Element not found for " - << pos - boundary_corr << "(" << boundary_corr << ")"; + lyxerr << "Element not found\n"; else - lyxerr << " in [" << cit->pos << "/" - << pos - boundary_corr << "(" << boundary_corr << ")" - << "/" << cit->endpos << "] of " << *cit << "\n"; + lyxerr << " found in " << *cit << "\n"; lyxerr << row <<endl; } -#endif - return int(x); + return int(x2); +#endif } ----------------------------------------------------------------------- Summary of changes: 00README_STR_METRICS_BRANCH | 18 +++++++++++---- src/Row.cpp | 37 +++++++++++++++++---------------- src/Row.h | 6 ++++- src/TextMetrics.cpp | 48 +++++++++++++++++++++++------------------- 4 files changed, 63 insertions(+), 46 deletions(-) hooks/post-receive -- Repository for new features