summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2011-06-01 15:33:38 +0200
committerQt by Nokia <qt-info@nokia.com>2011-08-19 10:18:04 +0200
commitb9224af92c128f7cc66bef11849db046f10dc81f (patch)
tree6cbf656d70aebeaffddda5c256840f952907a0d6
parent1e0d1c5f2996da33db1e3e4c1f7c6ef3e1f29416 (diff)
Enablers for using QGlyphRun in SceneGraph
Several required fixes and changes to fix problems that arose when porting SceneGraph's QSGTextInput and QSGTextEdit to use QSGTextNode, especially related to having selections on the text. Also fixes crashes with the threaded renderer on Mac OS X when using the TextEdit or TextInput elements. Task-number: QTBUG-18019, QTBUG-20017 Change-Id: I67f24465352daa1d2cb12b6d2f378feb676c9804 Reviewed-on: http://codereview.qt.nokia.com/2864 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com> Reviewed-by: Jiang Jiang <jiang.jiang@nokia.com>
-rw-r--r--src/gui/text/qglyphrun.cpp45
-rw-r--r--src/gui/text/qglyphrun.h3
-rw-r--r--src/gui/text/qglyphrun_p.h2
-rw-r--r--src/gui/text/qtextcontrol.cpp24
-rw-r--r--src/gui/text/qtextcontrol_p.h3
-rw-r--r--src/gui/text/qtextlayout.cpp63
-rw-r--r--src/gui/text/qtextobject.cpp17
-rw-r--r--src/gui/text/qtextobject.h2
-rw-r--r--src/gui/widgets/qlinecontrol.cpp43
-rw-r--r--src/gui/widgets/qlinecontrol_p.h33
10 files changed, 196 insertions, 39 deletions
diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp
index cc825525c4..be9c058693 100644
--- a/src/gui/text/qglyphrun.cpp
+++ b/src/gui/text/qglyphrun.cpp
@@ -45,6 +45,7 @@
#include "qglyphrun.h"
#include "qglyphrun_p.h"
+#include <qdebug.h>
QT_BEGIN_NAMESPACE
@@ -343,12 +344,44 @@ void QGlyphRun::setStrikeOut(bool strikeOut)
}
/*!
- Returns the smallest rectangle that contains all glyphs in this QGlyphRun.
+ Sets the bounding rect of the glyphs in this QGlyphRun to be \a boundingRect. This rectangle
+ will be returned by boundingRect() unless it is empty, in which case the bounding rectangle of the
+ glyphs in the glyph run will be returned instead.
+
+ \note Unless you are implementing text shaping, you should not have to use this function.
+ It is used specifically when the QGlyphRun should represent an area which is smaller than the
+ area of the glyphs it contains. This could happen e.g. if the glyph run is retrieved by calling
+ QTextLayout::glyphRuns() and the specified range only includes part of a ligature (where two or
+ more characters are combined to a single glyph.) When this is the case, the bounding rect should
+ only include the appropriate part of the ligature glyph, based on a calculation of the average
+ width of the characters in the ligature.
+
+ In order to support such a case (an example is selections which should be drawn with a different
+ color than the main text color), it is necessary to clip the painting mechanism to the rectangle
+ returned from boundingRect() to avoid drawing the entire ligature glyph.
+
+ \sa boundingRect()
+
+ \since 5.0
+*/
+void QGlyphRun::setBoundingRect(const QRectF &boundingRect)
+{
+ detach();
+ d->boundingRect = boundingRect;
+}
+
+/*!
+ Returns the smallest rectangle that contains all glyphs in this QGlyphRun. If a bounding rect
+ has been set using setBoundingRect(), then this will be returned. Otherwise the bounding rect
+ will be calculated based on the font metrics of the glyphs in the glyph run.
\since 5.0
*/
QRectF QGlyphRun::boundingRect() const
{
+ if (!d->boundingRect.isEmpty())
+ return d->boundingRect;
+
qreal minX, minY, maxX, maxY;
for (int i=0; i<qMin(d->glyphPositions.size(), d->glyphIndexes.size()); ++i) {
@@ -371,6 +404,16 @@ QRectF QGlyphRun::boundingRect() const
return QRectF(QPointF(minX, minY), QPointF(maxX, maxY));
}
+/*!
+ Returns true if the QGlyphRun does not contain any glyphs.
+
+ \since 5.0
+*/
+bool QGlyphRun::isEmpty() const
+{
+ return d->glyphIndexes.isEmpty();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_RAWFONT
diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h
index b4f02f0d87..da88bc72f9 100644
--- a/src/gui/text/qglyphrun.h
+++ b/src/gui/text/qglyphrun.h
@@ -91,8 +91,11 @@ public:
void setStrikeOut(bool strikeOut);
bool strikeOut() const;
+ void setBoundingRect(const QRectF &boundingRect);
QRectF boundingRect() const;
+ bool isEmpty() const;
+
private:
friend class QGlyphRunPrivate;
friend class QTextLine;
diff --git a/src/gui/text/qglyphrun_p.h b/src/gui/text/qglyphrun_p.h
index a7745e68ce..b632678971 100644
--- a/src/gui/text/qglyphrun_p.h
+++ b/src/gui/text/qglyphrun_p.h
@@ -83,6 +83,7 @@ public:
, glyphIndexes(other.glyphIndexes)
, glyphPositions(other.glyphPositions)
, rawFont(other.rawFont)
+ , boundingRect(other.boundingRect)
, overline(other.overline)
, underline(other.underline)
, strikeOut(other.strikeOut)
@@ -96,6 +97,7 @@ public:
QVector<quint32> glyphIndexes;
QVector<QPointF> glyphPositions;
QRawFont rawFont;
+ QRectF boundingRect;
uint overline : 1;
uint underline : 1;
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 424d1979b2..c29379ed28 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -409,6 +409,8 @@ void QTextControlPrivate::init(Qt::TextFormat format, const QString &text, QText
doc->setUndoRedoEnabled(interactionFlags & Qt::TextEditable);
q->setCursorWidth(-1);
+
+ QObject::connect(q, SIGNAL(updateCursorRequest(QRectF)), q, SIGNAL(updateRequest(QRectF)));
}
void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text, QTextDocument *document)
@@ -547,7 +549,7 @@ void QTextControlPrivate::setCursorPosition(int pos, QTextCursor::MoveMode mode)
void QTextControlPrivate::repaintCursor()
{
Q_Q(QTextControl);
- emit q->updateRequest(cursorRectPlusUnicodeDirectionMarkers(cursor));
+ emit q->updateCursorRequest(cursorRectPlusUnicodeDirectionMarkers(cursor));
}
void QTextControlPrivate::repaintOldAndNewSelection(const QTextCursor &oldSelection)
@@ -565,9 +567,16 @@ void QTextControlPrivate::repaintOldAndNewSelection(const QTextCursor &oldSelect
differenceSelection.setPosition(cursor.position(), QTextCursor::KeepAnchor);
emit q->updateRequest(q->selectionRect(differenceSelection));
} else {
- if (!oldSelection.isNull())
- emit q->updateRequest(q->selectionRect(oldSelection) | cursorRectPlusUnicodeDirectionMarkers(oldSelection));
- emit q->updateRequest(q->selectionRect() | cursorRectPlusUnicodeDirectionMarkers(cursor));
+ if (!oldSelection.hasSelection() && !cursor.hasSelection()) {
+ if (!oldSelection.isNull())
+ emit q->updateCursorRequest(q->selectionRect(oldSelection) | cursorRectPlusUnicodeDirectionMarkers(oldSelection));
+ emit q->updateCursorRequest(q->selectionRect() | cursorRectPlusUnicodeDirectionMarkers(cursor));
+
+ } else {
+ if (!oldSelection.isNull())
+ emit q->updateRequest(q->selectionRect(oldSelection) | cursorRectPlusUnicodeDirectionMarkers(oldSelection));
+ emit q->updateRequest(q->selectionRect() | cursorRectPlusUnicodeDirectionMarkers(cursor));
+ }
}
}
@@ -2959,6 +2968,12 @@ void QTextControl::setPalette(const QPalette &pal)
d->palette = pal;
}
+bool QTextControl::cursorOn() const
+{
+ Q_D(const QTextControl);
+ return d->cursorOn;
+}
+
QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget *widget) const
{
Q_D(const QTextControl);
@@ -3146,6 +3161,7 @@ void QTextEditMimeData::setup() const
fragment = QTextDocumentFragment();
}
+
QT_END_NAMESPACE
#include "moc_qtextcontrol_p.cpp"
diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h
index cbf26d2122..c5ed0ee1e0 100644
--- a/src/gui/text/qtextcontrol_p.h
+++ b/src/gui/text/qtextcontrol_p.h
@@ -226,6 +226,7 @@ Q_SIGNALS:
void cursorPositionChanged();
// control signals
+ void updateCursorRequest(const QRectF &rect = QRectF());
void updateRequest(const QRectF &rect = QRectF());
void documentSizeChanged(const QSizeF &);
void blockCountChanged(int newBlockCount);
@@ -258,6 +259,8 @@ public:
bool setFocusToNextOrPreviousAnchor(bool next);
bool findNextPrevAnchor(const QTextCursor& from, bool next, QTextCursor& newAnchor);
+ bool cursorOn() const;
+
protected:
virtual void timerEvent(QTimerEvent *e);
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 2535faddc3..8c5e63da54 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -42,6 +42,7 @@
#include "qtextlayout.h"
#include "qtextengine_p.h"
+#include <qthread.h>
#include <qfont.h>
#include <qapplication.h>
#include <qpainter.h>
@@ -2108,8 +2109,10 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q
}
+#if !defined(QT_NO_RAWFONT)
static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &glyphLayout,
- const QPointF &pos, const QTextItem::RenderFlags &flags)
+ const QPointF &pos, const QTextItem::RenderFlags &flags,
+ const QFixed &selectionX, const QFixed &selectionWidth)
{
QGlyphRun glyphRun;
@@ -2117,6 +2120,7 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &g
QRawFont font;
QRawFontPrivate *fontD = QRawFontPrivate::get(font);
fontD->fontEngine = fontEngine;
+ fontD->thread = QThread::currentThread();
fontD->fontEngine->ref.ref();
#if defined(Q_WS_WIN)
@@ -2151,13 +2155,27 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &g
positionsArray);
Q_ASSERT(glyphsArray.size() == positionsArray.size());
+ qreal fontHeight = font.ascent() + font.descent();
+ qreal minY;
+ qreal maxY;
QVector<quint32> glyphs;
QVector<QPointF> positions;
for (int i=0; i<glyphsArray.size(); ++i) {
glyphs.append(glyphsArray.at(i) & 0xffffff);
- positions.append(positionsArray.at(i).toPointF() + pos);
+
+ QPointF position = positionsArray.at(i).toPointF() + pos;
+ positions.append(position);
+
+ if (i == 0) {
+ maxY = minY = position.y();
+ } else {
+ minY = qMin(minY, position.y());
+ maxY = qMax(maxY, position.y());
+ }
}
+ qreal height = maxY + fontHeight - minY;
+
glyphRun.setGlyphIndexes(glyphs);
glyphRun.setPositions(positions);
@@ -2166,6 +2184,8 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &g
glyphRun.setStrikeOut(flags.testFlag(QTextItem::StrikeOut));
glyphRun.setRawFont(font);
+ glyphRun.setBoundingRect(QRectF(selectionX.toReal(), minY, selectionWidth.toReal(), height));
+
return glyphRun;
}
@@ -2182,7 +2202,6 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &g
\sa QTextLayout::glyphRuns()
*/
-#if !defined(QT_NO_RAWFONT)
QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
{
const QScriptLine &line = eng->lines[i];
@@ -2196,7 +2215,14 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
if (length < 0)
length = textLength();
- QTextLineItemIterator iterator(eng, i);
+ if (length == 0)
+ return QList<QGlyphRun>();
+
+ QTextLayout::FormatRange selection;
+ selection.start = from;
+ selection.length = length;
+
+ QTextLineItemIterator iterator(eng, i, QPointF(), &selection);
qreal y = line.y.toReal() + line.base().toReal();
QList<QGlyphRun> glyphRuns;
while (!iterator.atEnd()) {
@@ -2206,7 +2232,10 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
QPointF pos(iterator.x.toReal(), y);
if (from >= 0 && length >= 0 &&
- (from >= si.position + eng->length(&si) || from + length <= si.position)) {
+ (from >= si.position + eng->length(&si)
+ || from + length <= si.position
+ || from + length <= iterator.itemStart
+ || from >= iterator.itemEnd)) {
continue;
}
@@ -2235,19 +2264,22 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
? si.num_glyphs - 1
: logClusters[relativeTo];
+ int itemGlyphsStart = logClusters[iterator.itemStart - si.position];
+ int itemGlyphsEnd = logClusters[iterator.itemEnd - 1 - si.position];
+
QGlyphLayout glyphLayout = eng->shapedGlyphs(&si);
// Calculate new x position of glyph layout for a subset. This becomes somewhat complex
// when we're breaking a RTL script item, since the expected position passed into
// getGlyphPositions() is the left-most edge of the left-most glyph in an RTL run.
if (relativeFrom != (iterator.itemStart - si.position) && !rtl) {
- for (int i=0; i<glyphsStart; ++i) {
+ for (int i=itemGlyphsStart; i<glyphsStart; ++i) {
QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);
pos += QPointF((glyphLayout.advances_x[i] + justification).toReal(),
glyphLayout.advances_y[i].toReal());
}
} else if (relativeTo != (iterator.itemEnd - si.position - 1) && rtl) {
- for (int i=glyphLayout.numGlyphs - 1; i>glyphsEnd; --i) {
+ for (int i=itemGlyphsEnd; i>glyphsEnd; --i) {
QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);
pos += QPointF((glyphLayout.advances_x[i] + justification).toReal(),
glyphLayout.advances_y[i].toReal());
@@ -2256,6 +2288,10 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
glyphLayout = glyphLayout.mid(glyphsStart, glyphsEnd - glyphsStart + 1);
+ QFixed x;
+ QFixed width;
+ iterator.getSelectionBounds(&x, &width);
+
if (glyphLayout.numGlyphs > 0) {
QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script);
if (mainFontEngine->type() == QFontEngine::Multi) {
@@ -2270,7 +2306,7 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which),
- subLayout, pos, flags));
+ subLayout, pos, flags, x, width));
for (int i = 0; i < subLayout.numGlyphs; i++) {
pos += QPointF(subLayout.advances_x[i].toReal(),
subLayout.advances_y[i].toReal());
@@ -2281,10 +2317,15 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
}
QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
- glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which),
- subLayout, pos, flags));
+ QGlyphRun glyphRun = glyphRunWithInfo(multiFontEngine->engine(which),
+ subLayout, pos, flags, x, width);
+ if (!glyphRun.isEmpty())
+ glyphRuns.append(glyphRun);
} else {
- glyphRuns.append(glyphRunWithInfo(mainFontEngine, glyphLayout, pos, flags));
+ QGlyphRun glyphRun = glyphRunWithInfo(mainFontEngine, glyphLayout, pos, flags, x,
+ width);
+ if (!glyphRun.isEmpty())
+ glyphRuns.append(glyphRun);
}
}
}
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index cea5eac465..d641266367 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -1667,21 +1667,24 @@ QTextBlock::iterator &QTextBlock::iterator::operator--()
\sa QGlyphRun, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphRun()
*/
#if !defined(QT_NO_RAWFONT)
-QList<QGlyphRun> QTextFragment::glyphRuns() const
+QList<QGlyphRun> QTextFragment::glyphRuns(int pos, int len) const
{
if (!p || !n)
return QList<QGlyphRun>();
- int pos = position();
- int len = length();
- if (len == 0)
- return QList<QGlyphRun>();
-
- int blockNode = p->blockMap().findNode(pos);
+ int blockNode = p->blockMap().findNode(position());
const QTextBlockData *blockData = p->blockMap().fragment(blockNode);
QTextLayout *layout = blockData->layout;
+ int blockPosition = p->blockMap().position(blockNode);
+ if (pos < 0)
+ pos = position() - blockPosition;
+ if (len < 0)
+ len = length();
+ if (len == 0)
+ return QList<QGlyphRun>();
+
QList<QGlyphRun> ret;
for (int i=0; i<layout->lineCount(); ++i) {
QTextLine textLine = layout->lineAt(i);
diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h
index 9c5cc13539..c2b46e4d12 100644
--- a/src/gui/text/qtextobject.h
+++ b/src/gui/text/qtextobject.h
@@ -317,7 +317,7 @@ public:
QString text() const;
#if !defined(QT_NO_RAWFONT)
- QList<QGlyphRun> glyphRuns() const;
+ QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const;
#endif
private:
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
index 92c84d72e0..9b7d9b83ad 100644
--- a/src/gui/widgets/qlinecontrol.cpp
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -76,6 +76,28 @@ static int qt_passwordEchoDelay = QT_GUI_PASSWORD_ECHO_DELAY;
*/
/*!
+ \internal
+
+ Updates the internal text layout. Returns the ascent of the
+ created QTextLine.
+*/
+int QLineControl::redoTextLayout() const
+{
+ m_textLayout.clearLayout();
+
+ m_textLayout.beginLayout();
+ QTextLine l = m_textLayout.createLine();
+ m_textLayout.endLayout();
+
+#if defined(Q_WS_MAC)
+ if (m_threadChecks)
+ m_textLayoutThread = QThread::currentThread();
+#endif
+
+ return qRound(l.ascent());
+}
+
+/*!
\internal
Updates the display text based of the current edit text
@@ -124,15 +146,12 @@ void QLineControl::updateDisplayText(bool forceUpdate)
m_textLayout.setText(str);
- QTextOption option;
+ QTextOption option = m_textLayout.textOption();
option.setTextDirection(m_layoutDirection);
option.setFlags(QTextOption::IncludeTrailingSpaces);
m_textLayout.setTextOption(option);
- m_textLayout.beginLayout();
- QTextLine l = m_textLayout.createLine();
- m_textLayout.endLayout();
- m_ascent = qRound(l.ascent());
+ m_ascent = redoTextLayout();
if (str != orig || forceUpdate)
emit displayTextChanged(str);
@@ -228,7 +247,7 @@ void QLineControl::del()
if (hasSelectedText()) {
removeSelectedText();
} else {
- int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor;
+ int n = textLayout()->nextCursorPosition(m_cursor) - m_cursor;
while (n--)
internalDelete();
}
@@ -357,7 +376,7 @@ void QLineControl::updatePasswordEchoEditing(bool editing)
*/
int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
{
- return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn);
+ return textLayout()->lineAt(0).xToCursor(x, betweenOrOn);
}
/*!
@@ -368,7 +387,7 @@ int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
*/
QRect QLineControl::cursorRect() const
{
- QTextLine l = m_textLayout.lineAt(0);
+ QTextLine l = textLayout()->lineAt(0);
int c = m_cursor;
if (m_preeditCursor != -1)
c += m_preeditCursor;
@@ -578,14 +597,14 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl
}
if (flags & DrawText)
- m_textLayout.draw(painter, offset, selections, clip);
+ textLayout()->draw(painter, offset, selections, clip);
if (flags & DrawCursor){
int cursor = m_cursor;
if (m_preeditCursor != -1)
cursor += m_preeditCursor;
if (!m_hideCursor && (!m_blinkPeriod || m_blinkStatus))
- m_textLayout.drawCursor(painter, offset, cursor, m_cursorWidth);
+ textLayout()->drawCursor(painter, offset, cursor, m_cursorWidth);
}
}
@@ -601,10 +620,10 @@ void QLineControl::selectWordAtPos(int cursor)
int next = cursor + 1;
if(next > end())
--next;
- int c = m_textLayout.previousCursorPosition(next, QTextLayout::SkipWords);
+ int c = textLayout()->previousCursorPosition(next, QTextLayout::SkipWords);
moveCursor(c, false);
// ## text layout should support end of words.
- int end = m_textLayout.nextCursorPosition(c, QTextLayout::SkipWords);
+ int end = textLayout()->nextCursorPosition(c, QTextLayout::SkipWords);
while (end > cursor && m_text[end-1].isSpace())
--end;
moveCursor(end, true);
diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h
index 44bd7214be..d4c4154b3d 100644
--- a/src/gui/widgets/qlinecontrol_p.h
+++ b/src/gui/widgets/qlinecontrol_p.h
@@ -65,6 +65,7 @@
#include "QtCore/qpoint.h"
#include "QtGui/qcompleter.h"
#include "QtGui/qaccessible.h"
+#include "QtCore/qthread.h"
#include "qplatformdefs.h"
@@ -90,6 +91,10 @@ public:
#ifdef QT_GUI_PASSWORD_ECHO_DELAY
, m_passwordEchoTimer(0)
#endif
+#if defined(Q_WS_MAC)
+ , m_threadChecks(false)
+ , m_textLayoutThread(0)
+ #endif
{
init(txt);
}
@@ -332,11 +337,27 @@ public:
bool processEvent(QEvent *ev);
- QTextLayout *textLayout()
+ QTextLayout *textLayout() const
{
+#if defined(Q_WS_MAC)
+ if (m_threadChecks && QThread::currentThread() != m_textLayoutThread)
+ redoTextLayout();
+#endif
return &m_textLayout;
}
+#if defined(Q_WS_MAC)
+ void setThreadChecks(bool threadChecks)
+ {
+ m_threadChecks = threadChecks;
+ }
+
+ bool threadChecks() const
+ {
+ return m_threadChecks;
+ }
+#endif
+
private:
void init(const QString &txt);
void removeSelectedText();
@@ -433,8 +454,8 @@ private:
QString stripString(const QString &str) const;
int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const;
- // complex text layout
- QTextLayout m_textLayout;
+ // complex text layout (must be mutable so it can be reshaped at will)
+ mutable QTextLayout m_textLayout;
bool m_passwordEchoEditing;
QChar m_passwordCharacter;
@@ -451,6 +472,12 @@ private:
#endif
}
+ int redoTextLayout() const;
+#if defined(Q_WS_MAC)
+ bool m_threadChecks;
+ mutable QThread *m_textLayoutThread;
+#endif
+
Q_SIGNALS:
void cursorPositionChanged(int, int);
void selectionChanged();