Fix subpixel positioning support
authorJiang Jiang <jiang.jiang@nokia.com>
Fri, 4 Nov 2011 13:47:31 +0000 (14:47 +0100)
committerQt by Nokia <qt-info@nokia.com>
Tue, 8 Nov 2011 06:43:00 +0000 (07:43 +0100)
Move subpixelPositionForX from QTextureGlyphCache to QFontEngine,
since some font engines like QFontEngineFT may need a custom
implementation or tweak it a little bit.

In QRasterPaintEngine::drawCachedGlyphs, do not add aliasedCoodinate
to x offset as that will break subpixel positioning.

Change-Id: Idbcec617509459b80965220ceb07b17737649bbf
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
src/gui/opengl/qopenglpaintengine.cpp
src/gui/painting/qpaintengine_raster.cpp
src/gui/painting/qtextureglyphcache.cpp
src/gui/painting/qtextureglyphcache_p.h
src/gui/text/qfontengine.cpp
src/gui/text/qfontengine_ft.cpp
src/gui/text/qfontengine_ft_p.h
src/gui/text/qfontengine_p.h
src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp

index a87c354..c1bde75 100644 (file)
@@ -1536,12 +1536,13 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
 
     void *cacheKey = ctx->shareGroup();
     bool recreateVertexArrays = false;
+    QFontEngine *fe = staticTextItem->fontEngine();
 
     QOpenGLTextureGlyphCache *cache =
-            (QOpenGLTextureGlyphCache *) staticTextItem->fontEngine()->glyphCache(cacheKey, glyphType, QTransform());
+            (QOpenGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphType, QTransform());
     if (!cache || cache->cacheType() != glyphType || cache->contextGroup() == 0) {
         cache = new QOpenGLTextureGlyphCache(glyphType, QTransform());
-        staticTextItem->fontEngine()->setGlyphCache(cacheKey, cache);
+        fe->setGlyphCache(cacheKey, cache);
         recreateVertexArrays = true;
     }
 
@@ -1565,11 +1566,11 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
     // cache so this text is performed before we test if the cache size has changed.
     if (recreateVertexArrays) {
         cache->setPaintEnginePrivate(this);
-        if (!cache->populate(staticTextItem->fontEngine(), staticTextItem->numGlyphs,
+        if (!cache->populate(fe, staticTextItem->numGlyphs,
                              staticTextItem->glyphs, staticTextItem->glyphPositions)) {
             // No space for glyphs in cache. We need to reset it and try again.
             cache->clear();
-            cache->populate(staticTextItem->fontEngine(), staticTextItem->numGlyphs,
+            cache->populate(fe, staticTextItem->numGlyphs,
                             staticTextItem->glyphs, staticTextItem->glyphPositions);
         }
         cache->fillInPendingGlyphs();
@@ -1620,11 +1621,11 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type
         vertexCoordinates->clear();
         textureCoordinates->clear();
 
-        bool supportsSubPixelPositions = staticTextItem->fontEngine()->supportsSubPixelPositions();
+        bool supportsSubPixelPositions = fe->supportsSubPixelPositions();
         for (int i=0; i<staticTextItem->numGlyphs; ++i) {
             QFixed subPixelPosition;
             if (supportsSubPixelPositions)
-                subPixelPosition = cache->subPixelPositionForX(staticTextItem->glyphPositions[i].x);
+                subPixelPosition = fe->subPixelPositionForX(staticTextItem->glyphPositions[i].x);
 
             QTextureGlyphCache::GlyphAndSubPixelPosition glyph(staticTextItem->glyphs[i], subPixelPosition);
 
index e49bd22..d5449a7 100644 (file)
@@ -2752,13 +2752,13 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
         const uchar *bits = image.bits();
         for (int i=0; i<numGlyphs; ++i) {
 
-            QFixed subPixelPosition = cache->subPixelPositionForX(positions[i].x);
+            QFixed subPixelPosition = fontEngine->subPixelPositionForX(positions[i].x);
             QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition);
             const QTextureGlyphCache::Coord &c = cache->coords[glyph];
             if (c.isNull())
                 continue;
 
-            int x = qFloor(positions[i].x + offs) + c.baseLineX - margin;
+            int x = qFloor(positions[i].x) + c.baseLineX - margin;
             int y = qFloor(positions[i].y + offs) - c.baseLineY - margin;
 
             // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n",
index 5876f3b..1e0ed0f 100644 (file)
@@ -99,23 +99,6 @@ int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const
     return images.size();
 }
 
-QFixed QTextureGlyphCache::subPixelPositionForX(QFixed x) const
-{
-    if (m_subPixelPositionCount <= 1)
-        return QFixed();
-
-    QFixed subPixelPosition;
-    if (x != 0) {
-        subPixelPosition = x - x.floor();
-        QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();
-
-        // Compensate for precision loss in fixed point to make sure we are always drawing at a subpixel position over
-        // the lower boundary for the selected rasterization by adding 1/64.
-        subPixelPosition = fraction / QFixed(m_subPixelPositionCount) + QFixed::fromReal(0.015625);
-    }
-    return subPixelPosition;
-}
-
 bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs,
                                                 const QFixedPoint *positions)
 {
@@ -129,13 +112,13 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
     const int paddingDoubled = glyphPadding() * 2;
 
     bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions();
-    if (m_subPixelPositionCount == 0) {
+    if (fontEngine->m_subPixelPositionCount == 0) {
         if (!supportsSubPixelPositions) {
-            m_subPixelPositionCount = 1;
+            fontEngine->m_subPixelPositionCount = 1;
         } else {
             int i = 0;
-            while (m_subPixelPositionCount == 0 && i < numGlyphs)
-                m_subPixelPositionCount = calculateSubPixelPositionCount(glyphs[i++]);
+            while (fontEngine->m_subPixelPositionCount == 0 && i < numGlyphs)
+                fontEngine->m_subPixelPositionCount = calculateSubPixelPositionCount(glyphs[i++]);
         }
     }
 
@@ -156,7 +139,7 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
         QFixed subPixelPosition;
         if (supportsSubPixelPositions) {
             QFixed x = positions != 0 ? positions[i].x : QFixed();
-            subPixelPosition = subPixelPositionForX(x);
+            subPixelPosition = fontEngine->subPixelPositionForX(x);
         }
 
         if (coords.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition)))
index bc5eebb..d9d57f4 100644 (file)
@@ -81,7 +81,7 @@ class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache
 public:
     QTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix)
         : QFontEngineGlyphCache(matrix, type), m_current_fontengine(0),
-                                               m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0), m_subPixelPositionCount(0)
+                                               m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0)
         { }
 
     virtual ~QTextureGlyphCache() { }
