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>
bb10
Konstantin Ritt 2014-03-03 03:01:14 +02:00 committed by The Qt Project
parent 78d115f8f2
commit af74201edb
12 changed files with 142 additions and 0 deletions

View File

@ -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

View File

@ -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
{

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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
{

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)
{

View File

@ -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;