Fix potential crash when displaying multiscripted text
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Thu, 5 May 2011 14:49:06 +0000 (16:49 +0200)
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Fri, 6 May 2011 07:56:25 +0000 (09:56 +0200)
Shaping has to be done in the current thread, otherwise the
font engines index for each glyph (referenced in the msb of the glyph
index) might not be valid yet, because the font engines list is
populated when shaping is done. So we need to make sure that the
render thread relayouts. Geometry changes will already cause a
relayout, which will in turn cause another relayout when the
paint node is updated. There doesn't seem to be any convenient
and safe way of avoiding this doubling of the layout step if we
want to have rendering in a different thread than the QML graph.

Reviewed-by: Gunnar
src/declarative/items/qsgtext.cpp
src/declarative/items/qsgtext_p_p.h

index f2ec7b2..e7e655d 100644 (file)
@@ -106,7 +106,7 @@ QSGTextPrivate::QSGTextPrivate()
   imageCacheDirty(true), updateOnComponentComplete(true),
   richText(false), singleline(false), cacheAllTextAsImage(true), internalWidthUpdate(false),
   requireImplicitWidth(false), truncated(false), hAlignImplicit(true), rightToLeftText(false),
-  layoutTextElided(false), naturalWidth(0), doc(0), nodeType(NodeIsNull)
+  layoutTextElided(false), naturalWidth(0), doc(0), layoutThread(0), nodeType(NodeIsNull)
 {
     cacheAllTextAsImage = enableImageCache();
 }
@@ -378,6 +378,8 @@ QRect QSGTextPrivate::setupTextLayout()
     bool elideText = false;
     bool truncate = false;
 
+    layoutThread = QThread::currentThread();
+
     QFontMetrics fm(layout.font());
     elidePos = QPointF();
 
@@ -1070,6 +1072,10 @@ QSGNode *QSGText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
 
     QRectF bounds = boundingRect();
 
+    // We need to make sure the layout is done in the current thread
+    if (d->layoutThread != QThread::currentThread())
+        d->updateLayout();
+
     // XXX todo - some styled text can be done by the QSGTextNode
     if (richTextAsImage || d->cacheAllTextAsImage || (!QSGDistanceFieldGlyphCache::distanceFieldEnabled() && d->style != Normal)) {
         bool wasDirty = d->imageCacheDirty;
index 8d26394..a3836a1 100644 (file)
@@ -134,6 +134,7 @@ public:
     QPixmap textLayoutImage(bool drawStyle);
     void drawTextLayout(QPainter *p, const QPointF &pos, bool drawStyle);
     QTextLayout layout;
+    QThread *layoutThread;
 
     static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource);
     static QPixmap drawOutline(const QPixmap &source, const QPixmap &styleSource, int yOffset);