@@ -146,8 +146,6 @@ public:
 
     QImage textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const;
 
-    QFixed subPixelPositionForX(QFixed x) const;
-
 protected:
     int calculateSubPixelPositionCount(glyph_t) const;
 
@@ -159,7 +157,6 @@ protected:
     int m_cx; // current x
     int m_cy; // current y
     int m_currentRowHeight; // Height of last row
-    int m_subPixelPositionCount; // Number of positions within a single pixel for this cache
 };
 
 inline uint qHash(const QTextureGlyphCache::GlyphAndSubPixelPosition &g)
index 067a630..5c6c8d1 100644 (file)
@@ -179,6 +179,7 @@ QFontEngine::QFontEngine()
 
     hbFace = 0;
     glyphFormat = -1;
+    m_subPixelPositionCount = 0;
 }
 
 QFontEngine::~QFontEngine()
@@ -635,17 +636,19 @@ QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition
     return rgbMask;
 }
 
-QFixed QFontEngine::subPixelPositionForX(QFixed x)
+QFixed QFontEngine::subPixelPositionForX(QFixed x) const
 {
-    int m_subPixelPositionCount = 4;
-    if (!supportsSubPixelPositions())
-        return 0;
+    if (m_subPixelPositionCount <= 1 || !supportsSubPixelPositions())
+        return QFixed();
 
     QFixed subPixelPosition;
     if (x != 0) {
         subPixelPosition = x - x.floor();
         QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();
-        subPixelPosition = fraction / QFixed(m_subPixelPositionCount);
+
+        // Compensate for precision loss in fixed point to make sure we are always drawing at a subpixel position over
+        // the lower boundary for the selected rasterization by adding 1/64.
+        subPixelPosition = fraction / QFixed(m_subPixelPositionCount) + QFixed::fromReal(0.015625);
     }
     return subPixelPosition;
 }
index eb7415a..6845c67 100644 (file)
@@ -657,6 +657,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
     defaultFormat = Format_None;
     embeddedbitmap = false;
     cacheEnabled = qgetenv("QT_NO_FT_CACHE").isEmpty() || qgetenv("QT_NO_FT_CACHE").toInt() == 0;
+    m_subPixelPositionCount = 4;
 }
 
 QFontEngineFT::~QFontEngineFT()
index d4a6def..fd0be4f 100644 (file)
@@ -315,7 +315,6 @@ private:
     bool initFromFontEngine(const QFontEngineFT *fontEngine);
 
     HintStyle defaultHintStyle() const { return default_hint_style; }
-
 protected:
 
     QFreetypeFace *freetype;
index ec1f22b..4caf91e 100644 (file)
@@ -158,7 +158,7 @@ public:
     };
     virtual int synthesized() const { return 0; }
     virtual bool supportsSubPixelPositions() const { return false; }
-    QFixed subPixelPositionForX(QFixed x);
+    virtual QFixed subPixelPositionForX(QFixed x) const;
 
     virtual QFixed emSquareSize() const { return ascent(); }
 
@@ -277,6 +277,7 @@ public:
 
     int glyphFormat;
     QImage currentlyLockedAlphaMap;
+    int m_subPixelPositionCount; // Number of positions within a single pixel for this cache
 
 protected:
     static const QVector<QRgb> &grayPalette();
index 947abf8..45ac639 100644 (file)
@@ -1654,7 +1654,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
         for (int i=0; i<staticTextItem->numGlyphs; ++i) {
             QFixed subPixelPosition;
             if (supportsSubPixelPositions)
-                subPixelPosition = cache->subPixelPositionForX(staticTextItem->glyphPositions[i].x);
+                subPixelPosition = staticTextItem->fontEngine()->subPixelPositionForX(staticTextItem->glyphPositions[i].x);
 
             QTextureGlyphCache::GlyphAndSubPixelPosition glyph(staticTextItem->glyphs[i], subPixelPosition);