diff --git src/gui/painting/qpaintengine_raster.cpp src/gui/painting/qpaintengine_raster.cpp
index 78f899c..e6ce1c4 100644
--- src/gui/painting/qpaintengine_raster.cpp
+++ src/gui/painting/qpaintengine_raster.cpp
@@ -2909,7 +2909,20 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
             //        x, y,
             //        positions[i].x.toInt(), positions[i].y.toInt());
 
-            alphaPenBlt(bits + ((c.x << leftShift) >> rightShift) + c.y * bpl, bpl, depth, x, y, c.w, c.h);
+//             alphaPenBlt(bits + ((c.x << leftShift) >> rightShift) + c.y * bpl, bpl, depth, x, y, c.w, c.h);
+            const uchar *glyphBits = bits + ((c.x << leftShift) >> rightShift) + c.y * bpl;
+
+            if (glyphType == QFontEngineGlyphCache::Raster_ARGB) {
+                // The current state transform has already been applied to the positions,
+                // so we prevent drawImage() from re-applying the transform by clearing
+                // the state for the duration of the call.
+                QTransform originalTransform = s->matrix;
+                s->matrix = QTransform();
+                drawImage(QPoint(x, y), QImage(glyphBits, c.w, c.h, bpl, image.format()));
+                s->matrix = originalTransform;
+            } else {
+                alphaPenBlt(glyphBits, bpl, depth, x, y, c.w, c.h);
+            }
         }
     }
     return true;
diff --git src/gui/painting/qtextureglyphcache.cpp src/gui/painting/qtextureglyphcache.cpp
index 883433a..234cab3 100644
--- src/gui/painting/qtextureglyphcache.cpp
+++ src/gui/painting/qtextureglyphcache.cpp
@@ -151,6 +151,7 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
     switch (m_type) {
     case Raster_A8: format = QFontEngine::Format_A8; break;
     case Raster_RGBMask: format = QFontEngine::Format_A32; break;
+    case Raster_ARGB: format = QFontEngine::Format_ARGB; break;
     default: format = QFontEngine::Format_Mono; break;
     }
 
@@ -327,7 +328,7 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition
         }
     } else
 #endif
-    if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
+    if (m_type == QFontEngineGlyphCache::Raster_RGBMask || m_type == QFontEngineGlyphCache::Raster_ARGB)
         return m_current_fontengine->alphaRGBMapForGlyph(g, subPixelPosition, glyphMargin(), m_transform);
     else
         return m_current_fontengine->alphaMapForGlyph(g, subPixelPosition, m_transform);
@@ -362,6 +363,9 @@ void QImageTextureGlyphCache::createTextureData(int width, int height)
     case QFontEngineGlyphCache::Raster_RGBMask:
         m_image = QImage(width, height, QImage::Format_RGB32);
         break;
+    case QFontEngineGlyphCache::Raster_ARGB:
+        m_image = QImage(width, height, QImage::Format_ARGB32_Premultiplied);
+        break;
     }
 }
 
@@ -386,7 +390,8 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP
     }
 #endif
 
-    if (m_type == QFontEngineGlyphCache::Raster_RGBMask) {
+    if (m_type == QFontEngineGlyphCache::Raster_RGBMask
+        || m_type == QFontEngineGlyphCache::Raster_ARGB) {
         QImage ref(m_image.bits() + (c.x * 4 + c.y * m_image.bytesPerLine()),
                    qMax(mask.width(), c.w), qMax(mask.height(), c.h), m_image.bytesPerLine(),
                    m_image.format());
diff --git src/gui/text/qfontengine.cpp src/gui/text/qfontengine.cpp
index 67b8798..381166d 100644
--- src/gui/text/qfontengine.cpp
+++ src/gui/text/qfontengine.cpp
@@ -682,6 +682,13 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph)
     return indexed;
 }
 
+QImage QFontEngine::bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform&)
+{
+    Q_UNUSED(subPixelPosition);
+
+    return QImage();
+}
+
 void QFontEngine::removeGlyphFromCache(glyph_t)
 {
 }
