[LyX/master] Remove duplicate call to Cursor::selHandle
commit 220fe66a67602cd43b08c4c72aee0e39726ad795 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Mar 17 10:55:49 2014 +0100 Remove duplicate call to Cursor::selHandle diff --git a/src/Text3.cpp b/src/Text3.cpp index da9f876..41e47a5 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -743,7 +743,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) if (!atFirstOrLastRow) { needsUpdate |= cur.selHandle(select); - cur.selHandle(select); cur.upDownInText(up, needsUpdate); needsUpdate |= cur.beforeDispatchCursor().inMathed(); } else {
[LyX/master] Also show boundary when displaying Cursor value.
commit a27333144dc193e71bcef17944b73492b7bbfa2c Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Mar 17 11:14:19 2014 +0100 Also show boundary when displaying Cursor value. diff --git a/src/Cursor.cpp b/src/Cursor.cpp index be32a76..89db3a6 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -1324,7 +1324,8 @@ ostream & operator<<(ostream & os, Cursor const & cur) os << "--- | " << cur.anchor_[i] << "\n"; } os << " selection: " << cur.selection_ - << " x_target: " << cur.x_target_ << endl; + << " x_target: " << cur.x_target_ + << " boundary: " << cur.boundary() << endl; return os; }
[LyX/master] Fix bug #8837: LyX hangs on selection
commit 264ea28cbd2a4c24dc6b81fa77422898167fa9f4 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Mar 17 11:15:42 2014 +0100 Fix bug #8837: LyX hangs on selection The code that checks whether the cursor was at the end of a row in Cursor::upDowninText was not able to set boundary correctly. This causes a hang in because the cursor got stuck on a line and there is an infinite loop BufferView::dispatch when trying to go down. The fix is to avoid using the watered-down TextMetrics::x2pos wrapper around getColumnNearX and use the real thing instead. Eventually, the last user of x2pos (InsetTabular) should be fixed and the method should go away. diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 89db3a6..d431965 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -2107,17 +2107,13 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded) next_row = 0; } } - top().pos() = min(tm.x2pos(pit(), next_row, xo), top().lastpos()); - int const xpos = tm.x2pos(pit(), next_row, xo); - bool const at_end_row = xpos == tm.x2pos(pit(), next_row, tm.width()); - bool const at_beg_row = xpos == tm.x2pos(pit(), next_row, 0); - - if (at_end_row && at_beg_row) - // make sure the cursor ends up on this row - boundary(false); - else - boundary(at_end_row); + Row const & real_next_row = tm.parMetrics(pit()).rows()[next_row]; + bool bound = false; + pos_type const col = tm.getColumnNearX(pit(), real_next_row, + xo, bound); + top().pos() = real_next_row.pos() + col; + boundary(bound); updateNeeded |= bv().checkDepm(*this, old); }
[LyX/2.0.x] Fix bug #8837: LyX hangs on selection
commit e72b3f8e3e259df4fc7340e186d51c95eac8b70e Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Mar 17 11:15:42 2014 +0100 Fix bug #8837: LyX hangs on selection The code that checks whether the cursor was at the end of a row in Cursor::upDowninText was not able to set boundary correctly. This causes a hang in because the cursor got stuck on a line and there is an infinite loop BufferView::dispatch when trying to go down. The fix is to avoid using the watered-down TextMetrics::x2pos wrapper around getColumnNearX and use the real thing instead. Eventually, the last user of x2pos (InsetTabular) should be fixed and the method should go away. diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 7917636..7e6c399 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -2024,17 +2024,13 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded) next_row = 0; } } - top().pos() = min(tm.x2pos(pit(), next_row, xo), top().lastpos()); - int const xpos = tm.x2pos(pit(), next_row, xo); - bool const at_end_row = xpos == tm.x2pos(pit(), next_row, tm.width()); - bool const at_beg_row = xpos == tm.x2pos(pit(), next_row, 0); - - if (at_end_row && at_beg_row) - // make sure the cursor ends up on this row - boundary(false); - else - boundary(at_end_row); + Row const & real_next_row = tm.parMetrics(pit()).rows()[next_row]; + bool bound = false; + pos_type const col = tm.getColumnNearX(pit(), real_next_row, + xo, bound); + top().pos() = real_next_row.pos() + col; + boundary(bound); updateNeeded |= bv().checkDepm(*this, old); } diff --git a/status.20x b/status.20x index c63f0f6..dd5b8de 100644 --- a/status.20x +++ b/status.20x @@ -83,12 +83,15 @@ What's new - Fix crash when navigating to next change (bug 8684). -- Fix crash when optional argument inside a math macro was deleted (bug 8329). +- Fix crash when optional argument inside a math macro was deleted + (bug 8329). + +- Fix hang when selecting text (bug 8837). - Fix math-ams-matrix function that could corrupt documents if not used properly (part of bug 8359). -- Fix problem that led to assertion in some cases when space was at beginning of +- Fix problem that led to assertion in some cases when space was at beginning of line (bugs 8838 and 8947). - Correctly compare documents with different author sets (bug 8769).
[LyX features/str-metrics] Fix bug #9040: In RtL documents end-of-paragraph marker shifts the row display
The branch, str-metrics, has been updated. - Log - commit 82c77f14dbf637e793f38a62c020b024e2eece44 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Thu Mar 20 11:00:14 2014 +0100 Fix bug #9040: In RtL documents end-of-paragraph marker shifts the row display The fact that the bug was still present in the features/str-metrics branch comes from a goof in the initial implementation of 'virtual' row elements (completion and end-of-par markers). Now that this is corrected, everything works as it should. The fact that the bug is present in master is due to some other reason that is not useful to investigate now. diff --git a/src/Row.cpp b/src/Row.cpp index 15af2c2..6e60e97 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -282,7 +282,6 @@ void Row::add(pos_type const pos, char_type const c, Element e(STRING, pos, f, ch); elements_.push_back(e); } - //lyxerr << "FONT " <<back().font.language() << endl; back().str += c; back().endpos = pos + 1; } @@ -294,7 +293,8 @@ void Row::addVirtual(pos_type const pos, docstring const & s, finalizeLast(); Element e(VIRTUAL, pos, f, ch); e.str = s; - // A completion has no size + e.dim.wid = theFontMetrics(f).width(s); + dim_.wid += e.dim.wid; e.endpos = pos; elements_.push_back(e); finalizeLast(); --- Summary of changes: src/Row.cpp |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- Repository for new features
[LyX/2.2-staging] Do not store Languages objects in completion words lists
commit 8ac5f09c1783261018a107b54ce398733b8f97a4 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Mar 21 12:24:47 2014 +0100 Do not store Languages objects in completion words lists In the current code each paragraph contains a map<Language, WordList*>, which means that it contains a full copy of the language object. Since these objects contain translation tables nowadays, this is a very bad idea. This patch simply replaces the Language key by a string. When loading the Userguide on linux/x86_64, the total memory consumption decreases from 36.27MB to 31.50MB. diff --git a/src/LyX.cpp b/src/LyX.cpp index 41c69f7..b784831 100644 --- a/src/LyX.cpp +++ b/src/LyX.cpp @@ -33,6 +33,7 @@ #include "FuncStatus.h" #include "HunspellChecker.h" #include "KeyMap.h" +#include "Language.h" #include "LaTeXFonts.h" #include "LayoutFile.h" #include "Lexer.h" diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index ffcb5f2..4d9b37c 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -499,7 +499,7 @@ public: TextContainer text_; typedef set Words; - typedef map<Language, Words> LangWordsMap; + typedef map<string, Words> LangWordsMap; /// LangWordsMap words_; /// @@ -3867,7 +3867,7 @@ void Paragraph::collectWords() if (cit == d->fontlist_.end()) return; Language const * lang = cit->font().language(); - d->words_[*lang].insert(word); + d->words_[lang->lang()].insert(word); } } } diff --git a/src/Text.cpp b/src/Text.cpp index c4cac88..cdcc200 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -2120,7 +2120,7 @@ bool Text::completionSupported(Cursor const & cur) const CompletionList const * Text::createCompletionList(Cursor const & cur) const { - WordList const * list = theWordList(*cur.getFont().language()); + WordList const * list = theWordList(cur.getFont().language()->lang()); return new TextCompletionList(cur, list); } diff --git a/src/WordList.cpp b/src/WordList.cpp index 762e1b9..3a095af 100644 --- a/src/WordList.cpp +++ b/src/WordList.cpp @@ -12,14 +12,11 @@ #include "WordList.h" -#include "Language.h" - #include "support/convert.h" #include "support/debug.h" #include "support/docstring.h" -#include "support/weighted_btree.h" - #include "support/lassert.h" +#include "support/weighted_btree.h" #include @@ -28,12 +25,13 @@ using namespace std; namespace lyx { /// -map<Language, WordList *> theGlobalWordList; +typedef map<string, WordList *> GlobalWordList; +GlobalWordList theGlobalWordList; -WordList * theWordList(Language const & lang) +WordList * theWordList(string const & lang) { - map<Language, WordList *>::iterator it = theGlobalWordList.find(lang); + GlobalWordList::iterator it = theGlobalWordList.find(lang); if (it != theGlobalWordList.end()) return it->second; else @@ -44,7 +42,7 @@ WordList * theWordList(Language const & lang) void WordList::cleanupWordLists() { - map<Language, WordList *>::const_iterator it = theGlobalWordList.begin(); + GlobalWordList::const_iterator it = theGlobalWordList.begin(); for (; it != theGlobalWordList.end(); ++it) delete it->second; theGlobalWordList.clear(); diff --git a/src/WordList.h b/src/WordList.h index b7f88fb..f57f20b 100644 --- a/src/WordList.h +++ b/src/WordList.h @@ -14,8 +14,6 @@ #include "support/docstring.h" -#include "Language.h" - namespace lyx { class WordList { @@ -41,7 +39,7 @@ private: Impl * d; }; -WordList * theWordList(Language const & lang); +WordList * theWordList(std::string const & lang); } // namespace lyx
[LyX/2.1.1-staging] Do not store Languages objects in completion words lists
commit 531e46f2b863395368d4765ece07ba5bfb93a340 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Mar 21 12:24:47 2014 +0100 Do not store Languages objects in completion words lists In the current code each paragraph contains a map<Language, WordList*>, which means that it contains a full copy of the language object. Since these objects contain translation tables nowadays, this is a very bad idea. This patch simply replaces the Language key by a string. When loading the Userguide on linux/x86_64, the total memory consumption decreases from 36.27MB to 31.50MB. diff --git a/src/LyX.cpp b/src/LyX.cpp index 41c69f7..b784831 100644 --- a/src/LyX.cpp +++ b/src/LyX.cpp @@ -33,6 +33,7 @@ #include "FuncStatus.h" #include "HunspellChecker.h" #include "KeyMap.h" +#include "Language.h" #include "LaTeXFonts.h" #include "LayoutFile.h" #include "Lexer.h" diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index ffcb5f2..4d9b37c 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -499,7 +499,7 @@ public: TextContainer text_; typedef set Words; - typedef map<Language, Words> LangWordsMap; + typedef map<string, Words> LangWordsMap; /// LangWordsMap words_; /// @@ -3867,7 +3867,7 @@ void Paragraph::collectWords() if (cit == d->fontlist_.end()) return; Language const * lang = cit->font().language(); - d->words_[*lang].insert(word); + d->words_[lang->lang()].insert(word); } } } diff --git a/src/Text.cpp b/src/Text.cpp index c4cac88..cdcc200 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -2120,7 +2120,7 @@ bool Text::completionSupported(Cursor const & cur) const CompletionList const * Text::createCompletionList(Cursor const & cur) const { - WordList const * list = theWordList(*cur.getFont().language()); + WordList const * list = theWordList(cur.getFont().language()->lang()); return new TextCompletionList(cur, list); } diff --git a/src/WordList.cpp b/src/WordList.cpp index 762e1b9..3a095af 100644 --- a/src/WordList.cpp +++ b/src/WordList.cpp @@ -12,14 +12,11 @@ #include "WordList.h" -#include "Language.h" - #include "support/convert.h" #include "support/debug.h" #include "support/docstring.h" -#include "support/weighted_btree.h" - #include "support/lassert.h" +#include "support/weighted_btree.h" #include @@ -28,12 +25,13 @@ using namespace std; namespace lyx { /// -map<Language, WordList *> theGlobalWordList; +typedef map<string, WordList *> GlobalWordList; +GlobalWordList theGlobalWordList; -WordList * theWordList(Language const & lang) +WordList * theWordList(string const & lang) { - map<Language, WordList *>::iterator it = theGlobalWordList.find(lang); + GlobalWordList::iterator it = theGlobalWordList.find(lang); if (it != theGlobalWordList.end()) return it->second; else @@ -44,7 +42,7 @@ WordList * theWordList(Language const & lang) void WordList::cleanupWordLists() { - map<Language, WordList *>::const_iterator it = theGlobalWordList.begin(); + GlobalWordList::const_iterator it = theGlobalWordList.begin(); for (; it != theGlobalWordList.end(); ++it) delete it->second; theGlobalWordList.clear(); diff --git a/src/WordList.h b/src/WordList.h index b7f88fb..f57f20b 100644 --- a/src/WordList.h +++ b/src/WordList.h @@ -14,8 +14,6 @@ #include "support/docstring.h" -#include "Language.h" - namespace lyx { class WordList { @@ -41,7 +39,7 @@ private: Impl * d; }; -WordList * theWordList(Language const & lang); +WordList * theWordList(std::string const & lang); } // namespace lyx diff --git a/status.21x b/status.21x index 4c647a9..1394ef4 100644 --- a/status.21x +++ b/status.21x @@ -83,6 +83,7 @@ What's new - Fix a problem when PATH changes and python command is relative (bug 8950). +- Reduce memory use with large documents. * DOCUMENTATION AND LOCALIZATION
[LyX/2.2-staging] Fix oversight in autotools packaging selection
commit 8ce47ecdc85e89b1ee29524099140eff47a68120 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Thu Mar 27 13:51:25 2014 +0100 Fix oversight in autotools packaging selection The only consequence of this thinko is that the lyx.desktop and the svg icons were installed on Mac OS and Windows platform, whereas they are useless. diff --git a/config/lyxinclude.m4 b/config/lyxinclude.m4 index d1b78f9..61ea48d 100644 --- a/config/lyxinclude.m4 +++ b/config/lyxinclude.m4 @@ -463,6 +463,7 @@ AC_ARG_WITH(packaging, *) lyx_use_packaging=posix;; esac]) AC_MSG_RESULT($lyx_use_packaging) +lyx_install_posix=false lyx_install_macosx=false lyx_install_cygwin=false lyx_install_windows=false
[LyX features/str-metrics] Fix various selection-related problems
The branch, str-metrics, has been updated. - Log - commit 14f8a24b4aeeb4671a3117fb79ba56343a022f0e Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Mar 21 11:56:42 2014 +0100 Fix various selection-related problems All these problems are related to what happens at the extreme points of rows * since VIRTUAL elements have a width but no contents, they have to be treated specially at some places. It would have been better to avoid testing for them explicitly, but I did not find a way. * Improve and cleanup the code in breakRow and fix in passing a crash when clicking on the right of an incomplete MARGIN_MANUAL paragraph. * improve the computation of row width in TextMetrics::computeRowMetrics. * handle properly the case where a position if not found on the row in both cursorX and getPosNearX (actually, this happens when selecting). * Some code cleanup and comments. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 1bb7026..82026e8 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -44,18 +44,16 @@ What is done: 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. + problems related to compose characters. Investigate whether RtL + strings could be drawn on a string-wise basis. -* investigate whether RtL strings could be drawn on a string-wise basis. - -* investigate whether Row::SEPARATOR elements could be used only in - justified text. This would speed-up painting in other cases by - lowering the number of strings to draw. +* investigate whether strings could be cut at separators in RowPainter + only in justified text. This would speed-up painting in other cases + by lowering the number of strings to draw. * get lots of testing. -* Get rid of old code in cursorX and getColumnNearX; it has been +* Get rid of old code in cursorX and getPosNearX; it has been kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in order to check computations. @@ -67,33 +65,38 @@ Steps for later (aka out of the scope of this branch): * Re-implement row painting using row elements. This is not difficult in principle, but the code is intricate and needs some careful analysis. The first thing that needs to be done is to break row - elements with the same criteria. Currently TextMetrics::breakRow - does not consider on-the-fly spell-checking and selection changes, - but it is not clear to me that it is required. Moreover, this thing - would only work if we are sure that the Row object is up-to-date - when drawing happens. This depends on the update machinery. + elements with the same criteria. Currently breakRow does not + consider on-the-fly spell-checking and selection changes, but it is + not clear to me that it is required. Moreover, this thing would only + work if we are sure that the Row object is up-to-date when drawing + happens. This depends on the update machinery. This would allow to get rid of the Bidi code. Known bugs: -* in RtL paragraphs, the end-of-paragraph marker moves the row to the - right (ticket #9040, already present in master). - * there are still difference in what breaks words. In particular, RowPainter breaks strings at: selection end, spell-checking extremities. This seems to be harmless. -* when clicking in the right margin, GetColumnNearX does not return +* when clicking in the right margin, getPosNearX does not return the same value as before. I am not sure whether this is important. +* When selecting text, the display seems to move around. This is + because partly selected words are drawn in two parts, and in case + like "ef|fort" or "V|AN", there are some ligature or kerning effects + that change the display. I am not sure yet how to fix that. + Other differences in behavior (aka bug fixes): * end of paragraph markers metrics are computed with the font of the actual text, not default font. +* in RtL paragraphs, the end-of-paragraph marker does not move the row + to the right anymore (ticket #9040). + * When cursor is after a LtR separator just before a RtL chunk, the cursor position is computed better with the new code. diff --git a/src/Row.cpp b/src/Row.cpp index 6e60e97..48b4fff 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -63,18 +63,19 @@ double Row::Element::pos2x(pos_type const i) const pos_type Row::Element::x2pos(double , bool const low) const { //lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this; - // if element is rtl, flip x value + // If element is rtl, flip x value bool const rtl = font.isVi
Re: [LyX/master] Update INSTALL
Le 10/04/14 22:37, Vincent van Ravesteijn a écrit : * Other things to note -If you make modifications to files in src/ (for example by applying a -patch), you will need to have the GNU gettext package installed, due -to some dependencies in the makefiles. You can get the latest version -from: - ftp://ftp.gnu.org/gnu/gettext/ Are you sure? I think I left this part because of the gettext tools that create the .gmo files. I agree though that the description as it was is not really useful. JMarc
[LyX features/str-metrics] Draw right-to-left text string-wise using Qt
The branch, str-metrics, has been updated. - Log - commit b792eff2d6bd70f877ea217bccfd60893e7bd3ad Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Thu Apr 10 16:37:21 2014 +0200 Draw right-to-left text string-wise using Qt We rely on Qt built-in unicode support for handling Arabic and Hebrew compose characters. This allows to avoid to use our homegrown machinery. This should provide a nice speedup at a low cost and will eventually allow us to get rid of: * most of our Arabic/Hebrew machinery in Encodings.cpp, * Paragraph::transformChar, * and probably more. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 82026e8..359bb03 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -11,7 +11,7 @@ what we have with force_paint_single_char. Moreover there has been some code factorization in TextMetrics, where the same row-breaking algorithm was basically implemented 3 times. -Currently everything is supposed to work for LTR text, and RTL text +Currently everything is supposed to work for LTR text, and RtL text should work too except possibly metrics with Arabic and Hebrew fonts. When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code @@ -40,12 +40,13 @@ What is done: lyxrc.force_paint_single_char is false. In this case, remove also useless workarounds which disable kerning and ligatures. +* when lyxrc.force_paint_single_char is false, draw also RtL text + string-wise. This both speed-up drawing and prepare for code + removal, since we now rely on Qt to do things we use to do by + ourselves (see isArabic* and isHebrew* code in Encodings.cpp). -Next steps: -* check what happens with Arabic and/or Hebrew text. There may be some - problems related to compose characters. Investigate whether RtL - strings could be drawn on a string-wise basis. +Next steps: * investigate whether strings could be cut at separators in RowPainter only in justified text. This would speed-up painting in other cases @@ -76,18 +77,18 @@ Steps for later (aka out of the scope of this branch): Known bugs: -* there are still difference in what breaks words. In particular, - RowPainter breaks strings at: selection end, spell-checking - extremities. This seems to be harmless. - -* when clicking in the right margin, getPosNearX does not return - the same value as before. I am not sure whether this is important. - * When selecting text, the display seems to move around. This is because partly selected words are drawn in two parts, and in case like "ef|fort" or "V|AN", there are some ligature or kerning effects that change the display. I am not sure yet how to fix that. +* there are other differences in what breaks words. In particular, + RowPainter breaks strings at spell-checking extremities. This seems + to be harmless. + +* when clicking in the right margin, getPosNearX does not return + the same value as before. I am not sure whether this is important. + Other differences in behavior (aka bug fixes): diff --git a/src/Encoding.cpp b/src/Encoding.cpp index a231106..7167d7b 100644 --- a/src/Encoding.cpp +++ b/src/Encoding.cpp @@ -704,6 +704,12 @@ docstring Encodings::fromLaTeXCommand(docstring const & cmd, int cmdtype, } +bool Encodings::isHebrewChar(char_type c) +{ + return c >= 0x0590 && c <= 0x05ff; +} + + bool Encodings::isHebrewComposeChar(char_type c) { return c <= 0x05c2 && c >= 0x05b0 && c != 0x05be && c != 0x05c0; diff --git a/src/Encoding.h b/src/Encoding.h index 5f788f9..171b4f1 100644 --- a/src/Encoding.h +++ b/src/Encoding.h @@ -269,6 +269,8 @@ public: /// static bool isHebrewComposeChar(char_type c); /// + static bool isHebrewChar(char_type c); + /// static bool isArabicComposeChar(char_type c); /// static bool isArabicSpecialChar(char_type c); diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp index 5b69701..ea0f946 100644 --- a/src/rowpainter.cpp +++ b/src/rowpainter.cpp @@ -161,72 +161,7 @@ void RowPainter::paintInset(Inset const * inset, pos_type const pos) } -void RowPainter::paintHebrewComposeChar(pos_type & vpos, FontInfo const & font) -{ - pos_type pos = bidi_.vis2log(vpos); - - docstring str; - - // first char - char_type c = par_.getChar(pos); - str += c; - ++vpos; - - int const width = theFontMetrics(font).width(c); - int dx = 0; - - for (pos_type i = pos - 1; i >= 0; --i) { - c = par_.getChar(i); - if (!Encodings::isHebrewComposeChar(c)) { - if (isPrintableNonspace(c)) { - int const width2 = pm_.singleWidth(i, - text_metrics
[LyX/master] Respect group integrity when removing stuff from the Undo stack.
commit 4356f2254af1a0ea5e4215e29881296452b1e8d9 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Apr 7 16:46:47 2014 +0200 Respect group integrity when removing stuff from the Undo stack. Fixes: #9079 diff --git a/src/Undo.cpp b/src/Undo.cpp index a335873..31eaec3 100644 --- a/src/Undo.cpp +++ b/src/Undo.cpp @@ -160,13 +160,17 @@ public: /// Push an item on to the stack, deleting the bottom group on /// overflow. void push(UndoElement const & v) { - c_.push_front(v); - if (c_.size() > limit_) { + // Remove some entries if the limit has been reached. + // However, if the only group on the stack is the one + // we are currently populating, do nothing. + if (c_.size() >= limit_ + && c_.front().group_id != v.group_id) { // remove a whole group at once. const size_t gid = c_.back().group_id; while (!c_.empty() && c_.back().group_id == gid) c_.pop_back(); } + c_.push_front(v); } /// Mark all the elements of the stack as dirty
[LyX/2.2-staging] Use subdir-objects for automake 1.14 or newer
commit 330b4fbf5caddba022b1d86676c839ba31ecaa8e Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sun Apr 20 20:20:25 2014 +0200 Use subdir-objects for automake 1.14 or newer This option is going to be mandatory starting with automake 2.0. LyX is able to use this since version 2.1, but it turns out that it is badly implemented in versions of automake older than 1.14. We rely on some (undocumented) symbol to detect automake 1.14 and use the subdirs-objects option in this case. For more details, see: https://www.mail-archive.com/lyx-devel@lists.lyx.org/msg181023.html Making everything work with autotools required making a copy of two files from support/tests. It seems that we should not point to source files that are handled by another Makefile.am. diff --git a/configure.ac b/configure.ac index 1fe6d9d..1dcb8fd 100644 --- a/configure.ac +++ b/configure.ac @@ -27,7 +27,11 @@ fi AM_MAINTAINER_MODE save_PACKAGE=$PACKAGE -AM_INIT_AUTOMAKE([foreign dist-bzip2 no-define 1.8]) +dnl The test for _AM_PROG_CC_C_O intends to test for automake 1.14 or newer, +dnl which are the versions where subdir-objects can beused. +dnl see: https://www.mail-archive.com/lyx-devel@lists.lyx.org/msg181023.html +m4_define([LYX_OBJECTS_LAYOUT], m4_ifdef([_AM_PROG_CC_C_O],[subdir-objects],)) +AM_INIT_AUTOMAKE([foreign dist-bzip2 no-define 1.8] LYX_OBJECTS_LAYOUT) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) PACKAGE=$save_PACKAGE diff --git a/src/Makefile.am b/src/Makefile.am index ea5ca42..2a98643 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -708,7 +708,7 @@ check_layout_SOURCES = \ Spacing.cpp \ TextClass.cpp \ tests/check_layout.cpp \ - support/tests/boost.cpp \ - support/tests/dummy_functions.cpp + tests/boost.cpp \ + tests/dummy_functions.cpp .PHONY: alltests alltests-recursive updatetests diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 2a8b39e..ce5b355 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -8,7 +8,7 @@ set(check_layout_SOURCES) foreach(_f insets/InsetLayout.cpp Color.cpp Counters.cpp Floating.cpp FloatList.cpp FontInfo.cpp Layout.cpp LayoutFile.cpp Lexer.cpp ModuleList.cpp Spacing.cpp TextClass.cpp tests/check_layout.cpp - support/tests/boost.cpp support/tests/dummy_functions.cpp) + tests/boost.cpp tests/dummy_functions.cpp) list(APPEND check_layout_SOURCES "${TOP_SRC_DIR}/src/${_f}") endforeach() diff --git a/src/tests/boost.cpp b/src/tests/boost.cpp new file mode 100644 index 000..426263b --- /dev/null +++ b/src/tests/boost.cpp @@ -0,0 +1,36 @@ +/** + * \file boost.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Lars Gullik Bjønnes + * + * Full author contact details are available in file CREDITS. + */ + +#include + +#include "support/lassert.h" + +#include +#include + +using namespace std; + +namespace boost { + +#ifndef BOOST_NO_EXCEPTIONS +void throw_exception(exception const & /*e*/) +{ + LASSERT(false, /**/); +} +#endif + + +void assertion_failed(char const * /*expr*/, char const * /*function*/, + char const * /*file*/, long /*line*/) +{ + ::abort(); +} + +} // namespace boost diff --git a/src/tests/dummy_functions.cpp b/src/tests/dummy_functions.cpp new file mode 100644 index 000..5a99081 --- /dev/null +++ b/src/tests/dummy_functions.cpp @@ -0,0 +1,38 @@ +#include + +#include "../Messages.h" + +using namespace std; + +namespace lyx { + // Dummy LyXRC support + class LyXRC { string icon_set; } lyxrc; + + // Dummy LyXAlignment support + enum LyXAlignment { + DUMMY + }; + + // Keep the linker happy on Windows + void lyx_exit(int) {} + + // Dummy language support + Messages const & getGuiMessages() + { + static Messages lyx_messages; + + return lyx_messages; + } + Messages const & getMessages(string const &) + { + static Messages lyx_messages; + + return lyx_messages; + } + + string alignmentToCSS(LyXAlignment) + { + return string(); + } + +}
[LyX/2.1.x] Respect group integrity when removing stuff from the Undo stack.
commit 6bce9abfee581c5ca03670a5b7f8e50dd911d83e Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Apr 7 16:46:47 2014 +0200 Respect group integrity when removing stuff from the Undo stack. Fixes: #9079 diff --git a/src/Undo.cpp b/src/Undo.cpp index a335873..31eaec3 100644 --- a/src/Undo.cpp +++ b/src/Undo.cpp @@ -160,13 +160,17 @@ public: /// Push an item on to the stack, deleting the bottom group on /// overflow. void push(UndoElement const & v) { - c_.push_front(v); - if (c_.size() > limit_) { + // Remove some entries if the limit has been reached. + // However, if the only group on the stack is the one + // we are currently populating, do nothing. + if (c_.size() >= limit_ + && c_.front().group_id != v.group_id) { // remove a whole group at once. const size_t gid = c_.back().group_id; while (!c_.empty() && c_.back().group_id == gid) c_.pop_back(); } + c_.push_front(v); } /// Mark all the elements of the stack as dirty diff --git a/status.21x b/status.21x index add6a75..8e794d3 100644 --- a/status.21x +++ b/status.21x @@ -80,6 +80,8 @@ What's new - Fix select-by-doubleclick in mathed (bug 8829). +- Fix undo with many individual changes (e.g. with replace all) + (bug #7079). * INTERNALS
[LyX features/str-metrics] Speed-up drawing when text is not justified.
The branch, str-metrics, has been updated. - Log - commit 37494dfbccb8c0d9a66cedd059efc39903c44385 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri May 2 15:03:20 2014 +0200 Speed-up drawing when text is not justified. Do not cut strings at separators in RowPainter when text is not justified. This speeds-up painting by reducing the number of strings to draw. Do also a modest cleanup of paintChar (remove dubious optimization). diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index e7a6f29..73f5ed3 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -40,16 +40,16 @@ What is done: useless workarounds which disable kerning and ligatures. * when lyxrc.force_paint_single_char is false, draw also RtL text - string-wise. This both speed-up drawing and prepare for code + string-wise. This both speeds-up drawing and prepares for code removal, since we now rely on Qt to do things we use to do by ourselves (see isArabic* and isHebrew* code in Encodings.cpp). +* Do not cut strings at separators in RowPainter when text is not + justified. This speeds-up painting by reducing the number of strings + to draw. -Next steps: -* investigate whether strings could be cut at separators in RowPainter - only in justified text. This would speed-up painting in other cases - by lowering the number of strings to draw. +Next steps: * get lots of testing. diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp index b0708bf..8286ec7 100644 --- a/src/rowpainter.cpp +++ b/src/rowpainter.cpp @@ -165,10 +165,9 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) // This method takes up 70% of time when typing pos_type pos = bidi_.vis2log(vpos); // first character - char_type prev_char = par_.getChar(pos); - vector str; + char_type c = par_.getChar(pos); + docstring str; str.reserve(100); - str.push_back(prev_char); // special case for arabic string const & lang = font.language()->lang(); @@ -179,13 +178,12 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) // FIXME: Why only round brackets and why the difference to // Hebrew? See also Paragraph::getUChar if (swap_paren) { - char_type c = str[0]; if (c == '(') c = ')'; else if (c == ')') c = '('; - str[0] = c; } + str.push_back(c); pos_type const end = row_.endpos(); FontSpan const font_span = par_.fontSpan(pos); @@ -230,7 +228,8 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) if (c == '\t') break; - if (!isPrintableNonspace(c)) + if (!isPrintableNonspace(c) + && (c != ' ' || row_.separator > 0)) break; // FIXME: Why only round brackets and why the difference to @@ -243,13 +242,10 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) } str.push_back(c); - prev_char = c; } - docstring s([0], str.size()); - - if (s[0] == '\t') - s.replace(0,1,from_ascii("")); + if (str[0] == '\t') + str.replace(0,1,from_ascii("")); /* Because we do our own bidi, at this point the strings are * already in visual order. However, Qt also applies its own @@ -267,13 +263,13 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) // Pop directional formatting: return to previous state char_type const PDF = 0x202C; if (font.isVisibleRightToLeft()) { - reverse(s.begin(), s.end()); - s = RLO + s + PDF; + reverse(str.begin(), str.end()); + str = RLO + str + PDF; } else - s = LRO + s + PDF; + str = LRO + str + PDF; if (!selection && !change_running.changed()) { - x_ += pi_.pain.text(int(x_), yo_, s, font.fontInfo()); + x_ += pi_.pain.text(int(x_), yo_, str, font.fontInfo()); return; } @@ -283,7 +279,7 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) else if (selection) copy.setPaintColor(Color_selectiontext); - x_ += pi_.pain.text(int(x_), yo_, s, copy); + x_ += pi_.pain.text(int(x_), yo_, str, copy); } --- Summary of changes: 00README_STR_METRICS_BRANCH | 10 +- src/rowpainter.cpp | 28 2 files changed, 17 insertions(+), 21 deletions(-) hooks/post-receive -- Repository for new features
[LyX/master] Cleanup the code for boost configuration
commit 3cbd343a55780dc646833bc3a1d3373909e950ca Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Apr 21 16:10:49 2014 +0200 Cleanup the code for boost configuration diff --git a/config/common.am b/config/common.am index 6f7e310..cabc35a 100644 --- a/config/common.am +++ b/config/common.am @@ -28,14 +28,4 @@ endif SUFFIXES = .gch -if USE_INCLUDED_BOOST -BOOST_INCLUDES = -I$(top_srcdir)/boost -BOOST_LIBS = $(top_builddir)/boost/liblyxboost.a -else -BOOST_INCLUDES = -BOOST_REGEX = -lboost_regex$(BOOST_MT) -BOOST_SIGNALS = -lboost_signals$(BOOST_MT) -BOOST_LIBS = $(BOOST_REGEX) $(BOOST_SIGNALS) -endif - LIBS = diff --git a/config/lyxinclude.m4 b/config/lyxinclude.m4 index 61ea48d..ac0b642 100644 --- a/config/lyxinclude.m4 +++ b/config/lyxinclude.m4 @@ -311,28 +311,39 @@ AC_DEFUN([LYX_USE_INCLUDED_BOOST],[ [lyx_cv_with_included_boost=yes]) AM_CONDITIONAL(USE_INCLUDED_BOOST, test x$lyx_cv_with_included_boost = xyes) AC_MSG_RESULT([$lyx_cv_with_included_boost]) - if test x$lyx_cv_with_included_boost != xyes ; then - AC_LANG_PUSH(C++) - save_LIBS=$LIBS - - LIBS="$save_LIBS -lboost_signals -lm" - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [boost::signal s;])], [lyx_boost_plain=yes], []) - LIBS="$save_LIBS -lboost_signals-mt -lm $LIBTHREAD" - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [boost::signal s;])], [lyx_boost_mt=yes], []) - - LIBS=$save_LIBS - AC_LANG_POP(C++) - - if test x$lyx_boost_mt = xyes ; then - BOOST_MT="-mt" - else - BOOST_MT="" - if test x$lyx_boost_plain != xyes ; then - AC_MSG_ERROR([cannot find suitable boost library (do not use --without-included-boost)]) - fi - fi - AC_SUBST(BOOST_MT) + if test x$lyx_cv_with_included_boost = xyes ; then + BOOST_INCLUDES='-I$(top_srcdir)/boost' + BOOST_LIBS='$(top_builddir)/boost/liblyxboost.a' + else + AC_LANG_PUSH(C++) + save_LIBS=$LIBS + + AC_MSG_CHECKING([for multithreaded boost libraries]) + LIBS="$save_LIBS -lboost_signals-mt -lm $LIBTHREAD" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([#include ], + [boost::signal s;])], + [AC_MSG_RESULT([yes]) +BOOST_MT="-mt"], + [AC_MSG_RESULT([no]) +AC_MSG_CHECKING([for plain boost libraries]) +LIBS="$save_LIBS -lboost_signals -lm" +AC_LINK_IFELSE( +[AC_LANG_PROGRAM([#include ], +[boost::signal s;])], +[AC_MSG_RESULT([yes]) + BOOST_MT=""], +[AC_MSG_RESULT([no]) + AC_MSG_ERROR([cannot find suitable boost library (do not use --without-included-boost)]) +]) + ]) + LIBS=$save_LIBS + AC_LANG_POP(C++) + BOOST_INCLUDES= + BOOST_LIBS="-lboost_regex${BOOST_MT} -lboost_signals${BOOST_MT}" fi + AC_SUBST(BOOST_INCLUDES) + AC_SUBST(BOOST_LIBS) ])
[LyX/master] Turn an error message into a Debug::LOCALE warning
commit ac9a2fa9f8eea4afc9d5afee48328b900838aa34 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue May 6 14:29:42 2014 +0200 Turn an error message into a Debug::LOCALE warning diff --git a/src/support/Messages.cpp b/src/support/Messages.cpp index ef6bb2d..fd5d228 100644 --- a/src/support/Messages.cpp +++ b/src/support/Messages.cpp @@ -250,7 +250,7 @@ bool Messages::readMoFile() string const code = realCode(lang_); if (code.empty()) { - LYXERR0("Cannot find translation for language " << lang_); + LYXERR(Debug::LOCALE, "Cannot find translation for language " << lang_); return false; }
[LyX/2.1.x] Turn an error message into a Debug::LOCALE warning
commit bd206ff5f5b2902ef87baa27c359f7a1b58f418d Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue May 6 14:29:42 2014 +0200 Turn an error message into a Debug::LOCALE warning diff --git a/src/support/Messages.cpp b/src/support/Messages.cpp index ef6bb2d..fd5d228 100644 --- a/src/support/Messages.cpp +++ b/src/support/Messages.cpp @@ -250,7 +250,7 @@ bool Messages::readMoFile() string const code = realCode(lang_); if (code.empty()) { - LYXERR0("Cannot find translation for language " << lang_); + LYXERR(Debug::LOCALE, "Cannot find translation for language " << lang_); return false; } diff --git a/status.21x b/status.21x index 7a6b793..87cac02 100644 --- a/status.21x +++ b/status.21x @@ -117,6 +117,9 @@ What's new - Fix a problem when PATH changes and python command is relative (bug 8950). - Reduce memory use with large documents. + +- Disable a console message when loading a document in a language for + which the UI is not translated. * DOCUMENTATION AND LOCALIZATION
[LyX/master] Rely on Qt to handle small caps text
commit 015333d987ae029aa1a6d3bcab3e96d70658a256 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed May 7 12:06:56 2014 +0200 Rely on Qt to handle small caps text This has the advantage of simplifying our code and to produce the correct output: the small capitals should have the exact same width as the lower case letters. The slanted fonts are also translated to oblique on Qt side, but this does not seems to have an effect in my testing. It may be that proper oblique fonts need to be installed. diff --git a/src/frontends/qt4/GuiFontLoader.cpp b/src/frontends/qt4/GuiFontLoader.cpp index 9fd2060..3d0f2b0 100644 --- a/src/frontends/qt4/GuiFontLoader.cpp +++ b/src/frontends/qt4/GuiFontLoader.cpp @@ -304,8 +304,13 @@ GuiFontInfo::GuiFontInfo(FontInfo const & f) switch (f.realShape()) { case ITALIC_SHAPE: + font.setStyle(QFont::StyleItalic); + break; case SLANTED_SHAPE: - font.setItalic(true); + font.setStyle(QFont::StyleOblique); + break; + case SMALLCAPS_SHAPE: + font.setCapitalization(QFont::SmallCaps); break; default: break; @@ -327,19 +332,7 @@ GuiFontInfo::GuiFontInfo(FontInfo const & f) LYXERR(Debug::FONT, "The font has size: " << font.pointSizeF()); - if (f.realShape() != SMALLCAPS_SHAPE) { - metrics = GuiFontMetrics(font); - } else { - // handle small caps ourselves ... - FontInfo smallfont = f; - smallfont.decSize().decSize().setShape(UP_SHAPE); - QFont font2(font); - font2.setKerning(false); - font2.setPointSizeF(convert(lyxrc.font_sizes[smallfont.size()]) - * lyxrc.zoom / 100.0); - - metrics = GuiFontMetrics(font, font2); - } + metrics = GuiFontMetrics(font); } diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp index 9304465..e007b4a 100644 --- a/src/frontends/qt4/GuiFontMetrics.cpp +++ b/src/frontends/qt4/GuiFontMetrics.cpp @@ -40,7 +40,7 @@ namespace { * these are not real ucs4 characters. These are codepoints in the * computer modern fonts used, nothing unicode related. * See comment in QLPainter::text() for more explanation. - **/ + **/ inline QChar const ucs4_to_qchar(char_type const ucs4) { LATTEST(is_utf16(ucs4)); @@ -49,14 +49,7 @@ inline QChar const ucs4_to_qchar(char_type const ucs4) } // anon namespace -GuiFontMetrics::GuiFontMetrics(QFont const & font) -: metrics_(font, 0), smallcaps_metrics_(font), smallcaps_shape_(false) -{ -} - - -GuiFontMetrics::GuiFontMetrics(QFont const & font, QFont const & smallcaps_font) -: metrics_(font, 0), smallcaps_metrics_(smallcaps_font), smallcaps_shape_(true) +GuiFontMetrics::GuiFontMetrics(QFont const & font) : metrics_(font, 0) { } @@ -115,27 +108,6 @@ int GuiFontMetrics::rbearing(char_type c) const } -int GuiFontMetrics::smallcapsWidth(char_type c) const -{ - // FIXME: Optimisation probably needed: we don't use the width cache. - if (is_utf16(c)) { - QChar const qc = ucs4_to_qchar(c); - QChar const uc = qc.toUpper(); - if (qc != uc) - return smallcaps_metrics_.width(uc); - else - return metrics_.width(qc); - } else { - QString const s = toqstr(docstring(1, c)); - QString const us = s.toUpper(); - if (s != us) - return smallcaps_metrics_.width(us); - else - return metrics_.width(s); - } -} - - int GuiFontMetrics::width(docstring const & s) const { size_t ls = s.size(); @@ -145,10 +117,7 @@ int GuiFontMetrics::width(docstring const & s) const /** if isSurrogateBase(s[i]) { docstring c = s[i]; - if (smallcaps_shape_) - w += metrics_.width(toqstr(c + s[i + 1])); - else - w += smallcaps_metrics_.width(toqstr(c + s[i + 1])); + w += metrics_.width(toqstr(c + s[i + 1])); ++i; } else @@ -230,9 +199,6 @@ GuiFontMetrics::AscendDescend const GuiFontMetrics::fillMetricsCache( int GuiFontMetrics::width(char_type c) const { - if (smallcaps_shape_) - return smallcapsWidth(c); - int value = width_cache_.value(c, outOfLimitMetric); if (value != outOfLimitMetric) return value; @@ -250,7 +216,7 @@ int GuiFontMetrics::width(char_type c)
[LyX features/str-metrics] Update description of what has been done in the branch.
The branch, str-metrics, has been updated. - Log - commit c8d3203da8ffa9e0547a06822a529b0b801144ee Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon May 12 11:02:22 2014 +0200 Update description of what has been done in the branch. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 73f5ed3..0ab1589 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -13,11 +13,8 @@ algorithm was basically implemented 3 times. Currently everything is supposed to work for both LTR and RTL text. -When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code -is tested against the old one in getPosNearX and cursorX. This can be -helpful when looking for discrepancies between the algorithms. Note -that this only makes sense when force_paint_single_char=true, since -this enforces char-by-char metrics computation. +The bugs fixed and caused by this branch are tracked at ticket #9003: +http://www.lyx.org/trac/ticket/9003 What is done: @@ -51,11 +48,11 @@ What is done: Next steps: -* get lots of testing. +* Fix bugs uncovered by testing. -* Get rid of old code in cursorX and getPosNearX; it has been - kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in - order to check computations. +* Get rid of LyXRC::force_paint_single_char, which is only a workaround. + +* Maybe get rid of LyXRC::rtl_support, which does not have a real use case. * Profile and see how performance can be improved. @@ -71,33 +68,6 @@ Steps for later (aka out of the scope of this branch): work if we are sure that the Row object is up-to-date when drawing happens. This depends on the update machinery. - This would allow to get rid of the Bidi code. - - -Known bugs: - -* When selecting text, the display seems to move around. This is - because partly selected words are drawn in two parts, and in case - like "ef|fort" or "V|AN", there are some ligature or kerning effects - that change the display. I am not sure yet how to fix that. - -* there are other differences in what breaks words. In particular, - RowPainter breaks strings at spell-checking extremities. This seems - to be harmless. - -* when clicking in the right margin, getPosNearX does not return - the same value as before. I am not sure whether this is important. - - -Other differences in behavior (aka bug fixes): - -* end of paragraph markers metrics are computed with the font of the - actual text, not default font. - -* in RtL paragraphs, the end-of-paragraph marker does not move the row - to the right anymore (ticket #9040). - -* When cursor is after a LtR separator just before a RtL chunk, the - cursor position is computed better with the new code. + This would allow to get rid of the Bidi.cpp code. --- Summary of changes: 00README_STR_METRICS_BRANCH | 44 ++ 1 files changed, 7 insertions(+), 37 deletions(-) hooks/post-receive -- Repository for new features
[LyX features/str-metrics] Remove support for LyXRC::force_paint_single_char
The branch, str-metrics, has been updated. - Log - commit f5ed81b270502b31cf2a6969573dc7488714ea31 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed May 14 15:36:44 2014 +0200 Remove support for LyXRC::force_paint_single_char This workaround is not necessary anymore, and it complicates the code. The variable itself will be removed after the landing of the branch on master. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 0ab1589..568ac8f 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -32,14 +32,16 @@ What is done: * Re-implement cursorX and getPosNearX using row elements. -* Implement proper string metrics computation (with cache), when - lyxrc.force_paint_single_char is false. In this case, remove also +* Do not honor lyxrc.force_paint_single_char anymore. This is a + workaround that is not necessary anymore. + +* Implement proper string metrics computation (with cache). Remove useless workarounds which disable kerning and ligatures. -* when lyxrc.force_paint_single_char is false, draw also RtL text - string-wise. This both speeds-up drawing and prepares for code - removal, since we now rely on Qt to do things we use to do by - ourselves (see isArabic* and isHebrew* code in Encodings.cpp). +* Draw also RtL text string-wise. This both speeds-up drawing and + prepares for code removal, since we now rely on Qt to do things we + use to do by ourselves (see isArabic* and isHebrew* code in + Encodings.cpp). * Do not cut strings at separators in RowPainter when text is not justified. This speeds-up painting by reducing the number of strings @@ -50,7 +52,8 @@ Next steps: * Fix bugs uncovered by testing. -* Get rid of LyXRC::force_paint_single_char, which is only a workaround. +* Get rid of LyXRC::force_paint_single_char, which is not used anymore + in the source. * Maybe get rid of LyXRC::rtl_support, which does not have a real use case. diff --git a/src/LyXRC.h b/src/LyXRC.h index 14f73d9..405f935 100644 --- a/src/LyXRC.h +++ b/src/LyXRC.h @@ -551,7 +551,8 @@ public: }; /// ScrollWheelZoom scroll_wheel_zoom; - /// + /// FIXME: this shall be removed, as the source does not refer + /// to it anymore. bool force_paint_single_char; /// int cursor_width; diff --git a/src/frontends/qt4/GuiFontLoader.cpp b/src/frontends/qt4/GuiFontLoader.cpp index 7f08817..d7c015f 100644 --- a/src/frontends/qt4/GuiFontLoader.cpp +++ b/src/frontends/qt4/GuiFontLoader.cpp @@ -165,8 +165,6 @@ QFont symbolFont(QString const & family, bool * ok) upper[0] = family[0].toUpper(); QFont font; - if (lyxrc.force_paint_single_char) - font.setKerning(false); font.setFamily(family); if (isChosenFont(font, family)) { @@ -257,8 +255,6 @@ static QString makeFontName(QString const & family, QString const & foundry) GuiFontInfo::GuiFontInfo(FontInfo const & f) : metrics(QFont()) { - if (lyxrc.force_paint_single_char) - font.setKerning(false); QString const pat = symbolFamily(f.family()); if (!pat.isEmpty()) { bool ok; diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp index 4be0fb2..27d4446 100644 --- a/src/frontends/qt4/GuiFontMetrics.cpp +++ b/src/frontends/qt4/GuiFontMetrics.cpp @@ -112,18 +112,12 @@ int GuiFontMetrics::rbearing(char_type c) const int GuiFontMetrics::width(docstring const & s) const { int w = 0; - if (lyxrc.force_paint_single_char) { - size_t const ls = s.size(); - for (size_t i = 0; i < ls; ++i) - w += width(s[i]); + map<docstring, int>::const_iterator it = strwidth_cache_.find(s); + if (it != strwidth_cache_.end()) { + w = it->second; } else { - map<docstring, int>::const_iterator it = strwidth_cache_.find(s); - if (it != strwidth_cache_.end()) { - w = it->second; - } else { - w = metrics_.width(toqstr(s)); - strwidth_cache_[s] = w; - } + w = metrics_.width(toqstr(s)); + strwidth_cache_[s] = w; } return w; } diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp index ca63966..1b81d62 100644 --- a/src/frontends/qt4/GuiPainter.cpp +++ b/src/frontends/qt4/GuiPainter.cpp @@ -321,8 +321,6 @@ int GuiPainter::text(int x, int y, docstring const & s, // occurs at a line-break. As a kludge, we force Qt to // render this glyph using a one-column line. // This is needed for some math glyphs. - // FIXME In texted, this behaves differently depending
[LyX/master] Rename misleading parameter.
commit 3b3d28cf8ed2168637ff7a3491a82a330e70c28e Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed May 14 18:03:37 2014 +0200 Rename misleading parameter. ... and a typo and some whitespace. diff --git a/src/mathed/MathData.h b/src/mathed/MathData.h index 6f92852..e216941 100644 --- a/src/mathed/MathData.h +++ b/src/mathed/MathData.h @@ -145,8 +145,8 @@ public: /// returns position of given x coordinate int pos2x(BufferView const * bv, size_type pos, int glue) const; /// returns position of given x coordinate - size_type x2pos(BufferView const * bv, int pos) const; - /// returns position of given x coordinate fstarting from a certain pos + size_type x2pos(BufferView const * bv, int targetx) const; + /// returns position of given x coordinate starting from a certain pos size_type x2pos(BufferView const * bv, int targetx, int glue) const; /// returns distance of this cell to the point given by x and y // assumes valid position and size cache @@ -165,7 +165,7 @@ public: /// void swap(MathData & ar) { base_type::swap(ar); } - /// attach/detach arguments to macros, updating the cur to + /// attach/detach arguments to macros, updating the cur to /// stay visually at the same position (cur==0 is allowed) void updateMacros(Cursor * cur, MacroContext const & mc, UpdateType); ///
[LyX/master] Do not forget last word of paragraph in completion
commit ee7c4db72a9dd392d7e1e34463c3ae11fce670ee Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri May 16 15:17:10 2014 +0200 Do not forget last word of paragraph in completion With the old code, the last word of a paragraph would not be added in the completion list. The key difference is to pass `from' instead of `pos' to FontList::fontiterator. Slight cleanup of the code. diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index b6ca893..c551ea0 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -3840,20 +3840,19 @@ void Paragraph::locateWord(pos_type & from, pos_type & to, void Paragraph::collectWords() { - pos_type n = size(); - for (pos_type pos = 0; pos < n; ++pos) { + for (pos_type pos = 0; pos < size(); ++pos) { if (isWordSeparator(pos)) continue; pos_type from = pos; locateWord(from, pos, WHOLE_WORD); - if ((pos - from) >= (int)lyxrc.completion_minlength) { - docstring word = asString(from, pos, AS_STR_NONE); - FontList::const_iterator cit = d->fontlist_.fontIterator(pos); - if (cit == d->fontlist_.end()) - return; - Language const * lang = cit->font().language(); - d->words_[lang->lang()].insert(word); - } + if (pos < from + lyxrc.completion_minlength) + continue; + FontList::const_iterator cit = d->fontlist_.fontIterator(from); + if (cit == d->fontlist_.end()) + return; + Language const * lang = cit->font().language(); + docstring const word = asString(from, pos, AS_STR_NONE); + d->words_[lang->lang()].insert(word); } }
[LyX/master] Remove unused parameter.
commit f9e0d4a595bb568ca5f952e507d39487b05b8dd7 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri May 16 15:25:17 2014 +0200 Remove unused parameter. diff --git a/src/insets/InsetSeparator.cpp b/src/insets/InsetSeparator.cpp index 68b2fb8..ba98552 100644 --- a/src/insets/InsetSeparator.cpp +++ b/src/insets/InsetSeparator.cpp @@ -137,7 +137,7 @@ ColorCode InsetSeparator::ColorName() const } -void InsetSeparator::latex(otexstream & os, OutputParams const & rp) const +void InsetSeparator::latex(otexstream & os, OutputParams const &) const { switch (params_.kind) { case InsetSeparatorParams::PLAIN:
[LyX features/str-metrics] Fix positionning of cursor
The branch, str-metrics, has been updated. - Log - commit 7b9b69f33c6d9bf0e6611e5fb8c406f3d3cefb80 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed May 14 17:46:43 2014 +0200 Fix positionning of cursor The old implementation of Row::Element::pos2x and x2pos did not work correctly with Arabic text, because characters can have shapes that depend on context. This new implementation leverages QTextLayout in a simplified way, since only one word is added to the layout. This allows to make Row::Element::x2pos more readable. Fixes: #9115. diff --git a/src/Row.cpp b/src/Row.cpp index 48b4fff..50a47d3 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -36,78 +36,65 @@ using frontend::FontMetrics; double Row::Element::pos2x(pos_type const i) const { - LASSERT(i >= pos && i <= endpos, return 0); + // This can happen with inline completion when clicking on the + // row after the completion. + if (i < pos || i > endpos) + return 0; bool const rtl = font.isVisibleRightToLeft(); int w = 0; //handle first the two bounds of the element - if (i == pos) - w = 0; + if (i == pos || type != STRING) + w = rtl ? width() : 0; else if (i == endpos) - w = width(); + w = rtl ? 0 : width(); else { - LASSERT(type == STRING, return 0); FontMetrics const & fm = theFontMetrics(font); - // FIXME Avoid caching of metrics there? - w = fm.width(str.substr(0, i - pos)); + w = fm.pos2x(str, i - pos, font.isVisibleRightToLeft()); } - if (rtl) - return width() - w; - else - return w; + return w; } -pos_type Row::Element::x2pos(double , bool const low) const +pos_type Row::Element::x2pos(double ) 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; + size_t i; - double last_w = 0; - double w = 0; - size_t i = 0; switch (type) { - case VIRTUAL: - // those elements are actually empty (but they have a width) - break; case STRING: { FontMetrics const & fm = theFontMetrics(font); - // FIXME: implement dichotomy search? - for ( ; i < str.size() ; ++i) { - last_w = w; - w = fm.width(str.substr(0, i + 1)); - if (w > x2) - break; - } + // FIXME: is it really necessary for x to be a double? + int xx = x; + i = fm.x2pos(str, xx, rtl); + x = xx; break; } + case VIRTUAL: + // those elements are actually empty (but they have a width) + i = 0; + x = rtl ? width() : 0; + break; case SEPARATOR: case INSET: case SPACE: - // those elements contain only one position - w = width(); - } - - if (type == STRING && i == str.size()) - x2 = w; - // round to the closest side. The !rtl is here to obtain the - // same rounding as with the old code (this is cosmetic and - // can be eventually removed). - else if (type != VIRTUAL && !low && (x2 - last_w + !rtl > w - x2)) { - x2 = w; - ++i; - } else - x2 = last_w; - - // is element is rtl, flip values back - x = rtl ? width() - x2 : x2; + // those elements contain only one position. Round to + // the closest side. + if (x > width()) { + x = width(); + i = !rtl; + } else { + x = 0; + i = rtl; + } + } //lyxerr << "=> p=" << pos + i << " x=" << x << endl; return pos + i; + } @@ -389,7 +376,8 @@ void Row::shorten_if_needed(pos_type const keep, int const w) // If there is a paragraph marker, it should be taken in account if (elements_.size() == 2) xstr -= back().width(); - pos_type new_pos = front.x2pos(xstr, true); + //FIXME: use FontMetrics::x2pos here?? handle rtl? + pos_type new_pos = front.x2pos(xstr); front.str = front.str.substr(0, new_pos - po
[LyX features/str-metrics] Fix bug where x2pos could return negative values
The branch, str-metrics, has been updated. - Log - commit 13551a9f203a5f8d2d28ea9af4eeeb7fe15171b0 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri May 16 20:59:22 2014 +0200 Fix bug where x2pos could return negative values diff --git a/src/Row.cpp b/src/Row.cpp index 50a47d3..a0c0dc4 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -62,7 +62,7 @@ pos_type Row::Element::x2pos(double ) const { //lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this; bool const rtl = font.isVisibleRightToLeft(); - size_t i; + size_t i = 0; switch (type) { case STRING: { diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp index b6b2f5d..2ac588c 100644 --- a/src/frontends/qt4/GuiFontMetrics.cpp +++ b/src/frontends/qt4/GuiFontMetrics.cpp @@ -183,7 +183,12 @@ int GuiFontMetrics::x2pos(docstring const & s, int & x, bool const rtl) const { QTextLayout tl; setTextLayout(tl, s, font_, rtl); - int const pos = tl.lineForTextPosition(0).xToCursor(x) - 1; + int pos = tl.lineForTextPosition(0).xToCursor(x); + // take into account the unicode formatting characters + if (pos > 0) + --pos; + if (pos > int(s.length())) + pos = s.length(); // correct x value to the actual cursor position. x = tl.lineForTextPosition(0).cursorToX(pos + 1); return pos; --- Summary of changes: src/Row.cpp |2 +- src/frontends/qt4/GuiFontMetrics.cpp |7 ++- 2 files changed, 7 insertions(+), 2 deletions(-) hooks/post-receive -- Repository for new features
[LyX features/str-metrics] Fix breaking of loooong word in RTL languages
The branch, str-metrics, has been updated. - Log - commit c73940031ae93d40fb72798a4373eb7771090caa Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon May 19 11:35:15 2014 +0200 Fix breaking of lng word in RTL languages Moreover, breaks row at insets when there is no suitable separator. Also make the code of Row::shorten_if_needed somewhat simpler by using iterators and factoring the code. Fixes: #9120 diff --git a/src/Row.cpp b/src/Row.cpp index a0c0dc4..b47b564 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -28,6 +28,8 @@ #include #include +#include + using namespace std; namespace lyx { @@ -98,6 +100,27 @@ pos_type Row::Element::x2pos(double ) const } +bool Row::Element::breakAt(double w) +{ + if (type != STRING || width() <= w) + return false; + + bool const rtl = font.isVisibleRightToLeft(); + if (rtl) + w = width() - w; + pos_type new_pos = x2pos(w); + if (new_pos == pos) + return false; + str = str.substr(0, new_pos - pos); + if (rtl) + dim.wid -= w; + else + dim.wid = w; + endpos = new_pos; + return true; +} + + pos_type Row::Element::left_pos() const { return font.isVisibleRightToLeft() ? endpos : pos; @@ -110,7 +133,6 @@ pos_type Row::Element::right_pos() const } - Row::Row() : separator(0), label_hfill(0), x(0), right_margin(0), sel_beg(-1), sel_end(-1), @@ -334,63 +356,63 @@ void Row::pop_back() } -void Row::shorten_if_needed(pos_type const keep, int const w) +void Row::shortenIfNeeded(pos_type const keep, int const w) { - if (empty() || width() < w) + if (empty() || width() <= w) return; /** First, we try to remove elements one by one from the end -* until a separator is found. +* until a separator is found. cit points to the first element +* we want to remove from the row. */ - int i = elements_.size(); + Elements::iterator const beg = elements_.begin(); + Elements::iterator const end = elements_.end(); + Elements::iterator cit = end; + Elements::iterator first_below = end; int new_end = end_; int new_wid = dim_.wid; - if (i > 0 && elements_[i - 1].type == SEPARATOR && new_end > keep) { - --i; - new_end = elements_[i].pos; - new_wid -= elements_[i].dim.wid; + // if the row ends with a separator, skip it. + if (cit != beg && boost::prior(cit)->type == SEPARATOR && new_end > keep) { + --cit; + new_end = cit->pos; + new_wid -= cit->dim.wid; } - while (i > 0 && elements_[i - 1].type != SEPARATOR && new_end > keep) { - --i; - new_end = elements_[i].pos; - new_wid -= elements_[i].dim.wid; + // Search for a separator where the row can be broken. + while (cit != beg && boost::prior(cit)->type != SEPARATOR && new_end > keep) { + --cit; + new_end = cit->pos; + new_wid -= cit->dim.wid; + if (new_wid < w && first_below == end) + first_below = cit; } - if (i == 0) { - /* If we are here, it means that we have not found a -* separator to shorten the row. There is one case -* where we can do something: when we have one big -* string, maybe with a paragraph marker after it. -*/ - Element & front = elements_.front(); - if (!(front.type == STRING - && (elements_.size() == 1 - || (elements_.size() == 2 - && back().type == VIRTUAL - return; - - // If this is a string element, we can try to split it. - if (front.type != STRING) - return; - double xstr = w - x; - // If there is a paragraph marker, it should be taken in account - if (elements_.size() == 2) - xstr -= back().width(); - //FIXME: use FontMetrics::x2pos here?? handle rtl? - pos_type new_pos = front.x2pos(xstr); - front.str = front.str.substr(0, new_pos - pos_); - front.dim.wid = xstr; - front.endpos = new_pos; - end_ = new_pos; - dim_.wid = x + xstr; - // If there is a paragraph marker, it should be removed. - if (elements_.size() == 2) - elements_.pop_back(); + + i
[LyX/master] Code cleanup: get rid of RenderPreview::status()
commit 275b7af75e5367c449d0f680d0965994c92d37d9 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue May 20 12:19:26 2014 +0200 Code cleanup: get rid of RenderPreview::status() This method is a proxy for LyXRC::preview that forces to forward declare some wrapper around an enum... Instead, two simple static methods previewMath() and previewText() are introduced, that make the code much easier to follow. diff --git a/src/LyXRC.h b/src/LyXRC.h index 14f73d9..2814959 100644 --- a/src/LyXRC.h +++ b/src/LyXRC.h @@ -560,17 +560,6 @@ public: }; -/** \c LyXRC_PreviewStatus is a wrapper for LyXRC::PreviewStatus. - * It can be forward-declared and passed as a function argument without - * having to expose LyXRC.h. - */ -class LyXRC_PreviewStatus { - LyXRC::PreviewStatus val_; -public: - LyXRC_PreviewStatus(LyXRC::PreviewStatus val) : val_(val) {} - operator LyXRC::PreviewStatus() const { return val_; } -}; - void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new); /// diff --git a/src/insets/InsetExternal.cpp b/src/insets/InsetExternal.cpp index 278168a..50c6e4b 100644 --- a/src/insets/InsetExternal.cpp +++ b/src/insets/InsetExternal.cpp @@ -542,8 +542,7 @@ static void add_preview_and_start_loading(RenderMonitoredPreview & renderer, { InsetExternalParams const & params = inset.params(); - if (RenderPreview::status() != LyXRC::PREVIEW_OFF && - isPreviewWanted(params)) { + if (RenderPreview::previewText() && isPreviewWanted(params)) { renderer.setAbsFile(params.filename); docstring const snippet = latexString(inset); renderer.addPreview(snippet, buffer); @@ -577,7 +576,7 @@ void InsetExternal::setParams(InsetExternalParams const & p) || !lyxrc.display_graphics || params_.preview_mode == PREVIEW_OFF || (params_.preview_mode == PREVIEW_INSTANT - && RenderPreview::status() == LyXRC::PREVIEW_OFF)) { + && !RenderPreview::previewText())) { RenderButton * button_ptr = renderer_->asButton(); if (!button_ptr) { renderer_.reset(new RenderButton); diff --git a/src/insets/InsetIPA.cpp b/src/insets/InsetIPA.cpp index 6fe0a90..33ede55 100644 --- a/src/insets/InsetIPA.cpp +++ b/src/insets/InsetIPA.cpp @@ -19,7 +19,6 @@ #include "FuncStatus.h" #include "LaTeXFeatures.h" #include "Lexer.h" -#include "LyXRC.h" #include "MetricsInfo.h" #include "OutputParams.h" #include "RenderPreview.h" @@ -122,8 +121,7 @@ void InsetIPA::preparePreview(DocIterator const & pos) const bool InsetIPA::previewState(BufferView * bv) const { - if (!editing(bv) && (RenderPreview::status() == LyXRC::PREVIEW_ON || -RenderPreview::status() == LyXRC::PREVIEW_NO_MATH)) { + if (!editing(bv) && RenderPreview::previewText()) { graphics::PreviewImage const * pimage = preview_->getPreviewImage(bv->buffer()); return pimage && pimage->image(); diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp index 506f358..ff4a329 100644 --- a/src/insets/InsetInclude.cpp +++ b/src/insets/InsetInclude.cpp @@ -31,7 +31,6 @@ #include "LayoutFile.h" #include "LayoutModuleList.h" #include "LyX.h" -#include "LyXRC.h" #include "Lexer.h" #include "MetricsInfo.h" #include "output_plaintext.h" @@ -989,7 +988,7 @@ void InsetInclude::metrics(MetricsInfo & mi, Dimension & dim) const LBUFERR(mi.base.bv); bool use_preview = false; - if (RenderPreview::status() != LyXRC::PREVIEW_OFF) { + if (RenderPreview::previewText()) { graphics::PreviewImage const * pimage = preview_->getPreviewImage(mi.base.bv->buffer()); use_preview = pimage && pimage->image(); @@ -1015,7 +1014,7 @@ void InsetInclude::draw(PainterInfo & pi, int x, int y) const LBUFERR(pi.base.bv); bool use_preview = false; - if (RenderPreview::status() != LyXRC::PREVIEW_OFF) { + if (RenderPreview::previewText()) { graphics::PreviewImage const * pimage = preview_->getPreviewImage(pi.base.bv->buffer()); use_preview = pimage && pimage->image(); @@ -1094,8 +1093,7 @@ void add_preview(RenderMonitoredPreview & renderer, InsetInclude const & inset, Buffer const & buffer) { InsetCommandParams const & params = inset.params(); - if (RenderPreview::status() != LyXRC::PREVIEW_OFF && - preview_wanted
[LyX features/str-metrics] Do not split words at selection boundary
The branch, str-metrics, has been updated. - Log - commit 0096a8716c2d5219ac0854a076bcaa73dab86be3 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri May 23 18:59:53 2014 +0200 Do not split words at selection boundary The display of partially-selected word is now done in a new Painter::text method which displays the string twice with different clip settings. This allows to catter for the case where Color_selectiontext is not black. Morover, the code that uses unicode override characters to force the direction of a string is moved to lstrings.h. Fixes: #9116 diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 568ac8f..2dc3cad 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -47,6 +47,10 @@ What is done: justified. This speeds-up painting by reducing the number of strings to draw. +* Do not cut strings at selection boundary in RowPainter. This avoids + ligature/kerning breaking in latin text, and bad rendering problems + in Arabic. + Next steps: @@ -72,5 +76,3 @@ Steps for later (aka out of the scope of this branch): happens. This depends on the update machinery. This would allow to get rid of the Bidi.cpp code. - - diff --git a/src/frontends/Painter.h b/src/frontends/Painter.h index 7267839..3302d16 100644 --- a/src/frontends/Painter.h +++ b/src/frontends/Painter.h @@ -14,9 +14,11 @@ #define PAINTER_H #include "support/strfwd.h" +#include "support/types.h" namespace lyx { +class Font; class FontInfo; namespace graphics { class Image; } @@ -106,12 +108,26 @@ public: virtual void image(int x, int y, int w, int h, graphics::Image const & image) = 0; - /// draw a string at position x, y (y is the baseline) - /** - * \return the width of the drawn text. - */ + /** draw a string at position x, y (y is the baseline). The +* text direction is deduced from \c str. +* \return the width of the drawn text. +*/ virtual int text(int x, int y, docstring const & str, FontInfo const & f) = 0; + /** draw a string at position x, y (y is the baseline). The +* text direction is enforced by the \c Font. +* \return the width of the drawn text. +*/ + virtual int text(int x, int y, docstring const & str, Font const & f) = 0; + + /** draw a string at position x, y (y is the baseline), but +* make sure that the part between \c from and \c to is in +* \c other color. The text direction is enforced by the \c Font. +* \return the width of the drawn text. +*/ + virtual int text(int x, int y, docstring const & str, Font const & f, +Color other, size_type from, size_type to) = 0; + void setDrawingEnabled(bool drawing_enabled) { drawing_enabled_ = drawing_enabled; } diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp index 2ac588c..492a0a9 100644 --- a/src/frontends/qt4/GuiFontMetrics.cpp +++ b/src/frontends/qt4/GuiFontMetrics.cpp @@ -22,10 +22,12 @@ #include "insets/Inset.h" #include "support/lassert.h" +#include "support/lstrings.h" #include using namespace std; +using namespace lyx::support; namespace lyx { namespace frontend { @@ -42,7 +44,7 @@ namespace { * why this works well for symbol fonts used in mathed too, even though * these are not real ucs4 characters. These are codepoints in the * computer modern fonts used, nothing unicode related. - * See comment in QLPainter::text() for more explanation. + * See comment in GuiPainter::text() for more explanation. **/ inline QChar const ucs4_to_qchar(char_type const ucs4) { @@ -146,22 +148,7 @@ namespace { void setTextLayout(QTextLayout & tl, docstring const & s, QFont const & font, bool const rtl) { - QString qs; - /* In LyX, the character direction is forced by the language. -* Therefore, we have to signal that fact to Qt. -* Source: http://www.iamcal.com/understanding-bidirectional-text/ -*/ - // Left-to-right override: forces to draw text left-to-right - char_type const LRO = 0x202D; - // Right-to-left override: forces to draw text right-to-left - char_type const RLO = 0x202E; - // Pop directional formatting: return to previous state - char_type const PDF = 0x202C; - if (rtl) - qs = toqstr(RLO + s + PDF); - else - qs = toqstr(LRO + s + PDF); - + QString const qs = toqstr(directedString(s, rtl)); tl.setText(qs); tl.setFont(font); tl.beginLayout(); @@ -175,6 +162,7 @@ int GuiFontMetrics::pos2x(docstring const & s, int const pos, bool c
[LyX features/str-metrics] Some cleanup of previous patch
The branch, str-metrics, has been updated. - Log - commit 544c7e01ca7039b11bf9304213ca9cd94e580c09 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue May 27 16:50:49 2014 +0200 Some cleanup of previous patch diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp index b49a94a..b6e7f24 100644 --- a/src/rowpainter.cpp +++ b/src/rowpainter.cpp @@ -237,11 +237,14 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) str.push_back(c); } - // At the end of the row, pos points to the last pos in the string. + // Make pos point to the last character in the string. // Using "pos = bidi_.vis2log(vpos)" does not work for some reason. if (vpos < end) pos = bidi_.vis2log(vpos - 1); + // Now make pos point to the position _after_ the string. + // Using vis2log for that is not a good idea in general, we + // want logical ordering. if (font.isVisibleRightToLeft()) --pos; else @@ -261,6 +264,7 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) */ if (font.isVisibleRightToLeft()) { reverse(str.begin(), str.end()); + // If the string is reversed, the positions need to be adjusted ++pos; ++start_pos; swap(start_pos, pos); @@ -272,8 +276,6 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) // all the text selected? bool const all_sel = (start_pos >= row_.sel_beg && pos < row_.sel_end) || pi_.selected; - if (some_sel) - LYXERR0("pos=[" << start_pos << ", " << pos << "[ sel=[" << row_.sel_beg << ", " << row_.sel_end << "[ span=[" <
[LyX features/str-metrics] Do not allow Row::shortenIfNeeded to create empty rows
The branch, str-metrics, has been updated. - Log - commit 06e4a11deb2678fb712546c7ae571b7ce5f70b86 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri May 30 18:50:35 2014 +0200 Do not allow Row::shortenIfNeeded to create empty rows Otherwise this leads to an endless loop in redoParagraph. diff --git a/src/Row.cpp b/src/Row.cpp index b47b564..1336d05 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -407,7 +407,7 @@ void Row::shortenIfNeeded(pos_type const keep, int const w) dim_.wid = x + first_below->width(); // If there are other elements, they should be removed. elements_.erase(boost::next(first_below), end); - } else { + } else if (first_below->pos > pos_) { end_ = first_below->pos; dim_.wid = new_wid; // Remove all elements from first_below. --- Summary of changes: src/Row.cpp |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- Repository for new features
[LyX/2.1.x] Make TextMetrics::editXY more robust
commit d4faf127d74643ce10a1a5240ea02601336e48fe Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue May 27 15:14:14 2014 +0200 Make TextMetrics::editXY more robust This fixes a crash in examples/fa/splash.lyx when selecting text representing menu entries. This happens because menu names are in LTR English, while the inset itself is in RTL. The problem is that the current code relies on the fact that 1. getColumnNearX and checkInsetHit share the same idea about cursor position. 2. pos and pos + 1 are in general consecutive on screen. It seems that 1. is wrong here (for reasons I did not try to understand); the second assumption is definitely false with bi-directional text. This makes editXY very fragile. The new code should be more robust in this respect. The logic is: * if checkInsetHit finds an inset, use its position, * otherwise, ask getColumnNearX for the cursor position. Fixes: #9142 diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index a0f8f72..7f82675 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -1492,37 +1492,30 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y, int yy = y; // is modified by getPitAndRowNearY Row const & row = getPitAndRowNearY(yy, pit, assert_in_view, up); - bool bound = false; // is modified by getColumnNearX - int xx = x; // is modified by getColumnNearX - pos_type const pos = row.pos() - + getColumnNearX(pit, row, xx, bound); cur.pit() = pit; - cur.pos() = pos; - cur.boundary(bound); - cur.setTargetX(x); - // try to descend into nested insets - Inset * inset = checkInsetHit(x, yy); - //lyxerr << "inset " << inset << " hit at x: " << x << " y: " << y << endl; - if (!inset) { + // Do we cover an inset? + InsetList::InsetTable * it = checkInsetHit(pit, x, yy); + + if (!it) { + // No inset, set position in the text + bool bound = false; // is modified by getColumnNearX + int xx = x; // is modified by getColumnNearX + cur.pos() = row.pos() + + getColumnNearX(pit, row, xx, bound); + cur.boundary(bound); cur.setCurrentFont(); + cur.setTargetX(xx); return 0; } - ParagraphList const & pars = text_->paragraphs(); - Inset const * inset_before = pos ? pars[pit].getInset(pos - 1) : 0; - - // This should be just before or just behind the - // cursor position set above. - LASSERT(inset == inset_before - || inset == pars[pit].getInset(pos), return 0); - - // Make sure the cursor points to the position before - // this inset. - if (inset == inset_before) { - --cur.pos(); - cur.boundary(false); - } + Inset * inset = it->inset; + //lyxerr << "inset " << inset << " hit at x: " << x << " y: " << y << endl; + + // Set position in front of inset + cur.pos() = it->pos; + cur.boundary(false); + cur.setTargetX(x); // Try to descend recursively inside the inset. inset = inset->editXY(cur, x, yy); @@ -1571,11 +1564,8 @@ void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const //takes screen x,y coordinates -Inset * TextMetrics::checkInsetHit(int x, int y) +InsetList::InsetTable * TextMetrics::checkInsetHit(pit_type pit, int x, int y) { - pit_type pit = getPitNearY(y); - LASSERT(pit != -1, return 0); - Paragraph const & par = text_->paragraphs()[pit]; ParagraphMetrics const & pm = par_metrics_[pit]; @@ -1604,7 +1594,7 @@ Inset * TextMetrics::checkInsetHit(int x, int y) && y >= p.y_ - dim.asc && y <= p.y_ + dim.des) { LYXERR(Debug::DEBUG, "Hit inset: " << inset); - return inset; + return const_cast(&(*iit)); } } @@ -1613,6 +1603,20 @@ Inset * TextMetrics::checkInsetHit(int x, int y) } +//takes screen x,y coordinates +Inset * TextMetrics::checkInsetHit(int x, int y) +{ + pit_type const pit = getPitNearY(y); + LASSERT(pit != -1, return 0); + InsetList::InsetTable * it = checkInsetHit(pit, x, y); + + if (!it) + return 0; + + return it->inset; +} + + int TextMetrics::cursorX(CursorSlice const & sl, bool boundary) const { diff --git a/src/TextMetrics.h b/src/TextMetrics.h index 66d310f..2acded9 100644 --- a/src/TextMetrics.h +++ b/src/TextMetrics.h @@ -15,6 +1
[LyX/master] Fix crash when accepting change
commit 7c3d1d7423908c4e2481f320876400622f78f359 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Thu Jun 5 12:18:09 2014 +0200 Fix crash when accepting change The problem is the use of cursor movement methods to update cursor. Cursor::forwardPos() steps into insets, which is not always what we want. The problem here is that there is a math inset just after the accepted change, and that the cursor steps into it for some reason. This code is a nightmare anyway. Fixes: bug #9145 diff --git a/src/lyxfind.cpp b/src/lyxfind.cpp index 0c10e19..6b9556e 100644 --- a/src/lyxfind.cpp +++ b/src/lyxfind.cpp @@ -400,7 +400,7 @@ bool findChange(DocIterator & cur, bool next) if (!next) // if we search backwards, take a step forward // to correctly set the anchor - cur.forwardPos(); + cur.top().forwardPos(); return true; }
[LyX/master] Fix checkmark on current entry for InsetSeparator context menu
commit 01ba22efffaa06e8c8ee4730b5d63ffd16e95c9f Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Jun 13 10:30:25 2014 +0200 Fix checkmark on current entry for InsetSeparator context menu The code supposed to do that contained a typo and was not completely correct. diff --git a/src/insets/InsetSeparator.cpp b/src/insets/InsetSeparator.cpp index eaf376f..05aa456 100644 --- a/src/insets/InsetSeparator.cpp +++ b/src/insets/InsetSeparator.cpp @@ -60,7 +60,7 @@ void InsetSeparatorParams::read(Lexer & lex) { string token; lex.setContext("InsetSeparatorParams::read"); - lex >> token; + lex >> token; if (token == "plain") kind = InsetSeparatorParams::PLAIN; else if (token == "parbreak") @@ -108,17 +108,19 @@ bool InsetSeparator::getStatus(Cursor & cur, FuncRequest const & cmd, { switch (cmd.action()) { // we handle these - case LFUN_INSET_MODIFY: - if (cmd.getArg(0) == "plain") { - InsetSeparatorParams params; - string2params(to_utf8(cmd.argument()), params); - status.setOnOff(params_.kind == params.kind); - } + case LFUN_INSET_MODIFY: { + if (cmd.getArg(0) != "separator") + break; + InsetSeparatorParams params; + string2params(to_utf8(cmd.argument()), params); + status.setOnOff(params_.kind == params.kind); status.setEnabled(true); return true; + } default: return Inset::getStatus(cur, cmd, status); } + return false; }
[LyX features/str-metrics] Remove obsolete code to handle Hebrew and Arabic characters
The branch, str-metrics, has been updated. - Log - commit 7a23bfc80742c7ecaf758073e818c63c07ec0009 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Jun 13 16:33:58 2014 +0200 Remove obsolete code to handle Hebrew and Arabic characters This is handled by Qt now. Note that a small optimization (do not draw text that is to the left og WorkArea) is removed because it cannot be guarranteed to be exact anymore. It was probably not very useful anway, and would become useless once the RowPainter is rewritten to use Row information. diff --git a/src/Encoding.cpp b/src/Encoding.cpp index a231106..be60107 100644 --- a/src/Encoding.cpp +++ b/src/Encoding.cpp @@ -41,190 +41,6 @@ Encodings::MathSymbolSet Encodings::mathsym; namespace { -char_type arabic_table[172][4] = { - {0xfe80, 0xfe80, 0xfe80, 0xfe80}, // 0x0621 = hamza - {0xfe81, 0xfe82, 0xfe81, 0xfe82}, // 0x0622 = ligature madda on alef - {0xfe83, 0xfe84, 0xfe83, 0xfe84}, // 0x0623 = ligature hamza on alef - {0xfe85, 0xfe86, 0xfe85, 0xfe86}, // 0x0624 = ligature hamza on waw - {0xfe87, 0xfe88, 0xfe87, 0xfe88}, // 0x0625 = ligature hamza under alef - {0xfe89, 0xfe8a, 0xfe8b, 0xfe8c}, // 0x0626 = ligature hamza on ya - {0xfe8d, 0xfe8e, 0xfe8d, 0xfe8e}, // 0x0627 = alef - {0xfe8f, 0xfe90, 0xfe91, 0xfe92}, // 0x0628 = baa - {0xfe93, 0xfe94, 0xfe93, 0xfe94}, // 0x0629 = taa marbuta - {0xfe95, 0xfe96, 0xfe97, 0xfe98}, // 0x062a = taa - {0xfe99, 0xfe9a, 0xfe9b, 0xfe9c}, // 0x062b = thaa - {0xfe9d, 0xfe9e, 0xfe9f, 0xfea0}, // 0x062c = jeem - {0xfea1, 0xfea2, 0xfea3, 0xfea4}, // 0x062d = haa - {0xfea5, 0xfea6, 0xfea7, 0xfea8}, // 0x062e = khaa - {0xfea9, 0xfeaa, 0xfea9, 0xfeaa}, // 0x062f = dal - - {0xfeab, 0xfeac, 0xfeab, 0xfeac}, // 0x0630 = thal - {0xfead, 0xfeae, 0xfead, 0xfeae}, // 0x0631 = ra - {0xfeaf, 0xfeb0, 0xfeaf, 0xfeb0}, // 0x0632 = zain - {0xfeb1, 0xfeb2, 0xfeb3, 0xfeb4}, // 0x0633 = seen - {0xfeb5, 0xfeb6, 0xfeb7, 0xfeb8}, // 0x0634 = sheen - {0xfeb9, 0xfeba, 0xfebb, 0xfebc}, // 0x0635 = sad - {0xfebd, 0xfebe, 0xfebf, 0xfec0}, // 0x0636 = dad - {0xfec1, 0xfec2, 0xfec3, 0xfec4}, // 0x0637 = tah - {0xfec5, 0xfec6, 0xfec7, 0xfec8}, // 0x0638 = zah - {0xfec9, 0xfeca, 0xfecb, 0xfecc}, // 0x0639 = ain - {0xfecd, 0xfece, 0xfecf, 0xfed0}, // 0x063a = ghain - {0, 0, 0, 0}, // 0x063b - {0, 0, 0, 0}, // 0x063c - {0, 0, 0, 0}, // 0x063d - {0, 0, 0, 0}, // 0x063e - {0, 0, 0, 0}, // 0x063f - - {0, 0, 0, 0}, // 0x0640 - {0xfed1, 0xfed2, 0xfed3, 0xfed4}, // 0x0641 = fa - {0xfed5, 0xfed6, 0xfed7, 0xfed8}, // 0x0642 = qaf - {0xfed9, 0xfeda, 0xfedb, 0xfedc}, // 0x0643 = kaf - {0xfedd, 0xfede, 0xfedf, 0xfee0}, // 0x0644 = lam - {0xfee1, 0xfee2, 0xfee3, 0xfee4}, // 0x0645 = meem - {0xfee5, 0xfee6, 0xfee7, 0xfee8}, // 0x0646 = noon - {0xfee9, 0xfeea, 0xfeeb, 0xfeec}, // 0x0647 = ha - {0xfeed, 0xfeee, 0xfeed, 0xfeee}, // 0x0648 = waw - {0xfeef, 0xfef0, 0xfeef, 0xfef0}, // 0x0649 = alef maksura - {0xfef1, 0xfef2, 0xfef3, 0xfef4}, // 0x064a = ya - {0x065b, 0x065b, 0x065b, 0x065b}, // 0x064b = fathatan - {0x065c, 0x065c, 0x065c, 0x065c}, // 0x064c = dammatan - {0x064d, 0x064d, 0x064d, 0x064d}, // 0x064d = kasratan - {0x064e, 0x064e, 0x064e, 0x064e}, // 0x064e = fatha - {0x064f, 0x064f, 0x064f, 0x064f}, // 0x064f = damma - - {0x0650, 0x0650, 0x0650, 0x0650}, // 0x0650 = kasra - {0x0651, 0x0651, 0x0651, 0x0651}, // 0x0651 = shadda - {0x0652, 0x0652, 0x0652, 0x0652}, // 0x0652 = sukun - - {0, 0, 0, 0}, // 0x0653 - {0, 0, 0, 0}, // 0x0654 - {0, 0, 0, 0}, // 0x0655 - {0, 0, 0, 0}, // 0x0656 - {0, 0, 0, 0}, // 0x0657 - {0, 0, 0, 0}, // 0x0658 - {0, 0, 0, 0}, // 0x0659 - {0, 0, 0, 0}, // 0x065a - {0, 0, 0, 0}, // 0x065b - {0, 0, 0, 0}, // 0x065c - {0, 0, 0, 0}, // 0x065d - {0, 0, 0, 0}, // 0x065e - {0, 0, 0, 0}, // 0x065f - {0, 0, 0, 0}, // 0x0660 - {0, 0, 0, 0}, // 0x0661 - {0, 0, 0, 0}, // 0x0662 - {0, 0, 0, 0}, // 0x0663 - {0, 0, 0, 0}, // 0x0664 - {0, 0, 0, 0}, // 0x0665 - {0, 0, 0, 0}, // 0x0666 - {0, 0, 0, 0}, // 0x0667 - {0, 0, 0, 0}, // 0x0668 - {0, 0, 0, 0}, // 0x0669 - {0, 0, 0, 0}, // 0x066a - {0, 0, 0, 0}, // 0x066b - {0, 0, 0, 0}, // 0x066c - {0, 0, 0, 0}, // 0x066d - {0, 0, 0, 0}, // 0x066e - {0, 0, 0, 0}, // 0x066f - {0, 0, 0, 0}, // 0x0670 - {0, 0, 0, 0}, // 0x0671 - {0, 0, 0, 0}, // 0x0672 - {0, 0, 0, 0}, // 0x0673 - {0, 0, 0, 0}, // 0x0674 - {0, 0, 0, 0}, // 0x0675 - {0, 0, 0, 0}, // 0x0676 - {0, 0, 0, 0}, // 0x0677 - {0, 0
[LyX features/str-metrics] Update 00README_STR_METRICS_BRANCH
The branch, str-metrics, has been updated. - Log - commit 0bdf12ff4ff041d8a37abd8c7b7d625e17302acb Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Jun 13 16:46:05 2014 +0200 Update 00README_STR_METRICS_BRANCH diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 2dc3cad..6668623 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -16,6 +16,7 @@ Currently everything is supposed to work for both LTR and RTL text. The bugs fixed and caused by this branch are tracked at ticket #9003: http://www.lyx.org/trac/ticket/9003 + What is done: * Make TextMetrics methods operate on Row objects: breakRow and @@ -38,10 +39,7 @@ What is done: * Implement proper string metrics computation (with cache). Remove useless workarounds which disable kerning and ligatures. -* Draw also RtL text string-wise. This both speeds-up drawing and - prepares for code removal, since we now rely on Qt to do things we - use to do by ourselves (see isArabic* and isHebrew* code in - Encodings.cpp). +* Draw also RtL text string-wise. This speeds-up drawing. * Do not cut strings at separators in RowPainter when text is not justified. This speeds-up painting by reducing the number of strings @@ -51,16 +49,19 @@ What is done: ligature/kerning breaking in latin text, and bad rendering problems in Arabic. +* Remove homebrew Arabic and Hebrew support from Encoding.cpp. We now + rely on Qt to do handle complex scripts. -Next steps: -* Fix bugs uncovered by testing. +Next steps: * Get rid of LyXRC::force_paint_single_char, which is not used anymore in the source. * Maybe get rid of LyXRC::rtl_support, which does not have a real use case. +* Fix bugs uncovered by testing. + * Profile and see how performance can be improved. @@ -70,9 +71,14 @@ Steps for later (aka out of the scope of this branch): in principle, but the code is intricate and needs some careful analysis. The first thing that needs to be done is to break row elements with the same criteria. Currently breakRow does not - consider on-the-fly spell-checking and selection changes, but it is - not clear to me that it is required. Moreover, this thing would only - work if we are sure that the Row object is up-to-date when drawing - happens. This depends on the update machinery. + consider on-the-fly spell-checking, but it is not clear to me that + it is required. Moreover, this thing would only work if we are sure + that the Row object is up-to-date when drawing happens. This depends + on the update machinery. This would allow to get rid of the Bidi.cpp code. + +* Change Row object to operate only on integers and not doubles. Then, + rewrite the computation of spacing in justified paragraphs so that + strings can be drawn without cutting at separators. This will improve + performance. --- Summary of changes: 00README_STR_METRICS_BRANCH | 26 -- 1 files changed, 16 insertions(+), 10 deletions(-) hooks/post-receive -- Repository for new features
[LyX features/str-metrics] Fix Qt5 incompatibility
The branch, str-metrics, has been updated. - Log - commit 14ef2214cd68ad75e5a309595ef27bc34f5b4dba Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue Jul 1 23:54:14 2014 +0200 Fix Qt5 incompatibility Support for Qt::UniteClip has been removed in Qt5. Therefore, we replace its use by two consecutive draw() with different clip rectangle. diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp index 99d4685..a33aebf 100644 --- a/src/frontends/qt4/GuiPainter.cpp +++ b/src/frontends/qt4/GuiPainter.cpp @@ -426,11 +426,12 @@ int GuiPainter::text(int x, int y, docstring const & str, Font const & f, setClipRect(QRect(x + xmin, y - ascent, xmax - xmin, height)); int const textwidth = text(x, y, dstr, fi); - // First the part in normal color + // Then the part in normal color + // Note that in Qt5, it is not possible to use Qt::UniteClip fi.setPaintColor(orig); setClipRect(QRect(x, y - ascent, xmin, height)); - setClipRect(QRect(x + xmax, y - ascent, textwidth - xmax, height), - Qt::UniteClip); + text(x, y, dstr, fi); + setClipRect(QRect(x + xmax, y - ascent, textwidth - xmax, height)); text(x, y, dstr, fi); setClipping(false); --- Summary of changes: src/frontends/qt4/GuiPainter.cpp |7 --- 1 files changed, 4 insertions(+), 3 deletions(-) hooks/post-receive -- Repository for new features
Re: [LyX/master] Update autotools for building with Qt5.
Le 19/07/14 03:41, Enrico Forestieri a écrit : commit 4bdeae27334536164cb7e37da9a9e491075fd682 Author: Enrico ForestieriDate: Sat Jul 19 03:34:28 2014 +0200 Update autotools for building with Qt5. The option --enable-qt5 allows configuring for Qt5. The default is Qt4. Nothing special is done with respect to Qt4, apart from pulling in the correct libraries. Indeed, other than the core and gui libraries, now also the concurrent and widgets libraries are needed. Is this --enable-qt5 needed? The version number is already available, isn't it? JMarc
[LyX/2.1.x] Fix error spotted by cppcheck
commit fa67a6ae89e94fcbd1dbd7446320a7806b74ff21 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sun Jul 20 00:04:45 2014 +0200 Fix error spotted by cppcheck diff --git a/src/support/lstrings.cpp b/src/support/lstrings.cpp index 7af8aae..d4b1ccf 100644 --- a/src/support/lstrings.cpp +++ b/src/support/lstrings.cpp @@ -1407,7 +1407,7 @@ docstring bformat(docstring const & fmt, char const * arg1, docstring arg2) LATTEST(contains(fmt, from_ascii("%1$s"))); LATTEST(contains(fmt, from_ascii("%2$s"))); docstring str = subst(fmt, from_ascii("%1$s"), from_ascii(arg1)); - str = subst(fmt, from_ascii("%2$s"), arg2); + str = subst(str, from_ascii("%2$s"), arg2); return subst(str, from_ascii("%%"), from_ascii("%")); } diff --git a/status.21x b/status.21x index 0522009..3db8551 100644 --- a/status.21x +++ b/status.21x @@ -65,7 +65,9 @@ What's new * INTERNALS -- Improve thread-safety +- Improve thread-safety. + +- Fix potential bug spotted by cppcheck. * DOCUMENTATION AND LOCALIZATION
[LyX/2.1.x] Do not forget last word of paragraph in completion
commit 3e60f58a92e6860d904b8c1373b9968603a1d180 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri May 16 15:17:10 2014 +0200 Do not forget last word of paragraph in completion With the old code, the last word of a paragraph would not be added in the completion list. The key difference is to pass `from' instead of `pos' to FontList::fontiterator. Slight cleanup of the code. diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index fccc28f..81ca225 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -3861,20 +3861,19 @@ void Paragraph::locateWord(pos_type & from, pos_type & to, void Paragraph::collectWords() { - pos_type n = size(); - for (pos_type pos = 0; pos < n; ++pos) { + for (pos_type pos = 0; pos < size(); ++pos) { if (isWordSeparator(pos)) continue; pos_type from = pos; locateWord(from, pos, WHOLE_WORD); - if ((pos - from) >= (int)lyxrc.completion_minlength) { - docstring word = asString(from, pos, AS_STR_NONE); - FontList::const_iterator cit = d->fontlist_.fontIterator(pos); - if (cit == d->fontlist_.end()) - return; - Language const * lang = cit->font().language(); - d->words_[lang->lang()].insert(word); - } + if (pos < from + lyxrc.completion_minlength) + continue; + FontList::const_iterator cit = d->fontlist_.fontIterator(from); + if (cit == d->fontlist_.end()) + return; + Language const * lang = cit->font().language(); + docstring const word = asString(from, pos, AS_STR_NONE); + d->words_[lang->lang()].insert(word); } } diff --git a/status.21x b/status.21x index 3db8551..46333c2 100644 --- a/status.21x +++ b/status.21x @@ -55,12 +55,14 @@ What's new * LYX2LYX -- Fix warning "Missing \use_indices" when converting from 1.6.x format or older +- Fix warning "Missing \use_indices" when converting from 1.6.x format + or older. * USER INTERFACE +- Do not forget last words of paragraphs in completion possibilities. * INTERNALS
[LyX features/str-metrics] Revert optimization where several words are drawn at the same time
The branch, str-metrics, has been updated. - Log - commit bbe6e9f593fc585ee9f5d69275487bf3ddbcaf47 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sun Jul 20 18:54:31 2014 +0200 Revert optimization where several words are drawn at the same time This can only be done where splitting of string is identical in row breaking and display. It will be possible to reintroduce this when row painting uses the tokenized row information. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index e901b51..342d2f6 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -39,10 +39,6 @@ What is done: * Draw also RtL text string-wise. This speeds-up drawing. -* Do not cut strings at separators in RowPainter when text is not - justified. This speeds-up painting by reducing the number of strings - to draw. - * Do not cut strings at selection boundary in RowPainter. This avoids ligature/kerning breaking in latin text, and bad rendering problems in Arabic. diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 4dde5fd..45a5007 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -565,7 +565,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit, Paragraph const & par = text_->getPar(pit); - double w = width - row.right_margin - row.width(); + double const w = width - row.right_margin - row.width(); // FIXME: put back this assertion when the crash on new doc is solved. //LASSERT(w >= 0, /**/); @@ -607,9 +607,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit, } else if (int(row.width()) < max_width_) { // is it block, flushleft or flushright? // set x how you need it - int const align = getAlign(par, row.pos()); - - switch (align) { + switch (getAlign(par, row.pos())) { case LYX_ALIGN_BLOCK: { int const ns = numberOfSeparators(row); /** If we have separators, and this row has @@ -650,12 +648,12 @@ void TextMetrics::computeRowMetrics(pit_type const pit, } #endif + // Finally, handle hfill insets pos_type const endpos = row.endpos(); pos_type body_pos = par.beginOfBody(); if (body_pos > 0 && (body_pos > endpos || !par.isLineSeparator(body_pos - 1))) body_pos = 0; - ParagraphMetrics & pm = par_metrics_[pit]; Row::iterator cit = row.begin(); Row::iterator const cend = row.end(); @@ -798,8 +796,7 @@ 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.x = leftMargin(max_width_, pit, pos); - row.dimension().wid = row.x; + row.dimension().wid = leftMargin(max_width_, pit, pos); row.right_margin = right_margin; if (pos >= end || row.width() > width) { diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp index a33aebf..2b51f47 100644 --- a/src/frontends/qt4/GuiPainter.cpp +++ b/src/frontends/qt4/GuiPainter.cpp @@ -273,14 +273,14 @@ void GuiPainter::image(int x, int y, int w, int h, graphics::Image const & i) int GuiPainter::text(int x, int y, char_type c, FontInfo const & f) { - docstring s(1, c); - return text(x, y, s, f); + return text(x, y, docstring(1, c), f); } int GuiPainter::text(int x, int y, docstring const & s, FontInfo const & f) { + //LYXERR0("text: x=" << x << ", s=" << s); if (s.empty()) return 0; diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp index ee4cd18..8c8ac4c 100644 --- a/src/rowpainter.cpp +++ b/src/rowpainter.cpp @@ -186,16 +186,15 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) } str.push_back(c); - pos_type const end = row_.endpos(); FontSpan const font_span = par_.fontSpan(pos); // Track-change status. Change const & change_running = par_.lookupChange(pos); - // spelling correct? bool const spell_state = lyxrc.spellcheck_continuously && par_.isMisspelled(pos); // collect as much similar chars as we can + pos_type const end = row_.endpos(); for (++vpos ; vpos < end ; ++vpos) { pos = bidi_.vis2log(vpos); @@ -218,11 +217,7 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) if (c == '\t') break; - // When row_.separator == 0, it is possible to print a - // string longer than a word in one fell swoop. -
[LyX/master] Handle boundary in getColumnNearX (and more)
commit ff608f46fdb40aa565190aa050e49df16ee96040 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sun Jul 21 20:22:32 2013 +0200 Handle boundary in getColumnNearX (and more) Use proper font everywhere for end-of-par marker Fix getColumnNearX for RTL text and for centered/right-justified paragraphs. Let computeRowMetrics update the row width. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 0727011..2e27eee 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -8,13 +8,12 @@ What is done: setRowHeight instead of rowBreakPoint and rowHeight. * change breakRow operation to operate on text strings on which - metrics are computed. The list of elements is stored in the row object - in visual ordering, not logical. + metrics are computed. The list of elements is stored in the row + object in visual ordering, not logical. * re-implement cursorX using row elements -* re-implement getColumnNearX using row elements (boundary is not - considered yet). +* re-implement getColumnNearX using row elements. * Implement proper string metrics computation (with cache), when lyxrc.force_paint_single_char is false. In this case, remove also @@ -23,7 +22,8 @@ What is done: Next steps: * get rid of old code of cursorX and getColumnNearX (which have been - kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE). + kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in + order to check computations). * re-implement row painting using row elements (can it be done?) @@ -31,17 +31,15 @@ Next steps: * Document the code -Difference in behavior +Difference in behavior (aka bug fixes) + * end of paragraph markers metrics are computed with the font of the - actual text, not default font. This will be extended to the other - methods. + actual text, not default font. -* When cursor is after a LtR separator just before a RtL chunk, the +* When cursor is after a LTR separator just before a RTL chunk, the cursor posiiton is computed better with the new code. -Other differences that should be considered as bugs +Other differences (aka real 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 diff --git a/src/Row.cpp b/src/Row.cpp index c32be85..aef6efb 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -54,7 +54,7 @@ double Row::Element::pos2x(pos_type const i) const } -pos_type Row::Element::x2pos(double ) const + pos_type Row::Element::x2pos(double , bool const low) const { //lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this; // if element is rtl, flip x value @@ -84,7 +84,7 @@ pos_type Row::Element::x2pos(double ) const } // round to the closest side - if (x2 - last_w > w - x2) { + if (!low && (x2 - last_w > w - x2)) { x2 = w; ++i; } else @@ -92,15 +92,13 @@ pos_type Row::Element::x2pos(double ) const // is element is rtl, flip values if (rtl) { - x = last_w - x2; - i = endpos - i; + x = width() - x2; } else { x = x2; - i = pos + i; } //lyxerr << "=> p=" << i << " x=" << x << endl; - return i; + return pos + i; } @@ -335,9 +333,9 @@ void Row::pop_back() } -void Row::separate_back(pos_type const keep) +void Row::shorten_if_needed(pos_type const keep, int const w) { - if (empty()) + if (empty() || width() < w) return; int i = elements_.size(); int new_end = end_; @@ -353,15 +351,32 @@ void Row::separate_back(pos_type const keep) new_end = elements_[i].pos; new_wid -= elements_[i].dim.wid; } - if (i == 0) + if (i == 0) { + if (elements_.size() != 1) { + LYXERR0("Row is too large but has more than one element. " << *this); + return; + } +#if 1 return; +#else + // does not work yet + if (back().type != STRING) + return; + double xstr = w - x; + pos_type new_pos = back().x2pos(xstr, true); + back().str = back().str.substr(0, new_pos); + back().endpos = new_pos; + end_ = new_pos; + dim_.wid = x + xstr; +#endif + } end_ = new_end; dim_.wid = new_wid; elements_.erase(elements_.begin() + i, elements_.end()); } -void Row::reverseRtL() +void Row::reverseRTL() { pos_typ
[LyX/master] Revert temporarily changes related to InsetSeparator
commit edcedf33243d549c24a9ed9e37383f9c7d14d1e0 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed Jun 25 12:39:58 2014 +0200 Revert temporarily changes related to InsetSeparator This is to avoid many conflicts with the str-metrics branch. diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 1b434a5..66771d4 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -348,7 +348,6 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos, // FED FED| FED ) if (startpos == pos && endpos == pos && endpos != par.size() && (par.isNewline(pos - 1) - || par.isEnvSeparator(pos - 1) || par.isLineSeparator(pos - 1) || par.isSeparator(pos - 1))) return false; @@ -629,7 +628,6 @@ void TextMetrics::computeRowMetrics(pit_type const pit, if (ns && row.endpos() < par.size() && !par.isNewline(row.endpos() - 1) - && !par.isEnvSeparator(row.endpos() - 1) && !disp_inset ) { row.separator = w / ns; @@ -695,13 +693,13 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const Paragraph const & par = text_->getPar(pit); pos_type last = par.beginOfBody(); - LBUFERR(last > 0 || par.isEnvSeparator(0)); + LBUFERR(last > 0); // -1 because a label ends with a space that is in the label --last; // a separator at this end does not count - if (last >= 0 && par.isLineSeparator(last)) + if (par.isLineSeparator(last)) --last; int w = 0; @@ -899,7 +897,7 @@ pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit, break; } - if (par.isNewline(i) || par.isEnvSeparator(i)) { + if (par.isNewline(i)) { point = i + 1; break; } @@ -1271,7 +1269,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit, if (lastrow && ((rtl_on_lastrow && left_side && vc == row.pos() && x < tmpx - 5) || (!rtl_on_lastrow && !left_side && vc == end && x > tmpx + 5))) { - if (!(par.isNewline(end - 1) || par.isEnvSeparator(end - 1))) + if (!par.isNewline(end - 1)) c = end; } else if (vc == row.pos()) { c = bidi.vis2log(vc); @@ -1320,9 +1318,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit, if (!c || end == par.size()) return col; - if (c==end && !par.isLineSeparator(c-1) - && !par.isNewline(c-1) - && !par.isEnvSeparator(c-1)) { + if (c==end && !par.isLineSeparator(c-1) && !par.isNewline(c-1)) { boundary = true; return col; } @@ -1818,8 +1814,7 @@ bool TextMetrics::cursorEnd(Cursor & cur) bool boundary = false; if (end != cur.lastpos()) { if (!cur.paragraph().isLineSeparator(end-1) - && !cur.paragraph().isNewline(end-1) - && !cur.paragraph().isEnvSeparator(end-1)) + && !cur.paragraph().isNewline(end-1)) boundary = true; else --end; @@ -1902,9 +1897,7 @@ int TextMetrics::leftMargin(int max_width, l_margin = leftMargin(max_width, newpar); // Remove the parindent that has been added // if the paragraph was empty. - if (pars[newpar].empty() && - buffer.params().paragraph_separation == - BufferParams::ParagraphIndentSeparation) { + if (pars[newpar].empty()) { docstring pi = pars[newpar].layout().parindent; l_margin -= theFontMetrics( buffer.params().getFont()).signedWidth(pi); @@ -1922,16 +1915,10 @@ int TextMetrics::leftMargin(int max_width, // This happens after sections or environments in standard classes. // We have to check the previous layout at same depth. - if (buffer.params().paragraph_separation == - BufferParams::ParagraphSkipSeparation) - parindent.erase(); - else if (pit > 0 &a
[LyX/master] Get rid of ugly font metrics workarounds.
commit 01c9bcb4328b286a922215c3c1a1583949c33d10 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sun Jul 21 12:24:08 2013 +0200 Get rid of ugly font metrics workarounds. Now we have proper ligatures and kerning on screen... diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp index 2cc0369..0138f61 100644 --- a/src/LyXRC.cpp +++ b/src/LyXRC.cpp @@ -448,7 +448,8 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format) return ReadError; // default for current rowpainter capabilities - force_paint_single_char = true; + //force_paint_single_char = true; + force_paint_single_char = false; // format prior to 2.0 and introduction of format tag unsigned int format = 0; diff --git a/src/frontends/qt4/GuiApplication.cpp b/src/frontends/qt4/GuiApplication.cpp index f6c8433..660b122 100644 --- a/src/frontends/qt4/GuiApplication.cpp +++ b/src/frontends/qt4/GuiApplication.cpp @@ -2417,7 +2417,6 @@ void GuiApplication::restoreGuiSession() QString const GuiApplication::romanFontName() { QFont font; - font.setKerning(false); font.setStyleHint(QFont::Serif); font.setFamily("serif"); @@ -2428,7 +2427,6 @@ QString const GuiApplication::romanFontName() QString const GuiApplication::sansFontName() { QFont font; - font.setKerning(false); font.setStyleHint(QFont::SansSerif); font.setFamily("sans"); @@ -2439,7 +2437,6 @@ QString const GuiApplication::sansFontName() QString const GuiApplication::typewriterFontName() { QFont font; - font.setKerning(false); font.setStyleHint(QFont::TypeWriter); font.setFamily("monospace"); diff --git a/src/frontends/qt4/GuiFontLoader.cpp b/src/frontends/qt4/GuiFontLoader.cpp index fa5370c..4b79071 100644 --- a/src/frontends/qt4/GuiFontLoader.cpp +++ b/src/frontends/qt4/GuiFontLoader.cpp @@ -165,7 +165,8 @@ QFont symbolFont(QString const & family, bool * ok) upper[0] = family[0].toUpper(); QFont font; - font.setKerning(false); + if (lyxrc.force_paint_single_char) + font.setKerning(false); font.setFamily(family); if (isChosenFont(font, family)) { @@ -256,7 +257,8 @@ static QString makeFontName(QString const & family, QString const & foundry) GuiFontInfo::GuiFontInfo(FontInfo const & f) : metrics(QFont()) { - font.setKerning(false); + if (lyxrc.force_paint_single_char) + font.setKerning(false); QString const pat = symbolFamily(f.family()); if (!pat.isEmpty()) { bool ok; diff --git a/src/frontends/qt4/GuiLog.cpp b/src/frontends/qt4/GuiLog.cpp index d81849a..2f1ef16 100644 --- a/src/frontends/qt4/GuiLog.cpp +++ b/src/frontends/qt4/GuiLog.cpp @@ -132,7 +132,6 @@ GuiLog::GuiLog(GuiView & lv) logTB->setReadOnly(true); QFont font(guiApp->typewriterFontName()); - font.setKerning(false); font.setFixedPitch(true); font.setStyleHint(QFont::TypeWriter); logTB->setFont(font); diff --git a/src/frontends/qt4/GuiPrefs.cpp b/src/frontends/qt4/GuiPrefs.cpp index 6dfd337..396cab3 100644 --- a/src/frontends/qt4/GuiPrefs.cpp +++ b/src/frontends/qt4/GuiPrefs.cpp @@ -314,7 +314,6 @@ static void setComboxFont(QComboBox * cb, string const & family, // for bug 1063. QFont font; - font.setKerning(false); QString const font_family = toqstr(family); if (font_family == guiApp->romanFontName()) { diff --git a/src/frontends/qt4/GuiProgressView.cpp b/src/frontends/qt4/GuiProgressView.cpp index a22ea60..2e0dfad 100644 --- a/src/frontends/qt4/GuiProgressView.cpp +++ b/src/frontends/qt4/GuiProgressView.cpp @@ -61,7 +61,6 @@ GuiProgressView::GuiProgressView(GuiView & parent, Qt::DockWidgetArea area, setWidget(widget_); QFont font(guiApp->typewriterFontName()); - font.setKerning(false); font.setFixedPitch(true); font.setStyleHint(QFont::TypeWriter); widget_->outTE->setFont(font); diff --git a/src/frontends/qt4/GuiViewSource.cpp b/src/frontends/qt4/GuiViewSource.cpp index b2df874..68041d8 100644 --- a/src/frontends/qt4/GuiViewSource.cpp +++ b/src/frontends/qt4/GuiViewSource.cpp @@ -72,7 +72,6 @@ ViewSourceWidget::ViewSourceWidget() ///dialog_->viewSourceTV->setAcceptRichText(false); // this is personal. I think source code should be in fixed-size font QFont font(guiApp->typewriterFontName()); - font.setKerning(false); font.setFixedPitch(true); font.setStyleHint(QFont::TypeWriter); viewSourceTV->setFont(font); diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp index cfa7f51..3f664f0 100644 --- a/src/rowpainter.cpp +++ b/src/rowpainter.cpp @@ -264,15 +264,7 @@ void RowPainter::paintChars(pos_type & vpos, FontInfo con
[LyX/master] Fix line breaking algorithm
commit 6258cebb77d63928313cae14bbba5d7f092d0a5e Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue Jul 23 16:24:01 2013 +0200 Fix line breaking algorithm Break words longer than the screen width. The code is more complicated than I would like, but I have no better idea right now. Implement properly the notion of a row broken by a display inset. This is useful in different places. Also fix a bug with last line of a paragraph spotted by Kornel. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 2e27eee..31cc489 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -1,35 +1,41 @@ This branch is where I (jmarc) try to implement string_wise metrics -computation. This is done through a series of cleanups. The expected -speed improvement will only be visible at the end of the road: indeed -for now we intend to keep unchanged behavior for testing purposes. +computation. This is done through a series of cleanups. The goal is to +have both good metrics computation (and font with proper kerning and +ligatures) and better performance than what we have with +force_paint_single_char. + +Currently everything is supposed to work for LTR text, and RTL text +should work too except possibly metrics with Arabic and Hebrew fonts. +We'll see what to do after some feedback. What is done: + * Make TextMetrics methods operate on Row objects: breakRow and setRowHeight instead of rowBreakPoint and rowHeight. -* change breakRow operation to operate on text strings on which +* Change breakRow operation to operate on text strings on which metrics are computed. The list of elements is stored in the row object in visual ordering, not logical. -* re-implement cursorX using row elements - -* re-implement getColumnNearX using row elements. +* Re-implement cursorX and getColumnNearX using row elements * Implement proper string metrics computation (with cache), when lyxrc.force_paint_single_char is false. In this case, remove also useless workarounds which disable kerning and ligatures. -Next steps: -* get rid of old code of cursorX and getColumnNearX (which have been +Next possible steps: + +* Get rid of old code of cursorX and getColumnNearX (which have been kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in order to check computations). -* re-implement row painting using row elements (can it be done?) +* Re-implement row painting using row elements. This is not difficult + in principle, but the code is intricate and needs some careful + analysis. -* profile and see how performance can be improved. +* Profile and see how performance can be improved. -* Document the code Difference in behavior (aka bug fixes) @@ -39,7 +45,7 @@ Difference in behavior (aka bug fixes) * When cursor is after a LTR separator just before a RTL chunk, the cursor posiiton is computed better with the new code. + Other differences (aka real 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. + +You tell me. diff --git a/src/Row.cpp b/src/Row.cpp index aef6efb..1a3bb24 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -54,7 +54,7 @@ double Row::Element::pos2x(pos_type const i) const } - pos_type Row::Element::x2pos(double , bool const low) const +pos_type Row::Element::x2pos(double , bool const low) const { //lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this; // if element is rtl, flip x value @@ -104,9 +104,9 @@ double Row::Element::pos2x(pos_type const i) const Row::Row() : 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) + 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) {} @@ -117,18 +117,6 @@ void Row::setCrc(size_type crc) const } -void Row::pos(pos_type p) -{ - pos_ = p; -} - - -void Row::endpos(pos_type p) -{ - end_ = p; -} - - bool Row::isMarginSelected(bool left_margin, DocIterator const & beg, DocIterator const & end) const { @@ -337,6 +325,10 @@ void Row::shorten_if_needed(pos_type const keep, int const w) { if (empty() || width() < w) return; + + /** First, we try to remove elements one by one from the end +* until a separator is found. +*/ int i = elements_.size(); int new_end = end_; int new_wid = dim_.wid; @@ -352,23 +344,35 @@ void Row::shorten_if_needed(pos_type const keep, int const w) new_wid -= elements_[i].dim.wid; } if (i == 0) { -
[LyX/master] Change TextMetrics::rowHeight to setRowHeight
commit cf3107793295e5550c67a1bd7e26776309e5dbc7 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Jun 14 19:24:29 2013 +0200 Change TextMetrics::rowHeight to setRowHeight This new function takes a row as parameter. Also, add direct access to Row::dim_ diff --git a/src/Row.cpp b/src/Row.cpp index 66b1726..5fd2abb 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -41,12 +41,6 @@ void Row::setCrc(size_type crc) const } -void Row::setDimension(Dimension const & dim) -{ - dim_ = dim; -} - - void Row::pos(pos_type p) { pos_ = p; diff --git a/src/Row.h b/src/Row.h index c26752b..2806824 100644 --- a/src/Row.h +++ b/src/Row.h @@ -61,10 +61,10 @@ public: /// pos_type endpos() const { return end_; } /// - void setDimension(Dimension const & dim); - /// Dimension const & dimension() const { return dim_; } /// + Dimension & dimension() { return dim_; } + /// int height() const { return dim_.height(); } /// int width() const { return dim_.wid; } diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 3026367..6880e14 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -460,32 +460,27 @@ bool TextMetrics::redoParagraph(pit_type const pit) pos_type first = 0; size_t row_index = 0; // maximum pixel width of a row - int width = max_width_ - right_margin; // - leftMargin(max_width_, pit, row); do { - Dimension dim; - pos_type end = rowBreakPoint(width, pit, first); - if (row_index || end < par.size()) - // If there is more than one row, expand the text to - // the full allowable width. This setting here is needed - // for the computeRowMetrics() below. - dim_.wid = max_width_; - - dim = rowHeight(pit, first, end); - dim.wid = rowWidth(right_margin, pit, first, end); if (row_index == pm.rows().size()) pm.rows().push_back(Row()); Row & row = pm.rows()[row_index]; - row.setChanged(false); row.pos(first); - row.endpos(end); - row.setDimension(dim); - int const max_row_width = max(dim_.wid, dim.wid); + breakRow(row, right_margin, pit); + setRowHeight(row, pit); + row.dimension().wid = rowWidth(right_margin, pit, first, row.endpos()); + row.setChanged(false); + if (row_index || row.endpos() < par.size()) + // If there is more than one row, expand the text to + // the full allowable width. This setting here is needed + // for the computeRowMetrics() below. + dim_.wid = max_width_; + int const max_row_width = max(dim_.wid, row.width()); computeRowMetrics(pit, row, max_row_width); - first = end; + first = row.endpos(); ++row_index; - pm.dim().wid = max(pm.dim().wid, dim.wid); - pm.dim().des += dim.height(); + pm.dim().wid = max(pm.dim().wid, row.width()); + pm.dim().des += row.height(); } while (first < par.size()); if (row_index < pm.rows().size()) @@ -494,18 +489,17 @@ bool TextMetrics::redoParagraph(pit_type const pit) // Make sure that if a par ends in newline, there is one more row // under it if (first > 0 && par.isNewline(first - 1)) { - Dimension dim = rowHeight(pit, first, first); - dim.wid = rowWidth(right_margin, pit, first, first); if (row_index == pm.rows().size()) pm.rows().push_back(Row()); Row & row = pm.rows()[row_index]; - row.setChanged(false); row.pos(first); row.endpos(first); - row.setDimension(dim); - int const max_row_width = max(dim_.wid, dim.wid); + row.dimension().wid = rowWidth(right_margin, pit, first, first); + setRowHeight(row, pit); + row.setChanged(false); + int const max_row_width = max(dim_.wid, row.width()); computeRowMetrics(pit, row, max_row_width); - pm.dim().des += dim.height(); + pm.dim().des += row.height(); } pm.dim().asc += pm.rows()[0].ascent(); @@ -719,7 +713,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const #if 0 -// Not used, see TextMetrics::rowBreakPoint. +// Not used, see TextMetrics::breakRow // this needs special handling - only newlines count as a break point static pos_type addressBreakPoint(pos_type i, Paragraph co
[LyX/master] Store in the Row object the list of elements it contains
commit 452fb6035999c88279a72b3e374bd69d39a3d67f Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue Jun 25 14:57:09 2013 +0200 Store in the Row object the list of elements it contains * Row now contains a vector of Elements * replace Row::dump by a proper << operator * the width is updated as elements are added * breakRow is reimplmented to use this infrastructure diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 53d9fd3..26c2fba 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -8,18 +8,13 @@ What is done: setRowHeight instead of rowBreakPoint and rowHeight. * change breakRow operation to operate on text strings on which - metrics are computed. Note that for now - FontMetrics::width(docstring) still computes the sum of character - widths, so that behavior is unchanged. + metrics are computed. The list of elements is stored in the row object * Implement proper string metrics computation (with cache), when lyxrc.force_paint_single_char is false. Next steps: -* Make breakRow build a list of elements (string, inset, - separator,...) in the row. This will be reused by other methods - * get rid of rowWidth (breakRow does compute this) * re-implement getColumnNearX using row elements @@ -37,4 +32,9 @@ point. This will not be useful anymore with horizontal scrolling. actual text, not default font. This will be extended to the other methods. -The other differences should be considered as bugs. +Other differences that should be considered as bugs +* there are still some difference in width computation wrt + TextMetrics::rowWidth. This happens in particular with Description + environment when the row is broken at bodypos. The method rowWidth + is kept for now in order to be able to detect row parsing errors, + but it could be removed right now. diff --git a/src/ParagraphMetrics.cpp b/src/ParagraphMetrics.cpp index d7fb42b..93b0461 100644 --- a/src/ParagraphMetrics.cpp +++ b/src/ParagraphMetrics.cpp @@ -190,8 +190,7 @@ void ParagraphMetrics::dump() const { lyxerr << "Paragraph::dump: rows.size(): " << rows_.size() << endl; for (size_t i = 0; i != rows_.size(); ++i) { - lyxerr << " row " << i << ": "; - rows_[i].dump(); + lyxerr << " row " << i << ": " << rows_[i]; } } diff --git a/src/Row.cpp b/src/Row.cpp index 5fd2abb..ef2fbbb 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -20,8 +20,13 @@ #include "DocIterator.h" +#include "frontends/FontMetrics.h" + #include "support/debug.h" +#include + +using namespace std; namespace lyx { @@ -29,7 +34,7 @@ namespace lyx { Row::Row() : separator(0), label_hfill(0), x(0), 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) {} @@ -62,7 +67,7 @@ bool Row::isMarginSelected(bool left_margin, DocIterator const & beg, // Is the chosen margin selected ? if (sel_pos == margin_pos) { if (beg.pos() == end.pos()) - // This is a special case in which the space between after + // This is a special case in which the space between after // pos i-1 and before pos i is selected, i.e. the margins // (see DocIterator::boundary_). return beg.boundary() && !end.boundary(); @@ -71,21 +76,21 @@ bool Row::isMarginSelected(bool left_margin, DocIterator const & beg, // drawn if the cursor is after the margin. return !end.boundary(); else if (beg.pos() == margin_pos) - // If the selection begins around the margin, it is + // If the selection begins around the margin, it is // only drawn if the cursor is before the margin. return beg.boundary(); - else + else return true; } return false; } -void Row::setSelectionAndMargins(DocIterator const & beg, +void Row::setSelectionAndMargins(DocIterator const & beg, DocIterator const & end) const { setSelection(beg.pos(), end.pos()); - + if (selection()) { end_margin_sel = isMarginSelected(false, beg, end); begin_margin_sel = isMarginSelected(true, beg, end); @@ -116,14 +121,151 @@ bool Row::selection() const return sel_beg != -1 && sel_end != -1; } +ostream & operator<<(ostream & os, Row const & row) +{ + os << "
[LyX/master] Implement proper handling of RtL in Rows
commit b2eba66083f41b242faaad45d192abeb7d7480d2 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed Jul 17 00:59:34 2013 +0200 Implement proper handling of RtL in Rows Now the row elements are sorted according to RtL/LtR. Some additional cleanup. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 26c2fba..4b6ef10 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -9,6 +9,7 @@ What is done: * change breakRow operation to operate on text strings on which metrics are computed. The list of elements is stored in the row object + in visual ordering, not logical. * Implement proper string metrics computation (with cache), when lyxrc.force_paint_single_char is false. @@ -26,13 +27,15 @@ Next steps: * profile and see how performance can be improved. Difference in behavior -* words longer than the screen are no monger broken at an arbitrary -point. This will not be useful anymore with horizontal scrolling. * end of paragraph markers metrics are computed with the font of the -actual text, not default font. This will be extended to the other -methods. + actual text, not default font. This will be extended to the other + methods. 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. + * there are still some difference in width computation wrt TextMetrics::rowWidth. This happens in particular with Description environment when the row is broken at bodypos. The method rowWidth diff --git a/src/Row.cpp b/src/Row.cpp index ef2fbbb..ce1a440 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -130,16 +130,16 @@ ostream & operator<<(ostream & os, Row const & row) Row::Elements::const_iterator it = row.elements_.begin(); for ( ; it != row.elements_.end() ; ++it) { switch (it->type) { - case Row::Element::STRING_ELT: + case Row::Element::STRING: os << "**STRING: " << to_utf8(it->str) << endl; break; - case Row::Element::INSET_ELT: + case Row::Element::INSET: os << "**INSET: " << to_utf8(it->inset->layoutName()) << endl; break; - case Row::Element::SEPARATOR_ELT: + case Row::Element::SEPARATOR: os << "**SEPARATOR: " << endl; break; - case Row::Element::SPACE_ELT: + case Row::Element::SPACE: os << "**SPACE: " << it->dim.wid << endl; break; } @@ -153,7 +153,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 && !elt.final + return elt.type == Element::STRING && !elt.final && elt.font == f && elt.change == ch; } @@ -167,18 +167,18 @@ void Row::finalizeLast() return; elt.final = true; - if (elt.type == Element::STRING_ELT) { + if (elt.type == Element::STRING) { elt.dim.wid = theFontMetrics(elt.font).width(elt.str); dim_.wid += elt.dim.wid; } } -void Row::add(pos_type const pos, Inset const * ins, Dimension const & dim) +void Row::add(pos_type const pos, Inset const * ins, Dimension const & dim, + Font const & f, Change const & ch) { finalizeLast(); - Element e(Element::INSET_ELT); - e.pos = pos; + Element e(Element::INSET, pos, f, ch); e.inset = ins; e.dim = dim; elements_.push_back(e); @@ -186,27 +186,30 @@ void Row::add(pos_type const pos, Inset const * ins, Dimension const & dim) } -void Row::add(pos_type const pos, docstring const & s, +void Row::add(pos_type const pos, char_type const c, Font const & f, Change const & ch) { - if (sameString(f, ch)) - elements_.back().str += s; - else { + if (!sameString(f, ch)) { finalizeLast(); - Element e(Element::STRING_ELT); - e.pos = pos; - e.str = s; - e.font = f; - e.change = ch; + Element e(Element::STRING, pos, f, ch); elements_.push_back(e); } + //lyxerr << "FONT " <<back().font.language() << endl; + back().str += c; + back().endpos = pos + 1; } -void Row::add(pos_type const pos, char_type const c,
[LyX/master] Fix getColumnNearX for nested insets
commit 059de2d04c40c63a013896e99a444b65529eb82d Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Oct 11 16:12:20 2013 +0200 Fix getColumnNearX for nested insets The horizontal position of the inset was not taken in account. The rounding is not always the same as with the old code, but this is not really important. Additional changes: * improve debug output of rows * remove Bidi& argument of the RowPainter constructor, since it is always an empty Bifi that is passed. This means that the Bidi class is not used at all any more in TextMetrics.cpp. The only remaining user is RowPainter. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 31cc489..18c68ca 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -17,18 +17,24 @@ What is done: metrics are computed. The list of elements is stored in the row object in visual ordering, not logical. -* Re-implement cursorX and getColumnNearX using row elements +* Re-implement cursorX and getColumnNearX using row elements. * Implement proper string metrics computation (with cache), when lyxrc.force_paint_single_char is false. In this case, remove also useless workarounds which disable kerning and ligatures. +Next steps needed: + +* 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 of cursorX and getColumnNearX (which have been +* 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). + order to check computations. * Re-implement row painting using row elements. This is not difficult in principle, but the code is intricate and needs some careful @@ -43,9 +49,11 @@ Difference in behavior (aka bug fixes) actual text, not default font. * When cursor is after a LTR separator just before a RTL chunk, the - cursor posiiton is computed better with the new code. + cursor position is computed better with the new code. Other differences (aka real bugs) -You tell me. +* there are still difference in what breaks words. In particular, + RowPainter breaks strings at: selection end, spellchecking + extremity. diff --git a/src/Row.cpp b/src/Row.cpp index 1a3bb24..d784979 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -218,9 +218,11 @@ ostream & operator<<(ostream & os, Row const & row) << " descent: " << row.dim_.des << " separator: " << row.separator << " label_hfill : " << row.label_hfill << "\n"; + double x = row.x; Row::Elements::const_iterator it = row.elements_.begin(); for ( ; it != row.elements_.end() ; ++it) { - os << "** " << *it << endl; + os << "x=" << x << " => " << *it << endl; + x += it->width(); } return os; } diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index f4e03c3..d949e3a 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -21,7 +21,9 @@ #include "TextMetrics.h" +#ifdef KEEP_OLD_METRICS_CODE #include "Bidi.h" +#endif #include "Buffer.h" #include "buffer_funcs.h" #include "BufferParams.h" @@ -1115,9 +1117,18 @@ 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 { - boundary = false; + + /// 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; +#ifdef KEEP_OLD_METRICS_CODE + int const x_orig = x; +#endif pos_type pos = row.pos(); + boundary = false; if (row.x >= x || row.empty()) x = row.x; else if (x >= row.width() - row.right_margin) { @@ -1158,16 +1169,13 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit, && row.back().endpos == row.endpos()) boundary = row.right_boundary(); + x += xo; #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_; - int x2 = x - xo; + int x2 = x_
[LyX/master] Implement real string width computation
commit 8539f756ed20092fc6ea6273e77299963f6cc7b6 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue Jun 25 08:18:25 2013 +0200 Implement real string width computation Important features: * widths are cached in a map * old behavior is still used when lyxrc.force_paint_single_char is true. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index b34ba5b..53d9fd3 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -5,20 +5,29 @@ for now we intend to keep unchanged behavior for testing purposes. What is done: * Make TextMetrics methods operate on Row objects: breakRow and -setRowHeight instead of rowBreakPoint and rowHeight. + setRowHeight instead of rowBreakPoint and rowHeight. + * change breakRow operation to operate on text strings on which -metrics are computed. Note that for now FontMetrics::width(docstring) -still computes the sum of character widths, so that behavior is -unchanged. + metrics are computed. Note that for now + FontMetrics::width(docstring) still computes the sum of character + widths, so that behavior is unchanged. + +* Implement proper string metrics computation (with cache), when + lyxrc.force_paint_single_char is false. Next steps: + * Make breakRow build a list of elements (string, inset, -separator,...) in the row. This will be reused by other methods + separator,...) in the row. This will be reused by other methods + * get rid of rowWidth (breakRow does compute this) + * re-implement getColumnNearX using row elements -* re-implement x2pos using row elements -* re-implement row painting using row elements -* Finally, implement proper string metrics computation (with cache) + +* re-implement cursorX using row elements + +* re-implement row painting using row elements (can it be done?) + * profile and see how performance can be improved. Difference in behavior diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp index e007b4a..4be0fb2 100644 --- a/src/frontends/qt4/GuiFontMetrics.cpp +++ b/src/frontends/qt4/GuiFontMetrics.cpp @@ -15,8 +15,9 @@ #include "qt_helpers.h" -#include "Language.h" #include "Dimension.h" +#include "Language.h" +#include "LyXRC.h" #include "insets/Inset.h" @@ -110,21 +111,20 @@ int GuiFontMetrics::rbearing(char_type c) const int GuiFontMetrics::width(docstring const & s) const { - size_t ls = s.size(); int w = 0; - for (unsigned int i = 0; i < ls; ++i) { - //FIXME: we need to detect surrogate pairs and act accordingly - /** - if isSurrogateBase(s[i]) { - docstring c = s[i]; - w += metrics_.width(toqstr(c + s[i + 1])); - ++i; + if (lyxrc.force_paint_single_char) { + size_t const ls = s.size(); + for (size_t i = 0; i < ls; ++i) + w += width(s[i]); + } else { + map<docstring, int>::const_iterator it = strwidth_cache_.find(s); + if (it != strwidth_cache_.end()) { + w = it->second; + } else { + w = metrics_.width(toqstr(s)); + strwidth_cache_[s] = w; } - else - */ - w += width(s[i]); } - return w; } diff --git a/src/frontends/qt4/GuiFontMetrics.h b/src/frontends/qt4/GuiFontMetrics.h index be36dbf..a2c57ec 100644 --- a/src/frontends/qt4/GuiFontMetrics.h +++ b/src/frontends/qt4/GuiFontMetrics.h @@ -16,6 +16,8 @@ #include "support/docstring.h" +#include + #include #include @@ -59,6 +61,10 @@ private: /// Cache of char widths mutable QHash<char_type, int> width_cache_; + /// Cache of string widths + /// FIXME Try to use a QHash (this requires to define qHash(docstring)) + mutable std::map<docstring, int> strwidth_cache_; + struct AscendDescend { int ascent; int descent;
[LyX/master] Small fixes to cursor positioning.
commit 9ba97a85f06c6f0272d43e61a86cceefbec8fa29 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Dec 20 12:12:27 2013 +0100 Small fixes to cursor positioning. Two small fixed to Row::Element::x2pos: * fix position for elements that are not strings * make rounding match the old code diff --git a/src/Row.cpp b/src/Row.cpp index d7940e9..86b7d06 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -86,10 +86,12 @@ pos_type Row::Element::x2pos(double , bool const low) const // lyxerr << " NOT FOUND "; } - if (i == str.size()) + if (type == STRING && i == str.size()) x2 = w; - // round to the closest side - else if (!low && (x2 - last_w > w - x2)) { + // round to the closest side. The !rtl is here to obtain the + // same rounding as with the old code (this is cosmetic and + // can be eventually removed). + else if (!low && (x2 - last_w + !rtl > w - x2)) { x2 = w; ++i; } else
[LyX/master] New reverseRTL implementation
commit 443a45342743615977b024ebfbaf1ecf1af7ddc8 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed Mar 19 14:44:31 2014 +0100 New reverseRTL implementation The old version was a bit complicated and wrong for RtL paragraphs containing LtR text. THe new one is clearer. diff --git a/src/Row.cpp b/src/Row.cpp index d784979..9da174f 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -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..2282c82 100644 --- a/src/Row.h +++ b/src/Row.h @@ -212,7 +212,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 d949e3a..ca6408d 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -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; }
[LyX/master] Change getColumnNearX to getPosNearX
commit f686375eecc92a2658425a6bb93ee184c5049ec1 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Dec 20 14:02:31 2013 +0100 Change getColumnNearX to getPosNearX The semantics was bad: the old implementation would return pos - row.pos(), and then all user of the function had to re-add row.pos(). diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index e38d4b6..1983dfe 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -17,7 +17,11 @@ What is done: metrics are computed. The list of elements is stored in the row object in visual ordering, not logical. -* Re-implement cursorX and getColumnNearX using row elements. +* rename getColumnNearX to getPosNearX (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 cursorX and getPosNearX using row elements. * Implement proper string metrics computation (with cache), when lyxrc.force_paint_single_char is false. In this case, remove also @@ -34,10 +38,6 @@ Next steps: 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. First thing that needs to be done is to break row elements diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 7dff932..61e4b60 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -2090,9 +2090,7 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded) Row const & real_next_row = tm.parMetrics(pit()).rows()[next_row]; bool bound = false; - pos_type const col = tm.getColumnNearX(pit(), real_next_row, - xo, bound); - top().pos() = real_next_row.pos() + col; + top().pos() = tm.getPosNearX(pit(), real_next_row, xo, bound); boundary(bound); updateNeeded |= bv().checkDepm(*this, old); diff --git a/src/Row.cpp b/src/Row.cpp index 86b7d06..15af2c2 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -104,7 +104,7 @@ pos_type Row::Element::x2pos(double , bool const low) const x = x2; } - //lyxerr << "=> p=" << i << " x=" << x << endl; + //lyxerr << "=> p=" << pos + i << " x=" << x << endl; return pos + i; } diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index b894133..9e775e0 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -1114,7 +1114,7 @@ void TextMetrics::setRowHeight(Row & row, pit_type const pit, // x is an absolute screen coord // returns the column near the specified x-coordinate of the row // x is set to the real beginning of this column -pos_type TextMetrics::getColumnNearX(pit_type const pit, +pos_type TextMetrics::getPosNearX(pit_type const pit, Row const & row, int & x, bool & boundary) const { @@ -1291,7 +1291,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit, if (abs(x2 - x) > 0.1 || boundary != boundary || c != pos) { - lyxerr << "getColumnNearX(" << x_orig << "): new=(x=" << x - xo << ", b=" << boundary << ", p=" << pos << "), " + lyxerr << "getPosNearX(" << x_orig << "): new=(x=" << x - xo << ", b=" << boundary << ", p=" << pos << "), " << "old=(x=" << x2 - xo << ", b=" << boundary2 << ", p=" << c << "), " << row; } @@ -1307,7 +1307,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit, return min(col, end - 1 - row.pos()); #endif // 0 #endif // KEEP_OLD_METRICS_CODE - return pos - row.pos(); + return pos; } @@ -1322,7 +1322,7 @@ pos_type TextMetrics::x2pos(pit_type pit, int row, int x) const LBUFERR(row < int(pm.rows().size())); bool bound = false; Row const & r = pm.rows()[row]; - return r.pos() + getColumnNearX(pit, r, x, bound); + return getPosNearX(pit, r, x, bound); } @@ -1482,10 +1482,9 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y, if (!it) { // No inset, set position in the text - bool bound = false; // is modified by getColumnNearX - int xx
[LyX/master] Update README and do a small code cleanup
commit 1a4b3201e747c45d12044105d86cfc4a3f11af3c Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Mar 3 15:29:37 2014 +0100 Update README and do a small code cleanup diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 1983dfe..1bb7026 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -1,21 +1,34 @@ -This branch is where I (jmarc) try to implement string_wise metrics -computation. This is done through a series of cleanups. The goal is to -have both good metrics computation (and font with proper kerning and -ligatures) and better performance than what we have with -force_paint_single_char. + + +PLEASE DO NOT DO WORK ON TOP OF THIS BRANCH. +I INTEND TO REWRITE HISTORY LATER!!! + + +This branch is where I (jmarc) try to implement string-wise metrics +computation. The goal is to have both good metrics computation (and +font with proper kerning and ligatures) and better performance than +what we have with force_paint_single_char. Moreover there has been +some code factorization in TextMetrics, where the same row-breaking +algorithm was basically implemented 3 times. Currently everything is supposed to work for LTR text, and RTL text should work too except possibly metrics with Arabic and Hebrew fonts. -We'll see what to do after some feedback. + +When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code +is tested against the old one in getPosNearX and cursorX. This can be +helpful when looking for discrepancies between the algorithms. Note +that this only makes sense when force_paint_single_char=true, since +this enforces char-by-char metrics computation. What is done: * Make TextMetrics methods operate on Row objects: breakRow and setRowHeight instead of rowBreakPoint and rowHeight. -* Change breakRow operation to operate on text strings on which - metrics are computed. The list of elements is stored in the row - object in visual ordering, not logical. +* Change breakRow operation to operate at strings level to compute + metrics The list of elements is stored in the row object in visual + ordering, not logical. This will eventually allow to get rid of the + Bidi class. * rename getColumnNearX to getPosNearX (and change code accordingly). It does not make sense to return a position relative to the start of @@ -30,38 +43,58 @@ What is done: Next steps: -* check what happens with arabic and/or hebrew text. There may be some +* 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. +* investigate whether RtL strings could be drawn on a string-wise basis. + +* investigate whether Row::SEPARATOR elements could be used only in + justified text. This would speed-up painting in other cases by + lowering the number of strings to draw. + +* get lots of testing. + * 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. +* Profile and see how performance can be improved. + + +Steps for later (aka out of the scope of this branch): + * Re-implement row painting using row elements. This is not difficult in principle, but the code is intricate and needs some careful - 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. + analysis. The first thing that needs to be done is to break row + elements with the same criteria. Currently TextMetrics::breakRow + does not consider on-the-fly spell-checking and selection changes, + but it is not clear to me that it is required. Moreover, this thing + would only work if we are sure that the Row object is up-to-date + when drawing happens. This depends on the update machinery. -* Profile and see how performance can be improved. + This would allow to get rid of the Bidi code. -Difference in behavior (aka bug fixes) +Known bugs: + +* in RtL paragraphs, the end-of-paragraph marker moves the row to the + right (ticket #9040, already present in master). + +* there are still difference in what breaks words. In particular, + RowPainter breaks strings at: selection end, spell-checking + extremities. This seems to be harmless. + +* when clicking in the right margin, GetColumnNearX does not return + the same value as before. I am not sure whether this is important. + + +Other differences in behavior (aka bug fixes): * end of paragraph markers metrics are computed with the font of the actual text, not default font. -* When cursor is after a LTR separator just before a RTL chunk, the +* When cursor is after a LtR separator just before a RtL
[LyX/master] Remove debug code from TextMetrics
commit b0543270a9055dcd43df3d72e2a5584895c77ac4 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri May 2 15:55:10 2014 +0200 Remove debug code from TextMetrics After this, it is possible to remove one parameter to getPosNearX. diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 61e4b60..fe03a31 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -2090,7 +2090,7 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded) Row const & real_next_row = tm.parMetrics(pit()).rows()[next_row]; bool bound = false; - top().pos() = tm.getPosNearX(pit(), real_next_row, xo, bound); + top().pos() = tm.getPosNearX(real_next_row, xo, bound); boundary(bound); updateNeeded |= bv().checkDepm(*this, old); diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 61a0758..12a42e2 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -15,15 +15,10 @@ * Full author contact details are available in file CREDITS. */ -//#define KEEP_OLD_METRICS_CODE 1 - #include #include "TextMetrics.h" -#ifdef KEEP_OLD_METRICS_CODE -#include "Bidi.h" -#endif #include "Buffer.h" #include "buffer_funcs.h" #include "BufferParams.h" @@ -1104,17 +1099,14 @@ void TextMetrics::setRowHeight(Row & row, pit_type const pit, // x is an absolute screen coord // returns the column near the specified x-coordinate of the row // x is set to the real beginning of this column -pos_type TextMetrics::getPosNearX(pit_type const pit, - Row const & row, int & x, bool & boundary) const +pos_type TextMetrics::getPosNearX(Row const & row, int & x, + bool & boundary) const { /// 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; -#ifdef KEEP_OLD_METRICS_CODE - int const x_orig = x; -#endif pos_type pos = row.pos(); boundary = false; @@ -1163,138 +1155,6 @@ pos_type TextMetrics::getPosNearX(pit_type const pit, boundary = row.right_boundary(); x += xo; -#ifdef KEEP_OLD_METRICS_CODE - Buffer const & buffer = bv_->buffer(); - - int x2 = x_orig; - Paragraph const & par = text_->getPar(pit); - Bidi bidi; - bidi.computeTables(par, buffer, row); - - pos_type vc = row.pos(); - pos_type const end = row.endpos(); - pos_type c = 0; - Layout const & layout = par.layout(); - - bool left_side = false; - - pos_type body_pos = par.beginOfBody(); - - double tmpx = row.x; - double last_tmpx = tmpx; - - if (body_pos > 0 && - (body_pos > end || !par.isLineSeparator(body_pos - 1))) - body_pos = 0; - - // check for empty row - if (vc == end) { - x2 = int(tmpx) + xo; - return 0; - } - - // This (rtl_support test) is not needed, but gives - // some speedup if rtl_support == false - bool const lastrow = lyxrc.rtl_support && row.endpos() == par.size(); - - // If lastrow is false, we don't need to compute - // the value of rtl. - bool const rtl_on_lastrow = lastrow ? text_->isRTL(par) : false; - - while (vc < end && tmpx <= x2) { - c = bidi.vis2log(vc); - last_tmpx = tmpx; - if (body_pos > 0 && c == body_pos - 1) { - FontMetrics const & fm = theFontMetrics( - text_->labelFont(par)); - tmpx += row.label_hfill + fm.width(layout.labelsep); - if (par.isLineSeparator(body_pos - 1)) - tmpx -= singleWidth(pit, body_pos - 1); - } - - tmpx += singleWidth(pit, c); - if (par.isSeparator(c) && c >= body_pos) - tmpx += row.separator; - ++vc; - } - - if ((tmpx + last_tmpx) / 2 > x2) { - tmpx = last_tmpx; - left_side = true; - } - - // This shouldn't happen. But we can reset and try to continue. - LASSERT(vc <= end, vc = end); - - bool boundary2 = false; - - if (lastrow && - ((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()) { - c = bidi.vis2log(vc); - if (bidi.level(c) % 2 == 1) -
[LyX/master] Implement a better solution for painting of RTL text
commit 3013ce3716603e751152e162a5b155cd455c745e Author: Jean-Marc Lasgouttes <jean-marc.lasgout...@inria.fr> Date: Wed Apr 30 16:15:31 2014 +0200 Implement a better solution for painting of RTL text Instead of relying on character range (Hebrew or Arabic) or character direction, use RLO unicode character (Right-to-Left override) to force painting in the direction indicated by the current font. This should be as close as we can to the old LyX behavior (and requires less code). If this code works as intended, it will be possible to remove a lot of code from Encodings.cpp. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 359bb03..e7a6f29 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -11,8 +11,7 @@ what we have with force_paint_single_char. Moreover there has been some code factorization in TextMetrics, where the same row-breaking algorithm was basically implemented 3 times. -Currently everything is supposed to work for LTR text, and RtL text -should work too except possibly metrics with Arabic and Hebrew fonts. +Currently everything is supposed to work for both LTR and RTL text. When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code is tested against the old one in getPosNearX and cursorX. This can be diff --git a/src/Encoding.cpp b/src/Encoding.cpp index 7c5dc87..a6f6a60 100644 --- a/src/Encoding.cpp +++ b/src/Encoding.cpp @@ -711,12 +711,6 @@ docstring Encodings::fromLaTeXCommand(docstring const & cmd, int cmdtype, } -bool Encodings::isHebrewChar(char_type c) -{ - return c >= 0x0590 && c <= 0x05ff; -} - - bool Encodings::isHebrewComposeChar(char_type c) { return c <= 0x05c2 && c >= 0x05b0 && c != 0x05be && c != 0x05c0; diff --git a/src/Encoding.h b/src/Encoding.h index 63aa93b..ed9c27e 100644 --- a/src/Encoding.h +++ b/src/Encoding.h @@ -269,8 +269,6 @@ public: /// static bool isHebrewComposeChar(char_type c); /// - static bool isHebrewChar(char_type c); - /// static bool isArabicComposeChar(char_type c); /// static bool isArabicSpecialChar(char_type c); diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp index ea0f946..b0708bf 100644 --- a/src/rowpainter.cpp +++ b/src/rowpainter.cpp @@ -20,7 +20,6 @@ #include "BufferParams.h" #include "BufferView.h" #include "Changes.h" -#include "Encoding.h" #include "Language.h" #include "Layout.h" #include "LyXRC.h" @@ -201,12 +200,6 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) bool const spell_state = lyxrc.spellcheck_continuously && par_.isMisspelled(pos); - // are we building a RtL string? - //FIXME: I would like to use the new isRTL() from textutils.h, - // but it does not give the same results for some reason I do - // not understand. - bool const rtl = Encodings::isArabicChar(str[0]) || Encodings::isHebrewChar(str[0]); - // collect as much similar chars as we can for (++vpos ; vpos < end ; ++vpos) { if (lyxrc.force_paint_single_char) @@ -234,14 +227,6 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) char_type c = par_.getChar(pos); - //FIXME: I would like to use the new isRTL() from textutils.h, - // but it does not give the same results for some reason I do - // not understand. - bool const new_rtl = Encodings::isArabicChar(c) || Encodings::isHebrewChar(c); - if (new_rtl != rtl) - // String direction has changed - break; - if (c == '\t') break; @@ -263,20 +248,29 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) docstring s([0], str.size()); + if (s[0] == '\t') + s.replace(0,1,from_ascii("")); + /* Because we do our own bidi, at this point the strings are * already in visual order. However, Qt also applies its own * bidi algorithm to strings that it paints to the screen. * Therefore, if we were to paint Hebrew/Arabic words as a * single string, the letters in the words would get reversed -* again. In order to avoid that, we reverse the string in advance. +* again. In order to avoid that, we force LTR drawing. * See also http://thread.gmane.org/gmane.editors.lyx.devel/79740 * for an earlier thread on the subject */ - if (rtl) + // Left-to-right override: forces to draw text left-to-right + char_type const LRO = 0x202D; + // Right-to-left override: forces to draw text right-to-left +
[LyX/master] Update description of what has been done in the branch.
commit 973adaf7d1eb874741ac140c987901367dd9e887 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon May 12 11:02:22 2014 +0200 Update description of what has been done in the branch. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 73f5ed3..0ab1589 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -13,11 +13,8 @@ algorithm was basically implemented 3 times. Currently everything is supposed to work for both LTR and RTL text. -When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code -is tested against the old one in getPosNearX and cursorX. This can be -helpful when looking for discrepancies between the algorithms. Note -that this only makes sense when force_paint_single_char=true, since -this enforces char-by-char metrics computation. +The bugs fixed and caused by this branch are tracked at ticket #9003: +http://www.lyx.org/trac/ticket/9003 What is done: @@ -51,11 +48,11 @@ What is done: Next steps: -* get lots of testing. +* Fix bugs uncovered by testing. -* Get rid of old code in cursorX and getPosNearX; it has been - kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in - order to check computations. +* Get rid of LyXRC::force_paint_single_char, which is only a workaround. + +* Maybe get rid of LyXRC::rtl_support, which does not have a real use case. * Profile and see how performance can be improved. @@ -71,33 +68,6 @@ Steps for later (aka out of the scope of this branch): work if we are sure that the Row object is up-to-date when drawing happens. This depends on the update machinery. - This would allow to get rid of the Bidi code. - - -Known bugs: - -* When selecting text, the display seems to move around. This is - because partly selected words are drawn in two parts, and in case - like "ef|fort" or "V|AN", there are some ligature or kerning effects - that change the display. I am not sure yet how to fix that. - -* there are other differences in what breaks words. In particular, - RowPainter breaks strings at spell-checking extremities. This seems - to be harmless. - -* when clicking in the right margin, getPosNearX does not return - the same value as before. I am not sure whether this is important. - - -Other differences in behavior (aka bug fixes): - -* end of paragraph markers metrics are computed with the font of the - actual text, not default font. - -* in RtL paragraphs, the end-of-paragraph marker does not move the row - to the right anymore (ticket #9040). - -* When cursor is after a LtR separator just before a RtL chunk, the - cursor position is computed better with the new code. + This would allow to get rid of the Bidi.cpp code.
[LyX/master] Fix positionning of cursor
commit 2ff639a0e6d051c6411fe6655cefc36a4e902211 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed May 14 17:46:43 2014 +0200 Fix positionning of cursor The old implementation of Row::Element::pos2x and x2pos did not work correctly with Arabic text, because characters can have shapes that depend on context. This new implementation leverages QTextLayout in a simplified way, since only one word is added to the layout. This allows to make Row::Element::x2pos more readable. Fixes: #9115. diff --git a/src/Row.cpp b/src/Row.cpp index 48b4fff..a0c0dc4 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -36,78 +36,65 @@ using frontend::FontMetrics; double Row::Element::pos2x(pos_type const i) const { - LASSERT(i >= pos && i <= endpos, return 0); + // This can happen with inline completion when clicking on the + // row after the completion. + if (i < pos || i > endpos) + return 0; bool const rtl = font.isVisibleRightToLeft(); int w = 0; //handle first the two bounds of the element - if (i == pos) - w = 0; + if (i == pos || type != STRING) + w = rtl ? width() : 0; else if (i == endpos) - w = width(); + w = rtl ? 0 : width(); else { - LASSERT(type == STRING, return 0); FontMetrics const & fm = theFontMetrics(font); - // FIXME Avoid caching of metrics there? - w = fm.width(str.substr(0, i - pos)); + w = fm.pos2x(str, i - pos, font.isVisibleRightToLeft()); } - if (rtl) - return width() - w; - else - return w; + return w; } -pos_type Row::Element::x2pos(double , bool const low) const +pos_type Row::Element::x2pos(double ) 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; - - double last_w = 0; - double w = 0; size_t i = 0; + switch (type) { - case VIRTUAL: - // those elements are actually empty (but they have a width) - break; case STRING: { FontMetrics const & fm = theFontMetrics(font); - // FIXME: implement dichotomy search? - for ( ; i < str.size() ; ++i) { - last_w = w; - w = fm.width(str.substr(0, i + 1)); - if (w > x2) - break; - } + // FIXME: is it really necessary for x to be a double? + int xx = x; + i = fm.x2pos(str, xx, rtl); + x = xx; break; } + case VIRTUAL: + // those elements are actually empty (but they have a width) + i = 0; + x = rtl ? width() : 0; + break; case SEPARATOR: case INSET: case SPACE: - // those elements contain only one position - w = width(); - } - - if (type == STRING && i == str.size()) - x2 = w; - // round to the closest side. The !rtl is here to obtain the - // same rounding as with the old code (this is cosmetic and - // can be eventually removed). - else if (type != VIRTUAL && !low && (x2 - last_w + !rtl > w - x2)) { - x2 = w; - ++i; - } else - x2 = last_w; - - // is element is rtl, flip values back - x = rtl ? width() - x2 : x2; + // those elements contain only one position. Round to + // the closest side. + if (x > width()) { + x = width(); + i = !rtl; + } else { + x = 0; + i = rtl; + } + } //lyxerr << "=> p=" << pos + i << " x=" << x << endl; return pos + i; + } @@ -389,7 +376,8 @@ void Row::shorten_if_needed(pos_type const keep, int const w) // If there is a paragraph marker, it should be taken in account if (elements_.size() == 2) xstr -= back().width(); - pos_type new_pos = front.x2pos(xstr, true); + //FIXME: use FontMetrics::x2pos here?? handle rtl? + pos_type new_pos = front.x2pos(xstr); front.str = front.str.substr(0, new_pos - pos_); front.dim.wid = xstr; front.endpos = new_pos; diff --git a/src/Row.h b/src/Row.h index 7725427.
[LyX/master] Draw right-to-left text string-wise using Qt
commit ea1a5cb80eaef71bc1cb7021bc3dbf2ef7a793b7 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Thu Apr 10 16:37:21 2014 +0200 Draw right-to-left text string-wise using Qt We rely on Qt built-in unicode support for handling Arabic and Hebrew compose characters. This allows to avoid to use our homegrown machinery. This should provide a nice speedup at a low cost and will eventually allow us to get rid of: * most of our Arabic/Hebrew machinery in Encodings.cpp, * Paragraph::transformChar, * and probably more. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 82026e8..359bb03 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -11,7 +11,7 @@ what we have with force_paint_single_char. Moreover there has been some code factorization in TextMetrics, where the same row-breaking algorithm was basically implemented 3 times. -Currently everything is supposed to work for LTR text, and RTL text +Currently everything is supposed to work for LTR text, and RtL text should work too except possibly metrics with Arabic and Hebrew fonts. When KEEP_OLD_METRICS_CODE is defined in TextMetrics.cpp, the new code @@ -40,12 +40,13 @@ What is done: lyxrc.force_paint_single_char is false. In this case, remove also useless workarounds which disable kerning and ligatures. +* when lyxrc.force_paint_single_char is false, draw also RtL text + string-wise. This both speed-up drawing and prepare for code + removal, since we now rely on Qt to do things we use to do by + ourselves (see isArabic* and isHebrew* code in Encodings.cpp). -Next steps: -* check what happens with Arabic and/or Hebrew text. There may be some - problems related to compose characters. Investigate whether RtL - strings could be drawn on a string-wise basis. +Next steps: * investigate whether strings could be cut at separators in RowPainter only in justified text. This would speed-up painting in other cases @@ -76,18 +77,18 @@ Steps for later (aka out of the scope of this branch): Known bugs: -* there are still difference in what breaks words. In particular, - RowPainter breaks strings at: selection end, spell-checking - extremities. This seems to be harmless. - -* when clicking in the right margin, getPosNearX does not return - the same value as before. I am not sure whether this is important. - * When selecting text, the display seems to move around. This is because partly selected words are drawn in two parts, and in case like "ef|fort" or "V|AN", there are some ligature or kerning effects that change the display. I am not sure yet how to fix that. +* there are other differences in what breaks words. In particular, + RowPainter breaks strings at spell-checking extremities. This seems + to be harmless. + +* when clicking in the right margin, getPosNearX does not return + the same value as before. I am not sure whether this is important. + Other differences in behavior (aka bug fixes): diff --git a/src/Encoding.cpp b/src/Encoding.cpp index a6f6a60..7c5dc87 100644 --- a/src/Encoding.cpp +++ b/src/Encoding.cpp @@ -711,6 +711,12 @@ docstring Encodings::fromLaTeXCommand(docstring const & cmd, int cmdtype, } +bool Encodings::isHebrewChar(char_type c) +{ + return c >= 0x0590 && c <= 0x05ff; +} + + bool Encodings::isHebrewComposeChar(char_type c) { return c <= 0x05c2 && c >= 0x05b0 && c != 0x05be && c != 0x05c0; diff --git a/src/Encoding.h b/src/Encoding.h index ed9c27e..63aa93b 100644 --- a/src/Encoding.h +++ b/src/Encoding.h @@ -269,6 +269,8 @@ public: /// static bool isHebrewComposeChar(char_type c); /// + static bool isHebrewChar(char_type c); + /// static bool isArabicComposeChar(char_type c); /// static bool isArabicSpecialChar(char_type c); diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp index 5b69701..ea0f946 100644 --- a/src/rowpainter.cpp +++ b/src/rowpainter.cpp @@ -161,72 +161,7 @@ void RowPainter::paintInset(Inset const * inset, pos_type const pos) } -void RowPainter::paintHebrewComposeChar(pos_type & vpos, FontInfo const & font) -{ - pos_type pos = bidi_.vis2log(vpos); - - docstring str; - - // first char - char_type c = par_.getChar(pos); - str += c; - ++vpos; - - int const width = theFontMetrics(font).width(c); - int dx = 0; - - for (pos_type i = pos - 1; i >= 0; --i) { - c = par_.getChar(i); - if (!Encodings::isHebrewComposeChar(c)) { - if (isPrintableNonspace(c)) { - int const width2 = pm_.singleWidth(i, - text_metrics_.displayFont(pit_, i)); - dx = (c == 0x05e8 || // resh -
[LyX/master] Fix various selection-related problems
commit b8170e0e01f486fefb94b19566e24dd391419c12 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Mar 21 11:56:42 2014 +0100 Fix various selection-related problems All these problems are related to what happens at the extreme points of rows * since VIRTUAL elements have a width but no contents, they have to be treated specially at some places. It would have been better to avoid testing for them explicitly, but I did not find a way. * Improve and cleanup the code in breakRow and fix in passing a crash when clicking on the right of an incomplete MARGIN_MANUAL paragraph. * improve the computation of row width in TextMetrics::computeRowMetrics. * handle properly the case where a position if not found on the row in both cursorX and getPosNearX (actually, this happens when selecting). * Some code cleanup and comments. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 1bb7026..82026e8 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -44,18 +44,16 @@ What is done: 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. + problems related to compose characters. Investigate whether RtL + strings could be drawn on a string-wise basis. -* investigate whether RtL strings could be drawn on a string-wise basis. - -* investigate whether Row::SEPARATOR elements could be used only in - justified text. This would speed-up painting in other cases by - lowering the number of strings to draw. +* investigate whether strings could be cut at separators in RowPainter + only in justified text. This would speed-up painting in other cases + by lowering the number of strings to draw. * get lots of testing. -* Get rid of old code in cursorX and getColumnNearX; it has been +* Get rid of old code in cursorX and getPosNearX; it has been kept for comparison purpose, guarded with KEEP_OLD_METRICS_CODE in order to check computations. @@ -67,33 +65,38 @@ Steps for later (aka out of the scope of this branch): * Re-implement row painting using row elements. This is not difficult in principle, but the code is intricate and needs some careful analysis. The first thing that needs to be done is to break row - elements with the same criteria. Currently TextMetrics::breakRow - does not consider on-the-fly spell-checking and selection changes, - but it is not clear to me that it is required. Moreover, this thing - would only work if we are sure that the Row object is up-to-date - when drawing happens. This depends on the update machinery. + elements with the same criteria. Currently breakRow does not + consider on-the-fly spell-checking and selection changes, but it is + not clear to me that it is required. Moreover, this thing would only + work if we are sure that the Row object is up-to-date when drawing + happens. This depends on the update machinery. This would allow to get rid of the Bidi code. Known bugs: -* in RtL paragraphs, the end-of-paragraph marker moves the row to the - right (ticket #9040, already present in master). - * there are still difference in what breaks words. In particular, RowPainter breaks strings at: selection end, spell-checking extremities. This seems to be harmless. -* when clicking in the right margin, GetColumnNearX does not return +* when clicking in the right margin, getPosNearX does not return the same value as before. I am not sure whether this is important. +* When selecting text, the display seems to move around. This is + because partly selected words are drawn in two parts, and in case + like "ef|fort" or "V|AN", there are some ligature or kerning effects + that change the display. I am not sure yet how to fix that. + Other differences in behavior (aka bug fixes): * end of paragraph markers metrics are computed with the font of the actual text, not default font. +* in RtL paragraphs, the end-of-paragraph marker does not move the row + to the right anymore (ticket #9040). + * When cursor is after a LtR separator just before a RtL chunk, the cursor position is computed better with the new code. diff --git a/src/Row.cpp b/src/Row.cpp index 6e60e97..48b4fff 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -63,18 +63,19 @@ double Row::Element::pos2x(pos_type const i) const pos_type Row::Element::x2pos(double , bool const low) const { //lyxerr << "x2pos: x=" << x << " w=" << width() << " " << *this; - // if element is rtl, flip x value + // If element is rtl, flip x value bool const rtl = font.isVisibleRightToLeft(); double x2 = rtl ? (width() - x) : x; - FontMetrics const & fm = theFontMetr
[LyX/master] Do not split words at selection boundary
commit ec42b2e4c9daa458df1c5c0454d61fbe4987701c Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri May 23 18:59:53 2014 +0200 Do not split words at selection boundary The display of partially-selected word is now done in a new Painter::text method which displays the string twice with different clip settings. This allows to catter for the case where Color_selectiontext is not black. Morover, the code that uses unicode override characters to force the direction of a string is moved to lstrings.h. Fixes: #9116 diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 568ac8f..2dc3cad 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -47,6 +47,10 @@ What is done: justified. This speeds-up painting by reducing the number of strings to draw. +* Do not cut strings at selection boundary in RowPainter. This avoids + ligature/kerning breaking in latin text, and bad rendering problems + in Arabic. + Next steps: @@ -72,5 +76,3 @@ Steps for later (aka out of the scope of this branch): happens. This depends on the update machinery. This would allow to get rid of the Bidi.cpp code. - - diff --git a/src/frontends/Painter.h b/src/frontends/Painter.h index 7267839..3302d16 100644 --- a/src/frontends/Painter.h +++ b/src/frontends/Painter.h @@ -14,9 +14,11 @@ #define PAINTER_H #include "support/strfwd.h" +#include "support/types.h" namespace lyx { +class Font; class FontInfo; namespace graphics { class Image; } @@ -106,12 +108,26 @@ public: virtual void image(int x, int y, int w, int h, graphics::Image const & image) = 0; - /// draw a string at position x, y (y is the baseline) - /** - * \return the width of the drawn text. - */ + /** draw a string at position x, y (y is the baseline). The +* text direction is deduced from \c str. +* \return the width of the drawn text. +*/ virtual int text(int x, int y, docstring const & str, FontInfo const & f) = 0; + /** draw a string at position x, y (y is the baseline). The +* text direction is enforced by the \c Font. +* \return the width of the drawn text. +*/ + virtual int text(int x, int y, docstring const & str, Font const & f) = 0; + + /** draw a string at position x, y (y is the baseline), but +* make sure that the part between \c from and \c to is in +* \c other color. The text direction is enforced by the \c Font. +* \return the width of the drawn text. +*/ + virtual int text(int x, int y, docstring const & str, Font const & f, +Color other, size_type from, size_type to) = 0; + void setDrawingEnabled(bool drawing_enabled) { drawing_enabled_ = drawing_enabled; } diff --git a/src/frontends/qt4/GuiFontMetrics.cpp b/src/frontends/qt4/GuiFontMetrics.cpp index 2ac588c..492a0a9 100644 --- a/src/frontends/qt4/GuiFontMetrics.cpp +++ b/src/frontends/qt4/GuiFontMetrics.cpp @@ -22,10 +22,12 @@ #include "insets/Inset.h" #include "support/lassert.h" +#include "support/lstrings.h" #include using namespace std; +using namespace lyx::support; namespace lyx { namespace frontend { @@ -42,7 +44,7 @@ namespace { * why this works well for symbol fonts used in mathed too, even though * these are not real ucs4 characters. These are codepoints in the * computer modern fonts used, nothing unicode related. - * See comment in QLPainter::text() for more explanation. + * See comment in GuiPainter::text() for more explanation. **/ inline QChar const ucs4_to_qchar(char_type const ucs4) { @@ -146,22 +148,7 @@ namespace { void setTextLayout(QTextLayout & tl, docstring const & s, QFont const & font, bool const rtl) { - QString qs; - /* In LyX, the character direction is forced by the language. -* Therefore, we have to signal that fact to Qt. -* Source: http://www.iamcal.com/understanding-bidirectional-text/ -*/ - // Left-to-right override: forces to draw text left-to-right - char_type const LRO = 0x202D; - // Right-to-left override: forces to draw text right-to-left - char_type const RLO = 0x202E; - // Pop directional formatting: return to previous state - char_type const PDF = 0x202C; - if (rtl) - qs = toqstr(RLO + s + PDF); - else - qs = toqstr(LRO + s + PDF); - + QString const qs = toqstr(directedString(s, rtl)); tl.setText(qs); tl.setFont(font); tl.beginLayout(); @@ -175,6 +162,7 @@ int GuiFontMetrics::pos2x(docstring const & s, int const pos, bool const rtl) co { QTextLayout tl; setTextLayout(tl, s, font_, rtl); + // we take into accoun
[LyX/master] Move some text from the readme file to relevant source files
commit 4bd5a7e883b76f36d1ebc3ae1c9a6765da5165f6 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Jun 30 15:55:30 2014 +0200 Move some text from the readme file to relevant source files diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 6668623..1292390 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -11,8 +11,6 @@ what we have with force_paint_single_char. Moreover there has been some code factorization in TextMetrics, where the same row-breaking algorithm was basically implemented 3 times. -Currently everything is supposed to work for both LTR and RTL text. - The bugs fixed and caused by this branch are tracked at ticket #9003: http://www.lyx.org/trac/ticket/9003 @@ -59,26 +57,3 @@ Next steps: in the source. * Maybe get rid of LyXRC::rtl_support, which does not have a real use case. - -* Fix bugs uncovered by testing. - -* Profile and see how performance can be improved. - - -Steps for later (aka out of the scope of this branch): - -* Re-implement row painting using row elements. This is not difficult - in principle, but the code is intricate and needs some careful - analysis. The first thing that needs to be done is to break row - elements with the same criteria. Currently breakRow does not - consider on-the-fly spell-checking, but it is not clear to me that - it is required. Moreover, this thing would only work if we are sure - that the Row object is up-to-date when drawing happens. This depends - on the update machinery. - - This would allow to get rid of the Bidi.cpp code. - -* Change Row object to operate only on integers and not doubles. Then, - rewrite the computation of spacing in justified paragraphs so that - strings can be drawn without cutting at separators. This will improve - performance. diff --git a/src/Row.h b/src/Row.h index a1e707e..04890f7 100644 --- a/src/Row.h +++ b/src/Row.h @@ -30,6 +30,18 @@ class DocIterator; class Inset; /** + * FIXME: Change Row object to operate only on integers and not doubles. + * + * This use of double is only useful to distribute the extra + * horizontal space between separators in justified text. If we do + * integer arithmetic, then it is possible to have two groups of + * separators, with size s or s+1. Then strings can be drawn without + * cutting at separators in justfied text, as it is done in + * non-justified text. This will improve performance. + */ + + +/** * 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. diff --git a/src/rowpainter.h b/src/rowpainter.h index ae1a590..7e29c0e 100644 --- a/src/rowpainter.h +++ b/src/rowpainter.h @@ -37,6 +37,21 @@ class TextMetrics; namespace frontend { class Painter; } /** + * FIXME: Re-implement row painting using row elements. + * + * This is not difficult in principle, but the code is intricate and + * needs some careful analysis. The first thing that needs to be done + * is to break row elements with the same criteria. Currently breakRow + * does not consider on-the-fly spell-checking, but it is not clear to + * me that it is required. Moreover, this thing would only work if we + * are sure that the Row object is up-to-date when drawing happens. + * This depends on the update machinery. + * + * This would allow to get rid of the Bidi class. + */ + + +/** * A class used for painting an individual row of text. * FIXME: get rid of that class. */
[LyX/master] Get rid of rtl_support preference
commit 45eb314a863a7bc76c2880f2352b7b430eeaf1c0 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed Jul 9 20:12:06 2014 +0200 Get rid of rtl_support preference This variable was introduced to guard against any bad consequence of the then-new right-to-left languages support. Let's be bold and get rid of it altogether! Now right to left support is always enabled. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 7095f9f..e901b51 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -50,7 +50,4 @@ What is done: * Remove homebrew Arabic and Hebrew support from Encoding.cpp. We now rely on Qt to do handle complex scripts. - -Next steps: - -* Maybe get rid of LyXRC::rtl_support, which does not have a real use case. +* Get rid of LyXRC::rtl_support, which does not have a real use case. diff --git a/lib/configure.py b/lib/configure.py index f0b7166..ac8df63 100644 --- a/lib/configure.py +++ b/lib/configure.py @@ -1479,7 +1479,7 @@ if __name__ == '__main__': lyx_check_config = True lyx_kpsewhich = True outfile = 'lyxrc.defaults' -lyxrc_fileformat = 16 +lyxrc_fileformat = 17 rc_entries = '' lyx_keep_temps = False version_suffix = '' diff --git a/lib/scripts/prefs2prefs_prefs.py b/lib/scripts/prefs2prefs_prefs.py index 4770fbf..9776cfe 100644 --- a/lib/scripts/prefs2prefs_prefs.py +++ b/lib/scripts/prefs2prefs_prefs.py @@ -70,6 +70,9 @@ # Incremented to format 16, by lasgouttes # Remove force_paint_single_char rc. +# Incremented to format 17, by lasgouttes +# Remove rtl_support rc. + # NOTE: The format should also be updated in LYXRC.cpp and # in configure.py. @@ -321,6 +324,11 @@ def remove_force_paint_single_char(line): return no_match return (True, "") +def remove_rtl(line): + if not line.lower().startswith("\\rtl "): + return no_match + return (True, "") + # End conversions for LyX 2.1 to 2.2 @@ -346,5 +354,6 @@ conversions = [ [ 13, [mac_cursor_movement]], [ 14, []], [ 15, []], - [ 16, [remove_force_paint_single_char]] + [ 16, [remove_force_paint_single_char]], + [ 17, [remove_rtl]] ] diff --git a/src/Bidi.cpp b/src/Bidi.cpp index d5a631e..3b598a4 100644 --- a/src/Bidi.cpp +++ b/src/Bidi.cpp @@ -57,10 +57,6 @@ void Bidi::computeTables(Paragraph const & par, Buffer const & buf, Row const & row) { same_direction_ = true; - if (!lyxrc.rtl_support) { - start_ = -1; - return; - } if (par.inInset().forceLTR()) { start_ = -1; @@ -192,7 +188,7 @@ void Bidi::computeTables(Paragraph const & par, bool Bidi::isBoundary(Buffer const & buf, Paragraph const & par, pos_type pos) const { - if (!lyxrc.rtl_support || pos == 0) + if (pos == 0) return false; if (!inRange(pos - 1)) { @@ -212,9 +208,6 @@ bool Bidi::isBoundary(Buffer const & buf, Paragraph const & par, bool Bidi::isBoundary(Buffer const & buf, Paragraph const & par, pos_type pos, Font const & font) const { - if (!lyxrc.rtl_support) - return false;// This is just for speedup - bool const rtl = font.isVisibleRightToLeft(); bool const rtl2 = inRange(pos) ? level(pos) % 2 diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 301fd2a..bc8162b 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -803,14 +803,12 @@ bool BufferView::moveToPosition(pit_type bottom_pit, pos_type bottom_pos, void BufferView::translateAndInsert(char_type c, Text * t, Cursor & cur) { - if (lyxrc.rtl_support) { - if (d->cursor_.real_current_font.isRightToLeft()) { - if (d->intl_.keymap == Intl::PRIMARY) - d->intl_.keyMapSec(); - } else { - if (d->intl_.keymap == Intl::SECONDARY) - d->intl_.keyMapPrim(); - } + if (d->cursor_.real_current_font.isRightToLeft()) { + if (d->intl_.keymap == Intl::PRIMARY) + d->intl_.keyMapSec(); + } else { + if (d->intl_.keymap == Intl::SECONDARY) + d->intl_.keyMapPrim(); } d->intl_.getTransManager().translateAndInsert(c, t, cur); diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp index 46309ee..5e1efcf 100644 --- a/src/LyXRC.cpp +++ b/src/LyXRC.cpp @@ -58,7 +58,7 @@ namespace { // The format should also be updated in configure.py, and conversion code // should be added to prefs2prefs_prefs.py. -static unsigned int const LYXRC_FILEFORMAT = 16; // lasgouttes: remove \\force_paint_single_char +static unsigned int const LYXRC
[LyX/master] Remove obsolete code to handle Hebrew and Arabic characters
commit d6337a248847aa4c72f8a813d92d349d1035c79f Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Jun 13 16:33:58 2014 +0200 Remove obsolete code to handle Hebrew and Arabic characters This is handled by Qt now. Note that a small optimization (do not draw text that is to the left of WorkArea) is removed because it cannot be guaranteed to be exact anymore. It was probably not very useful anyway, and would become useless once the RowPainter is rewritten to use Row information. Update 00README_STR_METRICS_BRANCH. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 2dc3cad..6668623 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -16,6 +16,7 @@ Currently everything is supposed to work for both LTR and RTL text. The bugs fixed and caused by this branch are tracked at ticket #9003: http://www.lyx.org/trac/ticket/9003 + What is done: * Make TextMetrics methods operate on Row objects: breakRow and @@ -38,10 +39,7 @@ What is done: * Implement proper string metrics computation (with cache). Remove useless workarounds which disable kerning and ligatures. -* Draw also RtL text string-wise. This both speeds-up drawing and - prepares for code removal, since we now rely on Qt to do things we - use to do by ourselves (see isArabic* and isHebrew* code in - Encodings.cpp). +* Draw also RtL text string-wise. This speeds-up drawing. * Do not cut strings at separators in RowPainter when text is not justified. This speeds-up painting by reducing the number of strings @@ -51,16 +49,19 @@ What is done: ligature/kerning breaking in latin text, and bad rendering problems in Arabic. +* Remove homebrew Arabic and Hebrew support from Encoding.cpp. We now + rely on Qt to do handle complex scripts. -Next steps: -* Fix bugs uncovered by testing. +Next steps: * Get rid of LyXRC::force_paint_single_char, which is not used anymore in the source. * Maybe get rid of LyXRC::rtl_support, which does not have a real use case. +* Fix bugs uncovered by testing. + * Profile and see how performance can be improved. @@ -70,9 +71,14 @@ Steps for later (aka out of the scope of this branch): in principle, but the code is intricate and needs some careful analysis. The first thing that needs to be done is to break row elements with the same criteria. Currently breakRow does not - consider on-the-fly spell-checking and selection changes, but it is - not clear to me that it is required. Moreover, this thing would only - work if we are sure that the Row object is up-to-date when drawing - happens. This depends on the update machinery. + consider on-the-fly spell-checking, but it is not clear to me that + it is required. Moreover, this thing would only work if we are sure + that the Row object is up-to-date when drawing happens. This depends + on the update machinery. This would allow to get rid of the Bidi.cpp code. + +* Change Row object to operate only on integers and not doubles. Then, + rewrite the computation of spacing in justified paragraphs so that + strings can be drawn without cutting at separators. This will improve + performance. diff --git a/src/Encoding.cpp b/src/Encoding.cpp index a6f6a60..e4bbbc0 100644 --- a/src/Encoding.cpp +++ b/src/Encoding.cpp @@ -42,190 +42,6 @@ Encodings::MathSymbolSet Encodings::mathsym; namespace { -char_type arabic_table[172][4] = { - {0xfe80, 0xfe80, 0xfe80, 0xfe80}, // 0x0621 = hamza - {0xfe81, 0xfe82, 0xfe81, 0xfe82}, // 0x0622 = ligature madda on alef - {0xfe83, 0xfe84, 0xfe83, 0xfe84}, // 0x0623 = ligature hamza on alef - {0xfe85, 0xfe86, 0xfe85, 0xfe86}, // 0x0624 = ligature hamza on waw - {0xfe87, 0xfe88, 0xfe87, 0xfe88}, // 0x0625 = ligature hamza under alef - {0xfe89, 0xfe8a, 0xfe8b, 0xfe8c}, // 0x0626 = ligature hamza on ya - {0xfe8d, 0xfe8e, 0xfe8d, 0xfe8e}, // 0x0627 = alef - {0xfe8f, 0xfe90, 0xfe91, 0xfe92}, // 0x0628 = baa - {0xfe93, 0xfe94, 0xfe93, 0xfe94}, // 0x0629 = taa marbuta - {0xfe95, 0xfe96, 0xfe97, 0xfe98}, // 0x062a = taa - {0xfe99, 0xfe9a, 0xfe9b, 0xfe9c}, // 0x062b = thaa - {0xfe9d, 0xfe9e, 0xfe9f, 0xfea0}, // 0x062c = jeem - {0xfea1, 0xfea2, 0xfea3, 0xfea4}, // 0x062d = haa - {0xfea5, 0xfea6, 0xfea7, 0xfea8}, // 0x062e = khaa - {0xfea9, 0xfeaa, 0xfea9, 0xfeaa}, // 0x062f = dal - - {0xfeab, 0xfeac, 0xfeab, 0xfeac}, // 0x0630 = thal - {0xfead, 0xfeae, 0xfead, 0xfeae}, // 0x0631 = ra - {0xfeaf, 0xfeb0, 0xfeaf, 0xfeb0}, // 0x0632 = zain - {0xfeb1, 0xfeb2, 0xfeb3, 0xfeb4}, // 0x0633 = seen - {0xfeb5, 0xfeb6, 0xfeb7, 0xfeb8}, // 0x0634 = sheen - {0xfeb9, 0xfeba, 0xfebb, 0xfebc}, // 0x0635 = sad - {0xfebd, 0xfebe, 0xfebf, 0xfec0}, // 0x0636 = dad - {0xfec1, 0xfec2, 0xfec3, 0xfec4}, // 0x0637 = tah - {0xfec5, 0xfec6, 0xfec7, 0xfec8}, // 0x0638
[LyX/master] Fix bug #9040: In RtL documents end-of-paragraph marker shifts the row display
commit 7167d90b505f9b98db3de00d081023afed473913 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Thu Mar 20 11:00:14 2014 +0100 Fix bug #9040: In RtL documents end-of-paragraph marker shifts the row display The fact that the bug was still present in the features/str-metrics branch comes from a goof in the initial implementation of 'virtual' row elements (completion and end-of-par markers). Now that this is corrected, everything works as it should. The fact that the bug is present in master is due to some other reason that is not useful to investigate now. diff --git a/src/Row.cpp b/src/Row.cpp index 15af2c2..6e60e97 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -282,7 +282,6 @@ void Row::add(pos_type const pos, char_type const c, Element e(STRING, pos, f, ch); elements_.push_back(e); } - //lyxerr << "FONT " <<back().font.language() << endl; back().str += c; back().endpos = pos + 1; } @@ -294,7 +293,8 @@ void Row::addVirtual(pos_type const pos, docstring const & s, finalizeLast(); Element e(VIRTUAL, pos, f, ch); e.str = s; - // A completion has no size + e.dim.wid = theFontMetrics(f).width(s); + dim_.wid += e.dim.wid; e.endpos = pos; elements_.push_back(e); finalizeLast();
[LyX/master] Fix breaking of loooong word in RTL languages
commit e1c4cb7146e0dfd25bb705178618da251bdfde8c Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon May 19 11:35:15 2014 +0200 Fix breaking of lng word in RTL languages Moreover, breaks row at insets when there is no suitable separator. Also make the code of Row::shorten_if_needed somewhat simpler by using iterators and factoring the code. Fixes: #9120 diff --git a/src/Row.cpp b/src/Row.cpp index a0c0dc4..1336d05 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -28,6 +28,8 @@ #include #include +#include + using namespace std; namespace lyx { @@ -98,6 +100,27 @@ pos_type Row::Element::x2pos(double ) const } +bool Row::Element::breakAt(double w) +{ + if (type != STRING || width() <= w) + return false; + + bool const rtl = font.isVisibleRightToLeft(); + if (rtl) + w = width() - w; + pos_type new_pos = x2pos(w); + if (new_pos == pos) + return false; + str = str.substr(0, new_pos - pos); + if (rtl) + dim.wid -= w; + else + dim.wid = w; + endpos = new_pos; + return true; +} + + pos_type Row::Element::left_pos() const { return font.isVisibleRightToLeft() ? endpos : pos; @@ -110,7 +133,6 @@ pos_type Row::Element::right_pos() const } - Row::Row() : separator(0), label_hfill(0), x(0), right_margin(0), sel_beg(-1), sel_end(-1), @@ -334,63 +356,63 @@ void Row::pop_back() } -void Row::shorten_if_needed(pos_type const keep, int const w) +void Row::shortenIfNeeded(pos_type const keep, int const w) { - if (empty() || width() < w) + if (empty() || width() <= w) return; /** First, we try to remove elements one by one from the end -* until a separator is found. +* until a separator is found. cit points to the first element +* we want to remove from the row. */ - int i = elements_.size(); + Elements::iterator const beg = elements_.begin(); + Elements::iterator const end = elements_.end(); + Elements::iterator cit = end; + Elements::iterator first_below = end; int new_end = end_; int new_wid = dim_.wid; - if (i > 0 && elements_[i - 1].type == SEPARATOR && new_end > keep) { - --i; - new_end = elements_[i].pos; - new_wid -= elements_[i].dim.wid; + // if the row ends with a separator, skip it. + if (cit != beg && boost::prior(cit)->type == SEPARATOR && new_end > keep) { + --cit; + new_end = cit->pos; + new_wid -= cit->dim.wid; } - while (i > 0 && elements_[i - 1].type != SEPARATOR && new_end > keep) { - --i; - new_end = elements_[i].pos; - new_wid -= elements_[i].dim.wid; + // Search for a separator where the row can be broken. + while (cit != beg && boost::prior(cit)->type != SEPARATOR && new_end > keep) { + --cit; + new_end = cit->pos; + new_wid -= cit->dim.wid; + if (new_wid < w && first_below == end) + first_below = cit; } - if (i == 0) { - /* If we are here, it means that we have not found a -* separator to shorten the row. There is one case -* where we can do something: when we have one big -* string, maybe with a paragraph marker after it. -*/ - Element & front = elements_.front(); - if (!(front.type == STRING - && (elements_.size() == 1 - || (elements_.size() == 2 - && back().type == VIRTUAL - return; - - // If this is a string element, we can try to split it. - if (front.type != STRING) - return; - double xstr = w - x; - // If there is a paragraph marker, it should be taken in account - if (elements_.size() == 2) - xstr -= back().width(); - //FIXME: use FontMetrics::x2pos here?? handle rtl? - pos_type new_pos = front.x2pos(xstr); - front.str = front.str.substr(0, new_pos - pos_); - front.dim.wid = xstr; - front.endpos = new_pos; - end_ = new_pos; - dim_.wid = x + xstr; - // If there is a paragraph marker, it should be removed. - if (elements_.size() == 2) - elements_.pop_back(); + + if (cit != beg) { + // We have found a suitable separator. This is the + // common case. +
[LyX/master] Remove LyXRC option force_paint_single_char
commit 9d5c9471104cedc4600daab101ef1958f48dab76 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue Jul 8 23:12:09 2014 +0200 Remove LyXRC option force_paint_single_char It was not honored anymore. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 1292390..7095f9f 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -31,8 +31,8 @@ What is done: * Re-implement cursorX and getPosNearX using row elements. -* Do not honor lyxrc.force_paint_single_char anymore. This is a - workaround that is not necessary anymore. +* Get rid of lyxrc.force_paint_single_char. This was a workaround that + is not necessary anymore. * Implement proper string metrics computation (with cache). Remove useless workarounds which disable kerning and ligatures. @@ -53,7 +53,4 @@ What is done: Next steps: -* Get rid of LyXRC::force_paint_single_char, which is not used anymore - in the source. - * Maybe get rid of LyXRC::rtl_support, which does not have a real use case. diff --git a/lib/configure.py b/lib/configure.py index c8e8267..f0b7166 100644 --- a/lib/configure.py +++ b/lib/configure.py @@ -1479,7 +1479,7 @@ if __name__ == '__main__': lyx_check_config = True lyx_kpsewhich = True outfile = 'lyxrc.defaults' -lyxrc_fileformat = 15 +lyxrc_fileformat = 16 rc_entries = '' lyx_keep_temps = False version_suffix = '' diff --git a/lib/scripts/prefs2prefs_prefs.py b/lib/scripts/prefs2prefs_prefs.py index 66423ae..4770fbf 100644 --- a/lib/scripts/prefs2prefs_prefs.py +++ b/lib/scripts/prefs2prefs_prefs.py @@ -63,6 +63,13 @@ # New RC default_otf_view_format # No conversion necessary. +# Incremented to format 15, by prannoy +# Add fullscreen_statusbar +# No conversion necessary. + +# Incremented to format 16, by lasgouttes +# Remove force_paint_single_char rc. + # NOTE: The format should also be updated in LYXRC.cpp and # in configure.py. @@ -306,6 +313,17 @@ def mac_cursor_movement(line): +# +# Conversions from LyX 2.1 to 2.2 + +def remove_force_paint_single_char(line): + if not line.lower().startswith("\\force_paint_single_char"): + return no_match + return (True, "") + +# End conversions for LyX 2.1 to 2.2 + + conversions = [ [ 1, [ # there were several conversions for format 1 export_menu, @@ -327,5 +345,6 @@ conversions = [ [ 12, []], [ 13, [mac_cursor_movement]], [ 14, []], - [ 15, []] + [ 15, []], + [ 16, [remove_force_paint_single_char]] ] diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp index 0138f61..46309ee 100644 --- a/src/LyXRC.cpp +++ b/src/LyXRC.cpp @@ -58,7 +58,7 @@ namespace { // The format should also be updated in configure.py, and conversion code // should be added to prefs2prefs_prefs.py. -static unsigned int const LYXRC_FILEFORMAT = 15; // prannoy: statusbar on/off in full screen +static unsigned int const LYXRC_FILEFORMAT = 16; // lasgouttes: remove \\force_paint_single_char // when adding something to this array keep it sorted! LexerKeyword lyxrcTags[] = { @@ -106,7 +106,6 @@ LexerKeyword lyxrcTags[] = { { "\\example_path", LyXRC::RC_EXAMPLEPATH }, { "\\export_overwrite", LyXRC::RC_EXPORT_OVERWRITE }, { "\\font_encoding", LyXRC::RC_FONT_ENCODING }, - { "\\force_paint_single_char", LyXRC::RC_FORCE_PAINT_SINGLE_CHAR }, { "\\format", LyXRC::RC_FILEFORMAT }, { "\\forward_search_dvi", LyXRC::RC_FORWARD_SEARCH_DVI }, { "\\forward_search_pdf", LyXRC::RC_FORWARD_SEARCH_PDF }, @@ -447,10 +446,6 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format) if (!lexrc.isOK()) return ReadError; - // default for current rowpainter capabilities - //force_paint_single_char = true; - force_paint_single_char = false; - // format prior to 2.0 and introduction of format tag unsigned int format = 0; @@ -556,10 +551,6 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format) lexrc >> fontenc; break; - case RC_FORCE_PAINT_SINGLE_CHAR: - lexrc >> force_paint_single_char; - break; - case RC_PRINTER: lexrc >> printer; break; @@ -,14 +2213,6 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c if (tag != RC_LAST) break; - case RC_FORCE_PAINT_SINGLE_CHAR: - if (ignore_system_lyxrc || - force_paint_single_char != system_
[LyX/master] Some fixes related to RTL text
commit 8649ac7fe66ac0efca20918fff2fea051cc88512 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed Mar 19 14:44:53 2014 +0100 Some fixes related to 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; * 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 9da174f..d074d73 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -64,27 +64,26 @@ pos_type Row::Element::x2pos(double , 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 diff --git a/src/Row.h b/src/Row.h index 2282c82..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(); } diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index ca6408d..8563975 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 @@ -810,8 +810,8 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit int const
[LyX/master] Speed-up drawing when text is not justified.
commit 7734270163ed1e689dc5f7db06a85f876f96f399 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri May 2 15:03:20 2014 +0200 Speed-up drawing when text is not justified. Do not cut strings at separators in RowPainter when text is not justified. This speeds-up painting by reducing the number of strings to draw. Do also a modest cleanup of paintChar (remove dubious optimization). diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index e7a6f29..73f5ed3 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -40,16 +40,16 @@ What is done: useless workarounds which disable kerning and ligatures. * when lyxrc.force_paint_single_char is false, draw also RtL text - string-wise. This both speed-up drawing and prepare for code + string-wise. This both speeds-up drawing and prepares for code removal, since we now rely on Qt to do things we use to do by ourselves (see isArabic* and isHebrew* code in Encodings.cpp). +* Do not cut strings at separators in RowPainter when text is not + justified. This speeds-up painting by reducing the number of strings + to draw. -Next steps: -* investigate whether strings could be cut at separators in RowPainter - only in justified text. This would speed-up painting in other cases - by lowering the number of strings to draw. +Next steps: * get lots of testing. diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp index b0708bf..8286ec7 100644 --- a/src/rowpainter.cpp +++ b/src/rowpainter.cpp @@ -165,10 +165,9 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) // This method takes up 70% of time when typing pos_type pos = bidi_.vis2log(vpos); // first character - char_type prev_char = par_.getChar(pos); - vector str; + char_type c = par_.getChar(pos); + docstring str; str.reserve(100); - str.push_back(prev_char); // special case for arabic string const & lang = font.language()->lang(); @@ -179,13 +178,12 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) // FIXME: Why only round brackets and why the difference to // Hebrew? See also Paragraph::getUChar if (swap_paren) { - char_type c = str[0]; if (c == '(') c = ')'; else if (c == ')') c = '('; - str[0] = c; } + str.push_back(c); pos_type const end = row_.endpos(); FontSpan const font_span = par_.fontSpan(pos); @@ -230,7 +228,8 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) if (c == '\t') break; - if (!isPrintableNonspace(c)) + if (!isPrintableNonspace(c) + && (c != ' ' || row_.separator > 0)) break; // FIXME: Why only round brackets and why the difference to @@ -243,13 +242,10 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) } str.push_back(c); - prev_char = c; } - docstring s([0], str.size()); - - if (s[0] == '\t') - s.replace(0,1,from_ascii("")); + if (str[0] == '\t') + str.replace(0,1,from_ascii("")); /* Because we do our own bidi, at this point the strings are * already in visual order. However, Qt also applies its own @@ -267,13 +263,13 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) // Pop directional formatting: return to previous state char_type const PDF = 0x202C; if (font.isVisibleRightToLeft()) { - reverse(s.begin(), s.end()); - s = RLO + s + PDF; + reverse(str.begin(), str.end()); + str = RLO + str + PDF; } else - s = LRO + s + PDF; + str = LRO + str + PDF; if (!selection && !change_running.changed()) { - x_ += pi_.pain.text(int(x_), yo_, s, font.fontInfo()); + x_ += pi_.pain.text(int(x_), yo_, str, font.fontInfo()); return; } @@ -283,7 +279,7 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) else if (selection) copy.setPaintColor(Color_selectiontext); - x_ += pi_.pain.text(int(x_), yo_, s, copy); + x_ += pi_.pain.text(int(x_), yo_, str, copy); }
[LyX/master] Revert optimization where several words are drawn at the same time
commit bbe6e9f593fc585ee9f5d69275487bf3ddbcaf47 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sun Jul 20 18:54:31 2014 +0200 Revert optimization where several words are drawn at the same time This can only be done where splitting of string is identical in row breaking and display. It will be possible to reintroduce this when row painting uses the tokenized row information. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index e901b51..342d2f6 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -39,10 +39,6 @@ What is done: * Draw also RtL text string-wise. This speeds-up drawing. -* Do not cut strings at separators in RowPainter when text is not - justified. This speeds-up painting by reducing the number of strings - to draw. - * Do not cut strings at selection boundary in RowPainter. This avoids ligature/kerning breaking in latin text, and bad rendering problems in Arabic. diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 4dde5fd..45a5007 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -565,7 +565,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit, Paragraph const & par = text_->getPar(pit); - double w = width - row.right_margin - row.width(); + double const w = width - row.right_margin - row.width(); // FIXME: put back this assertion when the crash on new doc is solved. //LASSERT(w >= 0, /**/); @@ -607,9 +607,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit, } else if (int(row.width()) < max_width_) { // is it block, flushleft or flushright? // set x how you need it - int const align = getAlign(par, row.pos()); - - switch (align) { + switch (getAlign(par, row.pos())) { case LYX_ALIGN_BLOCK: { int const ns = numberOfSeparators(row); /** If we have separators, and this row has @@ -650,12 +648,12 @@ void TextMetrics::computeRowMetrics(pit_type const pit, } #endif + // Finally, handle hfill insets pos_type const endpos = row.endpos(); pos_type body_pos = par.beginOfBody(); if (body_pos > 0 && (body_pos > endpos || !par.isLineSeparator(body_pos - 1))) body_pos = 0; - ParagraphMetrics & pm = par_metrics_[pit]; Row::iterator cit = row.begin(); Row::iterator const cend = row.end(); @@ -798,8 +796,7 @@ 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.x = leftMargin(max_width_, pit, pos); - row.dimension().wid = row.x; + row.dimension().wid = leftMargin(max_width_, pit, pos); row.right_margin = right_margin; if (pos >= end || row.width() > width) { diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp index a33aebf..2b51f47 100644 --- a/src/frontends/qt4/GuiPainter.cpp +++ b/src/frontends/qt4/GuiPainter.cpp @@ -273,14 +273,14 @@ void GuiPainter::image(int x, int y, int w, int h, graphics::Image const & i) int GuiPainter::text(int x, int y, char_type c, FontInfo const & f) { - docstring s(1, c); - return text(x, y, s, f); + return text(x, y, docstring(1, c), f); } int GuiPainter::text(int x, int y, docstring const & s, FontInfo const & f) { + //LYXERR0("text: x=" << x << ", s=" << s); if (s.empty()) return 0; diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp index ee4cd18..8c8ac4c 100644 --- a/src/rowpainter.cpp +++ b/src/rowpainter.cpp @@ -186,16 +186,15 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) } str.push_back(c); - pos_type const end = row_.endpos(); FontSpan const font_span = par_.fontSpan(pos); // Track-change status. Change const & change_running = par_.lookupChange(pos); - // spelling correct? bool const spell_state = lyxrc.spellcheck_continuously && par_.isMisspelled(pos); // collect as much similar chars as we can + pos_type const end = row_.endpos(); for (++vpos ; vpos < end ; ++vpos) { pos = bidi_.vis2log(vpos); @@ -218,11 +217,7 @@ void RowPainter::paintChars(pos_type & vpos, Font const & font) if (c == '\t') break; - // When row_.separator == 0, it is possible to print a - // string longer than a word in one fell swoop. - // Therefore there is no need to break at spaces. - if (!isPrintableNonspace(c)
[LyX/master] More fixes to cursorX
commit 79014c7551de71488bb18e58ae8344cdbbde9490 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Oct 18 17:55:30 2013 +0200 More fixes to cursorX In Row::Element::pos2x, handle the boundaries in a cleaner way. diff --git a/src/Row.cpp b/src/Row.cpp index d074d73..d7940e9 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -36,17 +36,23 @@ using frontend::FontMetrics; double Row::Element::pos2x(pos_type const i) const { + LASSERT(i >= pos && i <= endpos, return 0); + bool const rtl = font.isVisibleRightToLeft(); - // handle first the two bounds of the element - if ((!rtl && pos >= i) || (rtl && endpos <= i)) - return 0; - if ((!rtl && endpos <= i) || (rtl && pos >= i)) - return width(); + int w = 0; + //handle first the two bounds of the element + if (i == pos) + w = 0; + else if (i == endpos) + w = width(); + else { + LASSERT(type == STRING, return 0); + FontMetrics const & fm = theFontMetrics(font); + // FIXME Avoid caching of metrics there? + w = fm.width(str.substr(0, i - pos)); + } - FontMetrics const & fm = theFontMetrics(font); - // FIXME Avoid caching of metrics there? - int const w = fm.width(str.substr(0, i - pos)); if (rtl) return width() - w; else diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 8563975..b894133 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -1613,15 +1613,16 @@ int TextMetrics::cursorX(CursorSlice const & sl, double x = row.x; /** -* When boundary is true, position is on the row element (pos, endpos) +* When boundary is true, position i is in the row element (pos, endpos) * if -*pos < pos <= endpos +*pos < i <= endpos * whereas, when boundary is false, the test is -*pos <= pos < endpos +*pos <= i < endpos * The correction below allows to handle both cases. */ int const boundary_corr = (boundary && pos) ? -1 : 0; + //? if (row.empty() || (row.begin()->font.isVisibleRightToLeft() && pos == row.begin()->endpos))
[LyX/master] Re-implement getColumNearX using row elements
commit f215bb3b926d8b7d9240f0f08793fc3d731d5398 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sun Jul 21 20:22:32 2013 +0200 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. diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH index 7c87c0a..0727011 100644 --- a/00README_STR_METRICS_BRANCH +++ b/00README_STR_METRICS_BRANCH @@ -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 diff --git a/src/Row.cpp b/src/Row.cpp index 9e40986..c32be85 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -54,8 +54,58 @@ double Row::Element::pos2x(pos_type const i) const } +pos_type Row::Element::x2pos(double ) 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 &am
[LyX/master] Reintroduce the code related to InsetEnvSeparator
commit f3924a52b32cdddec0fbcac40d631a3f27761e37 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Jun 30 11:45:24 2014 +0200 Reintroduce the code related to InsetEnvSeparator This commits (tries to) reintroduce properly the code that was reverted at the beginning of this branch. This had to be done because these patches interefered with the big refactoring of TextMetrics.cpp. This commit reintroduces the changes to TextMetrics.cpp contained in c668ebf6, c85dbfea9 and 061509bf. diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index bda3b2f..c168998 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -346,6 +346,7 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos, // FED FED| FED ) if (startpos == pos && endpos == pos && endpos != par.size() && (par.isNewline(pos - 1) + || par.isEnvSeparator(pos - 1) || par.isLineSeparator(pos - 1) || par.isSeparator(pos - 1))) return false; @@ -680,7 +681,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit, int TextMetrics::labelFill(pit_type const pit, Row const & row) const { Paragraph const & par = text_->getPar(pit); - LBUFERR(par.beginOfBody() > 0); + LBUFERR(par.beginOfBody() > 0 || par.isEnvSeparator(0)); int w = 0; Row::const_iterator cit = row.begin(); @@ -876,7 +877,7 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit // - Before a display inset // - After a display inset Inset const * inset = 0; - if (par.isNewline(i) + if (par.isNewline(i) || par.isEnvSeparator(i) || (i + 1 < end && (inset = par.getInset(i + 1)) && inset->display()) || (!row.empty() && row.back().inset @@ -1547,7 +1548,8 @@ bool TextMetrics::cursorEnd(Cursor & cur) bool boundary = false; if (end != cur.lastpos()) { if (!cur.paragraph().isLineSeparator(end-1) - && !cur.paragraph().isNewline(end-1)) + && !cur.paragraph().isNewline(end-1) + && !cur.paragraph().isEnvSeparator(end-1)) boundary = true; else --end; @@ -1630,7 +1632,9 @@ int TextMetrics::leftMargin(int max_width, l_margin = leftMargin(max_width, newpar); // Remove the parindent that has been added // if the paragraph was empty. - if (pars[newpar].empty()) { + if (pars[newpar].empty() && + buffer.params().paragraph_separation == + BufferParams::ParagraphIndentSeparation) { docstring pi = pars[newpar].layout().parindent; l_margin -= theFontMetrics( buffer.params().getFont()).signedWidth(pi); @@ -1648,10 +1652,16 @@ int TextMetrics::leftMargin(int max_width, // This happens after sections or environments in standard classes. // We have to check the previous layout at same depth. - if (tclass.isDefaultLayout(par.layout()) && pit > 0 - && pars[pit - 1].getDepth() >= par.getDepth()) { + if (buffer.params().paragraph_separation == + BufferParams::ParagraphSkipSeparation) + parindent.erase(); + else if (pit > 0 && pars[pit - 1].getDepth() >= par.getDepth()) { pit_type prev = text_->depthHook(pit, par.getDepth()); - if (pars[prev < pit ? prev : pit - 1].layout().nextnoindent) + if (par.layout() == pars[prev].layout()) { + if (prev != pit - 1 + && pars[pit - 1].layout().nextnoindent) + parindent.erase(); + } else if (pars[prev].layout().nextnoindent) parindent.erase(); }
[LyX/master] Add a readme file describing the state of the branch
commit b044696d592b1602015828eb3db66c54562751c9 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue Jun 18 10:18:32 2013 +0200 Add a readme file describing the state of the branch diff --git a/00README_STR_METRICS_BRANCH b/00README_STR_METRICS_BRANCH new file mode 100644 index 000..b34ba5b --- /dev/null +++ b/00README_STR_METRICS_BRANCH @@ -0,0 +1,31 @@ +This branch is where I (jmarc) try to implement string_wise metrics +computation. This is done through a series of cleanups. The expected +speed improvement will only be visible at the end of the road: indeed +for now we intend to keep unchanged behavior for testing purposes. + +What is done: +* Make TextMetrics methods operate on Row objects: breakRow and +setRowHeight instead of rowBreakPoint and rowHeight. +* change breakRow operation to operate on text strings on which +metrics are computed. Note that for now FontMetrics::width(docstring) +still computes the sum of character widths, so that behavior is +unchanged. + +Next steps: +* Make breakRow build a list of elements (string, inset, +separator,...) in the row. This will be reused by other methods +* get rid of rowWidth (breakRow does compute this) +* re-implement getColumnNearX using row elements +* re-implement x2pos using row elements +* re-implement row painting using row elements +* Finally, implement proper string metrics computation (with cache) +* profile and see how performance can be improved. + +Difference in behavior +* words longer than the screen are no monger broken at an arbitrary +point. This will not be useful anymore with horizontal scrolling. +* end of paragraph markers metrics are computed with the font of the +actual text, not default font. This will be extended to the other +methods. + +The other differences should be considered as bugs.
[LyX/master] Cleanup TextMetrics::rowBreakPoint.
commit fe8c3b4348b47099171957ea76daf9ccc019a5d1 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Jun 14 00:01:49 2013 +0200 Cleanup TextMetrics::rowBreakPoint. Collect properly all strings to compute string metrics Some changes with respect to existing code - end of paragraph font is now the one of the text - words longer than a line are not broken anymore. I think this is not useful if we have horizontal scrollbar Other than that, the code is still compatible with rowWidth and friends. diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 66771d4..3026367 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -27,6 +27,7 @@ #include "CoordCache.h" #include "Cursor.h" #include "CutAndPaste.h" +#include "Encoding.h" #include "HSpace.h" #include "InsetList.h" #include "Layout.h" @@ -800,26 +801,25 @@ private: } // anon namespace -pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit, - pos_type pos) const +pos_type TextMetrics::rowBreakPoint(int const width, pit_type const pit, + pos_type const pos) const { - ParagraphMetrics const & pm = par_metrics_[pit]; Paragraph const & par = text_->getPar(pit); pos_type const end = par.size(); if (pos == end || width < 0) return end; - Layout const & layout = par.layout(); + ParagraphMetrics const & pm = par_metrics_[pit]; + ParagraphList const & pars = text_->paragraphs(); #if 0 //FIXME: As long as leftMargin() is not correctly implemented for // MARGIN_RIGHT_ADDRESS_BOX, we should also not do this here. // Otherwise, long rows will be painted off the screen. - if (layout.margintype == MARGIN_RIGHT_ADDRESS_BOX) + if (par.layout().margintype == MARGIN_RIGHT_ADDRESS_BOX) return addressBreakPoint(pos, par); #endif - pos_type const body_pos = par.beginOfBody(); // check for possible inline completion DocIterator const & inlineCompletionPos = bv_->inlineCompletionPos(); @@ -831,70 +831,69 @@ pos_type TextMetrics::rowBreakPoint(int width, pit_type const pit, inlineCompletionLPos = inlineCompletionPos.pos() - 1; } - // Now we iterate through until we reach the right margin - // or the end of the par, then choose the possible break - // nearest that. - - int label_end = labelEnd(pit); int const left = leftMargin(max_width_, pit, pos); + pos_type const body_pos = par.beginOfBody(); int x = left; - - // pixel width since last breakpoint - int chunkwidth = 0; - - docstring const s(1, char_type(0x00B6)); - Font f; - int par_marker_width = theFontMetrics(f).width(s); + pos_type point = end; FontIterator fi = FontIterator(*this, par, pit, pos); - pos_type point = end; - pos_type i = pos; + // Accumulator for character strings + docstring chunkstr; + Font chunkfont = *fi; - ParagraphList const & pars_ = text_->paragraphs(); - bool const draw_par_end_marker = lyxrc.paragraph_markers - && size_type(pit + 1) < pars_.size(); + // Now we iterate through until we reach the right margin + // or the end of the par, then choose the possible break + // nearest that. + pos_type i = pos; for ( ; i < end; ++i, ++fi) { - int thiswidth = pm.singleWidth(i, *fi); + // Add the chunk width when it is finished + if (par.isInset(i) || *fi != chunkfont + || (body_pos && i == body_pos)) { + x += theFontMetrics(chunkfont).width(chunkstr); + chunkstr.clear(); + chunkfont = *fi; + } + + char_type c = par.getChar(i); + Language const * language = fi->language(); + // The most special cases are handled first. + if (par.isInset(i)) { + x += pm.insetDimension(par.getInset(i)).wid; + } else if (c == '\t') + chunkstr += ""; + else if (language->rightToLeft()) { + if (language->lang() == "arabic_arabtex" || + language->lang() == "arabic_arabi" || + language->lang() == "farsi") { + if (!Encodings::isArabicComposeChar(c)) + chunkstr += par.transformChar(c, i); + } else if (language->lang() == "hebrew" && + !Encodings::isHebrewComposeChar(c)) { +
[LyX/master] Rename rowpainter.* to RowPainter.*
commit b54deb36839c97886ac9ff607e248cf16b0443c7 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Jul 25 21:55:08 2014 +0200 Rename rowpainter.* to RowPainter.* This is the convention for files that define classes. diff --git a/src/Makefile.am b/src/Makefile.am index e40a3bc..17bad02 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -168,7 +168,7 @@ SOURCEFILESCORE = \ ParIterator.cpp \ PDFOptions.cpp \ Row.cpp \ - rowpainter.cpp \ + RowPainter.cpp \ Server.cpp \ ServerSocket.cpp \ sgml.cpp \ @@ -273,7 +273,7 @@ HEADERFILESCORE = \ ParIterator.h \ PDFOptions.h \ Row.h \ - rowpainter.h \ + RowPainter.h \ Server.h \ ServerSocket.h \ Session.h \ diff --git a/src/RowPainter.cpp b/src/RowPainter.cpp new file mode 100644 index 000..bf9f280 --- /dev/null +++ b/src/RowPainter.cpp @@ -0,0 +1,975 @@ +/** + * \file RowPainter.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author various + * \author John Levon + * + * Full author contact details are available in file CREDITS. + */ + +#include +#include + +#include "RowPainter.h" + +#include "Buffer.h" +#include "CoordCache.h" +#include "Cursor.h" +#include "BufferParams.h" +#include "BufferView.h" +#include "Changes.h" +#include "Language.h" +#include "Layout.h" +#include "LyXRC.h" +#include "Row.h" +#include "MetricsInfo.h" +#include "Paragraph.h" +#include "ParagraphMetrics.h" +#include "ParagraphParameters.h" +#include "TextMetrics.h" +#include "VSpace.h" + +#include "frontends/FontMetrics.h" +#include "frontends/Painter.h" + +#include "insets/InsetText.h" + +#include "mathed/InsetMath.h" + +#include "support/debug.h" +#include "support/gettext.h" +#include "support/textutils.h" + +#include "support/lassert.h" +#include + +using namespace std; + +namespace lyx { + +using frontend::Painter; +using frontend::FontMetrics; + + +RowPainter::RowPainter(PainterInfo & pi, + Text const & text, pit_type pit, Row const & row, int x, int y) + : pi_(pi), text_(text), + text_metrics_(pi_.base.bv->textMetrics()), + pars_(text.paragraphs()), + row_(row), pit_(pit), par_(text.paragraphs()[pit]), + pm_(text_metrics_.parMetrics(pit)), change_(pi_.change_), + xo_(x), yo_(y), width_(text_metrics_.width()), + solid_line_thickness_(1.0), solid_line_offset_(1), + dotted_line_thickness_(1.0), dotted_line_offset_(2) +{ + bidi_.computeTables(par_, pi_.base.bv->buffer(), row_); + + if (lyxrc.zoom >= 200) { + // derive the line thickness from zoom factor + // the zoom is given in percent + // (increase thickness at 250%, 450% etc.) + solid_line_thickness_ = (float)(int((lyxrc.zoom + 50) / 200.0)); + // adjust line_offset_ too + solid_line_offset_ = 1 + int(0.5 * solid_line_thickness_); + } + if (lyxrc.zoom >= 100) { + // derive the line thickness from zoom factor + // the zoom is given in percent + // (increase thickness at 150%, 250% etc.) + dotted_line_thickness_ = (float)(int((lyxrc.zoom + 50) / 100.0)); + // adjust line_offset_ too + dotted_line_offset_ = int(0.5 * dotted_line_thickness_) + 1; + } + + x_ = row_.x + xo_; + + //lyxerr << "RowPainter: x: " << x_ << " xo: " << xo_ << " yo: " << yo_ << endl; + //row_.dump(); + + LBUFERR(pit >= 0); + LBUFERR(pit < int(text.paragraphs().size())); +} + + +FontInfo RowPainter::labelFont() const +{ + FontInfo f = text_.labelFont(par_); + // selected text? + if (row_.begin_margin_sel || pi_.selected) + f.setPaintColor(Color_selectiontext); + return f; +} + + +int RowPainter::leftMargin() const +{ + return text_metrics_.leftMargin(text_metrics_.width(), pit_, + row_.pos()); +} + +// If you want to debug inset metrics uncomment the following line: +//#define DEBUG_METRICS +// This draws green lines around each inset. + + +void RowPainter::paintInset(Inset const * inset, pos_type const pos) +{ + Font const font = text_metrics_.displayFont(pit_, pos); + + LASSERT(inset, return); + // Backup full_repaint status because some insets (InsetTabular) + // requires a full repaint + bool pi_full_repaint = pi_.full_repaint; + + pi_.base.font = inset->inheritFont() ? font.fontInfo() : +
[LyX/master] Whitespace only
commit 5e126d2920df9fd48d24967f7b0a4a04e61aac65 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Jul 25 22:35:08 2014 +0200 Whitespace only diff --git a/src/BufferView.cpp b/src/BufferView.cpp index bc8162b..faa08f0 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -118,12 +118,12 @@ bool findNextInset(DocIterator & dit, vector const & codes, while (tmpdit) { Inset const * inset = tmpdit.nextInset(); if (inset) { - bool const valid_code = std::find(codes.begin(), codes.end(), + bool const valid_code = std::find(codes.begin(), codes.end(), inset->lyxCode()) != codes.end(); InsetCommand const * ic = inset->asInsetCommand(); bool const same_or_no_contents = contents.empty() || (ic && (ic->getFirstNonOptParam() == contents)); - + if (valid_code && same_or_no_contents) { dit = tmpdit; return true; @@ -228,7 +228,7 @@ struct BufferView::Private Private(BufferView & bv): wh_(0), cursor_(bv), anchor_pit_(0), anchor_ypos_(0), inlineCompletionUniqueChars_(0), - last_inset_(0), clickable_inset_(false), + last_inset_(0), clickable_inset_(false), mouse_position_cache_(), bookmark_edit_position_(-1), gui_(0) {} @@ -325,9 +325,9 @@ BufferView::~BufferView() fp.pit = d->cursor_.bottom().pit(); fp.pos = d->cursor_.bottom().pos(); theSession().lastFilePos().save(buffer_.fileName(), fp); - + if (d->last_inset_) - d->last_inset_->setMouseHover(this, false); + d->last_inset_->setMouseHover(this, false); delete d; } @@ -498,7 +498,7 @@ void BufferView::updateScrollbar() d->scrollbarParameters_.page_step = height_; Text & t = buffer_.text(); - TextMetrics & tm = d->text_metrics_[]; + TextMetrics & tm = d->text_metrics_[]; LYXERR(Debug::GUI, " Updating scrollbar: height: " << t.paragraphs().size() @@ -658,7 +658,7 @@ void BufferView::setCursorFromScrollbar() case CUR_INSIDE: int const y = getPos(oldcur).y_; newy = min(last, max(y, first)); - if (y == newy) + if (y == newy) return; } // We reset the cursor because cursorStatus() does not @@ -778,7 +778,7 @@ bool BufferView::moveToPosition(pit_type bottom_pit, pos_type bottom_pos, // the bookmark. if (bottom_pit < int(buffer_.paragraphs().size())) { dit = doc_iterator_begin(_); - + dit.pit() = bottom_pit; dit.pos() = min(bottom_pos, dit.paragraph().size()); success = true; @@ -958,7 +958,7 @@ void BufferView::makeDocumentClass() void BufferView::updateDocumentClass(DocumentClassConstPtr olddc) { message(_("Converting document to new document class...")); - + StableDocIterator backcur(d->cursor_); ErrorList & el = buffer_.errorList("Class Switch"); cap::switchBetweenClasses( @@ -1222,7 +1222,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) Cursor & cur = d->cursor_; // Don't dispatch function that does not apply to internal buffers. - if (buffer_.isInternal() + if (buffer_.isInternal() && lyxaction.funcHasFlag(cmd.action(), LyXAction::NoInternal)) return; @@ -1246,7 +1246,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) << (unknown_tokens == 1 ? "" : "s")); } updateDocumentClass(olddc); - + // We are most certainly here because of a change in the document // It is then better to make sure that all dialogs are in sync with // current document settings. @@ -1254,7 +1254,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) dr.forceBufferUpdate(); break; } - + case LFUN_LAYOUT_MODULES_CLEAR: { cur.recordUndoFullDocument(); buffer_.params().clearLayoutModules(); @@ -1267,7 +1267,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) case LFUN_LAYOUT_MODULE_ADD: { BufferParams const &a
[LyX features/scroll-reloaded] Fine tune the scroll offset setting code
The branch, scroll-reloaded, has been updated. - Log - commit b5e4ba6fa7cf3937a09eed143f4e17f236afe424 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sat Jul 26 16:25:56 2014 +0200 Fine tune the scroll offset setting code The new code should feel a bit more natural. It avoids explicit pixel values for the margins and does not scroll in some cases where it is not necessary. diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 4bd1c12..e4e2a83 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -35,6 +35,7 @@ #include "Language.h" #include "LaTeXFeatures.h" #include "LayoutFile.h" +#include "Length.h" #include "Lexer.h" #include "LyX.h" #include "LyXAction.h" @@ -2937,20 +2938,17 @@ void BufferView::checkCursorScrollOffset(PainterInfo & pi) // Horizontal scroll offset of the cursor row in pixels int offset = d->horiz_scroll_offset_; - int const MARGIN = 10; + int const MARGIN = Length(2, Length::EM).inPixels(workWidth()); if (cur_x < offset + MARGIN) { // scroll right offset = cur_x - MARGIN; } else if (cur_x > offset + workWidth() - MARGIN) { // scroll left offset = cur_x - workWidth() + MARGIN; - } else if(offset > 0 - && row.width() - offset < workWidth()){ - offset = row.width() - workWidth(); } - if (offset != d->horiz_scroll_offset_) - LYXERR0("Offset is now " << offset); + if (offset < 0 || row.width() <= workWidth()) + offset = 0; if (d->update_strategy_ == NoScreenUpdate && (offset != d->horiz_scroll_offset_ --- Summary of changes: src/BufferView.cpp | 10 -- 1 files changed, 4 insertions(+), 6 deletions(-) hooks/post-receive -- Repository for new features
[LyX/master] Whitespace
commit 7f7dc5d314791ed6894d9d18cda032f32093af21 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sat Jul 26 16:29:23 2014 +0200 Whitespace diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index 8a8c212..ac8e723 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -542,7 +542,7 @@ InsetTableCell splitCell(InsetTableCell & head, docstring const & align_d, bool if (hassep) { pit_type const psize = head.paragraphs().front().size(); head.paragraphs().front().eraseChars(dit.pos(), psize, false); - tail.paragraphs().front().eraseChars(0, + tail.paragraphs().front().eraseChars(0, dit.pos() < psize ? dit.pos() + 1 : psize, false); } @@ -738,9 +738,9 @@ void Tabular::appendRow(row_type row) void Tabular::insertRow(row_type const row, bool copy) { row_info.insert(row_info.begin() + row + 1, RowData(row_info[row])); - cell_info.insert(cell_info.begin() + row + 1, + cell_info.insert(cell_info.begin() + row + 1, cell_vector(0, CellData(buffer_))); - + for (col_type c = 0; c < ncols(); ++c) { cell_info[row + 1].insert(cell_info[row + 1].begin() + c, copy ? CellData(cell_info[row][c]) : CellData(buffer_)); @@ -749,7 +749,7 @@ void Tabular::insertRow(row_type const row, bool copy) if (cell_info[row][c].multirow == CELL_BEGIN_OF_MULTIROW) cell_info[row + 1][c].multirow = CELL_PART_OF_MULTIROW; } - + updateIndexes(); for (col_type c = 0; c < ncols(); ++c) { if (isPartOfMultiRow(row, c)) @@ -846,7 +846,7 @@ void Tabular::copyColumn(col_type const col) void Tabular::appendColumn(col_type col) -{ +{ insertColumn(col, false); } @@ -1029,7 +1029,7 @@ bool Tabular::updateColumnWidths() if (columnSpan(i) == 1) { if (getAlignment(i) == LYX_ALIGN_DECIMAL && cell_info[r][c].decimal_width!=0) - new_width = max(new_width, cellInfo(i).width + new_width = max(new_width, cellInfo(i).width + max_dwidth[c] - cellInfo(i).decimal_width); else new_width = max(new_width, cellInfo(i).width); @@ -1098,8 +1098,8 @@ void Tabular::setAlignment(idx_type cell, LyXAlignment align, if (align == LYX_ALIGN_DECIMAL && dpoint.empty()) dpoint = from_utf8(lyxrc.default_decimal_point); } else { - cellInfo(cell).alignment = align; - cellInset(cell).get()->setContentAlignment(align); + cellInfo(cell).alignment = align; + cellInset(cell).get()->setContentAlignment(align); } } @@ -1289,7 +1289,7 @@ bool Tabular::columnRightLine(col_type c) const idx_type i = cellIndex(r, c); if (c == cellColumn(i) + columnSpan(i) - 1) { ++total; - bool left = (c + 1 < ncols() + bool left = (c + 1 < ncols() && cellInfo(cellIndex(r, c + 1)).left_line) || c + 1 == ncols(); if (cellInfo(i).right_line && left) @@ -1304,7 +1304,7 @@ LyXAlignment Tabular::getAlignment(idx_type cell, bool onlycolumn) const { if (!onlycolumn && (isMultiColumn(cell) || isMultiRow(cell))) return cellInfo(cell).alignment; - + return column_info[cellColumn(cell)].alignment; } @@ -1376,7 +1376,7 @@ int Tabular::textVOffset(idx_type cell) const int voffset = cellInfo(cell).voffset; if (isMultiRow(cell)) { row_type const row = cellRow(cell); - voffset += (cellHeight(cell) - rowAscent(row) - rowDescent(row))/2; + voffset += (cellHeight(cell) - rowAscent(row) - rowDescent(row))/2; } return voffset; } @@ -1651,7 +1651,7 @@ void Tabular::read(Lexer & lex) bool Tabular::isMultiColumn(idx_type cell) const { - return (cellInfo(cell).multicolumn == CELL_BEGIN_OF_MULTICOLUMN + return (cellInfo(cell).multicolumn == CELL_BEGIN_OF_MULTICOLUMN || cellInfo(cell).multicolumn == CELL_PART_OF_MULTICOLUMN); } @@ -1769,7 +1769,7 @@ Tabular::idx_type Tabular::rowSpan(idx_type cell) const col_type row = cellRow(cell) + 1; while (row < nrows() && isPartOfMultiRow(row, column)) ++row; - + return row - cellRow(cell); } @@ -1849,7 +1849,7 @@ Tabular::idx_type Tabular::cel
[LyX features/scroll-reloaded] Remove the special horizontal scrolling support in InsetTabular
The branch, scroll-reloaded, has been updated. - Log - commit 3e44bc8bee905a4997ff55b4d8c9ecf0f292d274 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sat Jul 26 22:25:48 2014 +0200 Remove the special horizontal scrolling support in InsetTabular It is not necessary anymore now that there is a global mechanism. Also, fix the clearing of rows in SingleParUpdate mode. diff --git a/src/BufferView.cpp b/src/BufferView.cpp index e4e2a83..6c95d8d 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -2955,7 +2955,7 @@ void BufferView::checkCursorScrollOffset(PainterInfo & pi) || !d->last_row_slice_.empty())) { // FIXME: if one uses SingleParUpdate, then home/end // will not work on long rows. Why? - d->update_strategy_ = FullScreenUpdate;//DecorationUpdate; + d->update_strategy_ = FullScreenUpdate; } d->horiz_scroll_offset_ = offset; @@ -2982,6 +2982,7 @@ void BufferView::draw(frontend::Painter & pain) case NoScreenUpdate: // If no screen painting is actually needed, only some the different // coordinates of insets and paragraphs needs to be updated. + LYXERR(Debug::PAINTING, "Strategy: NoScreenUpdate"); pi.full_repaint = true; pi.pain.setDrawingEnabled(false); tm.draw(pi, 0, y); @@ -2989,6 +2990,7 @@ void BufferView::draw(frontend::Painter & pain) case SingleParUpdate: pi.full_repaint = false; + LYXERR(Debug::PAINTING, "Strategy: SingleParUpdate"); // In general, only the current row of the outermost paragraph // will be redrawn. Particular cases where selection spans // multiple paragraph are correctly detected in TextMetrics. @@ -3001,6 +3003,12 @@ void BufferView::draw(frontend::Painter & pain) // because of the single backing pixmap. case FullScreenUpdate: + + LYXERR(Debug::PAINTING, + ((d->update_strategy_ == FullScreenUpdate) + ? "Strategy: FullScreenUpdate" + : "Strategy: DecorationUpdate")); + // The whole screen, including insets, will be refreshed. pi.full_repaint = true; diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index f325da7..e41874a 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -1903,7 +1903,10 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co // Clear background of this row if paragraph background was not // already cleared because of a full repaint. if (!pi.full_repaint && row_has_changed) { - pi.pain.fillRectangle(x, y - row.ascent(), + LYXERR(Debug::PAINTING, "Clear rect@(" + << max(x, 0) << ", " << y-row.ascent() << ")=" + << width() << " x " << row.height()); + pi.pain.fillRectangle(max(x, 0), y - row.ascent(), width(), row.height(), pi.background_color); } diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index 8a8c212..507f302 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -3456,14 +3456,14 @@ docstring InsetTableCell::xhtml(XHTMLStream & xs, OutputParams const & rp) const InsetTabular::InsetTabular(Buffer * buf, row_type rows, col_type columns) - : Inset(buf), tabular(buf, max(rows, row_type(1)), max(columns, col_type(1))), scx_(0), + : Inset(buf), tabular(buf, max(rows, row_type(1)), max(columns, col_type(1))), rowselect_(false), colselect_(false) { } InsetTabular::InsetTabular(InsetTabular const & tab) - : Inset(tab), tabular(tab.tabular), scx_(0) + : Inset(tab), tabular(tab.tabular) { } @@ -3714,11 +3714,10 @@ bool InsetTabular::isCellSelected(Cursor & cur, row_type row, col_type col) void InsetTabular::draw(PainterInfo & pi, int x, int y) const { - x += scx_ + ADD_TO_TABULAR_WIDTH; + x += ADD_TO_TABULAR_WIDTH; BufferView * bv = pi.base.bv; Cursor & cur = pi.base.bv->cursor(); - resetPos(cur); // FIXME: As the full background is painted in drawBackground(), // we have no choice but to do a full repaint for the Text cells. @@ -3766,7 +3765,7 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const void InsetTabular::drawBackground(PainterInfo & pi, int x, int y)
[LyX features/scroll-reloaded] Fix some display glitches
The branch, scroll-reloaded, has been updated. - Log - commit 14ba5154aa10a7e0f7977e17f3b66483727644d1 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sun Jul 27 17:30:57 2014 +0200 Fix some display glitches * When doing a redraw with drawing disabled (to set inset positions properly), take horizontal scroll offset in account * reset horizontal scroll offset when it is smaller than the left margin. * when drawing a paragraph, do not modify x globally, only for the row that is offset. diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 6c95d8d..92ce6f6 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -2929,7 +2929,8 @@ void BufferView::checkCursorScrollOffset(PainterInfo & pi) bool const drawing = pi.pain.isDrawingEnabled(); pi.pain.setDrawingEnabled(false); // No need to care about vertical position. - RowPainter rp(pi, buffer().text(), d->cursor_.bottom().pit(), row, 0, 0); + RowPainter rp(pi, buffer().text(), d->cursor_.bottom().pit(), row, + -d->horiz_scroll_offset_, 0); rp.paintText(); pi.pain.setDrawingEnabled(drawing); @@ -2947,9 +2948,13 @@ void BufferView::checkCursorScrollOffset(PainterInfo & pi) offset = cur_x - workWidth() + MARGIN; } - if (offset < 0 || row.width() <= workWidth()) + if (offset < row.x || row.width() <= workWidth()) offset = 0; + if (offset != d->horiz_scroll_offset_) + LYXERR(Debug::PAINTING, "Horiz. scroll offset changed from " + << d->horiz_scroll_offset_ << " to " << offset); + if (d->update_strategy_ == NoScreenUpdate && (offset != d->horiz_scroll_offset_ || !d->last_row_slice_.empty())) { diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index e41874a..ab857a5 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -1807,7 +1807,7 @@ void TextMetrics::draw(PainterInfo & pi, int x, int y) const } -void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) const +void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const x, int y) const { BufferParams const & bparams = bv_->buffer().params(); ParagraphMetrics const & pm = par_metrics_[pit]; @@ -1847,6 +1847,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co for (size_t i = 0; i != nrows; ++i) { Row const & row = pm.rows()[i]; + int row_x = x; if (i) y += row.ascent(); @@ -1859,12 +1860,12 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co // Adapt to cursor row scroll offset if applicable. if (bv_->currentRowSlice() == rowSlice) - x -= bv_->horizScrollOffset(); + row_x -= bv_->horizScrollOffset(); // It is not needed to draw on screen if we are not inside. pi.pain.setDrawingEnabled(inside && original_drawing_state); - RowPainter rp(pi, *text_, pit, row, x, y); + RowPainter rp(pi, *text_, pit, row, row_x, y); if (selection) row.setSelectionAndMargins(sel_beg_par, sel_end_par); @@ -1903,10 +1904,10 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co // Clear background of this row if paragraph background was not // already cleared because of a full repaint. if (!pi.full_repaint && row_has_changed) { - LYXERR(Debug::PAINTING, "Clear rect@(" - << max(x, 0) << ", " << y-row.ascent() << ")=" + LYXERR(Debug::PAINTING, "Clear rect@(" + << max(row_x, 0) << ", " << y-row.ascent() << ")=" << width() << " x " << row.height()); - pi.pain.fillRectangle(max(x, 0), y - row.ascent(), + pi.pain.fillRectangle(max(row_x, 0), y - row.ascent(), width(), row.height(), pi.background_color); } --- Summary of changes: src/BufferView.cpp |9 +++-- src/TextMetrics.cpp | 13 +++-- 2 files changed, 14 insertions(+), 8 deletions(-) hooks/post-receive -- Repository for new features
[LyX features/scroll-reloaded] Add marks to indicate when a row is too large
The branch, scroll-reloaded, has been updated. - Log - commit b13ce27430f78fff9c8c58e1bd26d73c9f355aec Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sun Jul 27 18:55:10 2014 +0200 Add marks to indicate when a row is too large A dotted line is shown on the left or on the right to indicate that a part of the row is not visible. For now, the color is hardcoded to Color_red. diff --git a/src/RowPainter.cpp b/src/RowPainter.cpp index 4f7e667..59b6770 100644 --- a/src/RowPainter.cpp +++ b/src/RowPainter.cpp @@ -439,6 +439,23 @@ int RowPainter::paintAppendixStart(int y) } +void RowPainter::paintTooLargeMarks(bool const left, bool const right) +{ + if (left) + pi_.pain.line(dotted_line_thickness_, yo_ - row_.ascent(), + dotted_line_thickness_, yo_ + row_.descent(), + Color_red, + Painter::line_onoffdash, dotted_line_thickness_); + if (right) { + int const wwidth = pi_.base.bv->workWidth() - dotted_line_thickness_; + pi_.pain.line(wwidth, yo_ - row_.ascent(), + wwidth, yo_ + row_.descent(), + Color_red, + Painter::line_onoffdash, dotted_line_thickness_); + } +} + + void RowPainter::paintFirst() { BufferParams const & bparams = pi_.base.bv->buffer().params(); diff --git a/src/RowPainter.h b/src/RowPainter.h index aebd73e..0628f32 100644 --- a/src/RowPainter.h +++ b/src/RowPainter.h @@ -66,6 +66,7 @@ public: void paintAppendix(); void paintDepthBar(); void paintChangeBar(); + void paintTooLargeMarks(bool const left, bool const right); void paintFirst(); void paintLast(); void paintText(); diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index ab857a5..9a6b67d 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -1942,6 +1942,8 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const rp.paintLast(); if (i == 0 && is_rtl) rp.paintFirst(); + rp.paintTooLargeMarks(row_x < 0, + row_x + row.width() > bv_->workWidth()); y += row.descent(); // Restore full_repaint status. --- Summary of changes: src/RowPainter.cpp | 17 + src/RowPainter.h|1 + src/TextMetrics.cpp |2 ++ 3 files changed, 20 insertions(+), 0 deletions(-) hooks/post-receive -- Repository for new features
[LyX/master] Fix compilation warnings on windows.
commit f9caebd29ff52ceee774af7152f0ad6bd1434071 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Jul 28 09:46:13 2014 +0200 Fix compilation warnings on windows. diff --git a/src/Row.cpp b/src/Row.cpp index 1336d05..cab3ab7 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -45,7 +45,7 @@ double Row::Element::pos2x(pos_type const i) const bool const rtl = font.isVisibleRightToLeft(); - int w = 0; + double w = 0; //handle first the two bounds of the element if (i == pos || type != STRING) w = rtl ? width() : 0; @@ -70,7 +70,7 @@ pos_type Row::Element::x2pos(double ) const case STRING: { FontMetrics const & fm = theFontMetrics(font); // FIXME: is it really necessary for x to be a double? - int xx = x; + int xx = int(x); i = fm.x2pos(str, xx, rtl); x = xx; break; @@ -113,9 +113,9 @@ bool Row::Element::breakAt(double w) return false; str = str.substr(0, new_pos - pos); if (rtl) - dim.wid -= w; + dim.wid -= int(w); else - dim.wid = w; + dim.wid = int(w); endpos = new_pos; return true; } @@ -404,7 +404,7 @@ void Row::shortenIfNeeded(pos_type const keep, int const w) double max_w = w - x; if (first_below->breakAt(max_w)) { end_ = first_below->endpos; - dim_.wid = x + first_below->width(); + dim_.wid = int(x + first_below->width()); // If there are other elements, they should be removed. elements_.erase(boost::next(first_below), end); } else if (first_below->pos > pos_) { diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index a5f0364..0e16ab4 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -627,7 +627,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit, row.x += w; break; case LYX_ALIGN_CENTER: - row.dimension().wid = width - w / 2; + row.dimension().wid = width - int(w / 2); row.x += w / 2; break; } @@ -660,7 +660,7 @@ void TextMetrics::computeRowMetrics(pit_type const pit, for ( ; cit != cend; ++cit) { if (row.label_hfill && cit->endpos == body_pos && cit->type == Row::SPACE) - cit->dim.wid -= row.label_hfill * (nlh - 1); + cit->dim.wid -= int(row.label_hfill * (nlh - 1)); if (!cit->inset || !cit->inset->isHfill()) continue; if (pm.hfillExpansion(row, cit->pos)) @@ -680,7 +680,7 @@ int TextMetrics::labelFill(pit_type const pit, Row const & row) const Paragraph const & par = text_->getPar(pit); LBUFERR(par.beginOfBody() > 0 || par.isEnvSeparator(0)); - int w = 0; + double 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, @@ -697,7 +697,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) - w); + return max(0, fm.width(label) - int(w)); } @@ -1108,10 +1108,10 @@ pos_type TextMetrics::getPosNearX(Row const & row, int & x, pos_type pos = row.pos(); boundary = false; if (row.empty()) - x = row.x; + x = int(row.x); else if (x <= row.x) { pos = row.front().left_pos(); - x = row.x; + x = int(row.x); } else if (x >= row.width() - row.right_margin) { pos = row.back().right_pos(); x = row.width() - row.right_margin; @@ -1123,7 +1123,7 @@ pos_type TextMetrics::getPosNearX(Row const & row, int & x, if (w <= x && w + cit->width() > x) { double x_offset = x - w; pos = cit->x2pos(x_offset); - x = x_offset + w; + x = int(x_offset + w); break; } w += cit->width(); diff --git a/src/frontends/qt4/ui/PrefLanguageUi.ui b/src/frontends/qt4/ui/PrefLanguageUi.ui index 2684ee0..44f2014 100644 --- a/src/frontends/qt4/ui/PrefLanguageUi.ui +++ b/src/frontends/qt4/ui/PrefLanguageUi.ui @@ -305,7 +305,6 @@ autoBeginCB autoEndCB markForeignCB - rtlGB logicalCursorRB visualCursorRB
[LyX/master] Use enum instead of int in TextMetrics::getAlign
commit 37fd7b24ba60d9357fde0c218de051b71e222f80 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue Jul 29 11:05:14 2014 +0200 Use enum instead of int in TextMetrics::getAlign This is just a code cleanup, no (intented) effect. diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 2927ca8..eb71f74 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -506,11 +506,11 @@ bool TextMetrics::redoParagraph(pit_type const pit) } -int TextMetrics::getAlign(Paragraph const & par, pos_type const pos) const +LyXAlignment TextMetrics::getAlign(Paragraph const & par, pos_type const pos) const { Layout const & layout = par.layout(); - int align; + LyXAlignment align; if (par.params().align() == LYX_ALIGN_LAYOUT) align = layout.align; else @@ -630,6 +630,12 @@ void TextMetrics::computeRowMetrics(pit_type const pit, row.dimension().wid = width - int(w / 2); row.x += w / 2; break; + case LYX_ALIGN_LEFT: + case LYX_ALIGN_NONE: + case LYX_ALIGN_LAYOUT: + case LYX_ALIGN_SPECIAL: + case LYX_ALIGN_DECIMAL: + break; } } diff --git a/src/TextMetrics.h b/src/TextMetrics.h index 92b1962..4e9fc0d 100644 --- a/src/TextMetrics.h +++ b/src/TextMetrics.h @@ -16,6 +16,7 @@ #include "Font.h" #include "InsetList.h" +#include "LayoutEnums.h" #include "ParagraphMetrics.h" #include "support/types.h" @@ -136,7 +137,7 @@ private: void breakRow(Row & row, int right_margin, pit_type const pit) const; // Expand the alignment of paragraph \param par at position \param pos - int getAlign(Paragraph const & par, pos_type pos) const; + LyXAlignment getAlign(Paragraph const & par, pos_type pos) const; /** this calculates the specified parameters. needed when setting * the cursor and when creating a visible row */ void computeRowMetrics(pit_type pit, Row & row, int width) const;
[LyX/master] Fix ticket #9276: Labeling cursor off by several characters
commit d605048b5c3efd3088c4db31147a633284ec30c9 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Thu Oct 9 22:09:33 2014 +0200 Fix ticket #9276: Labeling cursor off by several characters The length of STRING row elements is not updated until finalizeLast() is called. diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index eb71f74..c99517c 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -849,6 +849,8 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit // before body_pos. Instead, insert some spacing to // align text FontMetrics const & fm = theFontMetrics(text_->labelFont(par)); + // this is needed to make sure that the row width is correct + row.finalizeLast(); int const add = max(fm.width(par.layout().labelsep), labelEnd(pit) - row.width()); row.addSpace(i, add, *fi, par.lookupChange(i));
Re: [LyX/master] pass git commit hash within CPPFLAGS to add it to version info
Le 28/08/2014 08:31, Stephan Witt a écrit : commit f2aeca65b491f4a2396ec2b8834713e5c156c5ef Author: Stephan WittDate: Thu Aug 28 08:30:45 2014 +0200 pass git commit hash within CPPFLAGS to add it to version info Stephan, I was about to add this to autotools and then I wonder: where is this used??? JMarc diff --git a/development/LyX-Mac-binary-release.sh b/development/LyX-Mac-binary-release.sh index 4fb7547..45adfd8 100644 --- a/development/LyX-Mac-binary-release.sh +++ b/development/LyX-Mac-binary-release.sh @@ -303,6 +303,11 @@ if [ -z "${LyXVersion}" ]; then LyXVersion=$(grep AC_INIT "${LyxSourceDir}"/configure.ac | cut -d, -f2 | tr -d " ()") fi LyXVersionSuffix=${LyXVersionSuffix:-$(echo "${LyXVersion}" | cut -d. -f1-2)} +case "${LyXVersion}" in +*dev*) + LyXGitCommitHash=$(cd "${LyxSourceDir}" ; git log -1 --pretty=format:%H) + ;; +esac LyxName="LyX" LyxBase="${LyxName}-${LyXVersion}" @@ -627,6 +632,10 @@ build_lyx() { CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}" LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}" + if [ -n "${LyXGitCommitHash}" ]; then + CPPFLAGS="${CPPFLAGS} -DLYX_GIT_COMMIT_HASH='${LyXGitCommitHash}'" + fi + if [ "$configure_qt_frameworks" = "yes" ]; then export QT_CORE_CFLAGS="-FQtCore" export QT_CORE_LIBS="-framework QtCore"
Re: [LyX/master] Some more SVG icons
Le 10/10/2014 14:01, Juergen Spitzmueller a écrit : commit 8e12587910195a6dbfbae2838be0c0066cf30669 Author: Juergen SpitzmuellerDate: Fri Oct 10 14:00:52 2014 +0200 Some more SVG icons Hi Juergen, Why do we have a mix of svg and svgz files? Is that desirable? JMarc
[LyX/master] Fix ticket #9224: text overflows through adjacent insets
commit ac018bd8db4e81c92320fe026cceff4e9f2181d2 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Wed Oct 15 17:34:56 2014 +0200 Fix ticket #9224: text overflows through adjacent insets The logic of Row::shortenIfNeeded is completely changed to look at the row from the start and not the end. This leads to clearer code. diff --git a/src/Row.cpp b/src/Row.cpp index aeede91..d1f589c 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -362,37 +362,50 @@ void Row::shortenIfNeeded(pos_type const keep, int const w) if (empty() || width() <= w) return; - /** First, we try to remove elements one by one from the end -* until a separator is found. cit points to the first element -* we want to remove from the row. -*/ Elements::iterator const beg = elements_.begin(); Elements::iterator const end = elements_.end(); - Elements::iterator cit = end; - Elements::iterator first_below = end; - int new_end = end_; - int new_wid = dim_.wid; - // if the row ends with a separator, skip it. - if (cit != beg && boost::prior(cit)->type == SEPARATOR && new_end > keep) { - --cit; - new_end = cit->pos; - new_wid -= cit->dim.wid; + Elements::iterator last_sep = elements_.end(); + double last_width = 0; + double wid = x; + + Elements::iterator cit = beg; + for ( ; cit != end ; ++cit) { + if (cit->type == SEPARATOR && cit->pos >= keep) { + last_sep = cit; + last_width = wid; + } + if (wid + cit->width() > w) + break; + wid += cit->width(); } - // Search for a separator where the row can be broken. - while (cit != beg && boost::prior(cit)->type != SEPARATOR && new_end > keep) { + if (last_sep != end) { + // We have found a suitable separator. This is the + // common case. + end_ = last_sep->endpos; + dim_.wid = last_width; + elements_.erase(last_sep, end); + return; + } + + if (cit == end) { + // This should not happen since the row is too long. + LYXERR0("Something is wrong cannot shorten row: " << *this); + return; + } + + if (cit != beg && cit->type == VIRTUAL) { + // It is not possible to separate a virtual element from the + // previous one. --cit; - new_end = cit->pos; - new_wid -= cit->dim.wid; - if (new_wid < w && first_below == end) - first_below = cit; + wid -= cit->width(); } if (cit != beg) { - // We have found a suitable separator. This is the - // common case. - end_ = new_end; - dim_.wid = new_wid; + // There is no separator, but several elements (probably + // insets) have been added. We can cut at this place. + end_ = cit->pos; + dim_.wid = wid; elements_.erase(cit, end); return; } @@ -402,17 +415,11 @@ void Row::shortenIfNeeded(pos_type const keep, int const w) * something: when we have one big string, maybe with some * other things after it. */ - double max_w = w - x; - if (first_below->breakAt(max_w)) { - end_ = first_below->endpos; - dim_.wid = int(x + first_below->width()); + if (cit->breakAt(w - x)) { + end_ = cit->endpos; + dim_.wid = int(x + cit->width()); // If there are other elements, they should be removed. - elements_.erase(boost::next(first_below), end); - } else if (first_below->pos > pos_) { - end_ = first_below->pos; - dim_.wid = new_wid; - // Remove all elements from first_below. - elements_.erase(first_below, end); + elements_.erase(boost::next(cit), end); } } diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index c99517c..637ce1f 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -802,7 +802,9 @@ 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); + // This make get changed in computeRowMetrics depending on RTL + row.x = leftMargin(max_width_, pit, pos); + row.dimension().wid = row.x; row.right_margin = right_margin; if (pos >= end || row.width() > width) {
[LyX/master] Erase correctly math multi-cell selection
commit f58d9f27a239db757efbab54524bd5a6bb6a1532 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Thu Oct 16 16:16:15 2014 +0200 Erase correctly math multi-cell selection What a selection spans several cells in mathed, and a deletion occurs though LFUN_CHAR_DELETE_FORWARD for example, only the case of a proper grid was handled. When no such grid exists, all cells between the first and the last index are cleared now. diff --git a/src/CutAndPaste.cpp b/src/CutAndPaste.cpp index ad3ad7e..7329c24 100644 --- a/src/CutAndPaste.cpp +++ b/src/CutAndPaste.cpp @@ -1254,31 +1254,43 @@ void eraseSelection(Cursor & cur) //lyxerr << "cap::eraseSelection begin: " << cur << endl; CursorSlice const & i1 = cur.selBegin(); CursorSlice const & i2 = cur.selEnd(); - if (i1.inset().asInsetMath()) { - saveSelection(cur); - cur.top() = i1; - if (i1.idx() == i2.idx()) { - i1.cell().erase(i1.pos(), i2.pos()); - // We may have deleted i1.cell(cur.pos()). - // Make sure that pos is valid. - if (cur.pos() > cur.lastpos()) - cur.pos() = cur.lastpos(); - } else { - InsetMath * p = i1.asInsetMath(); - Inset::row_type r1, r2; - Inset::col_type c1, c2; - region(i1, i2, r1, r2, c1, c2); - for (Inset::row_type row = r1; row <= r2; ++row) - for (Inset::col_type col = c1; col <= c2; ++col) - p->cell(p->index(row, col)).clear(); - // We've deleted the whole cell. Only pos 0 is valid. - cur.pos() = 0; - } - // need a valid cursor. (Lgb) - cur.clearSelection(); + if (!i1.asInsetMath()) { + LYXERR0("Can't erase this selection"); + return; + } + + saveSelection(cur); + cur.top() = i1; + InsetMath * p = i1.asInsetMath(); + if (i1.idx() == i2.idx()) { + i1.cell().erase(i1.pos(), i2.pos()); + // We may have deleted i1.cell(cur.pos()). + // Make sure that pos is valid. + if (cur.pos() > cur.lastpos()) + cur.pos() = cur.lastpos(); + } else if (p->nrows() > 0 && p->ncols() > 0) { + // This is a grid, delete a nice square region + Inset::row_type r1, r2; + Inset::col_type c1, c2; + region(i1, i2, r1, r2, c1, c2); + for (Inset::row_type row = r1; row <= r2; ++row) + for (Inset::col_type col = c1; col <= c2; ++col) + p->cell(p->index(row, col)).clear(); + // We've deleted the whole cell. Only pos 0 is valid. + cur.pos() = 0; } else { - lyxerr << "can't erase this selection 1" << endl; + Inset::idx_type idx1 = i1.idx(); + Inset::idx_type idx2 = i2.idx(); + if (idx1 > idx2) + swap(idx1, idx2); + for (Inset::idx_type idx = idx1 ; idx <= idx2; ++idx) + p->cell(idx).clear(); + // We've deleted the whole cell. Only pos 0 is valid. + cur.pos() = 0; } + + // need a valid cursor. (Lgb) + cur.clearSelection(); //lyxerr << "cap::eraseSelection end: " << cur << endl; }
[LyX/master] Add Stéphane Mourey as contributor
commit 3706d900374407add26cea4b53ff5ece01d0659a Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Thu Oct 23 15:58:41 2014 +0200 Add Stéphane Mourey as contributor diff --git a/lib/CREDITS b/lib/CREDITS index afa88c1..048aca4 100644 --- a/lib/CREDITS +++ b/lib/CREDITS @@ -336,6 +336,9 @@ @bJoan Montané @iE-mail: jmontane () gmail ! com Catalan translations of menus +@bStéphane Mourey +@iE-mail: stephane.mourey () impossible-exil ! info + New lfun server-get-statistics @bIñaki Larrañaga Murgoitio @iE-mail: dooteo () euskalgnu ! org Basque documentation and localization diff --git a/lib/generate_contributions.py b/lib/generate_contributions.py index 2fc7df2..c2244a0 100755 --- a/lib/generate_contributions.py +++ b/lib/generate_contributions.py @@ -1219,6 +1219,14 @@ contributors = [ "21 August 2007", u"Catalan translations of menus"), + contributor(u"Stéphane Mourey", + "stephane.mourey () impossible-exil ! info", + "GPL", + "Re: gpl", + "m=141381522413781", + "20 October 2014", + u"New lfun server-get-statistics"), + contributor(u"Iñaki Larrañaga Murgoitio", "dooteo () euskalgnu ! org", "GPL",
[LyX/master] Add LFUN_SERVER_GET_STATISTICS command
commit 11e679f73ecca718c61307973c3d67739354e1c7 Author: brokenclockDate: Tue Oct 14 21:55:04 2014 +0200 Add LFUN_SERVER_GET_STATISTICS command This function can be used with the LyX server to obtain the word, character or character+space count in the current document or selection. diff --git a/lib/doc/LFUNs.lyx b/lib/doc/LFUNs.lyx index b0ac9f4..0d9bb93 100644 --- a/lib/doc/LFUNs.lyx +++ b/lib/doc/LFUNs.lyx @@ -98,7 +98,7 @@ The LyX Team \end_layout \begin_layout Date -2014-02-13 +2014-10-23 \end_layout \begin_layout Section* @@ -3076,6 +3076,22 @@ Origin lasgouttes, 14 Jan 2009 \end_layout \begin_layout Subsection* +separator-insert +\end_layout +\begin_layout Description +Action Inserts an environment separator or paragraph break. +\end_layout +\begin_layout Description +Syntax separator-insert [] +\end_layout +\begin_layout Description +Params : default: plain +\end_layout +\begin_layout Description +Origin ef, 2 May 2014 +\end_layout + +\begin_layout Subsection* set-graphics-group \end_layout \begin_layout Description @@ -5321,6 +5337,37 @@ Syntax server-get-layout \end_layout \begin_layout Subsection* +server-get-statistics +\end_layout +\begin_layout Description +Action Returns the statistics (number of words and characters) in the document or in the given selection. +\end_layout +\begin_layout Description +Notion Note that this function gives the number of words/chars written, not the number of characters which will be typeset. +\end_layout +\begin_layout Description +Syntax server-get-statistics [] +\end_layout +\begin_layout Description +Params : The requested count; if not specified, the three values are returned, separated by a space. +\begin_inset Newline newline +\end_inset + +words: count words. +\begin_inset Newline newline +\end_inset + +chars: count characters. +\begin_inset Newline newline +\end_inset + +chars-space: count characters and spaces. +\end_layout +\begin_layout Description +Origin brokenclock, Oct 10 2014 +\end_layout + +\begin_layout Subsection* server-get-xy \end_layout \begin_layout Description @@ -5411,7 +5458,7 @@ Origin SLior, 11 Jun 2000 statistics \end_layout \begin_layout Description -Action Count the statistics (number of words and characters) in the document or in the given selection. +Action Count the statistics (number of words and characters) in the document or in the given selection and display it in a dialog box. \end_layout \begin_layout Description Notion Note that this function gives the number of words/chars written, not the number of characters which will be typeset. diff --git a/src/FuncCode.h b/src/FuncCode.h index 2ae820a..3bd0cd0 100644 --- a/src/FuncCode.h +++ b/src/FuncCode.h @@ -458,6 +458,7 @@ enum FuncCode // 355 LFUN_SPELLING_CONTINUOUSLY, // vfr, 20130324 LFUN_SEPARATOR_INSERT, // ef 20140502 + LFUN_SERVER_GET_STATISTICS, // brokenclock 20141010 LFUN_LASTACTION // end of the table }; diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp index 175f68e..0efbb3c 100644 --- a/src/LyXAction.cpp +++ b/src/LyXAction.cpp @@ -3517,7 +3517,8 @@ void LyXAction::init() /*! * \var lyx::FuncCode lyx::LFUN_STATISTICS * \li Action: Count the statistics (number of words and characters) - in the document or in the given selection. + in the document or in the given selection and display it + in a dialog box. * \li Notion: Note that this function gives the number of words/chars written, not the number of characters which will be typeset. * \li Syntax: statistics @@ -3526,6 +3527,23 @@ void LyXAction::init() */ { LFUN_STATISTICS, "statistics", ReadOnly, System }, /*! + * \var lyx::FuncCode lyx::LFUN_SERVER_GET_STATISTICS + * \li Action: Returns the statistics (number of words and characters) + in the document or in the given selection. + * \li Notion: Note that this function gives the number of words/chars written, + not the number of characters which will be typeset. + * \li Syntax: server-get-statistics [] + * \li Params: : The requested count; if not + specified, the three values are returned, separated + by a space.\n +words: count words.\n +chars: count characters.\n +chars-space: count characters and spaces. + * \li Origin: brokenclock, Oct 10 2014 + * \endvar + */ + { LFUN_SERVER_GET_STATISTICS, "server-get-statistics", ReadOnly, System }, +/*! * \var lyx::FuncCode lyx::LFUN_COMPLETION_INLINE * \li Action: Show the inline completion at the cursor position. * \li Syntax: completion-inline diff --git a/src/Text3.cpp b/src/Text3.cpp index 79711f4..6bf3bc6 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@
[LyX/master] Fix wrong test: boolean variable is never negative
commit c559f85ccb3040af4117daa139a7a2c9c1f12b8a Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sat Nov 1 16:02:34 2014 +0100 Fix wrong test: boolean variable is never negative This has been spotted by clang++. diff --git a/src/Server.cpp b/src/Server.cpp index 1de758a..b7fa35e 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -878,7 +878,7 @@ void LyXComm::endPipe(int & fd, string const & filename, bool write) << '\n' << strerror(errno) << endl; } - if (FileName(filename).removeFile() < 0) { + if (!FileName(filename).removeFile()) { lyxerr << "LyXComm: Could not remove pipe " << filename << '\n' << strerror(errno) << endl; }
Re: [LyX/master] Fix wrong test: boolean variable is never negative
Le 01/11/2014 16:37, Jean-Marc Lasgouttes a écrit : commit c559f85ccb3040af4117daa139a7a2c9c1f12b8a Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sat Nov 1 16:02:34 2014 +0100 Fix wrong test: boolean variable is never negative This has been spotted by clang++. Richard, OK for branch? JMarc diff --git a/src/Server.cpp b/src/Server.cpp index 1de758a..b7fa35e 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -878,7 +878,7 @@ void LyXComm::endPipe(int & fd, string const & filename, bool write) << '\n' << strerror(errno) << endl; } - if (FileName(filename).removeFile() < 0) { + if (!FileName(filename).removeFile()) { lyxerr << "LyXComm: Could not remove pipe " << filename << '\n' << strerror(errno) << endl; }
[LyX/master] Reimplement inset-select-all in a generic way
commit e52a38549328a58b6fe8efeecef21a71fb9c8d65 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sun Oct 19 20:43:17 2014 +0200 Reimplement inset-select-all in a generic way There are 3 possible actions (in order) * select current cell * select all calls of inset * select the inset from outside (in the containing inset) This fixes completely #7727. diff --git a/src/BufferView.cpp b/src/BufferView.cpp index faa08f0..47e6512 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -1087,6 +1087,7 @@ bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag) case LFUN_KEYMAP_PRIMARY: case LFUN_KEYMAP_SECONDARY: case LFUN_KEYMAP_TOGGLE: + case LFUN_INSET_SELECT_ALL: flag.setEnabled(true); break; @@ -1800,6 +1801,38 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) } + case LFUN_INSET_SELECT_ALL: + if (cur.depth() > 1 + && cur.selBegin().at_begin() + && cur.selEnd().at_end()) { + // All the contents of the inset if selected. + // Select the inset from outside. + cur.pop(); + cur.resetAnchor(); + cur.setSelection(true); + cur.posForward(); + } else if (cur.selBegin().idx() != cur.selEnd().idx() + || (cur.selBegin().at_cell_begin() + && cur.selEnd().at_cell_end())) { + // At least one complete cell is selected. + // Select all cells + cur.pos() = 0; + cur.idx() = 0; + cur.resetAnchor(); + cur.setSelection(true); + cur.idx() = cur.lastidx(); + cur.pos() = cur.lastpos(); + } else { + // select current cell + cur.pos() = 0; + cur.resetAnchor(); + cur.setSelection(true); + cur.pos() = cur.lastpos(); + } + dr.screenUpdate(Update::Force); + break; + + // This would be in Buffer class if only Cursor did not // require a bufferview case LFUN_INSET_FORALL: { diff --git a/src/CursorSlice.cpp b/src/CursorSlice.cpp index 0e46c07..e7ef90e 100644 --- a/src/CursorSlice.cpp +++ b/src/CursorSlice.cpp @@ -158,15 +158,27 @@ void CursorSlice::backwardPos() } -bool CursorSlice::at_end() const +bool CursorSlice::at_cell_end() const { - return idx_ == lastidx() && pit_ == lastpit() && pos_ == lastpos(); + return pit_ == lastpit() && pos_ == lastpos(); +} + + +bool CursorSlice::at_cell_begin() const +{ + return pit_ == 0 && pos_ == 0; +} + + +bool CursorSlice::at_end() const +{ + return idx_ == lastidx() && at_cell_end(); } bool CursorSlice::at_begin() const { - return idx_ == 0 && pit_ == 0 && pos_ == 0; + return idx_ == 0 && at_cell_begin(); } diff --git a/src/CursorSlice.h b/src/CursorSlice.h index 01634bd..d703cb4 100644 --- a/src/CursorSlice.h +++ b/src/CursorSlice.h @@ -132,6 +132,10 @@ public: void forwardIdx(); /// move to previous cell void backwardIdx(); + /// are we at the end of the cell + bool at_cell_end() const; + /// are we at the start of the cell + bool at_cell_begin() const; /// are we at the end of this slice bool at_end() const; /// are we at the start of this slice diff --git a/src/Text3.cpp b/src/Text3.cpp index 6bf3bc6..20885dd 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -599,18 +599,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) cur.screenUpdateFlags(Update::FitCursor); break; - case LFUN_INSET_SELECT_ALL: - if (cur.depth() == 1 || !cur.selection() || !cur.selBegin().at_begin() - || !cur.selEnd().at_end()) { - needsUpdate |= cur.selHandle(false); - needsUpdate |= cursorTop(cur); - needsUpdate |= cur.selHandle(true); - needsUpdate |= cursorBottom(cur); - } else - cur.undispatched(); - cur.screenUpdateFlags(Update::FitCursor); - break; - case LFUN_CHAR_FORWARD: case LFUN_CHAR_FORWARD_SELECT: //LYXERR0(" LFUN_CHAR_FORWARD[SEL]:\n" << cur); @@ -3118,7 +3106,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_INSET_END: case LFUN_INSET_BEGIN_SELECT:
[LyX/master] Implement "callstack printing" checking for autotools
commit dc7ef3c81ff6e906c41da5ad40117ab87ac214da Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Tue Nov 4 23:30:53 2014 +0100 Implement "callstack printing" checking for autotools Contrary to cmake, we do not rely on platform/compiler check, but on the availability of the reauired API. diff --git a/config/lyxinclude.m4 b/config/lyxinclude.m4 index c781c1e..6b8d7a5 100644 --- a/config/lyxinclude.m4 +++ b/config/lyxinclude.m4 @@ -358,6 +358,29 @@ AC_DEFUN([LYX_USE_INCLUDED_BOOST],[ ]) +dnl Usage: LYX_CHECK_CALLSTACK_PRINTING: define LYX_CALLSTACK_PRINTING if the +dnlnecessary APIs are available to print callstacks. +AC_DEFUN([LYX_CHECK_CALLSTACK_PRINTING], +[AC_CACHE_CHECK([whether printing callstack is possible], + [lyx_cv_callstack_printing], +[AC_TRY_COMPILE([ +#include +#include +], [ + void* array[200]; + size_t size = backtrace(array, 200); + backtrace_symbols(array, size); + int status = 0; + abi::__cxa_demangle("abcd", 0, 0, ); +], +[lyx_cv_callstack_printing=yes], [lyx_cv_callstack_printing=no])]) +if test x"$lyx_cv_callstack_printing" = xyes; then + AC_DEFINE([LYX_CALLSTACK_PRINTING], 1, +[Define if callstack can be printed]) +fi +]) + + dnl Usage: LYX_USE_INCLUDED_MYTHES : select if the included MyThes should dnlbe used. AC_DEFUN([LYX_USE_INCLUDED_MYTHES],[ diff --git a/configure.ac b/configure.ac index 8539c7c..e05681c 100644 --- a/configure.ac +++ b/configure.ac @@ -104,6 +104,9 @@ LYX_USE_INCLUDED_MYTHES ### we need to know the byte order for unicode conversions AC_C_BIGENDIAN +# Nice to have when an assertion triggers +LYX_CHECK_CALLSTACK_PRINTING + # Needed for our char_type AC_CHECK_SIZEOF(wchar_t)
[LyX/2.1.x] Fix wrong test: boolean variable is never negative
commit 02a22417278f8dffcce65a170f87f18661df41af Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sat Nov 1 16:02:34 2014 +0100 Fix wrong test: boolean variable is never negative This has been spotted by clang++. diff --git a/src/Server.cpp b/src/Server.cpp index 1de758a..b7fa35e 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -878,7 +878,7 @@ void LyXComm::endPipe(int & fd, string const & filename, bool write) << '\n' << strerror(errno) << endl; } - if (FileName(filename).removeFile() < 0) { + if (!FileName(filename).removeFile()) { lyxerr << "LyXComm: Could not remove pipe " << filename << '\n' << strerror(errno) << endl; } diff --git a/status.21x b/status.21x index 1147844..6cc1f12 100644 --- a/status.21x +++ b/status.21x @@ -70,7 +70,7 @@ What's new - Fix export of documents that use the LaTeX-packages mhchem and wasysym (bug 9266). - + - Remove unnecessary preamble code in LaTeX export of documents using the class REVTeX 4.1 file (bug 4625). @@ -96,6 +96,7 @@ What's new * INTERNALS +- Fix wrong test in LyX server. * DOCUMENTATION AND LOCALIZATION
Re: [LyX/master] Fix wrong test: boolean variable is never negative
Le 01/11/2014 19:23, Richard Heck a écrit : On 11/01/2014 11:47 AM, Jean-Marc Lasgouttes wrote: Le 01/11/2014 16:37, Jean-Marc Lasgouttes a écrit : commit c559f85ccb3040af4117daa139a7a2c9c1f12b8a Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Sat Nov 1 16:02:34 2014 +0100 Fix wrong test: boolean variable is never negative This has been spotted by clang++. Richard, OK for branch? Yes, sure. Done. JMarc
[LyX/master] Fix some glitches in inset-select-all
commit 3cbdfa17629e4a1f78901c88231faf7e3d6470e3 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Nov 14 10:10:29 2014 +0100 Fix some glitches in inset-select-all Fix a crash reported in #7727. This happened because cur.pos() was reset before cur.pit(). In this case, cur.lastpos() will usually be wrong. Fix bad behaviour when selecting at top level with several paragraphs. Update documentation. diff --git a/lib/doc/LFUNs.lyx b/lib/doc/LFUNs.lyx index 0d9bb93..e36e00b 100644 --- a/lib/doc/LFUNs.lyx +++ b/lib/doc/LFUNs.lyx @@ -98,7 +98,7 @@ The LyX Team \end_layout \begin_layout Date -2014-10-23 +2014-11-14 \end_layout \begin_layout Section* @@ -2171,13 +2171,16 @@ Sample inset-modify note Note Comment inset-select-all \end_layout \begin_layout Description -Action Selects all contents of an inset. +Action Select all contents of an inset. +\end_layout +\begin_layout Description +Notion There are 3 successive levels: select current cell, select all cells of inset, select the inset from outside (in the enclosing inset). \end_layout \begin_layout Description Syntax inset-select-all \end_layout \begin_layout Description -Origin vfr, 22 Aug 2009 +Origin vfr, 22 Aug 2009; lasgouttes 1 Nov 2014 \end_layout \begin_layout Subsection* @@ -3047,7 +3050,7 @@ Origin Abdel, Dec 27 2007 section-select \end_layout \begin_layout Description -Action Selects the whole section. +Action Select the whole section. \end_layout \begin_layout Description Notion The cursor should be in a section heading before calling this lfun. diff --git a/src/BufferView.cpp b/src/BufferView.cpp index f404816..e982409 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -1812,24 +1812,25 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) cur.setSelection(true); cur.posForward(); } else if (cur.selBegin().idx() != cur.selEnd().idx() - || (cur.selBegin().at_cell_begin() + || (cur.depth() > 1 + && cur.selBegin().at_cell_begin() && cur.selEnd().at_cell_end())) { // At least one complete cell is selected. // Select all cells - cur.pos() = 0; cur.idx() = 0; + cur.pos() = 0; cur.resetAnchor(); cur.setSelection(true); cur.idx() = cur.lastidx(); cur.pos() = cur.lastpos(); } else { // select current cell - cur.pos() = 0; cur.pit() = 0; + cur.pos() = 0; cur.resetAnchor(); cur.setSelection(true); - cur.pos() = cur.lastpos(); cur.pit() = cur.lastpit(); + cur.pos() = cur.lastpos(); } dr.screenUpdate(Update::Force); break; diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp index 0efbb3c..01ddb19 100644 --- a/src/LyXAction.cpp +++ b/src/LyXAction.cpp @@ -1150,16 +1150,19 @@ void LyXAction::init() /*! * \var lyx::FuncCode lyx::LFUN_INSET_SELECT_ALL - * \li Action: Selects all contents of an inset. + * \li Action: Select all contents of an inset. + * \li Notion: There are 3 successive levels: select current cell, + * select all cells of inset, select the inset from outside + * (in the enclosing inset). * \li Syntax: inset-select-all - * \li Origin: vfr, 22 Aug 2009 + * \li Origin: vfr, 22 Aug 2009; lasgouttes 1 Nov 2014 * \endvar */ { LFUN_INSET_SELECT_ALL, "inset-select-all", ReadOnly, Edit }, /*! * \var lyx::FuncCode lyx::LFUN_SECTION_SELECT - * \li Action: Selects the whole section. + * \li Action: Select the whole section. * \li Notion: The cursor should be in a section heading before calling this lfun. * \li Syntax: section-select
[LyX/master] Fix overflow of inset over text (see #9224)
commit 81badf8550f2fd5e614a22261c4885d747a72106 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Fri Nov 14 11:13:38 2014 +0100 Fix overflow of inset over text (see #9224) The symptoms are the same as the original #9224, but the reason is different. In the new code, the width of justified rows includes the Row::separator value. Therefore the CRC computed in ParagrahMetrics::computeRowSignature is not updated in some cases. The fix is to add Row::separator as one of the elements of the row crc. diff --git a/src/ParagraphMetrics.cpp b/src/ParagraphMetrics.cpp index 97170bb..a911d14 100644 --- a/src/ParagraphMetrics.cpp +++ b/src/ParagraphMetrics.cpp @@ -97,13 +97,16 @@ size_t ParagraphMetrics::computeRowSignature(Row const & row, char_type const b[] = { static_cast(change.type) }; // 1 byte is enough to encode Change::Type crc.process_bytes(b, 1); - } + } } Dimension const & d = row.dimension(); char_type const b[] = { static_cast(row.sel_beg), - static_cast(row.sel_end), - row.begin_margin_sel, row.end_margin_sel, d.wid, d.asc, d.des}; + static_cast(row.sel_end), + row.begin_margin_sel, + row.end_margin_sel, + row.separator, + d.wid, d.asc, d.des }; crc.process_bytes(b, sizeof(b)); return crc.checksum();
[LyX/master] Make sure that UpdateLocker is used correctly in the future
commit 689e54f34a4d735e6081b1b1ac8487bf028f3982 Author: Jean-Marc Lasgouttes <lasgout...@lyx.org> Date: Mon Nov 17 11:52:14 2014 +0100 Make sure that UpdateLocker is used correctly in the future diff --git a/src/mathed/MathMacro.cpp b/src/mathed/MathMacro.cpp index 941e29a..38d07e6 100644 --- a/src/mathed/MathMacro.cpp +++ b/src/mathed/MathMacro.cpp @@ -326,6 +326,13 @@ public: private: MathMacro & mac; }; +/** Avoid wrong usage of UpdateLocker. +To avoid wrong usage: +UpdateLocker(...); // wrong +UpdateLocker locker(...); // right +*/ +#define UpdateLocker(x) unnamed_UpdateLocker; +// Tip gotten from Bobby Schmidt's column in C/C++ Users Journal void MathMacro::updateRepresentation(Cursor * cur, MacroContext const & mc,