From 354246566cf86f687ee897f95586ac17b5deb35c Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 12 Oct 2010 12:30:45 +0200 Subject: Fix text position with OpenGL engine and Freetype If you use the OpenGL engine, the left bearing of the glyph was incorrectly retrieved from the system as the glyph was queried with the wrong format, and adjustments for antialiasing were not applied. To make the position identical to painting with, new API was added to QFontEngine (The bounding box of a glyph is also not logically necessarily the same thing as the bounding box of the rasterized glyph.) Done-with: Trond Task-number: QTBUG-14410 --- src/gui/painting/qtextureglyphcache.cpp | 9 ++++++++- src/gui/text/qfontengine_ft.cpp | 25 +++++++++++++++++++++---- src/gui/text/qfontengine_ft_p.h | 11 +++-------- src/gui/text/qfontengine_p.h | 13 +++++++++++++ 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 9219876..78c1019 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -143,6 +143,13 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const QHash listItemCoordinates; int rowHeight = 0; + QFontEngine::GlyphFormat format; + switch (m_type) { + case Raster_A8: format = QFontEngine::Format_A8; break; + case Raster_RGBMask: format = QFontEngine::Format_A32; break; + default: format = QFontEngine::Format_Mono; break; + } + // check each glyph for its metrics and get the required rowHeight. for (int i=0; i < numGlyphs; ++i) { const glyph_t glyph = glyphs[i]; @@ -157,7 +164,7 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const continue; if (listItemCoordinates.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition))) continue; - glyph_metrics_t metrics = fontEngine->boundingBox(glyph, m_transform); + glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, m_transform, format); #ifdef CACHE_DEBUG printf("(%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n", diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 512afc8..6991143 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -755,10 +755,10 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format) return true; } -QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph) const +QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const { Glyph *g = set->getGlyph(glyph); - if (g) + if (g && g->format == format) return g; int load_flags = FT_LOAD_DEFAULT | default_load_flags; @@ -766,6 +766,18 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph ? FT_LOAD_TARGET_LIGHT : FT_LOAD_TARGET_NORMAL; + if (format == Format_Mono) { + load_target = FT_LOAD_TARGET_MONO; + } else if (format == Format_A32) { + if (subpixelType == QFontEngineFT::Subpixel_RGB || subpixelType == QFontEngineFT::Subpixel_BGR) { + if (default_hint_style == HintFull) + load_target = FT_LOAD_TARGET_LCD; + } else if (subpixelType == QFontEngineFT::Subpixel_VRGB || subpixelType == QFontEngineFT::Subpixel_VBGR) { + if (default_hint_style == HintFull) + load_target = FT_LOAD_TARGET_LCD_V; + } + } + if (set->outline_drawing) load_flags = FT_LOAD_NO_BITMAP; @@ -1767,6 +1779,11 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matrix) { + return alphaMapBoundingBox(glyph, matrix, QFontEngine::Format_None); +} + +glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, const QTransform &matrix, QFontEngine::GlyphFormat format) +{ FT_Face face = 0; glyph_metrics_t overall; QGlyphSet *glyphSet = 0; @@ -1810,9 +1827,9 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr glyphSet = &defaultGlyphSet; } Glyph * g = glyphSet->getGlyph(glyph); - if (!g) { + if (!g || g->format != format) { face = lockFace(); - g = loadGlyphMetrics(glyphSet, glyph); + g = loadGlyphMetrics(glyphSet, glyph, format); } if (g) { diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 72f7d9f..1a1cadb 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -130,13 +130,6 @@ private: class Q_GUI_EXPORT QFontEngineFT : public QFontEngine { public: - enum GlyphFormat { - Format_None, - Format_Render = Format_None, - Format_Mono, - Format_A8, - Format_A32 - }; /* we don't cache glyphs that are too large anyway, so we can make this struct rather small */ struct Glyph { @@ -242,6 +235,8 @@ private: virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const; virtual QImage alphaMapForGlyph(glyph_t); virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); + virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QTransform &matrix, + QFontEngine::GlyphFormat format); virtual void removeGlyphFromCache(glyph_t glyph); virtual int glyphCount() const; @@ -311,7 +306,7 @@ protected: bool embeddedbitmap; private: - QFontEngineFT::Glyph *loadGlyphMetrics(QGlyphSet *set, uint glyph) const; + QFontEngineFT::Glyph *loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const; GlyphFormat defaultFormat; FT_Matrix matrix; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index d07c8c9..d1ec4c1 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -120,6 +120,14 @@ public: TestFontEngine = 0x1000 }; + enum GlyphFormat { + Format_None, + Format_Render = Format_None, + Format_Mono, + Format_A8, + Format_A32 + }; + QFontEngine(); virtual ~QFontEngine(); @@ -191,6 +199,11 @@ public: virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t); virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); + virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QTransform &matrix, GlyphFormat /*format*/) + { + return boundingBox(glyph, matrix); + } + virtual void removeGlyphFromCache(glyph_t); virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) = 0; -- cgit v0.12