diff --git src/gui/text/qfontengine_coretext.mm src/gui/text/qfontengine_coretext.mm
index 204d685..ae07871 100644
--- src/gui/text/qfontengine_coretext.mm
+++ src/gui/text/qfontengine_coretext.mm
@@ -370,24 +370,76 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
 
     QVarLengthArray<CGGlyph> cgGlyphs(len);
     CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len);
+    CGGlyph placeHolder = 0;
 
     for (int i = 0; i < len; ++i) {
         if (cgGlyphs[i]) {
             glyphs->glyphs[i] = cgGlyphs[i];
         } else {
+            bool isUTF32 = false;
             if (!cfstring)
                 cfstring = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>(str), len, kCFAllocatorNull);
             QCFType<CTFontRef> substituteFont = CTFontCreateForString(ctfont, cfstring, CFRangeMake(i, 1));
+//             QCFString family = CTFontCopyFamilyName(substituteFont);
+//             QCFString styleName = (CFStringRef) CTFontCopyAttribute(substituteFont, kCTFontStyleNameAttribute);
+
             CGGlyph substituteGlyph = 0;
             CTFontGetGlyphsForCharacters(substituteFont, (const UniChar*)str + i, &substituteGlyph, 1);
+            if (!substituteGlyph && i < len-1) {
+                // try UTF32
+                substituteFont = QCFType<CTFontRef>(CTFontCreateForString(ctfont, cfstring, CFRangeMake(i, 2)));
+//                 family = CTFontCopyFamilyName(substituteFont);
+//                 styleName = (CFStringRef) CTFontCopyAttribute(substituteFont, kCTFontStyleNameAttribute);
+                CTFontGetGlyphsForCharacters(substituteFont, (const UniChar*)str + i, &substituteGlyph, 2);
+                isUTF32 = true;
+            }
             if (substituteGlyph) {
                 const uint fontIndex = (fontIndexForFont(substituteFont) << 24);
                 glyphs->glyphs[i] = substituteGlyph | fontIndex;
+#if 1
+                if (isUTF32) {
+                    if (!placeHolder) {
+                        CGFontRef fontRef = CTFontCopyGraphicsFont(ctfont, NULL);
+                        if (fontRef) {
+                            // look up the non-breaking-space glyph for the official font
+                            placeHolder = CGFontGetGlyphWithGlyphName(fontRef, CFSTR("uni00A0"));
+//                             // or rather use ".null" which might take less horizontal space.
+//                             placeHolder = CGFontGetGlyphWithGlyphName(fontRef, CFSTR(".null"));
+                            CFRelease(fontRef);
+                        }
+                    }
+                    if (placeHolder) {
+                        glyphs->glyphs[i+1] = placeHolder;
+                        // also set this one!
+                        cgGlyphs[i+1] = placeHolder;
+                    }
+                }
+#endif
                 if (!(flags & QTextEngine::GlyphIndicesOnly)) {
                     CGSize advance;
                     CTFontGetAdvancesForGlyphs(substituteFont, kCTFontHorizontalOrientation, &substituteGlyph, &advance, 1);
                     glyphs->advances_x[i] = QFixed::fromReal(advance.width);
                     glyphs->advances_y[i] = QFixed::fromReal(advance.height);
+#if 1
+                    if (isUTF32 && placeHolder) {
+                        CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &placeHolder, &advance, 1);
+                        glyphs->advances_x[i+1] = QFixed::fromReal(advance.width);
+                        glyphs->advances_y[i+1] = QFixed::fromReal(advance.height);
+                    }
+#endif
+                }
+                if (isUTF32) {
+//                     QCFType<CGFontRef> sFont = CTFontCopyGraphicsFont(substituteFont, NULL);
+//                     QCFString glyphName = CGFontCopyGlyphNameForGlyph(sFont, substituteGlyph);
+//                     qWarning() << Q_FUNC_INFO << "Font" << QString(family) << QString(styleName)
+//                         << "instead of" << fontDef.family << fontDef.styleName
+//                         << "for" << str[i].unicode() << str[i]
+//                         << substituteGlyph << QString(glyphName);
+                    // skip the next glyph!
+                    i += 1;
+//                     glyphName = CGFontCopyGlyphNameForGlyph(CTFontCopyGraphicsFont(ctfont, NULL), glyphs->glyphs[i]);
+//                     qWarning() << "\t: next glyph:" << glyphs->glyphs[i] << QString(glyphName) << "advances:"
+//                         << glyphs->advances_x[i] << glyphs->advances_y[i];
                 }
             }
         }
