diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index bfa2fccd67d0fe62eb92fc851d23f60a1e7d84f8..87255f4bd95d11ae15d648e8b3628b6b826be8f2 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -79,6 +79,7 @@ QQuickTextPrivate::QQuickTextPrivate()
     , requireImplicitSize(false), implicitWidthValid(false), implicitHeightValid(false)
     , truncated(false), hAlignImplicit(true), rightToLeftText(false)
     , layoutTextElided(false), textHasChanged(true), needToUpdateLayout(false), formatModifiesFontSize(false)
+    , polishSize(false)
 {
     implicitAntialiasing = true;
 }
@@ -356,6 +357,8 @@ void QQuickTextPrivate::updateLayout()
         textHasChanged = true;
         updateLayout();
     }
+
+    q->polish();
 }
 
 void QQuickText::imageDownloadFinished()
@@ -2248,13 +2251,22 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
                 node->addImage(QRectF(img->pos.x() + dx, img->pos.y() + dy, pix->width(), pix->height()), pix->image());
         }
     }
+
+    // The font caches have now been initialized on the render thread, so they have to be
+    // invalidated before we can use them from the main thread again.
+    invalidateFontCaches();
+
     return node;
 }
 
 void QQuickText::updatePolish()
 {
     Q_D(QQuickText);
-    d->updateSize();
+    if (d->polishSize) {
+        d->updateSize();
+        d->polishSize = false;
+    }
+    invalidateFontCaches();
 }
 
 /*!
@@ -2381,6 +2393,7 @@ void QQuickText::setFontSizeMode(FontSizeMode mode)
     if (d->fontSizeMode() == mode)
         return;
 
+    d->polishSize = true;
     polish();
 
     d->extra.value().fontSizeMode = mode;
@@ -2409,8 +2422,10 @@ void QQuickText::setMinimumPixelSize(int size)
     if (d->minimumPixelSize() == size)
         return;
 
-    if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid()))
+    if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) {
+        d->polishSize = true;
         polish();
+    }
     d->extra.value().minimumPixelSize = size;
     emit minimumPixelSizeChanged();
 }
@@ -2437,8 +2452,10 @@ void QQuickText::setMinimumPointSize(int size)
     if (d->minimumPointSize() == size)
         return;
 
-    if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid()))
+    if (d->fontSizeMode() != FixedSize && (widthValid() || heightValid())) {
+        d->polishSize = true;
         polish();
+    }
     d->extra.value().minimumPointSize = size;
     emit minimumPointSizeChanged();
 }
@@ -2699,4 +2716,26 @@ QString QQuickText::linkAt(qreal x, qreal y) const
     return d->anchorAt(QPointF(x, y));
 }
 
+/*!
+ * \internal
+ *
+ * Invalidates font caches owned by the text objects owned by the element
+ * to work around the fact that text objects cannot be used from multiple threads.
+ */
+void QQuickText::invalidateFontCaches()
+{
+    Q_D(QQuickText);
+
+    if (d->richText && d->extra->doc != 0) {
+        QTextBlock block;
+        for (block = d->extra->doc->firstBlock(); block.isValid(); block = block.next()) {
+            if (block.layout() != 0 && block.layout()->engine() != 0)
+                block.layout()->engine()->resetFontEngineCache();
+        }
+    } else {
+        if (d->layout.engine() != 0)
+            d->layout.engine()->resetFontEngineCache();
+    }
+}
+
 QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index c9f64d3fabc2069f4e30fb5dc33cacdce9fabc62..c3fa9e6935195295104dd3d64428ef015c33a80b 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -245,6 +245,7 @@ protected:
     void hoverEnterEvent(QHoverEvent *event);
     void hoverMoveEvent(QHoverEvent *event);
     void hoverLeaveEvent(QHoverEvent *event);
+    void invalidateFontCaches();
 
 private Q_SLOTS:
     void q_imagesLoaded();
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index 022c2ac9d53076f9401648d6e0f66f8f4d7b0c81..d645ce5ed5f0ca18390de32098b93b9ae78fbcb3 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -151,6 +151,7 @@ public:
     bool textHasChanged:1;
     bool needToUpdateLayout:1;
     bool formatModifiesFontSize:1;
