summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/opengl/qopenglpaintengine.cpp40
-rw-r--r--src/gui/opengl/qopenglpaintengine_p.h3
-rw-r--r--src/gui/opengl/qopengltextureglyphcache.cpp44
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp14
-rw-r--r--src/gui/painting/qpaintengineex.cpp3
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp7
-rw-r--r--src/gui/text/qfontengine.cpp7
-rw-r--r--src/gui/text/qfontengine_p.h4
8 files changed, 89 insertions, 33 deletions
diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp
index d248d2b8e5..555c47f265 100644
--- a/src/gui/opengl/qopenglpaintengine.cpp
+++ b/src/gui/opengl/qopenglpaintengine.cpp
@@ -624,7 +624,7 @@ void QOpenGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
if (newMode == mode)
return;
- if (mode == TextDrawingMode || mode == ImageDrawingMode || mode == ImageArrayDrawingMode) {
+ if (mode != BrushDrawingMode) {
lastTextureUsed = GLuint(-1);
}
@@ -639,10 +639,12 @@ void QOpenGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, staticTextureCoordinateArray);
}
- if (newMode == ImageArrayDrawingMode) {
+ if (newMode == ImageArrayDrawingMode || newMode == ImageOpacityArrayDrawingMode) {
setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data());
setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data());
- setVertexAttributePointer(QT_OPACITY_ATTR, (GLfloat*)opacityArray.data());
+
+ if (newMode == ImageOpacityArrayDrawingMode)
+ setVertexAttributePointer(QT_OPACITY_ATTR, (GLfloat*)opacityArray.data());
}
// This needs to change when we implement high-quality anti-aliasing...
@@ -1085,7 +1087,7 @@ bool QOpenGL2PaintEngineExPrivate::prepareForCachedGlyphDraw(const QFontEngineGl
bool QOpenGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
{
- if (brushTextureDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
+ if (brushTextureDirty && (mode == TextDrawingMode || mode == BrushDrawingMode))
updateBrushTexture();
if (compositionModeDirty)
@@ -1105,12 +1107,12 @@ bool QOpenGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
}
QOpenGLEngineShaderManager::OpacityMode opacityMode;
- if (mode == ImageArrayDrawingMode) {
+ if (mode == ImageOpacityArrayDrawingMode) {
opacityMode = QOpenGLEngineShaderManager::AttributeOpacity;
} else {
opacityMode = stateHasOpacity ? QOpenGLEngineShaderManager::UniformOpacity
: QOpenGLEngineShaderManager::NoOpacity;
- if (stateHasOpacity && (mode != ImageDrawingMode)) {
+ if (stateHasOpacity && (mode != ImageDrawingMode && mode != ImageArrayDrawingMode)) {
// Using a brush
bool brushIsPattern = (currentBrush.style() >= Qt::Dense1Pattern) &&
(currentBrush.style() <= Qt::DiagCrossPattern);
@@ -1130,7 +1132,7 @@ bool QOpenGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
matrixUniformDirty = true;
}
- if (brushUniformsDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
+ if (brushUniformsDirty && (mode == TextDrawingMode || mode == BrushDrawingMode))
updateBrushUniforms();
if (opacityMode == QOpenGLEngineShaderManager::UniformOpacity && opacityUniformDirty) {
@@ -1602,7 +1604,10 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
if (cache->width() == 0 || cache->height() == 0)
return;
- transferMode(TextDrawingMode);
+ if (glyphType == QFontEngineGlyphCache::Raster_ARGB)
+ transferMode(ImageArrayDrawingMode);
+ else
+ transferMode(TextDrawingMode);
int margin = fe->glyphMargin(glyphType);
@@ -1698,8 +1703,10 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
#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;
@@ -1782,6 +1789,11 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
glBlendFunc(GL_ONE, GL_ONE);
}
compositionModeDirty = true;
+ } else if (glyphType == QFontEngineGlyphCache::Raster_ARGB) {
+ currentBrush = noBrush;
+ shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
+ if (prepareForCachedGlyphDraw(*cache))
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
} else {
// Greyscale/mono glyphs
@@ -1792,7 +1804,11 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
QOpenGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QOpenGLTextureGlyphCache::Linear:QOpenGLTextureGlyphCache::Nearest;
if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) {
- funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
+ if (glyphType == QFontEngineGlyphCache::Raster_ARGB)
+ funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ else
+ funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
+
if (lastMaskTextureUsed != cache->texture()) {
glBindTexture(GL_TEXTURE_2D, cache->texture());
lastMaskTextureUsed = cache->texture();
@@ -1908,7 +1924,7 @@ void QOpenGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFra
funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap);
- transferMode(ImageArrayDrawingMode);
+ transferMode(ImageOpacityArrayDrawingMode);
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque;
diff --git a/src/gui/opengl/qopenglpaintengine_p.h b/src/gui/opengl/qopenglpaintengine_p.h
index 9c54eae3b3..d51f0e5256 100644
--- a/src/gui/opengl/qopenglpaintengine_p.h
+++ b/src/gui/opengl/qopenglpaintengine_p.h
@@ -70,7 +70,8 @@ enum EngineMode {
ImageDrawingMode,
TextDrawingMode,
BrushDrawingMode,
- ImageArrayDrawingMode
+ ImageArrayDrawingMode,
+ ImageOpacityArrayDrawingMode
};
QT_BEGIN_NAMESPACE
diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp
index b751629117..83f407575e 100644
--- a/src/gui/opengl/qopengltextureglyphcache.cpp
+++ b/src/gui/opengl/qopengltextureglyphcache.cpp
@@ -120,7 +120,7 @@ void QOpenGLTextureGlyphCache::createTextureData(int width, int height)
m_textureResource->m_width = width;
m_textureResource->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;
@@ -314,30 +314,40 @@ void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed
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.
+ } 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.
+#if defined(QT_OPENGL_ES_2)
+ || !hasBGRA // We need to reverse the bytes
+#endif
+ ) {
+ 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;
#if defined(QT_OPENGL_ES_2)
- if (!hasBGRA) {
- // Reverse bytes to match GL_RGBA
- src[x] = (avg << 24) | (quint32(r) << 0) | (quint32(g) << 8) | (quint32(b) << 16);
- } else
+ if (!hasBGRA) {
+ // Reverse bytes to match GL_RGBA
+ src[x] = (avg << 24) | (quint32(r) << 0) | (quint32(g) << 8) | (quint32(b) << 16);
+ } else
#endif
- src[x] = (src[x] & 0x00ffffff) | (avg << 24);
+ src[x] = (src[x] & 0x00ffffff) | (avg << 24);
+ }
}
}
}
glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
- if (mask.format() == QImage::Format_RGB32) {
+ if (mask.depth() == 32) {
#if defined(QT_OPENGL_ES_2)
glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, hasBGRA ? GL_BGRA_EXT : GL_RGBA, GL_UNSIGNED_BYTE, mask.bits());
#else
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index b9202e1612..fd867ebde6 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -2857,7 +2857,19 @@ 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);
+ 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 a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 5ca6075423..6e72b5db7f 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -1088,6 +1088,9 @@ bool QPaintEngineEx::requiresPretransformedGlyphPositions(QFontEngine *, const Q
bool QPaintEngineEx::shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &m) const
{
+ if (fontEngine->glyphFormat == QFontEngineGlyphCache::Raster_ARGB)
+ return true;
+
qreal pixelSize = fontEngine->fontDef.pixelSize;
return (pixelSize * pixelSize * qAbs(m.determinant())) <
QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE;
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 2ffdc9cd59..8769aeaba9 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -129,6 +129,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;
}
@@ -275,6 +276,8 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition
{
if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
return m_current_fontengine->alphaRGBMapForGlyph(g, subPixelPosition, m_transform);
+ else if (m_type == QFontEngineGlyphCache::Raster_ARGB)
+ return m_current_fontengine->bitmapForGlyph(g, subPixelPosition, m_transform);
return m_current_fontengine->alphaMapForGlyph(g, subPixelPosition, m_transform);
}
@@ -306,6 +309,7 @@ void QImageTextureGlyphCache::createTextureData(int width, int height)
m_image = QImage(width, height, QImage::Format_RGB32);
break;
case QFontEngineGlyphCache::Raster_ARGB:
+ m_image = QImage(width, height, QImage::Format_ARGB32_Premultiplied);
break;
}
}
@@ -322,7 +326,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 a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index b320dc0e66..1a7f2b7b4d 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -649,6 +649,13 @@ QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition
return rgbMask;
}
+QImage QFontEngine::bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform&)
+{
+ Q_UNUSED(subPixelPosition);
+
+ return QImage();
+}
+
QFixed QFontEngine::subPixelPositionForX(QFixed x) const
{
if (m_subPixelPositionCount <= 1 || !supportsSubPixelPositions())
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 854f6fbbb6..a373c3d5f1 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -112,7 +112,8 @@ public:
Format_Render = Format_None,
Format_Mono,
Format_A8,
- Format_A32
+ Format_A32,
+ Format_ARGB
};
enum ShaperFlag {
@@ -191,6 +192,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, const QTransform &t);
+ virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
GlyphFormat neededFormat,
const QTransform &t = QTransform(),