diff options
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qdistancefield.cpp | 14 | ||||
-rw-r--r-- | src/gui/text/qfont.cpp | 4 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase.h | 2 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase_qpa.cpp | 17 | ||||
-rw-r--r-- | src/gui/text/qfontengine.cpp | 82 | ||||
-rw-r--r-- | src/gui/text/qfontengine_ft.cpp | 19 | ||||
-rw-r--r-- | src/gui/text/qfontmetrics.cpp | 161 | ||||
-rw-r--r-- | src/gui/text/qfontsubset.cpp | 18 | ||||
-rw-r--r-- | src/gui/text/qharfbuzzng.cpp | 23 | ||||
-rw-r--r-- | src/gui/text/qplatformfontdatabase.cpp | 6 | ||||
-rw-r--r-- | src/gui/text/qplatformfontdatabase.h | 2 | ||||
-rw-r--r-- | src/gui/text/qrawfont.cpp | 17 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 134 | ||||
-rw-r--r-- | src/gui/text/qtextengine_p.h | 6 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 11 |
15 files changed, 311 insertions, 205 deletions
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/qfontdatabase.h b/src/gui/text/qfontdatabase.h index 708b8cbd58..9986ef6c60 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -167,8 +167,6 @@ private: friend class QFontPrivate; friend class QFontDialog; friend class QFontDialogPrivate; - friend class QFontEngineMultiXLFD; - friend class QFontEngineMultiQWS; friend class QFontEngineMultiQPA; QFontDatabasePrivate *d; diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp index 6f4971e267..1972f5d58c 100644 --- a/src/gui/text/qfontdatabase_qpa.cpp +++ b/src/gui/text/qfontdatabase_qpa.cpp @@ -182,10 +182,17 @@ QFontEngine *loadSingleEngine(int script, QFontCache::Key key(def,script); QFontEngine *engine = QFontCache::instance()->findEngine(key); if (!engine) { - engine = pfdb->fontEngine(def, QChar::Script(script), size->handle); + engine = pfdb->fontEngine(def, size->handle); if (engine) { - QFontCache::Key key(def,script); - QFontCache::instance()->instance()->insertEngine(key,engine); + // Also check for OpenType tables when using complex scripts + if (!engine->supportsScript(QChar::Script(script))) { + qWarning(" OpenType support missing for script %d", script); + if (engine->ref.load() == 0) + delete engine; + return 0; + } + + QFontCache::instance()->insertEngine(key, engine); } } return engine; @@ -221,10 +228,10 @@ QFontEngine *loadEngine(int script, const QFontDef &request, pfMultiEngine->setFallbackFamiliesList(fallbacks); engine = pfMultiEngine; - // Cache Multi font engine as well in case we got the FT single + // Cache Multi font engine as well in case we got the single // font engine when we are actually looking for a Multi one QFontCache::Key key(request, script, 1); - QFontCache::instance()->instance()->insertEngine(key, engine); + QFontCache::instance()->insertEngine(key, engine); } return engine; diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 71866119d4..14ce5d2396 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -48,6 +48,7 @@ #include "qvarlengtharray.h" #include <qmath.h> #include <qendian.h> +#include <private/qstringiterator_p.h> #ifdef QT_ENABLE_HARFBUZZ_NG # include "qharfbuzzng_p.h" @@ -395,23 +396,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; } @@ -470,11 +487,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; @@ -486,7 +514,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 { @@ -1348,14 +1376,12 @@ bool QFontEngineBox::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph } int ucs4Length = 0; - for (int i = 0; i < len; ++i) { - if (str[i].isHighSurrogate() && i + 1 < len && str[i + 1].isLowSurrogate()) - ++ucs4Length; - ++ucs4Length; + QStringIterator it(str, str + len); + while (it.hasNext()) { + it.advance(); + glyphs->glyphs[ucs4Length++] = 0; } - memset(glyphs->glyphs, 0, ucs4Length * sizeof(glyph_t)); - *nglyphs = ucs4Length; glyphs->numGlyphs = ucs4Length; @@ -1547,9 +1573,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); @@ -1860,16 +1887,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 5499757c3b..665932e4a5 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1283,13 +1283,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)); } 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<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; } diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp index 010f955c60..9f77083102 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/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp index 37610a9099..7936831e13 100644 --- a/src/gui/text/qplatformfontdatabase.cpp +++ b/src/gui/text/qplatformfontdatabase.cpp @@ -289,13 +289,11 @@ QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine Returns the font engine that can be used to render the font described by the font definition, \a fontDef, in the specified \a script. */ -QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle) +QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) { - Q_UNUSED(script); - Q_UNUSED(handle); QByteArray *fileDataPtr = static_cast<QByteArray *>(handle); QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr); - //qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family << script; + //qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family; return engine; } diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h index 6053f11051..5f2c9a74ba 100644 --- a/src/gui/text/qplatformfontdatabase.h +++ b/src/gui/text/qplatformfontdatabase.h @@ -97,7 +97,7 @@ public: virtual ~QPlatformFontDatabase(); virtual void populateFontDatabase(); virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script); - virtual QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle); + virtual QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); virtual void releaseHandle(void *handle); 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<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; } diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 2893d8b9b2..8a1096c269 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -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) { @@ -1393,9 +1383,9 @@ void QTextEngine::shape(int item) const if (layoutData->items[item].analysis.flags == QScriptAnalysis::Object) { ensureSpace(1); if (block.docHandle()) { - QTextFormat format = formats()->format(formatIndex(&layoutData->items[item])); docLayout()->resizeInlineObject(QTextInlineObject(item, const_cast<QTextEngine *>(this)), - layoutData->items[item].position + block.position(), format); + layoutData->items[item].position + block.position(), + format(&layoutData->items[item])); } } else if (layoutData->items[item].analysis.flags == QScriptAnalysis::Tab) { // set up at least the ascent/descent/leading of the script item for the tab @@ -1427,7 +1417,7 @@ void QTextEngine::invalidate() minWidth = 0; maxWidth = 0; if (specialData) - specialData->resolvedFormatIndices.clear(); + specialData->resolvedFormats.clear(); resetFontEngineCache(); } @@ -1501,8 +1491,18 @@ void QTextEngine::itemize() const { QVarLengthArray<uchar> scripts(length); QUnicodeTools::initScripts(string, length, scripts.data()); - for (int i = 0; i < length; ++i) - analysis[i].script = scripts.at(i); + for (int i = 0; i < length; ++i) { + ushort script = scripts.at(i); + switch (script) { + case QChar::Script_Hiragana: + case QChar::Script_Katakana: + script = QChar::Script_Han; + break; + default: + break; + } + analysis[i].script = script; + } } const ushort *uc = string; @@ -1596,10 +1596,9 @@ void QTextEngine::itemize() const #ifndef QT_NO_RAWFONT if (useRawFont && specialData) { int lastIndex = 0; - const QTextFormatCollection *collection = formats(); for (int i = 0; i < specialData->addFormats.size(); ++i) { const QTextLayout::FormatRange &range = specialData->addFormats.at(i); - const QTextCharFormat format = collection->charFormat(specialData->addFormatIndices.at(i)); + const QTextCharFormat &format = range.format; if (format.hasProperty(QTextFormat::FontCapitalization)) { itemizer.generate(lastIndex, range.start - lastIndex, QFont::MixedCase); itemizer.generate(range.start, range.length, format.fontCapitalization()); @@ -1996,11 +1995,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; @@ -2360,8 +2370,12 @@ void QTextEngine::freeMemory() int QTextEngine::formatIndex(const QScriptItem *si) const { - if (specialData && !specialData->resolvedFormatIndices.isEmpty()) - return specialData->resolvedFormatIndices.at(si - &layoutData->items[0]); + if (specialData && !specialData->resolvedFormats.isEmpty()) { + QTextFormatCollection *collection = formats(); + Q_ASSERT(collection); + return collection->indexForFormat(specialData->resolvedFormats.at(si - &layoutData->items[0])); + } + QTextDocumentPrivate *p = block.docHandle(); if (!p) return -1; @@ -2474,23 +2488,6 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText) clearLineData(); } -QList<QTextLayout::FormatRange> QTextEngine::additionalFormats() const -{ - QList<QTextLayout::FormatRange> formatList; - if (!specialData) - return formatList; - - formatList = specialData->addFormats; - if (!specialData->addFormatIndices.isEmpty()) { - const QTextFormatCollection *formats = this->formats(); - Q_ASSERT(formats); - for (int i = 0; i < specialData->addFormatIndices.size(); ++i) - formatList[i].format = formats->charFormat(specialData->addFormatIndices.at(i)); - } - - return formatList; -} - void QTextEngine::setAdditionalFormats(const QList<QTextLayout::FormatRange> &formatList) { if (formatList.isEmpty()) { @@ -2501,7 +2498,6 @@ void QTextEngine::setAdditionalFormats(const QList<QTextLayout::FormatRange> &fo specialData = 0; } else { specialData->addFormats.clear(); - specialData->addFormatIndices.clear(); } } else { if (!specialData) { @@ -2516,19 +2512,17 @@ void QTextEngine::setAdditionalFormats(const QList<QTextLayout::FormatRange> &fo void QTextEngine::indexAdditionalFormats() { - specialData->addFormatIndices.resize(specialData->addFormats.count()); - - QTextFormatCollection *formats = this->formats(); - - if (!formats) { + QTextFormatCollection *collection = formats(); + if (!collection) { Q_ASSERT(!block.docHandle()); specialData->formats.reset(new QTextFormatCollection); - formats = specialData->formats.data(); + collection = specialData->formats.data(); } + // replace with shared copies for (int i = 0; i < specialData->addFormats.count(); ++i) { - specialData->addFormatIndices[i] = formats->indexForFormat(specialData->addFormats.at(i).format); - specialData->addFormats[i].format = QTextCharFormat(); + QTextCharFormat &format = specialData->addFormats[i].format; + format = collection->charFormat(collection->indexForFormat(format)); } } @@ -2648,10 +2642,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]) { @@ -2663,8 +2657,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; @@ -2944,14 +2939,12 @@ public: void QTextEngine::resolveAdditionalFormats() const { if (!specialData || specialData->addFormats.isEmpty() - || !specialData->resolvedFormatIndices.isEmpty()) + || !specialData->resolvedFormats.isEmpty()) return; QTextFormatCollection *collection = formats(); - specialData->resolvedFormatIndices.clear(); - QVector<int> indices(layoutData->items.count()); - + specialData->resolvedFormats.resize(layoutData->items.count()); QVarLengthArray<int, 64> addFormatSortedByStart; addFormatSortedByStart.reserve(specialData->addFormats.count()); @@ -2987,21 +2980,22 @@ void QTextEngine::resolveAdditionalFormats() const currentFormats.remove(currentFormatIterator - currentFormats.begin()); ++endIt; } - QTextCharFormat format; + + QTextCharFormat &format = specialData->resolvedFormats[i]; if (block.docHandle()) { // when we have a docHandle, formatIndex might still return a valid index based // on the preeditPosition. for all other cases, we cleared the resolved format indices format = collection->charFormat(formatIndex(si)); } - - foreach (int cur, currentFormats) { - Q_ASSERT(specialData->addFormats.at(cur).start <= si->position - && specialData->addFormats.at(cur).start + specialData->addFormats.at(cur).length >= end); - format.merge(collection->format(specialData->addFormatIndices.at(cur))); + if (!currentFormats.isEmpty()) { + foreach (int cur, currentFormats) { + const QTextLayout::FormatRange &range = specialData->addFormats.at(cur); + Q_ASSERT(range.start <= si->position && range.start + range.length >= end); + format.merge(range.format); + } + format = collection->charFormat(collection->indexForFormat(format)); // get shared copy } - indices[i] = collection->indexForFormat(format); } - specialData->resolvedFormatIndices = indices; } QFixed QTextEngine::leadingSpaceWidth(const QScriptLine &line) diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index d399123609..1616a78937 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -603,7 +603,8 @@ public: void setPreeditArea(int position, const QString &text); inline bool hasFormats() const { return block.docHandle() || (specialData && !specialData->addFormats.isEmpty()); } - QList<QTextLayout::FormatRange> additionalFormats() const; + inline QList<QTextLayout::FormatRange> additionalFormats() const + { return specialData ? specialData->addFormats : QList<QTextLayout::FormatRange>(); } void setAdditionalFormats(const QList<QTextLayout::FormatRange> &formatList); private: @@ -613,8 +614,7 @@ private: int preeditPosition; QString preeditText; QList<QTextLayout::FormatRange> addFormats; - QVector<int> addFormatIndices; - QVector<int> resolvedFormatIndices; + QVector<QTextCharFormat> resolvedFormats; // only used when no docHandle is available QScopedPointer<QTextFormatCollection> formats; }; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index c6e5160edc..0c9866c6cf 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -239,9 +239,7 @@ int QTextInlineObject::formatIndex() const */ QTextFormat QTextInlineObject::format() const { - if (!eng->block.docHandle()) - return QTextFormat(); - return eng->formats()->format(eng->formatIndex(&eng->layoutData->items[itm])); + return eng->format(&eng->layoutData->items[itm]); } /*! @@ -1812,9 +1810,10 @@ void QTextLine::layout_helper(int maxGlyphs) lbh.whiteSpaceOrObject = true; lbh.tmpData.length++; - QTextFormat format = eng->formats()->format(eng->formatIndex(&eng->layoutData->items[item])); - if (eng->block.docHandle()) - eng->docLayout()->positionInlineObject(QTextInlineObject(item, eng), eng->block.position() + current.position, format); + if (eng->block.docHandle()) { + QTextInlineObject inlineObject(item, eng); + eng->docLayout()->positionInlineObject(inlineObject, eng->block.position() + current.position, inlineObject.format()); + } lbh.tmpData.textWidth += current.width; |