summaryrefslogtreecommitdiffstats
path: root/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
diff options
context:
space:
mode:
authorKim Motoyoshi Kalland <kim.kalland@nokia.com>2009-09-08 12:30:19 (GMT)
committerKim Motoyoshi Kalland <kim.kalland@nokia.com>2009-09-16 08:11:40 (GMT)
commitb8ff02a67ebd8246253823b53cfed98eef400547 (patch)
tree011c1ea8b6d860e5a43824caa6903977394048ad /src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
parent120329adb47dba60f532c1c2fd2ad0f37b812437 (diff)
downloadQt-b8ff02a67ebd8246253823b53cfed98eef400547.zip
Qt-b8ff02a67ebd8246253823b53cfed98eef400547.tar.gz
Qt-b8ff02a67ebd8246253823b53cfed98eef400547.tar.bz2
Added support for subpixel antialiasing on text in the GL2 engine.
The antialiasing is currently not gamma corrected. Reviewed-by: Samuel
Diffstat (limited to 'src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp')
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp136
1 files changed, 120 insertions, 16 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 837d055..20bbc1e 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -90,6 +90,10 @@ static const GLuint QT_IMAGE_TEXTURE_UNIT = 0; //Can be the same as brush
static const GLuint QT_MASK_TEXTURE_UNIT = 1;
static const GLuint QT_BACKGROUND_TEXTURE_UNIT = 2;
+#ifdef Q_WS_WIN
+extern Q_GUI_EXPORT bool qt_cleartype_enabled;
+#endif
+
class QGLTextureGlyphCache : public QObject, public QTextureGlyphCache
{
Q_OBJECT
@@ -100,6 +104,7 @@ public:
virtual void createTextureData(int width, int height);
virtual void resizeTextureData(int width, int height);
virtual void fillTexture(const Coord &c, glyph_t glyph);
+ virtual int glyphMargin() const;
inline GLuint texture() const { return m_texture; }
@@ -290,7 +295,7 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
glBindTexture(GL_TEXTURE_2D, m_texture);
if (mask.format() == QImage::Format_RGB32) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, m_height - c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits());
+ glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits());
} else {
#ifdef QT_OPENGL_ES2
glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());
@@ -310,6 +315,15 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
}
}
+int QGLTextureGlyphCache::glyphMargin() const
+{
+#ifdef Q_WS_MAC
+ return 2;
+#else
+ return m_type == QFontEngineGlyphCache::Raster_RGBMask ? 2 : 0;
+#endif
+}
+
extern QImage qt_imageForBrush(int brushStyle, bool invert);
////////////////////////////////// Private Methods //////////////////////////////////////////
@@ -1196,6 +1210,12 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
if (ti.fontEngine->fontDef.pixelSize * qSqrt(s->matrix.determinant()) >= 64)
drawCached = false;
+ if (d->glyphCacheType == QFontEngineGlyphCache::Raster_RGBMask
+ && state()->composition_mode != QPainter::CompositionMode_Source
+ && state()->composition_mode != QPainter::CompositionMode_SourceOver) {
+ drawCached = false;
+ }
+
if (drawCached) {
d->drawCachedGlyphs(p, ti);
return;
@@ -1216,7 +1236,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte
QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0
? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat)
- : QFontEngineGlyphCache::Raster_A8;
+ : glyphCacheType;
QGLTextureGlyphCache *cache =
(QGLTextureGlyphCache *) ti.fontEngine->glyphCache(ctx, s->matrix);
@@ -1235,12 +1255,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte
transferMode(BrushDrawingMode);
transferMode(TextDrawingMode);
- if (glyphType == QFontEngineGlyphCache::Raster_A8)
- shaderManager->setMaskType(QGLEngineShaderManager::PixelMask);
- else if (glyphType == QFontEngineGlyphCache::Raster_RGBMask)
- shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMask);
- //### TODO: Gamma correction
-
int margin = cache->glyphMargin();
GLfloat dx = 1.0 / cache->width();
@@ -1261,10 +1275,96 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte
textureCoordinateArray.addRect(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy));
}
+ if (vertexCoordinateArray.data() != oldVertexCoordinateDataPtr)
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
+ if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr)
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
+
QBrush pensBrush = q->state()->pen.brush();
setBrush(&pensBrush);
- prepareForDraw(false); // Text always causes src pixels to be transparent
+ if (glyphType == QFontEngineGlyphCache::Raster_A8) {
+
+ // Greyscale antialiasing
+
+ shaderManager->setMaskType(QGLEngineShaderManager::PixelMask);
+ prepareForDraw(false); // Text always causes src pixels to be transparent
+ } else if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) {
+
+ // Subpixel antialiasing without gamma correction
+
+ QPainter::CompositionMode compMode = q->state()->composition_mode;
+ Q_ASSERT(compMode == QPainter::CompositionMode_Source
+ || compMode == QPainter::CompositionMode_SourceOver);
+
+ shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass1);
+
+ if (pensBrush.style() == Qt::SolidPattern) {
+ // Solid patterns can get away with only one pass.
+ QColor c = pensBrush.color();
+ qreal oldOpacity = q->state()->opacity;
+ if (compMode == QPainter::CompositionMode_Source) {
+ c = premultiplyColor(c, q->state()->opacity);
+ q->state()->opacity = 1;
+ opacityUniformDirty = true;
+ }
+
+ compositionModeDirty = false; // I can handle this myself, thank you very much
+ prepareForDraw(false); // Text always causes src pixels to be transparent
+
+ // prepareForDraw() have set the opacity on the current shader, so the opacity state can now be reset.
+ if (compMode == QPainter::CompositionMode_Source) {
+ q->state()->opacity = oldOpacity;
+ opacityUniformDirty = true;
+ }
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
+ glBlendColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
+ } else {
+ // Other brush styles need two passes.
+
+ qreal oldOpacity = q->state()->opacity;
+ if (compMode == QPainter::CompositionMode_Source) {
+ q->state()->opacity = 1;
+ opacityUniformDirty = true;
+ pensBrush = Qt::white;
+ setBrush(&pensBrush);
+ }
+
+ compositionModeDirty = false; // I can handle this myself, thank you very much
+ prepareForDraw(false); // Text always causes src pixels to be transparent
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
+
+ glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
+ glBindTexture(GL_TEXTURE_2D, cache->texture());
+ updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
+
+#ifndef QT_OPENGL_ES_2
+ if (inRenderText)
+ shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), zValueForRenderText());
+#endif
+ shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT);
+ glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size());
+
+ shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass2);
+
+ if (compMode == QPainter::CompositionMode_Source) {
+ q->state()->opacity = oldOpacity;
+ opacityUniformDirty = true;
+ pensBrush = q->state()->pen.brush();
+ setBrush(&pensBrush);
+ }
+
+ compositionModeDirty = false;
+ prepareForDraw(false); // Text always causes src pixels to be transparent
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ }
+ compositionModeDirty = true;
+ }
+ //### TODO: Gamma correction
glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
glBindTexture(GL_TEXTURE_2D, cache->texture());
@@ -1274,14 +1374,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte
if (inRenderText)
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), zValueForRenderText());
#endif
-
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT);
-
- if (vertexCoordinateArray.data() != oldVertexCoordinateDataPtr)
- glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
- if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr)
- glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
-
glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size());
}
@@ -1340,6 +1433,17 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
glDisable(GL_MULTISAMPLE);
#endif
+ if (d->device->format().alpha()
+#if defined(Q_WS_WIN)
+ || !qt_cleartype_enabled
+#endif
+ ) {
+ d->glyphCacheType = QFontEngineGlyphCache::Raster_A8;
+ } else {
+ d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask;
+ }
+
+ d->systemStateChanged();
return true;
}