diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index b0cfa49b36943713886e99f4290cbc80593b3902..83d9edab9407171190d9f66ab701373f22c2bfaa 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -1459,10 +1459,7 @@ void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_me
 
 bool QFontEngineFT::supportsTransformation(const QTransform &transform) const
 {
-    // The freetype engine falls back to QFontEngine for tranformed glyphs,
-    // which uses fast-tranform and produces very ugly results, so we claim
-    // to support just translations.
-    return transform.type() <= QTransform::TxTranslate;
+    return transform.type() <= QTransform::TxRotate;
 }
 
 void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
@@ -1943,17 +1940,75 @@ void QFontEngineFT::unlockAlphaMapForGlyph()
     currentlyLockedAlphaMap = QImage();
 }
 
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format)
+QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
+                                                  QFixed subPixelPosition,
+                                                  GlyphFormat format,
+                                                  const QTransform &t)
 {
-    return defaultGlyphSet.outline_drawing ? 0 :
-            loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, g, subPixelPosition, format);
+    FT_Face face = 0;
+    QGlyphSet *glyphSet = 0;
+    FT_Matrix ftMatrix = QTransformToFTMatrix(t);
+    if (cacheEnabled) {
+        if (t.type() > QTransform::TxTranslate && FT_IS_SCALABLE(freetype->face)) {
+            for (int i = 0; i < transformedGlyphSets.count(); ++i) {
+                const QGlyphSet &g = transformedGlyphSets.at(i);
+                if (g.transformationMatrix.xx == ftMatrix.xx
+                    && g.transformationMatrix.xy == ftMatrix.xy
+                    && g.transformationMatrix.yx == ftMatrix.yx
+                    && g.transformationMatrix.yy == ftMatrix.yy) {
+
+                    // found a match, move it to the front
+                    transformedGlyphSets.move(i, 0);
+                    glyphSet = &transformedGlyphSets[0];
+                    break;
+                }
+            }
+
+            if (!glyphSet) {
+                // don't cache more than 10 transformations
+                if (transformedGlyphSets.count() >= 10) {
+                    transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
+                } else {
+                    transformedGlyphSets.prepend(QGlyphSet());
+                }
+                glyphSet = &transformedGlyphSets[0];
+                glyphSet->clear();
+                glyphSet->transformationMatrix = ftMatrix;
+            }
+        } else {
+            glyphSet = &defaultGlyphSet;
+        }
+        Q_ASSERT(glyphSet != 0);
+    }
+
+    if (glyphSet != 0 && glyphSet->outline_drawing)
+        return 0;
+
+    Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0;
+    if (!glyph || glyph->format != format) {
+        face = lockFace();
+        FT_Matrix m = this->matrix;
+        FT_Matrix_Multiply(&ftMatrix, &m);
+        freetype->matrix = m;
+        glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false);
+    }
+
+    if (face)
+        unlockFace();
+
+    return glyph;
 }
 
 QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
+{
+    return alphaMapForGlyph(g, subPixelPosition, QTransform());
+}
+
+QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
 {
     lockFace();
 
-    QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono));
+    QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono, t));
     if (!glyph || !glyph->data) {
         unlockFace();
         return QFontEngine::alphaMapForGlyph(g);
@@ -1987,12 +2042,12 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
 
 QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
 {
-    if (t.type() > QTransform::TxTranslate)
+    if (t.type() > QTransform::TxRotate)
         return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
 
     lockFace();
 
-    QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32));
+    QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32, t));
     if (!glyph || !glyph->data) {
         unlockFace();
         return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index a73c281f1d795ac8e9896b371ca033b173be708f..1894d25d70b9c759fde3fce48363dd58f300f05d 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -233,6 +233,7 @@ private:
     virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const;
     virtual QImage alphaMapForGlyph(glyph_t g) { return alphaMapForGlyph(g, 0); }
     virtual QImage alphaMapForGlyph(glyph_t, QFixed);
+    QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
     virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
     virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
                                                 QFixed subPixelPosition,
@@ -265,7 +266,7 @@ private:
     inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
     { return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly); }
     Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
-    Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format);
+    Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t);
 
     QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
     bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,