summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Ritt <ritt.ks@gmail.com>2014-03-03 03:01:14 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-03 11:11:24 +0100
commitaf74201edbb9dc344419ed3f8ebc35f8e8f05617 (patch)
tree3042ca9a1dc7c319bd60e0346a6a427320e721dc
parent78d115f8f28a7e3f15c0280e8d87d7041ecff793 (diff)
Introduce QFontEngine::glyphIndex(uint)
...an optimized drop-in replacement for the code like this: `stringToCMap(&uc, 1, &g, &numGlyphs, QFontEngine::GlyphIndicesOnly)` (aka "get the glyph index for exactly one Unicode character"). Change-Id: I22babf49f7cf28892d27533a5ac51ad449779f75 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--src/gui/text/qfontengine.cpp35
-rw-r--r--src/gui/text/qfontengine_ft.cpp30
-rw-r--r--src/gui/text/qfontengine_ft_p.h1
-rw-r--r--src/gui/text/qfontengine_p.h3
-rw-r--r--src/gui/text/qfontengine_qpa.cpp13
-rw-r--r--src/gui/text/qfontengine_qpa_p.h1
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm19
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp24
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp13
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h1
12 files changed, 142 insertions, 0 deletions
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 6f62d24f1e..61816c83fb 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1408,6 +1408,12 @@ QFontEngineBox::~QFontEngineBox()
{
}
+glyph_t QFontEngineBox::glyphIndex(uint ucs4) const
+{
+ Q_UNUSED(ucs4)
+ return 0;
+}
+
bool QFontEngineBox::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
@@ -1582,6 +1588,35 @@ QFontEngineMulti::~QFontEngineMulti()
}
}
+glyph_t QFontEngineMulti::glyphIndex(uint ucs4) const
+{
+ glyph_t glyph = engine(0)->glyphIndex(ucs4);
+ if (glyph == 0 && ucs4 != QChar::LineSeparator) {
+ const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
+ for (int x = 1, n = qMin(engines.size(), 256); x < n; ++x) {
+ QFontEngine *engine = engines.at(x);
+ if (!engine) {
+ if (!shouldLoadFontEngineForCharacter(x, ucs4))
+ continue;
+ const_cast<QFontEngineMulti *>(this)->loadEngine(x);
+ engine = engines.at(x);
+ }
+ Q_ASSERT(engine != 0);
+ if (engine->type() == Box)
+ continue;
+
+ glyph = engine->glyphIndex(ucs4);
+ if (glyph != 0) {
+ // set the high byte to indicate which engine the glyph came from
+ glyph |= (x << 24);
+ break;
+ }
+ }
+ }
+
+ return glyph;
+}
+
bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
QGlyphLayout *glyphs, int *nglyphs,
QFontEngine::ShaperFlags flags) const
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 140bf16394..b50c8fd95a 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -1525,6 +1525,36 @@ void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int
unlockFace();
}
+glyph_t QFontEngineFT::glyphIndex(uint ucs4) const
+{
+ glyph_t glyph = ucs4 < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[ucs4] : 0;
+ if (glyph == 0) {
+ FT_Face face = freetype->face;
+ glyph = FT_Get_Char_Index(face, ucs4);
+ if (glyph == 0) {
+ // Certain fonts don't have no-break space and tab,
+ // while we usually want to render them as space
+ if (ucs4 == QChar::Nbsp || ucs4 == QChar::Tabulation) {
+ glyph = FT_Get_Char_Index(face, QChar::Space);
+ } else if (freetype->symbol_map) {
+ // Symbol fonts can have more than one CMAPs, FreeType should take the
+ // correct one for us by default, so we always try FT_Get_Char_Index
+ // first. If it didn't work (returns 0), we will explicitly set the
+ // CMAP to symbol font one and try again. symbol_map is not always the
+ // correct one because in certain fonts like Wingdings symbol_map only
+ // contains PUA codepoints instead of the common ones.
+ FT_Set_Charmap(face, freetype->symbol_map);
+ glyph = FT_Get_Char_Index(face, ucs4);
+ FT_Set_Charmap(face, freetype->unicode_map);
+ }
+ }
+ if (ucs4 < QFreetypeFace::cmapCacheSize)
+ freetype->cmapCache[ucs4] = glyph;
+ }
+
+ return glyph;
+}
+
bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
QFontEngine::ShaperFlags flags) const
{
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index ad1598ba6d..7fc73c816d 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -225,6 +225,7 @@ private:
virtual QFixed lineThickness() const;
virtual QFixed underlinePosition() const;
+ virtual glyph_t glyphIndex(uint ucs4) const;
void doKerning(QGlyphLayout *, ShaperFlags) const;
inline virtual Type type() const
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 72f5c092dd..f497085ce2 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -167,6 +167,7 @@ public:
virtual QFixed emSquareSize() const { return ascent(); }
/* returns 0 as glyph index for non existent glyphs */
+ virtual glyph_t glyphIndex(uint ucs4) const = 0;
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const = 0;
virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const {}
virtual void doKerning(QGlyphLayout *, ShaperFlags) const;
@@ -352,6 +353,7 @@ public:
QFontEngineBox(int size);
~QFontEngineBox();
+ virtual glyph_t glyphIndex(uint ucs4) const;
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const;
@@ -388,6 +390,7 @@ public:
explicit QFontEngineMulti(int engineCount);
~QFontEngineMulti();
+ virtual glyph_t glyphIndex(uint ucs4) const;
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp
index c12cb37edf..f48b44374e 100644
--- a/src/gui/text/qfontengine_qpa.cpp
+++ b/src/gui/text/qfontengine_qpa.cpp
@@ -340,6 +340,19 @@ bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) con
return false;
}
+glyph_t QFontEngineQPA::glyphIndex(uint ucs4) const
+{
+ const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset);
+
+ glyph_t glyph = getTrueTypeGlyphIndex(cmap, ucs4);
+ if (glyph == 0 && symbol && ucs4 < 0x100)
+ glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000);
+ if (!findGlyph(glyph))
+ glyph = 0;
+
+ return glyph;
+}
+
bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
diff --git a/src/gui/text/qfontengine_qpa_p.h b/src/gui/text/qfontengine_qpa_p.h
index c8b40abd7f..bcd48ca690 100644
--- a/src/gui/text/qfontengine_qpa_p.h
+++ b/src/gui/text/qfontengine_qpa_p.h
@@ -163,6 +163,7 @@ public:
FaceId faceId() const { return face_id; }
bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
+ virtual glyph_t glyphIndex(uint ucs4) const;
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
void recalcAdvances(QGlyphLayout *, ShaperFlags) const;
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
index 4e50d6c53f..2ea7e6f00d 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
@@ -192,6 +192,25 @@ void QCoreTextFontEngine::init()
setUserData(QVariant::fromValue((void *)cgFont));
}
+glyph_t QCoreTextFontEngine::glyphIndex(uint ucs4) const
+{
+ int len = 0;
+
+ QChar str[2];
+ if (Q_UNLIKELY(QChar::requiresSurrogates(ucs4))) {
+ str[len++] = QChar(QChar::highSurrogate(ucs4));
+ str[len++] = QChar(QChar::lowSurrogate(ucs4));
+ } else {
+ str[len++] = QChar(ucs4);
+ }
+
+ CGGlyph glyphIndices[2];
+
+ CTFontGetGlyphsForCharacters(ctfont, (const UniChar *)str, glyphIndices, len);
+
+ return glyphIndices[0];
+}
+
bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
int *nglyphs, QFontEngine::ShaperFlags flags) const
{
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
index 1cdac820b6..0070aede24 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
@@ -62,6 +62,7 @@ public:
QCoreTextFontEngine(CGFontRef font, const QFontDef &def);
~QCoreTextFontEngine();
+ virtual glyph_t glyphIndex(uint ucs4) const;
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const;
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index 87eca98e44..a2f65c766d 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -340,6 +340,30 @@ QWindowsFontEngine::~QWindowsFontEngine()
}
}
+glyph_t QWindowsFontEngine::glyphIndex(uint ucs4) const
+{
+ glyph_t glyph;
+
+#if !defined(Q_OS_WINCE)
+ if (symbol) {
+ glyph = getTrueTypeGlyphIndex(cmap, ucs4);
+ if (glyph == 0 && ucs4 < 0x100)
+ glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000);
+ } else if (ttf) {
+ glyph = getTrueTypeGlyphIndex(cmap, ucs4);
+#else
+ if (tm.tmFirstChar > 60000) {
+ glyph = ucs4;
+#endif
+ } else if (ucs4 >= tm.tmFirstChar && ucs4 <= tm.tmLastChar) {
+ glyph = ucs4;
+ } else {
+ glyph = 0;
+ }
+
+ return glyph;
+}
+
HGDIOBJ QWindowsFontEngine::selectDesignFont() const
{
LOGFONT f = m_logfont;
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h
index e3fb3281a3..390de1d16e 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.h
+++ b/src/plugins/platforms/windows/qwindowsfontengine.h
@@ -86,6 +86,7 @@ public:
virtual int synthesized() const;
virtual QFixed emSquareSize() const;
+ virtual glyph_t glyphIndex(uint ucs4) const;
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const;
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
index a4e4dd38d4..cd5defdfea 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
@@ -301,6 +301,19 @@ QFixed QWindowsFontEngineDirectWrite::emSquareSize() const
return QFontEngine::emSquareSize();
}
+glyph_t QWindowsFontEngineDirectWrite::glyphIndex(uint ucs4) const
+{
+ UINT16 glyphIndex;
+
+ HRESULT hr = m_directWriteFontFace->GetGlyphIndicesW(&ucs4, 1, &glyphIndex);
+ if (FAILED(hr)) {
+ qErrnoWarning("%s: glyphIndex failed", __FUNCTION__);
+ glyphIndex = 0;
+ }
+
+ return glyphIndex;
+}
+
// ### Qt 5.1: replace with QStringIterator
inline unsigned int getChar(const QChar *str, int &i, const int len)
{
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
index 399bb5f5ad..aacdcd5a89 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
@@ -74,6 +74,7 @@ public:
bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
QFixed emSquareSize() const;
+ virtual glyph_t glyphIndex(uint ucs4) const;
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const;