Use QTextLayout for computing word withs rather than a homebrew solution
authorManuel Nickschas <sputnick@quassel-irc.org>
Mon, 7 Jul 2008 23:31:07 +0000 (01:31 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sat, 2 Aug 2008 13:17:10 +0000 (15:17 +0200)
According to my benchmarks, it's very slightly slower (on my machine, on the
order of 10 ms for 500 chatlines). It does make the code much nicer though.
Also we might catch details like kerning or ligatures where our own solution
might have failed.

src/qtui/chatlinemodelitem.cpp
src/qtui/chatlinemodelitem.h

index 38663bb..aebde9d 100644 (file)
@@ -68,38 +68,29 @@ bool ChatLineModelItem::setData(int column, const QVariant &value, int role) {
   return false;
 }
 
   return false;
 }
 
-// compute the width of a text snippet
-qreal ChatLineModelItem::snippetWidth(int start, int end, QFontMetricsF *&metrics, int &formatListIdx, int &formatEnd) {
-  qreal width = 0;
-  while(start < end) {
-    if(formatEnd <= start) {
-      formatListIdx++;
-      formatEnd = _contents.formatList.count() > formatListIdx+1 ? _contents.formatList[formatListIdx+1].first
-                                                                 : _contents.plainText.length();
-      metrics = QtUi::style()->fontMetrics(_contents.formatList[formatListIdx].second);
-      Q_ASSERT(formatEnd > start);
-    }
-    int i = qMin(end, formatEnd);
-    width += metrics->width(_contents.plainText.mid(start, i - start));
-    start = i;
-  }
-  return width;
-}
-
 void ChatLineModelItem::computeWrapList() {
   enum Mode { SearchStart, SearchEnd };
 
   QList<ChatLineModel::Word> wplist;  // use a temp list which we'll later copy into a QVector for efficiency
   QTextBoundaryFinder finder(QTextBoundaryFinder::Word, _contents.plainText);
   int idx, oldidx;
 void ChatLineModelItem::computeWrapList() {
   enum Mode { SearchStart, SearchEnd };
 
   QList<ChatLineModel::Word> wplist;  // use a temp list which we'll later copy into a QVector for efficiency
   QTextBoundaryFinder finder(QTextBoundaryFinder::Word, _contents.plainText);
   int idx, oldidx;
-  qreal pxpos = 0;
-  int flistidx = -1;
-  int fmtend = -1;
   bool wordStart = false; bool wordEnd = false;
   bool wordStart = false; bool wordEnd = false;
-  QFontMetricsF *metrics = 0;
   Mode mode = SearchEnd;
   ChatLineModel::Word word;
   word.start = 0;
   Mode mode = SearchEnd;
   ChatLineModel::Word word;
   word.start = 0;
+  int wordstartx = 0;
+
+  QTextLayout layout(_contents.plainText);
+  QTextOption option;
+  option.setWrapMode(QTextOption::NoWrap);
+  layout.setTextOption(option);
+
+  layout.setAdditionalFormats(QtUi::style()->toTextLayoutList(_contents.formatList, _contents.plainText.length()));
+  layout.beginLayout();
+  QTextLine line = layout.createLine();
+  line.setNumColumns(_contents.plainText.length());
+  layout.endLayout();
+
   do {
     idx = finder.toNextBoundary();
     if(idx < 0) idx = _contents.plainText.length();
   do {
     idx = finder.toNextBoundary();
     if(idx < 0) idx = _contents.plainText.length();
@@ -114,9 +105,11 @@ void ChatLineModelItem::computeWrapList() {
       mode = SearchStart;
       continue;
     }
       mode = SearchStart;
       continue;
     }
-    // mode == SearchStart
-    word.width = snippetWidth(word.start, oldidx, metrics, flistidx, fmtend);
-    word.trailing = snippetWidth(oldidx, idx, metrics, flistidx, fmtend);
+    int wordendx = line.cursorToX(oldidx);
+    int trailingendx = line.cursorToX(idx);
+    word.width = wordendx - wordstartx;
+    word.trailing = trailingendx - wordendx;
+    wordstartx = trailingendx;
     wplist.append(word);
 
     if(wordStart) {
     wplist.append(word);
 
     if(wordStart) {
index b76ea68..1018e99 100644 (file)
@@ -39,8 +39,7 @@ class ChatLineModelItem : public MessageModelItem {
 
   private:
     void computeWrapList();
 
   private:
     void computeWrapList();
-    qreal snippetWidth(int start, int end, QFontMetricsF *&metrics, int &formatListIdx, int &formatEnd);
-
+s
     struct ChatLinePart {
       QString plainText;
       UiStyle::FormatList formatList;
     struct ChatLinePart {
       QString plainText;
       UiStyle::FormatList formatList;