@@ -472,6 +524,16 @@ void QCoreTextFontEngine::init()
 
     synthesisFlags = 0;
     CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont);
+    // RJVB: backported, but only set glyphFormat for colour glyphs
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+    isColourFont = (traits & kCTFontColorGlyphsTrait);
+    if (isColourFont) {
+        glyphFormat = QFontEngineGlyphCache::Raster_ARGB;
+    }
+#else
+    isColourFont = false;
+#endif
+
     if (traits & kCTFontItalicTrait)
         fontDef.style = QFont::StyleItalic;
 
@@ -708,6 +770,9 @@ static void convertCGPathToQPainterPath(void *info, const CGPathElement *element
 void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs,
                                           QPainterPath *path, QTextItem::RenderFlags)
 {
+    if (isColourFont)
+        return; // We can't convert color-glyphs to path
+
     CGAffineTransform cgMatrix = CGAffineTransformIdentity;
     cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1);
 
@@ -725,16 +790,21 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
 {
     Q_UNUSED(margin);
     const glyph_metrics_t br = boundingBox(glyph);
-    QImage im(qRound(br.width) + 2, qRound(br.height) + 2, QImage::Format_RGB32);
+    QImage::Format imageFormat = isColourFont ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
+    QImage im(qRound(br.width) + 2, qRound(br.height) + 2, imageFormat);
     im.fill(0);
 
+    if (!im.width() || !im.height()) {
+        return im;
+    }
+
     CGColorSpaceRef colorspace =
 #ifdef Q_WS_MAC
             CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
 #else
             CGColorSpaceCreateDeviceRGB();
 #endif
-    uint cgflags = kCGImageAlphaNoneSkipFirst;
+    uint cgflags = isColourFont ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
 #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
     cgflags |= kCGBitmapByteOrder32Host;
 #endif
@@ -745,38 +815,51 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
     CGContextSetShouldAntialias(ctx, (aa || fontDef.pointSize > qt_antialiasing_threshold)
                                  && !(fontDef.styleStrategy & QFont::NoAntialias));
     CGContextSetShouldSmoothFonts(ctx, aa);
-    CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
-    CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
-
-    CGAffineTransformConcat(cgMatrix, oldTextMatrix);
+    CGAffineTransform cgMatrix = CGAffineTransformIdentity;
 
     if (synthesisFlags & QFontEngine::SynthesizedItalic)
         cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
 
-    cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
-
-    CGContextSetTextMatrix(ctx, cgMatrix);
-    CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
-    CGContextSetTextDrawingMode(ctx, kCGTextFill);
-
-    CGContextSetFont(ctx, cgFont);
+    if (!isColourFont) {
+        cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
+    }
 
+    CGGlyph cgGlyph = glyph;
     qreal pos_x = -br.x.truncate() + subPixelPosition.toReal();
     qreal pos_y = im.height() + br.y.toReal();
-    CGContextSetTextPosition(ctx, pos_x, pos_y);
 
-    CGSize advance;
-    advance.width = 0;
-    advance.height = 0;
-    CGGlyph cgGlyph = glyph;
-    CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
+    if (!isColourFont) {
+        CGContextSetTextMatrix(ctx, cgMatrix);
+        CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
+        CGContextSetTextDrawingMode(ctx, kCGTextFill);
 
-    if (synthesisFlags & QFontEngine::SynthesizedBold) {
-        CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y);
+        CGContextSetFont(ctx, cgFont);
+
+        CGContextSetTextPosition(ctx, pos_x, pos_y);
+
+        CGSize advance;
+        advance.width = 0;
+        advance.height = 0;
         CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
+
+        if (synthesisFlags & QFontEngine::SynthesizedBold) {
+            CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y);
+            CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
+        }
+    } else {
+        // CGContextSetTextMatrix does not work with color glyphs, so we use
+        // the CTM instead. This means we must translate the CTM as well, to
+        // set the glyph position, instead of using CGContextSetTextPosition.
+        CGContextTranslateCTM(ctx, pos_x, pos_y);
+        CGContextConcatCTM(ctx, cgMatrix);
+
+        // CGContextShowGlyphsWithAdvances does not support the 'sbix' color-bitmap
+        // glyphs in the Apple Color Emoji font, so we use CTFontDrawGlyphs instead.
+        CTFontDrawGlyphs(ctfont, &cgGlyph, &CGPointZero, 1, ctx);
     }
 
     CGContextRelease(ctx);
