diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2010-03-17 13:40:24 (GMT) |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2010-03-17 13:58:20 (GMT) |
commit | 1ebeb971d3382aec0fff927ce2d6ea7b0452584f (patch) | |
tree | 0400dae576726845e85f2ca407def59b0ca261b4 /src | |
parent | c950a2594f7c3102930541800edac5384827846d (diff) | |
download | Qt-1ebeb971d3382aec0fff927ce2d6ea7b0452584f.zip Qt-1ebeb971d3382aec0fff927ce2d6ea7b0452584f.tar.gz Qt-1ebeb971d3382aec0fff927ce2d6ea7b0452584f.tar.bz2 |
Optimize getting bearings of a glyph on Windows for true type fonts
Usually, the bearing of a glyph is calculated based on the bounding box
of the glyph. However, retrieving these bounds is a costly operation
on Windows. For true type fonts, we can retrieve the bearings directly
by getting the ABC widths, so as an optimization we implement a new
virtual function in QFontEngine which retrieves the bearings of the
glyph. The default implementation uses boundingBox, but on Windows we
try to take the shortcut.
Reviewed-by: Simon Hausmann
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/text/qfontengine.cpp | 14 | ||||
-rw-r--r-- | src/gui/text/qfontengine_p.h | 3 | ||||
-rw-r--r-- | src/gui/text/qfontengine_win.cpp | 24 | ||||
-rw-r--r-- | src/gui/text/qfontengine_win_p.h | 2 | ||||
-rw-r--r-- | src/gui/text/qfontmetrics.cpp | 21 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 6 |
6 files changed, 59 insertions, 11 deletions
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index c000457..3ec389f 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -379,6 +379,14 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform Q_ASSERT(positions.size() == glyphs_out.size()); } +void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) +{ + glyph_metrics_t gi = boundingBox(glyph); + if (leftBearing != 0) + *leftBearing = gi.x.toReal(); + if (rightBearing != 0) + *rightBearing = (gi.xoff - gi.x - gi.width).toReal(); +} glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs) { @@ -1385,6 +1393,12 @@ glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs) return overall; } +void QFontEngineMulti::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) +{ + int which = highByte(glyph); + engine(which)->getGlyphBearings(stripped(glyph), leftBearing, rightBearing); +} + void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) { diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 71ab5a5..e645caf 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -206,6 +206,8 @@ public: virtual qreal minLeftBearing() const { return qreal(); } virtual qreal minRightBearing() const { return qreal(); } + virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); + virtual const char *name() const = 0; virtual bool canRender(const QChar *string, int len) = 0; @@ -374,6 +376,7 @@ public: virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const; virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags); + virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); virtual QFixed ascent() const; virtual QFixed descent() const; diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index 1a815d3..a133b48 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -649,6 +649,30 @@ static const ushort char_table[] = { static const int char_table_entries = sizeof(char_table)/sizeof(ushort); +void QFontEngineWin::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) +{ + HDC hdc = shared_dc(); + SelectObject(hdc, hfont); + +#ifndef Q_WS_WINCE + if (ttf) +#endif + + { + ABC abcWidths; + GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths); + if (leftBearing) + *leftBearing = abcWidths.abcA; + if (rightBearing) + *rightBearing = abcWidths.abcC; + } + +#ifndef Q_WS_WINCE + else { + QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing); + } +#endif +} qreal QFontEngineWin::minLeftBearing() const { diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h index f9d8f8b..f19e48e 100644 --- a/src/gui/text/qfontengine_win_p.h +++ b/src/gui/text/qfontengine_win_p.h @@ -106,6 +106,8 @@ public: virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform); virtual QImage alphaRGBMapForGlyph(glyph_t t, int margin, const QTransform &xform); + virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); + int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const; void getCMap(); diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 41d0af1..44a18de 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -472,8 +472,9 @@ int QFontMetrics::leftBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); - return qRound(gi.x); + qreal lb; + engine->getGlyphBearings(glyphs.glyphs[0], &lb); + return qRound(lb); } /*! @@ -506,8 +507,9 @@ int QFontMetrics::rightBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); - return qRound(gi.xoff - gi.x - gi.width); + qreal rb; + engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb); + return qRound(rb); } /*! @@ -1317,8 +1319,9 @@ qreal QFontMetricsF::leftBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); - return gi.x.toReal(); + qreal lb; + engine->getGlyphBearings(glyphs.glyphs[0], &lb); + return lb; } /*! @@ -1351,8 +1354,10 @@ qreal QFontMetricsF::rightBearing(QChar ch) const int nglyphs = 9; engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0); // ### can nglyphs != 1 happen at all? Not currently I think - glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]); - return (gi.xoff - gi.x - gi.width).toReal(); + qreal rb; + engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb); + return rb; + } /*! diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 204effa..3c0e85e 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1688,9 +1688,9 @@ namespace { if (currentPosition <= 0) return; - glyph_metrics_t gi = fontEngine->boundingBox(currentGlyph()); - if (gi.isValid()) - rightBearing = qMin(QFixed(), gi.xoff - gi.x - gi.width); + qreal rb; + fontEngine->getGlyphBearings(currentGlyph(), 0, &rb); + rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); } inline void resetRightBearing() |