Optimize stringToCMap() usage

CMAP guarantees there is 1:1 mapping between the Unicode code points
array and the glyph indexes array, which means the QString length
always greater than or equal to a sufficient glyph indexes array length.

Simply add some asserts and improve the memory consumption
and the performance where possible.

Change-Id: I0bc8cdba5f86c1c0ba9e79c8d5f96cbe56ec463e
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Konstantin Ritt 2014-02-03 02:44:46 +02:00 committed by The Qt Project
parent 93aec932ff
commit 4e319ca4c4
10 changed files with 246 additions and 136 deletions

View File

@ -5845,11 +5845,8 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
int numGlyphs = len;
QVarLengthGlyphLayoutArray glyphs(len);
QFontEngine *fontEngine = d->state->font.d->engineForScript(QChar::Script_Common);
if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
glyphs.resize(numGlyphs);
if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
}
if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
Q_UNREACHABLE();
QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
drawTextItem(p, gf);

View File

@ -739,13 +739,19 @@ bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine)
if (!fe)
return false;
QGlyphLayout glyphs;
const QChar uc(QLatin1Char('O'));
glyph_t glyph;
glyphs.glyphs = &glyph;
QGlyphLayout glyphs;
glyphs.numGlyphs = 1;
glyphs.glyphs = &glyph;
int numGlyphs = 1;
QChar uc = QLatin1Char('O');
fe->stringToCMap(&uc, 1, &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly);
if (!fe->stringToCMap(&uc, 1, &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly))
Q_UNREACHABLE();
Q_ASSERT(numGlyphs == 1);
QImage im = fe->alphaMapForGlyph(glyph, QFixed(), QTransform());
Q_ASSERT(fe->ref.load() == 0);

View File

@ -2533,7 +2533,9 @@ bool QFontInfo::fixedPitch() const
QChar ch[2] = { QLatin1Char('i'), QLatin1Char('m') };
QGlyphLayoutArray<2> g;
int l = 2;
engine->stringToCMap(ch, 2, &g, &l, 0);
if (!engine->stringToCMap(ch, 2, &g, &l, 0))
Q_UNREACHABLE();
Q_ASSERT(l == 2);
engine->fontDef.fixedPitch = g.advances[0] == g.advances[1];
engine->fontDef.fixedPitchComputed = true;
}

View File

@ -384,23 +384,39 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix
QFixed QFontEngine::xHeight() const
{
QGlyphLayoutArray<8> glyphs;
int nglyphs = 7;
QChar x((ushort)'x');
stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly);
glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs.glyphs[0]);
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);
glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);
return bb.height;
}
QFixed QFontEngine::averageCharWidth() const
{
QGlyphLayoutArray<8> glyphs;
int nglyphs = 7;
QChar x((ushort)'x');
stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly);
glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs.glyphs[0]);
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);
glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);
return bb.xoff;
}
@ -459,11 +475,22 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
++current;
if (glyphs.justifications[i].nKashidas) {
QChar ch(0x640); // Kashida character
QGlyphLayoutArray<8> g;
int nglyphs = 7;
stringToCMap(&ch, 1, &g, &nglyphs, 0);
glyph_t kashidaGlyph;
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);
for (uint k = 0; k < glyphs.justifications[i].nKashidas; ++k) {
xpos -= g.advances[0];
xpos -= kashidaWidth;
QFixed gpos_x = xpos + glyphs.offsets[i].x;
QFixed gpos_y = ypos + glyphs.offsets[i].y;
@ -475,7 +502,7 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
}
positions[current].x = gpos_x;
positions[current].y = gpos_y;
glyphs_out[current] = g.glyphs[0];
glyphs_out[current] = kashidaGlyph;
++current;
}
} else {
@ -1536,9 +1563,10 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
if (!(flags & GlyphIndicesOnly))
glyphs->advances[glyph_pos] = QFixed();
int num = 2;
QGlyphLayout offs = glyphs->mid(glyph_pos, num);
engine->stringToCMap(str + i, surrogate ? 2 : 1, &offs, &num, flags);
Q_ASSERT(num == 1); // surrogates only give 1 glyph
QGlyphLayout g = glyphs->mid(glyph_pos, num);
if (!engine->stringToCMap(str + i, surrogate ? 2 : 1, &g, &num, flags))
Q_UNREACHABLE();
Q_ASSERT(num == 1);
if (glyphs->glyphs[glyph_pos]) {
// set the high byte to indicate which engine the glyph came from
glyphs->glyphs[glyph_pos] |= (x << 24);
@ -1849,16 +1877,11 @@ bool QFontEngineMulti::canRender(const QChar *string, int len)
QGlyphLayout g;
g.numGlyphs = nglyphs;
g.glyphs = glyphs.data();
if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly)) {
glyphs.resize(nglyphs);
g.numGlyphs = nglyphs;
g.glyphs = glyphs.data();
if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly))
Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
}
if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly))
Q_UNREACHABLE();
for (int i = 0; i < nglyphs; i++) {
if (g.glyphs[i] == 0)
if (glyphs[i] == 0)
return false;
}