+    bool polishSize:1; // Workaround for problem with polish called after updateSize (QTBUG-42636)
 
     static const QChar elideChar;
 
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index aca7150ca2dff965c9fc0bc5b1ca498ab59fc28f..b950f962773786cd14b0ce30cc166a05b53f68ea 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1739,6 +1739,7 @@ void QQuickTextEdit::triggerPreprocess()
     Q_D(QQuickTextEdit);
     if (d->updateType == QQuickTextEditPrivate::UpdateNone)
         d->updateType = QQuickTextEditPrivate::UpdateOnlyPreprocess;
+    polish();
     update();
 }
 
@@ -1758,6 +1759,25 @@ static inline void updateNodeTransform(QQuickTextNode* node, const QPointF &topL
     node->setMatrix(transformMatrix);
 }
 
+/*!
+ * \internal
+ *
+ * Invalidates font caches owned by the text objects owned by the element
+ * to work around the fact that text objects cannot be used from multiple threads.
+ */
+void QQuickTextEdit::invalidateFontCaches()
+{
+    Q_D(QQuickTextEdit);
+    if (d->document == 0)
+        return;
+
+    QTextBlock block;
+    for (block = d->document->firstBlock(); block.isValid(); block = block.next()) {
+        if (block.layout() != 0 && block.layout()->engine() != 0)
+            block.layout()->engine()->resetFontEngineCache();
+    }
+}
+
 QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
 {
     Q_UNUSED(updatePaintNodeData);
@@ -1911,9 +1931,16 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
         rootNode->resetCursorNode(cursor);
     }
 
+    invalidateFontCaches();
+
     return rootNode;
 }
 
