Avoid glyph rendering with FT when not needed
authorJiang Jiang <jiang.jiang@nokia.com>
Fri, 2 Mar 2012 13:22:10 +0000 (14:22 +0100)
committerQt by Nokia <qt-info@nokia.com>
Fri, 4 May 2012 13:35:30 +0000 (15:35 +0200)
If we only need to access the font metrics (like in scenegraph) for
layout, we don't need to render glyphs with FreeType at all.

Increase cached linearAdvance to 22 bits so that no overflow will
happen: FreeType returns 16.16 fixed point linearHoriAdvance, but
QFixed is 26.6, we store

    glyph->linearAdvance = linearHoriAdvance >> 10

Apparently 'short' is not enough since it's only 16 bits.

Change-Id: Id14eafa19f01a687de11997526281f9e7e860482
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
src/gui/text/qfontengine_ft.cpp
src/gui/text/qfontengine_ft_p.h

index 5dc757b..6bcc321 100644 (file)
@@ -835,7 +835,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
     }
 
     Glyph *g = set ? set->getGlyph(glyph, subPixelPosition) : 0;
-    if (g && g->format == format)
+    if (g && g->format == format && (fetchMetricsOnly || g->data))
         return g;
 
     QFontEngineFT::GlyphInfo info;
@@ -877,10 +877,28 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
     if (err != FT_Err_Ok)
         qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
 
-    if ((!set || set->outline_drawing) && fetchMetricsOnly)
-        return 0;
-
     FT_GlyphSlot slot = face->glyph;
+    if ((set && set->outline_drawing) || fetchMetricsOnly) {
+        g = new Glyph;
+        g->data = 0;
+        g->linearAdvance = slot->linearHoriAdvance >> 10;
+        int left  = FLOOR(slot->metrics.horiBearingX);
+        int right = CEIL(slot->metrics.horiBearingX + slot->metrics.width);
+        int top    = CEIL(slot->metrics.horiBearingY);
+        int bottom = FLOOR(slot->metrics.horiBearingY - slot->metrics.height);
+        g->width = TRUNC(right-left);
+        g->height = TRUNC(top-bottom);
+        g->x = TRUNC(left);
+        g->y = TRUNC(top);
+        g->advance = TRUNC(ROUND(slot->advance.x));
+        g->format = format;
+
+        if (set)
+            set->setGlyph(glyph, subPixelPosition, g);
+
+        return g;
+    }
+
     if (embolden) Q_FT_GLYPHSLOT_EMBOLDEN(slot);
     if (obliquen) {
         Q_FT_GLYPHSLOT_OBLIQUE(slot);
@@ -1870,7 +1888,7 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
     lockFace();
 
     Glyph *glyph = loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono);
-    if (!glyph) {
+    if (!glyph || !glyph->data) {
         unlockFace();
         return QFontEngine::alphaMapForGlyph(g);
     }
@@ -1907,7 +1925,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, co
     lockFace();
 
     Glyph *glyph = loadGlyphFor(g, subPixelPosition, Format_A32);
-    if (!glyph) {
+    if (!glyph || !glyph->data) {
         unlockFace();
         return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
     }
index 2add894..7793912 100644 (file)
@@ -144,7 +144,7 @@ public:
     /* we don't cache glyphs that are too large anyway, so we can make this struct rather small */
     struct Glyph {
         ~Glyph();
-        short linearAdvance;
+        int linearAdvance : 22; // 16.6
         unsigned char width;
         unsigned char height;
         signed char x;