View File

@ -1274,13 +1274,22 @@ qreal QFontEngineFT::minRightBearing() const
{
if (rbearing == SHRT_MIN) {
lbearing = rbearing = 0;
const QChar *ch = (const QChar *)(const void*)char_table;
QGlyphLayoutArray<char_table_entries> glyphs;
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;
stringToCMap(ch, char_table_entries, &glyphs, &ng, GlyphIndicesOnly);
if (!stringToCMap(ch, char_table_entries, &g, &ng, GlyphIndicesOnly))
Q_UNREACHABLE();
Q_ASSERT(ng == char_table_entries);
while (--ng) {
if (glyphs.glyphs[ng]) {
glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyphs.glyphs[ng]);
if (glyphs[ng]) {
glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyphs[ng]);
lbearing = qMin(lbearing, gi.x);
rbearing = qMin(rbearing, (gi.xoff - gi.x - gi.width));
}

View File

@ -458,12 +458,19 @@ int QFontMetrics::leftBearing(QChar ch) const
d->alterCharForCapitalization(ch);
QGlyphLayoutArray<10> glyphs;
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
// ### can nglyphs != 1 happen at all? Not currently I think
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);
qreal lb;
engine->getGlyphBearings(glyphs.glyphs[0], &lb);
engine->getGlyphBearings(glyph, &lb);
return qRound(lb);
}
@ -493,12 +500,19 @@ int QFontMetrics::rightBearing(QChar ch) const
d->alterCharForCapitalization(ch);
QGlyphLayoutArray<10> glyphs;
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
// ### can nglyphs != 1 happen at all? Not currently I think
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);
qreal rb;
engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
engine->getGlyphBearings(glyph, 0, &rb);
return qRound(rb);
}
@ -538,11 +552,8 @@ int QFontMetrics::width(const QString &text, int len, int flags) const
int numGlyphs = len;
QVarLengthGlyphLayoutArray glyphs(numGlyphs);
QFontEngine *engine = d->engineForScript(QChar::Script_Common);
if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0)) {
glyphs.resize(numGlyphs);
if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0))
Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
}
if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0))
Q_UNREACHABLE();
QFixed width;
for (int i = 0; i < numGlyphs; ++i)
@ -594,10 +605,20 @@ int QFontMetrics::width(QChar ch) const
d->alterCharForCapitalization(ch);
QGlyphLayoutArray<8> glyphs;
int nglyphs = 7;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
return qRound(glyphs.advances[0]);
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);
return qRound(advance);
}
/*! \obsolete
@ -639,10 +660,20 @@ int QFontMetrics::charWidth(const QString &text, int pos) const
d->alterCharForCapitalization(ch);
QGlyphLayoutArray<8> glyphs;
int nglyphs = 7;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
width = qRound(glyphs.advances[0]);
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);
width = qRound(advance);
}
return width;
}
@ -708,10 +739,18 @@ QRect QFontMetrics::boundingRect(QChar ch) const
d->alterCharForCapitalization(ch);
QGlyphLayoutArray<10> glyphs;
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
glyph_metrics_t gm = engine->boundingBox(glyphs.glyphs[0]);
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_metrics_t gm = engine->boundingBox(glyph);
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
}
@ -1326,12 +1365,19 @@ qreal QFontMetricsF::leftBearing(QChar ch) const
d->alterCharForCapitalization(ch);
QGlyphLayoutArray<10> glyphs;
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
// ### can nglyphs != 1 happen at all? Not currently I think
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);
qreal lb;
engine->getGlyphBearings(glyphs.glyphs[0], &lb);
engine->getGlyphBearings(glyph, &lb);
return lb;
}
@ -1361,12 +1407,19 @@ qreal QFontMetricsF::rightBearing(QChar ch) const
d->alterCharForCapitalization(ch);
QGlyphLayoutArray<10> glyphs;
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
// ### can nglyphs != 1 happen at all? Not currently I think
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);
qreal rb;
engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
engine->getGlyphBearings(glyph, 0, &rb);
return rb;
}
@ -1431,10 +1484,20 @@ qreal QFontMetricsF::width(QChar ch) const
d->alterCharForCapitalization(ch);
QGlyphLayoutArray<8> glyphs;
int nglyphs = 7;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
return glyphs.advances[0].toReal();
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);
return advance.toReal();
}
/*!
@ -1496,10 +1559,18 @@ QRectF QFontMetricsF::boundingRect(QChar ch) const
d->alterCharForCapitalization(ch);
QGlyphLayoutArray<10> glyphs;
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
glyph_metrics_t gm = engine->boundingBox(glyphs.glyphs[0]);
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_metrics_t gm = engine->boundingBox(glyph);
return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
}

View File

@ -201,12 +201,22 @@ static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges)
QVector<int> QFontSubset::getReverseMap() const
{
QVector<int> reverseMap(0x10000, 0);
QGlyphLayoutArray<10> glyphs;
glyph_t glyph;
QGlyphLayout glyphs;
glyphs.glyphs = &glyph;
glyphs.numGlyphs = 1;
for (uint uc = 0; uc < 0x10000; ++uc) {
QChar ch(uc);
int nglyphs = 10;
fontEngine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
int idx = glyph_indices.indexOf(glyphs.glyphs[0]);
int nglyphs = 1;
if (!fontEngine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
Q_UNREACHABLE();
Q_ASSERT(nglyphs == 1);
int idx = glyph_indices.indexOf(glyph);
if (idx >= 0 && !reverseMap.at(idx))
reverseMap[idx] = uc;
}

View File

@ -397,13 +397,7 @@ _hb_qt_font_get_glyph(hb_font_t * /*font*/, void *font_data,
QFontEngine *fe = (QFontEngine *)font_data;
Q_ASSERT(fe);
glyph_t glyphs[2] = { 0, 0 };
QGlyphLayout g;
g.numGlyphs = 2;
g.glyphs = glyphs;
QChar chars[4];
QChar chars[2];
int numChars = 0;
if (Q_UNLIKELY(QChar::requiresSurrogates(unicode))) {
chars[numChars++] = QChar(QChar::highSurrogate(unicode));
@ -422,11 +416,14 @@ _hb_qt_font_get_glyph(hb_font_t * /*font*/, void *font_data,
}
#endif
int numGlyphs = g.numGlyphs;
bool ok = fe->stringToCMap(chars, numChars, &g, &numGlyphs, QFontEngine::GlyphIndicesOnly);
Q_ASSERT(ok); Q_UNUSED(ok)
QGlyphLayout g;
g.numGlyphs = numChars;
g.glyphs = glyph;
*glyph = g.glyphs[0];
int numGlyphs = numChars;
if (!fe->stringToCMap(chars, numChars, &g, &numGlyphs, QFontEngine::GlyphIndicesOnly))
Q_UNREACHABLE();
Q_ASSERT(numGlyphs == 1);
return true;
}
@ -448,7 +445,7 @@ _hb_qt_font_get_glyph_h_advance(hb_font_t *font, void *font_data,
fe->recalcAdvances(&g, QFontEngine::ShaperFlags(hb_qt_font_get_use_design_metrics(font)));
return g.advances[0].value();
return advance.value();
}
static hb_position_t
@ -497,7 +494,7 @@ _hb_qt_font_get_glyph_h_kerning(hb_font_t *font, void *font_data,
fe->doKerning(&g, QFontEngine::ShaperFlags(hb_qt_font_get_use_design_metrics(font)));
return g.advances[0].value();
return advance.value();
}
static hb_position_t