+    CGColorSpaceRelease(colorspace);
 
     return im;
 }
diff --git src/gui/text/qfontengine_coretext_p.h src/gui/text/qfontengine_coretext_p.h
index 5a46c98..a8b01b8 100644
--- src/gui/text/qfontengine_coretext_p.h
+++ src/gui/text/qfontengine_coretext_p.h
@@ -116,6 +116,7 @@ private:
     CGAffineTransform transform;
     QFixed avgCharWidth;
     friend class QCoreTextFontEngineMulti;
+    bool isColourFont;
 };
 
 class QCoreTextFontEngineMulti : public QFontEngineMulti
diff --git src/gui/text/qfontengine_p.h src/gui/text/qfontengine_p.h
index f29ac47..d644e67 100644
--- src/gui/text/qfontengine_p.h
+++ src/gui/text/qfontengine_p.h
@@ -127,7 +127,8 @@ public:
         Format_Render = Format_None,
         Format_Mono,
         Format_A8,
-        Format_A32
+        Format_A32,
+        Format_ARGB
     };
 
     QFontEngine();
@@ -200,6 +201,7 @@ public:
     virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t);
     virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
     virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t);
+    virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
 
     virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed /*subPixelPosition*/, const QTransform &matrix, GlyphFormat /*format*/)
     {
diff --git src/gui/text/qfontengineglyphcache_p.h src/gui/text/qfontengineglyphcache_p.h
index 602927c..c8dc64b 100644
--- src/gui/text/qfontengineglyphcache_p.h
+++ src/gui/text/qfontengineglyphcache_p.h
@@ -79,6 +79,8 @@ public:
         Raster_RGBMask,
         Raster_A8,
         Raster_Mono
+        // RJVB backported
+        , Raster_ARGB
     };
 
     QFontEngineGlyphCache(const QTransform &matrix, Type type) : m_transform(matrix), m_type(type) { }
diff --git src/gui/text/qtextengine.cpp src/gui/text/qtextengine.cpp
index f50e711..765ccb8 100644
--- src/gui/text/qtextengine.cpp
+++ src/gui/text/qtextengine.cpp
@@ -1195,6 +1195,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
     QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading);
 
     bool kerningEnabled = this->font(si).d->kerning;
+    const int itemLength = length(item);
 
     HB_ShaperItem entire_shaper_item;
     qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item));
@@ -1202,7 +1203,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
     entire_shaper_item.stringLength = layoutData->string.length();
     entire_shaper_item.item.script = (HB_Script)si.analysis.script;
     entire_shaper_item.item.pos = si.position;
-    entire_shaper_item.item.length = length(item);
+    entire_shaper_item.item.length = itemLength;
     entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel;
 
     HB_UChar16 upperCased[256]; // XXX what about making this 4096, so we don't have to extend it ever.
@@ -1227,7 +1228,19 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
     if (option.useDesignMetrics())
         entire_shaper_item.shaperFlags |= HB_ShaperFlag_UseDesignMetrics;
 