+void QQuickTextEdit::updatePolish()
+{
+    invalidateFontCaches();
+}
+
 /*!
     \qmlproperty bool QtQuick::TextEdit::canPaste
 
@@ -2079,6 +2106,7 @@ void QQuickTextEdit::q_contentsChange(int pos, int charsRemoved, int charsAdded)
 
     markDirtyNodesForRange(pos, editRange, delta);
 
+    polish();
     if (isComponentComplete()) {
         d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
         update();
@@ -2106,6 +2134,7 @@ void QQuickTextEdit::updateSelection()
     // No need for node updates when we go from an empty selection to another empty selection
     if (d->control->textCursor().hasSelection() || d->hadSelection) {
         markDirtyNodesForRange(qMin(d->lastSelectionStart, d->control->textCursor().selectionStart()), qMax(d->control->textCursor().selectionEnd(), d->lastSelectionEnd), 0);
+        polish();
         if (isComponentComplete()) {
             d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
             update();
@@ -2246,6 +2275,7 @@ void QQuickTextEdit::updateWholeDocument()
             node->setDirty();
     }
 
+    polish();
     if (isComponentComplete()) {
         d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
         update();
@@ -2260,6 +2290,7 @@ void QQuickTextEdit::invalidateBlock(const QTextBlock &block)
 void QQuickTextEdit::updateCursor()
 {
     Q_D(QQuickTextEdit);
+    polish();
     if (isComponentComplete()) {
         d->updateType = QQuickTextEditPrivate::UpdatePaintNode;
         update();
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index 54e6dd229af48f2b41e1ed3a4751109c104a070c..5d1c026c5cf5ef8d40cd33bdd683f90acb1b1318 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -330,6 +330,7 @@ private Q_SLOTS:
 private:
     void markDirtyNodesForRange(int start, int end, int charDelta);
     void updateTotalLines();
+    void invalidateFontCaches();
 
 protected:
     virtual void geometryChanged(const QRectF &newGeometry,
@@ -354,6 +355,7 @@ protected:
     void inputMethodEvent(QInputMethodEvent *e);
 #endif
     QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
+    void updatePolish();
 
     friend class QQuickTextUtil;
     friend class QQuickTextDocument;
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 1f03fb21e21c224dd9fda36604f9b0db7b41e684..a9c60273d2b8de0cba65d548ff1cc16373ff5cd7 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -56,6 +56,8 @@
 #include "qquickaccessibleattached_p.h"
 #endif
 
+#include <QtGui/private/qtextengine_p.h>
+
 QT_BEGIN_NAMESPACE
 
 DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
@@ -362,6 +364,7 @@ void QQuickTextInput::setColor(const QColor &c)
         d->color = c;
         d->textLayoutDirty = true;
         d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+        polish();
         update();
         emit colorChanged();
     }
@@ -389,6 +392,7 @@ void QQuickTextInput::setSelectionColor(const QColor &color)
     if (d->hasSelectedText()) {
         d->textLayoutDirty = true;
         d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+        polish();
         update();
     }
     emit selectionColorChanged();
@@ -414,6 +418,7 @@ void QQuickTextInput::setSelectedTextColor(const QColor &color)
     if (d->hasSelectedText()) {
         d->textLayoutDirty = true;
         d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+        polish();
         update();
     }
     emit selectedTextColorChanged();
@@ -723,6 +728,7 @@ void QQuickTextInput::setCursorVisible(bool on)
     if (!d->cursorItem) {
         d->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0);
         d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+        polish();
         update();
     }
     emit cursorVisibleChanged(d->cursorVisible);
@@ -1830,9 +1836,23 @@ void QQuickTextInput::triggerPreprocess()
     Q_D(QQuickTextInput);
     if (d->updateType == QQuickTextInputPrivate::UpdateNone)
         d->updateType = QQuickTextInputPrivate::UpdateOnlyPreprocess;
+    polish();
     update();
 }
 
+void QQuickTextInput::updatePolish()
+{
+    invalidateFontCaches();
+}
+
+void QQuickTextInput::invalidateFontCaches()
+{
+    Q_D(QQuickTextInput);
+
+    if (d->m_textLayout.engine() != 0)
+        d->m_textLayout.engine()->resetFontEngineCache();
+}
+
 QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
 {
     Q_UNUSED(data);
@@ -1891,6 +1911,8 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
         d->textLayoutDirty = false;
     }
 
+    invalidateFontCaches();
+
     return node;
 }
 
@@ -2651,6 +2673,7 @@ void QQuickTextInput::updateCursorRectangle(bool scroll)
         d->updateVerticalScroll();
     }
     d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+    polish();
     update();
     emit cursorRectangleChanged();
     if (d->cursorItem) {
@@ -2668,6 +2691,7 @@ void QQuickTextInput::selectionChanged()
     Q_D(QQuickTextInput);
     d->textLayoutDirty = true; //TODO: Only update rect in selection
     d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+    polish();
     update();
     emit selectedTextChanged();
 
@@ -2879,6 +2903,7 @@ void QQuickTextInputPrivate::updateLayout()
     contentSize = QSizeF(width, height);
 
     updateType = UpdatePaintNode;
+    q->polish();
     q->update();
 
     if (!requireImplicitWidth && !q->widthValid())
@@ -4167,6 +4192,7 @@ void QQuickTextInputPrivate::setCursorBlinkPeriod(int msec)
         m_blinkTimer = 0;
         if (m_blinkStatus == 1) {
             updateType = UpdatePaintNode;
+            q->polish();
             q->update();
         }
     }
@@ -4179,6 +4205,7 @@ void QQuickTextInput::timerEvent(QTimerEvent *event)
     if (event->timerId() == d->m_blinkTimer) {
         d->m_blinkStatus = !d->m_blinkStatus;
         d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
+        polish();
         update();
     } else if (event->timerId() == d->m_passwordEchoTimer.timerId()) {
         d->m_passwordEchoTimer.stop();
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 4b945305870d35b07c9d0ffc8458e2327208aede..2386fc564299041496e52c2a8235b8ab65055f27 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -314,6 +314,9 @@ Q_SIGNALS:
 #endif
     void renderTypeChanged();
 
+private:
+    void invalidateFontCaches();
+
 protected:
     virtual void geometryChanged(const QRectF &newGeometry,
                                  const QRectF &oldGeometry);
@@ -332,6 +335,7 @@ protected:
     void focusInEvent(QFocusEvent *event);
     void timerEvent(QTimerEvent *event);
     QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);
+    void updatePolish();
 
 public Q_SLOTS:
     void selectAll();