View File

@ -479,16 +479,8 @@ QVector<quint32> QRawFont::glyphIndexesForString(const QString &text) const
QGlyphLayout glyphs;
glyphs.numGlyphs = numGlyphs;
glyphs.glyphs = glyphIndexes.data();
if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly)) {
glyphIndexes.resize(numGlyphs);
glyphs.numGlyphs = numGlyphs;
glyphs.glyphs = glyphIndexes.data();
if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly)) {
Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
return QVector<quint32>();
}
}
if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly))
Q_UNREACHABLE();
glyphIndexes.resize(numGlyphs);
return glyphIndexes;
@ -565,10 +557,11 @@ bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *adv
if (!d->isValid() || numGlyphs <= 0)
return false;
QVarLengthArray<QFixed> tmpAdvances(numGlyphs);
QGlyphLayout glyphs;
glyphs.glyphs = const_cast<glyph_t *>(glyphIndexes);
glyphs.numGlyphs = numGlyphs;
QVarLengthArray<QFixed> tmpAdvances(numGlyphs);
glyphs.advances = tmpAdvances.data();
bool design = layoutFlags & UseDesignMetrics;
@ -578,7 +571,7 @@ bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *adv
d->fontEngine->doKerning(&glyphs, design ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlag(0));
for (int i=0; i<numGlyphs; ++i)
advances[i] = QPointF(glyphs.advances[i].toReal(), 0.0);
advances[i] = QPointF(tmpAdvances[i].toReal(), 0.0);
return true;
}

