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
parent
78d115f8f2
commit
af74201edb
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue