From 4e319ca4c47a99295c1a07aa759e09d86f1b7c87 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Mon, 3 Feb 2014 02:44:46 +0200 Subject: 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 --- src/gui/painting/qpainter.cpp | 7 +- src/gui/text/qdistancefield.cpp | 14 +++- src/gui/text/qfont.cpp | 4 +- src/gui/text/qfontengine.cpp | 71 ++++++++++++------ src/gui/text/qfontengine_ft.cpp | 19 +++-- src/gui/text/qfontmetrics.cpp | 161 +++++++++++++++++++++++++++++----------- src/gui/text/qfontsubset.cpp | 18 ++++- src/gui/text/qharfbuzzng.cpp | 23 +++--- src/gui/text/qrawfont.cpp | 17 ++--- src/gui/text/qtextengine.cpp | 48 ++++++------ 10 files changed, 246 insertions(+), 136 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 2944130eaa..1fc044aa44 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -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); diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp index e584b66a25..f2b88c4692 100644 --- a/src/gui/text/qdistancefield.cpp +++ b/src/gui/text/qdistancefield.cpp @@ -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); diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index f2951611ff..12761d0d3e 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -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; } diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 32225750e4..d4e2090c8f 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -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(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(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(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(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; } diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 438c7b2141..a9195216ed 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -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 glyphs; + + const QChar *ch = reinterpret_cast(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(this)->boundingBox(glyphs.glyphs[ng]); + if (glyphs[ng]) { + glyph_metrics_t gi = const_cast(this)->boundingBox(glyphs[ng]); 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 08105834ea..2f4709afe4 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -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()); } diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp index 152e15a54d..2109b16bb5 100644 --- a/src/gui/text/qfontsubset.cpp +++ b/src/gui/text/qfontsubset.cpp @@ -201,12 +201,22 @@ static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges) QVector QFontSubset::getReverseMap() const { QVector 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; } diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp index bf34c74b49..7819cd4465 100644 --- a/src/gui/text/qharfbuzzng.cpp +++ b/src/gui/text/qharfbuzzng.cpp @@ -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 diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index e26f7cdc93..449278df06 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -479,16 +479,8 @@ QVector 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(); - } - } + 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 tmpAdvances(numGlyphs); + QGlyphLayout glyphs; glyphs.glyphs = const_cast(glyphIndexes); glyphs.numGlyphs = numGlyphs; - QVarLengthArray 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; istringToCMap(reinterpret_cast(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(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) { - Q_UNREACHABLE(); // ### if this happens there is a bug in the fontengine - return; - } - } + if (!fontEngine->stringToCMap(reinterpret_cast(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; -- cgit v1.2.3