summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Ritt <ritt.ks@gmail.com>2014-03-05 07:02:12 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-05 13:45:44 +0100
commitf697f3ceb6751cfa04338ac8a62ad54dfadad73d (patch)
treed81a343cf4b431f78bf6d3972dd845ef76b6006c
parentf99fd06d7d72627dcb92f6093537d64429d0563a (diff)
Optimize glyph lookups with QFontEngine::glyphIndex(uint)
Change-Id: I56c7e727f3d9b08195f38939106620c744c6eaf0 Reviewed-by: Lars Knoll <lars.knoll@digia.com> Reviewed-by: BogDan Vatra <bogdan@kde.org>
-rw-r--r--src/gui/text/qdistancefield.cpp17
-rw-r--r--src/gui/text/qfontengine.cpp72
-rw-r--r--src/gui/text/qfontengine_ft.cpp20
-rw-r--r--src/gui/text/qfontmetrics.cpp104
-rw-r--r--src/gui/text/qfontsubset.cpp16
-rw-r--r--src/gui/text/qharfbuzzng.cpp28
-rw-r--r--src/gui/text/qrawfont.cpp2
-rw-r--r--src/gui/text/qtextengine.cpp67
8 files changed, 62 insertions, 264 deletions
diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp
index f2b88c4692..17116ee2d0 100644
--- a/src/gui/text/qdistancefield.cpp
+++ b/src/gui/text/qdistancefield.cpp
@@ -739,20 +739,11 @@ bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine)
if (!fe)
return false;
- const QChar uc(QLatin1Char('O'));
+ QImage im;
- glyph_t glyph;
-
- QGlyphLayout glyphs;
- glyphs.numGlyphs = 1;
- glyphs.glyphs = &glyph;
- int numGlyphs = 1;
-
- if (!fe->stringToCMap(&uc, 1, &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(numGlyphs == 1);
-
- QImage im = fe->alphaMapForGlyph(glyph, QFixed(), QTransform());
+ const glyph_t glyph = fe->glyphIndex('O');
+ if (glyph != 0)
+ im = fe->alphaMapForGlyph(glyph, QFixed(), QTransform());
Q_ASSERT(fe->ref.load() == 0);
delete fe;
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 316b491e18..87d3090a39 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -101,35 +101,13 @@ static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint
*numGlyphs = nGlyphs;
if (rightToLeft && result && !fe->symbol) {
- uint glyph_pos = 0;
- for (uint i = 0; i < length; ++i, ++glyph_pos) {
- uint ucs4 = str[i].unicode();
- if (Q_UNLIKELY(QChar::isHighSurrogate(ucs4) && i + 1 < length)) {
- uint low = str[i + 1].unicode();
- if (Q_LIKELY(QChar::isLowSurrogate(low))) {
- ucs4 = QChar::surrogateToUcs4(ucs4, low);
- ++i;
- }
- }
-
- uint mirrored = QChar::mirroredChar(ucs4);
- if (Q_UNLIKELY(mirrored != ucs4)) {
- QChar chars[2];
- uint numChars = 0;
- if (Q_UNLIKELY(QChar::requiresSurrogates(mirrored))) {
- chars[numChars++] = QChar(QChar::highSurrogate(mirrored));
- chars[numChars++] = QChar(QChar::lowSurrogate(mirrored));
- } else {
- chars[numChars++] = QChar(mirrored);
- }
-
- qglyphs.numGlyphs = numChars;
- qglyphs.glyphs = glyphs + glyph_pos;
- nGlyphs = numChars;
- if (!fe->stringToCMap(chars, numChars, &qglyphs, &nGlyphs, QFontEngine::GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(nGlyphs == 1);
- }
+ QStringIterator it(str, str + length);
+ while (it.hasNext()) {
+ const uint ucs4 = it.next();
+ const uint mirrored = QChar::mirroredChar(ucs4);
+ if (Q_UNLIKELY(mirrored != ucs4))
+ *glyphs = fe->glyphIndex(mirrored);
+ ++glyphs;
}
}
@@ -417,38 +395,14 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix
QFixed QFontEngine::xHeight() const
{
- QChar x((ushort)'x');
-
- glyph_t glyph;
-
- QGlyphLayout glyphs;
- glyphs.numGlyphs = 1;
- glyphs.glyphs = &glyph;
-
- int nglyphs = 1;
- if (!stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
-
+ const glyph_t glyph = glyphIndex('x');
glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);
return bb.height;
}
QFixed QFontEngine::averageCharWidth() const
{
- QChar x((ushort)'x');
-
- glyph_t glyph;
-
- QGlyphLayout glyphs;
- glyphs.numGlyphs = 1;
- glyphs.glyphs = &glyph;
-
- int nglyphs = 1;
- if (!stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
-
+ const glyph_t glyph = glyphIndex('x');
glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);
return bb.xoff;
}
@@ -509,18 +463,14 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
if (glyphs.justifications[i].nKashidas) {
QChar ch(0x640); // Kashida character
- glyph_t kashidaGlyph;
+ glyph_t kashidaGlyph = glyphIndex(ch.unicode());
QFixed kashidaWidth;
QGlyphLayout g;
g.numGlyphs = 1;
g.glyphs = &kashidaGlyph;
g.advances = &kashidaWidth;
-
- int nglyphs = 1;
- if (!stringToCMap(&ch, 1, &g, &nglyphs, 0))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
+ recalcAdvances(&g, 0);
for (uint k = 0; k < glyphs.justifications[i].nKashidas; ++k) {
xpos -= kashidaWidth;
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 04cf6bfdcb..892fc22586 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -1282,22 +1282,10 @@ qreal QFontEngineFT::minRightBearing() const
{
if (rbearing == SHRT_MIN) {
lbearing = rbearing = 0;
-
- const QChar *ch = reinterpret_cast<const QChar *>(char_table);
-
- glyph_t glyphs[char_table_entries];
-
- QGlyphLayout g;
- g.glyphs = glyphs;
- g.numGlyphs = char_table_entries;
- int ng = char_table_entries;
- if (!stringToCMap(ch, char_table_entries, &g, &ng, GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(ng == char_table_entries);
-
- while (--ng) {
- if (glyphs[ng]) {
- glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyphs[ng]);
+ for (int i = 0; i < char_table_entries; ++i) {
+ const glyph_t glyph = glyphIndex(char_table[i]);
+ if (glyph != 0) {
+ glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyph);
lbearing = qMin(lbearing, gi.x);
rbearing = qMin(rbearing, (gi.xoff - gi.x - gi.width));
}
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 2f4709afe4..7868fd23d1 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -410,12 +410,7 @@ int QFontMetrics::averageCharWidth() const
*/
bool QFontMetrics::inFont(QChar ch) const
{
- const int script = ch.script();
- QFontEngine *engine = d->engineForScript(script);
- Q_ASSERT(engine != 0);
- if (engine->type() == QFontEngine::Box)
- return false;
- return engine->canRender(&ch, 1);
+ return inFontUcs4(ch.unicode());
}
/*!
@@ -458,16 +453,7 @@ int QFontMetrics::leftBearing(QChar ch) const
d->alterCharForCapitalization(ch);
- glyph_t glyph;
-
- QGlyphLayout glyphs;
- glyphs.numGlyphs = 1;
- glyphs.glyphs = &glyph;
-
- int nglyphs = 1;
- if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
+ glyph_t glyph = engine->glyphIndex(ch.unicode());
qreal lb;
engine->getGlyphBearings(glyph, &lb);
@@ -500,16 +486,7 @@ int QFontMetrics::rightBearing(QChar ch) const
d->alterCharForCapitalization(ch);
- glyph_t glyph;
-
- QGlyphLayout glyphs;
- glyphs.numGlyphs = 1;
- glyphs.glyphs = &glyph;
-
- int nglyphs = 1;
- if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
+ glyph_t glyph = engine->glyphIndex(ch.unicode());
qreal rb;
engine->getGlyphBearings(glyph, 0, &rb);
@@ -605,18 +582,14 @@ int QFontMetrics::width(QChar ch) const
d->alterCharForCapitalization(ch);
+ glyph_t glyph = engine->glyphIndex(ch.unicode());
QFixed advance;
QGlyphLayout glyphs;
glyphs.numGlyphs = 1;
- glyph_t glyph;
glyphs.glyphs = &glyph;
glyphs.advances = &advance;
-
- int nglyphs = 1;
- if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
+ engine->recalcAdvances(&glyphs, 0);
return qRound(advance);
}
@@ -660,18 +633,14 @@ int QFontMetrics::charWidth(const QString &text, int pos) const
d->alterCharForCapitalization(ch);
+ glyph_t glyph = engine->glyphIndex(ch.unicode());
QFixed advance;
QGlyphLayout glyphs;
glyphs.numGlyphs = 1;
- glyph_t glyph;
glyphs.glyphs = &glyph;
glyphs.advances = &advance;
-
- int nglyphs = 1;
- if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
+ engine->recalcAdvances(&glyphs, 0);
width = qRound(advance);
}
@@ -739,16 +708,7 @@ QRect QFontMetrics::boundingRect(QChar ch) const
d->alterCharForCapitalization(ch);
- glyph_t glyph;
-
- QGlyphLayout glyphs;
- glyphs.numGlyphs = 1;
- glyphs.glyphs = &glyph;
-
- int nglyphs = 1;
- if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
+ glyph_t glyph = engine->glyphIndex(ch.unicode());
glyph_metrics_t gm = engine->boundingBox(glyph);
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
@@ -1315,12 +1275,7 @@ qreal QFontMetricsF::averageCharWidth() const
*/
bool QFontMetricsF::inFont(QChar ch) const
{
- const int script = ch.script();
- QFontEngine *engine = d->engineForScript(script);
- Q_ASSERT(engine != 0);
- if (engine->type() == QFontEngine::Box)
- return false;
- return engine->canRender(&ch, 1);
+ return inFontUcs4(ch.unicode());
}
/*!
@@ -1365,16 +1320,7 @@ qreal QFontMetricsF::leftBearing(QChar ch) const
d->alterCharForCapitalization(ch);
- glyph_t glyph;
-
- QGlyphLayout glyphs;
- glyphs.numGlyphs = 1;
- glyphs.glyphs = &glyph;
-
- int nglyphs = 1;
- if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
+ glyph_t glyph = engine->glyphIndex(ch.unicode());
qreal lb;
engine->getGlyphBearings(glyph, &lb);
@@ -1407,16 +1353,7 @@ qreal QFontMetricsF::rightBearing(QChar ch) const
d->alterCharForCapitalization(ch);
- glyph_t glyph;
-
- QGlyphLayout glyphs;
- glyphs.numGlyphs = 1;
- glyphs.glyphs = &glyph;
-
- int nglyphs = 1;
- if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
+ glyph_t glyph = engine->glyphIndex(ch.unicode());
qreal rb;
engine->getGlyphBearings(glyph, 0, &rb);
@@ -1484,18 +1421,14 @@ qreal QFontMetricsF::width(QChar ch) const
d->alterCharForCapitalization(ch);
+ glyph_t glyph = engine->glyphIndex(ch.unicode());
QFixed advance;
QGlyphLayout glyphs;
glyphs.numGlyphs = 1;
- glyph_t glyph;
glyphs.glyphs = &glyph;
glyphs.advances = &advance;
-
- int nglyphs = 1;
- if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
+ engine->recalcAdvances(&glyphs, 0);
return advance.toReal();
}
@@ -1559,16 +1492,7 @@ QRectF QFontMetricsF::boundingRect(QChar ch) const
d->alterCharForCapitalization(ch);
- glyph_t glyph;
-
- QGlyphLayout glyphs;
- glyphs.numGlyphs = 1;
- glyphs.glyphs = &glyph;
-
- int nglyphs = 1;
- if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
+ glyph_t glyph = engine->glyphIndex(ch.unicode());
glyph_metrics_t gm = engine->boundingBox(glyph);
return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp
index 2109b16bb5..4bb29da2af 100644
--- a/src/gui/text/qfontsubset.cpp
+++ b/src/gui/text/qfontsubset.cpp
@@ -201,22 +201,8 @@ static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges)
QVector<int> QFontSubset::getReverseMap() const
{
QVector<int> reverseMap(0x10000, 0);
-
- glyph_t glyph;
-
- QGlyphLayout glyphs;
- glyphs.glyphs = &glyph;
- glyphs.numGlyphs = 1;
-
for (uint uc = 0; uc < 0x10000; ++uc) {
- QChar ch(uc);
-
- int nglyphs = 1;
- if (!fontEngine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
-
- int idx = glyph_indices.indexOf(glyph);
+ int idx = glyph_indices.indexOf(fontEngine->glyphIndex(uc));
if (idx >= 0 && !reverseMap.at(idx))
reverseMap[idx] = uc;
}
diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp
index 31bb6f38f2..f7a1d30e6f 100644
--- a/src/gui/text/qharfbuzzng.cpp
+++ b/src/gui/text/qharfbuzzng.cpp
@@ -397,33 +397,7 @@ _hb_qt_font_get_glyph(hb_font_t * /*font*/, void *font_data,
QFontEngine *fe = (QFontEngine *)font_data;
Q_ASSERT(fe);
- QChar chars[2];
- int numChars = 0;
- if (Q_UNLIKELY(QChar::requiresSurrogates(unicode))) {
- chars[numChars++] = QChar(QChar::highSurrogate(unicode));
- chars[numChars++] = QChar(QChar::lowSurrogate(unicode));
- } else {
- chars[numChars++] = QChar(unicode);
- }
-#if 0
- if (Q_UNLIKELY(variation_selector != 0)) {
- if (Q_UNLIKELY(QChar::requiresSurrogates(variation_selector))) {
- chars[numChars++] = QChar(QChar::highSurrogate(variation_selector));
- chars[numChars++] = QChar(QChar::lowSurrogate(variation_selector));
- } else {
- chars[numChars++] = QChar(variation_selector);
- }
- }
-#endif
-
- QGlyphLayout g;
- g.numGlyphs = numChars;
- g.glyphs = glyph;
-
- int numGlyphs = numChars;
- if (!fe->stringToCMap(chars, numChars, &g, &numGlyphs, QFontEngine::GlyphIndicesOnly))
- Q_UNREACHABLE();
- Q_ASSERT(numGlyphs == 1);
+ *glyph = fe->glyphIndex(unicode);
return true;
}
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index 449278df06..2ba350fb67 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -665,7 +665,7 @@ QList<QFontDatabase::WritingSystem> QRawFont::supportedWritingSystems() const
*/
bool QRawFont::supportsCharacter(QChar character) const
{
- return d->isValid() && d->fontEngine->canRender(&character, 1);
+ return supportsCharacter(character.unicode());
}
/*!
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 45894d27b6..2d7611774b 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -2011,21 +2011,16 @@ static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph,
if (type >= Justification_Arabic_Normal) {
QChar ch(0x640); // Kashida character
- glyph_t kashidaGlyph;
- QFixed kashidaWidth;
-
- QGlyphLayout glyphs;
- glyphs.numGlyphs = 1;
- glyphs.glyphs = &kashidaGlyph;
- glyphs.advances = &kashidaWidth;
-
- int nglyphs = 1;
- if (!fe->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
- Q_UNREACHABLE();
- Q_ASSERT(nglyphs == 1);
-
- if (kashidaGlyph != 0 && kashidaWidth != 0) {
- point->kashidaWidth = kashidaWidth;
+ glyph_t kashidaGlyph = fe->glyphIndex(ch.unicode());
+ if (kashidaGlyph != 0) {
+ QGlyphLayout g;
+ g.numGlyphs = 1;
+ g.glyphs = &kashidaGlyph;
+ g.advances = &point->kashidaWidth;
+ fe->recalcAdvances(&g, 0);
+
+ if (point->kashidaWidth == 0)
+ point->type = Justification_Prohibited;
} else {
point->type = Justification_Prohibited;
point->kashidaWidth = 0;
@@ -2644,40 +2639,30 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
QFixed ellipsisWidth;
QString ellipsisText;
{
- QChar ellipsisChar(0x2026);
-
QFontEngine *fe = fnt.d->engineForScript(QChar::Script_Common);
+ QFontEngine *engine = fe->type() == QFontEngine::Multi ? static_cast<QFontEngineMulti *>(fe)->engine(0) : fe;
- QGlyphLayoutArray<1> ellipsisGlyph;
- {
- QFontEngine *feForEllipsis = (fe->type() == QFontEngine::Multi)
- ? static_cast<QFontEngineMulti *>(fe)->engine(0)
- : fe;
+ QChar ellipsisChar(0x2026);
- if (feForEllipsis->type() == QFontEngine::Mac)
- feForEllipsis = fe;
+ glyph_t glyph = engine->glyphIndex(ellipsisChar.unicode());
- int nGlyphs = 1;
- if (!feForEllipsis->stringToCMap(&ellipsisChar, 1, &ellipsisGlyph, &nGlyphs, 0))
- Q_UNREACHABLE();
- Q_ASSERT(nGlyphs == 1);
- }
+ QGlyphLayout glyphs;
+ glyphs.numGlyphs = 1;
+ glyphs.glyphs = &glyph;
+ glyphs.advances = &ellipsisWidth;
+
+ if (glyph != 0) {
+ engine->recalcAdvances(&glyphs, 0);
- if (ellipsisGlyph.glyphs[0]) {
- ellipsisWidth = ellipsisGlyph.advances[0];
ellipsisText = ellipsisChar;
} else {
- QString dotDotDot(QLatin1String("..."));
-
- QGlyphLayoutArray<3> glyphs;
- int nGlyphs = 3;
- if (!fe->stringToCMap(dotDotDot.constData(), 3, &glyphs, &nGlyphs, 0))
- Q_UNREACHABLE();
- Q_ASSERT(nGlyphs == 3);
+ glyph = engine->glyphIndex('.');
+ if (glyph != 0) {
+ engine->recalcAdvances(&glyphs, 0);
- for (int i = 0; i < nGlyphs; ++i)
- ellipsisWidth += glyphs.advances[i];
- ellipsisText = dotDotDot;
+ ellipsisWidth *= 3;
+ ellipsisText = QStringLiteral("...");
+ }
}
}