-    entire_shaper_item.num_glyphs = qMax(layoutData->glyphLayout.numGlyphs - layoutData->used, int(entire_shaper_item.item.length));
+//     entire_shaper_item.num_glyphs = qMax(layoutData->glyphLayout.numGlyphs - layoutData->used, int(entire_shaper_item.item.length));
+    // RJVB backported from Qt 5.9, scoped for `string`
+    {
+        // ensure we are not asserting in HB_HeuristicSetGlyphAttributes()
+        entire_shaper_item.num_glyphs = 0;
+        const ushort *string = reinterpret_cast<const ushort *>(layoutData->string.constData());
+        for (int i = 0; i < itemLength; ++i, ++entire_shaper_item.num_glyphs) {
+            if (QChar::isHighSurrogate(string[i]) && i + 1 < itemLength && QChar::isLowSurrogate(string[i + 1])) {
+                ++i;
+           }
+        }
+    }
+
     if (! ensureSpace(entire_shaper_item.num_glyphs)) {
         if (hasCaseChange(si))
             delete [] const_cast<HB_UChar16 *>(entire_shaper_item.string);
@@ -1292,6 +1305,10 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
             shaper_item.item.length -= shaper_item.item.pos - entire_shaper_item.item.pos;
             shaper_item.num_glyphs -= itemBoundaries[k + 1];
         }
+        if (static_cast<int>(shaper_item.item.length) < 0) {
+            remaining_glyphs -= shaper_item.initialGlyphCount;
+            continue;
+        }
         shaper_item.initialGlyphCount = shaper_item.num_glyphs;
         if (shaper_item.num_glyphs < shaper_item.item.length)
             shaper_item.num_glyphs = shaper_item.item.length;
diff --git src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 6bf9399..41c1f4f 100644
--- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -1104,7 +1104,8 @@ void QGL2PaintEngineExPrivate::resetClipIfNeeded()
 
 bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
 {
-    if (brushTextureDirty && !imageDrawingMode)
+    if (brushTextureDirty
+        && (!imageDrawingMode || imageDrawingMode == TextDrawingMode || imageDrawingMode == BrushDrawingMode))
         updateBrushTexture();
 
     if (compositionModeDirty)
@@ -1129,7 +1130,8 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
     } else {
         opacityMode = stateHasOpacity ? QGLEngineShaderManager::UniformOpacity
                                       : QGLEngineShaderManager::NoOpacity;
-        if (stateHasOpacity && !imageDrawingMode) {
+        if (stateHasOpacity && !imageDrawingMode
+            && imageDrawingMode != ImageDrawingMode && imageDrawingMode != ImageArrayDrawingMode) {
             // Using a brush
             bool brushIsPattern = (currentBrush.style() >= Qt::Dense1Pattern) &&
                                   (currentBrush.style() <= Qt::DiagCrossPattern);
@@ -1149,7 +1151,8 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
         matrixUniformDirty = true;
     }
 
-    if (brushUniformsDirty && !imageDrawingMode)
+    if (brushUniformsDirty
+        && (!imageDrawingMode || imageDrawingMode == TextDrawingMode || imageDrawingMode == BrushDrawingMode))
         updateBrushUniforms();
 
     if (opacityMode == QGLEngineShaderManager::UniformOpacity && opacityUniformDirty) {
@@ -1641,7 +1644,10 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
     if (cache->width() == 0 || cache->height() == 0)
         return;
 
-    transferMode(TextDrawingMode);
+    if (glyphType == QFontEngineGlyphCache::Raster_ARGB)
+        transferMode(ImageArrayDrawingMode);
+    else
+        transferMode(TextDrawingMode);
 
     int margin = cache->glyphMargin();
 
@@ -1737,8 +1743,10 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
 #endif
     }
 
-    setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data());
-    setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data());
+    if (glyphType != QFontEngineGlyphCache::Raster_ARGB || recreateVertexArrays) {
+        setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data());
+        setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data());
+    }
 
     if (!snapToPixelGrid) {
         snapToPixelGrid = true;
@@ -1852,6 +1860,11 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
             glBlendFunc(GL_ONE, GL_ONE);
         }
         compositionModeDirty = true;
+    } else if (glyphType == QFontEngineGlyphCache::Raster_ARGB) {
+        currentBrush = noBrush;
+        shaderManager->setSrcPixelType(QGLEngineShaderManager::ImageSrc);
+        if (prepareForDraw(true))
+            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
     } else {
         // Greyscale/mono glyphs
 
@@ -1862,7 +1875,11 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
     QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest;
     if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) {
 
-        glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
+        if (glyphType == QFontEngineGlyphCache::Raster_ARGB)
+            glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+        else
+            glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
+
         if (lastMaskTextureUsed != cache->texture()) {
             glBindTexture(GL_TEXTURE_2D, cache->texture());
             lastMaskTextureUsed = cache->texture();
@@ -2073,7 +2090,8 @@ void QGL2PaintEngineExPrivate::drawPixmapFragments(const QRectF *targetRects, co
             data[i].y = 1 - data[i].y;
     }
 
-    transferMode(ImageArrayDrawingMode);
+//     transferMode(ImageArrayDrawingMode);
+    transferMode(ImageArrayWithOpacityDrawingMode);
 
     bool isBitmap = pixmap.isQBitmap();
     bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint));
diff --git src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index 75a67e8..8897448 100644
--- src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -127,7 +127,7 @@ void QGLTextureGlyphCache::createTextureData(int width, int height)
     glyphTexture->m_width = width;
     glyphTexture->m_height = height;
 
-    if (m_type == QFontEngineGlyphCache::Raster_RGBMask) {
+    if (m_type == QFontEngineGlyphCache::Raster_RGBMask || m_type == QFontEngineGlyphCache::Raster_ARGB) {
         QVarLengthArray<uchar> data(width * height * 4);
         for (int i = 0; i < data.size(); ++i)
             data[i] = 0;
@@ -311,23 +311,29 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub
             for (int x = 0; x < maskWidth; ++x)
                 src[x] = -src[x]; // convert 0 and 1 into 0 and 255
         }
-    } else if (mask.format() == QImage::Format_RGB32) {
-        // Make the alpha component equal to the average of the RGB values.
-        // This is needed when drawing sub-pixel antialiased text on translucent targets.
-        for (int y = 0; y < maskHeight; ++y) {
-            quint32 *src = (quint32 *) mask.scanLine(y);
-            for (int x = 0; x < maskWidth; ++x) {
-                uchar r = src[x] >> 16;
-                uchar g = src[x] >> 8;
-                uchar b = src[x];
-                quint32 avg = (quint32(r) + quint32(g) + quint32(b) + 1) / 3; // "+1" for rounding.
-                src[x] = (src[x] & 0x00ffffff) | (avg << 24);
+    } else if (mask.depth() == 32) {
+        if (mask.format() == QImage::Format_RGB32) {
+            // We need to make the alpha component equal to the average of the RGB values.
+            // This is needed when drawing sub-pixel antialiased text on translucent targets.
+            for (int y = 0; y < maskHeight; ++y) {
+                quint32 *src = (quint32 *) mask.scanLine(y);
+                for (int x = 0; x < maskWidth; ++x) {
+                    uchar r = src[x] >> 16;
+                    uchar g = src[x] >> 8;
+                    uchar b = src[x];
+                    quint32 avg;
+                    if (mask.format() == QImage::Format_RGB32)
+                        avg = (quint32(r) + quint32(g) + quint32(b) + 1) / 3; // "+1" for rounding.
+                    else // Format_ARGB_Premultiplied
+                        avg = src[x] >> 24;
+                    src[x] = (src[x] & 0x00ffffff) | (avg << 24);
+                }
             }
         }
     }
 
     glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture);
-    if (mask.format() == QImage::Format_RGB32) {
+    if (mask.depth() == 32) {
         glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits());
     } else {
         // glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is