View File

@ -932,18 +932,8 @@ void QTextEngine::shapeText(int item) const
int nGlyphs = initialGlyphs.numGlyphs;
QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly);
if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) {
nGlyphs = qMax(nGlyphs, itemLength); // ### needed for QFontEngine::stringToCMap() to not fail twice
if (!ensureSpace(nGlyphs)) {
Q_UNREACHABLE(); // ### report OOM error somehow
return;
}
initialGlyphs = availableGlyphs(&si);
if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) {
Q_UNREACHABLE(); // ### if this happens there is a bug in the fontengine
return;
}
}
if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags))
Q_UNREACHABLE();
uint lastEngine = 0;
for (int i = 0, glyph_pos = 0; i < itemLength; ++i, ++glyph_pos) {
@ -2003,11 +1993,22 @@ static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph,
if (type >= QGlyphAttributes::Arabic_Normal) {
QChar ch(0x640); // Kashida character
QGlyphLayoutArray<8> glyphs;
int nglyphs = 7;
fe->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
if (glyphs.glyphs[0] != 0 && glyphs.advances[0].value() != 0) {
point->kashidaWidth = glyphs.advances[0];
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;
} else {
point->type = QGlyphAttributes::NoJustification;
point->kashidaWidth = 0;
@ -2639,10 +2640,10 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
if (feForEllipsis->type() == QFontEngine::Mac)
feForEllipsis = fe;
if (feForEllipsis->canRender(&ellipsisChar, 1)) {
int nGlyphs = 1;
feForEllipsis->stringToCMap(&ellipsisChar, 1, &ellipsisGlyph, &nGlyphs, 0);
}
int nGlyphs = 1;
if (!feForEllipsis->stringToCMap(&ellipsisChar, 1, &ellipsisGlyph, &nGlyphs, 0))
Q_UNREACHABLE();
Q_ASSERT(nGlyphs == 1);
}
if (ellipsisGlyph.glyphs[0]) {
@ -2654,8 +2655,9 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
QGlyphLayoutArray<3> glyphs;
int nGlyphs = 3;
if (!fe->stringToCMap(dotDotDot.constData(), 3, &glyphs, &nGlyphs, 0))
// should never happen...
return layoutData->string;
Q_UNREACHABLE();
Q_ASSERT(nGlyphs == 3);
for (int i = 0; i < nGlyphs; ++i)
ellipsisWidth += glyphs.advances[i];
ellipsisText = dotDotDot;