diff options
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qfontdatabase.cpp | 85 | ||||
-rw-r--r-- | src/gui/text/qfontengine.cpp | 14 | ||||
-rw-r--r-- | src/gui/text/qfontmetrics.cpp | 5 | ||||
-rw-r--r-- | src/gui/text/qplatformfontdatabase.cpp | 14 | ||||
-rw-r--r-- | src/gui/text/qtextdocument.cpp | 3 | ||||
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 81 |
6 files changed, 140 insertions, 62 deletions
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 6b7a9837cb..85a804acfe 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -72,12 +72,14 @@ QT_BEGIN_NAMESPACE #define SMOOTH_SCALABLE 0xffff +#if defined(QT_BUILD_INTERNAL) bool qt_enable_test_font = false; Q_AUTOTEST_EXPORT void qt_setQtEnableTestFont(bool value) { qt_enable_test_font = value; } +#endif static int getFontWeight(const QString &weightString) { @@ -756,7 +758,47 @@ QString qt_resolveFontFamilyAlias(const QString &alias) return alias; } -static QStringList fallbackFamilies(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) +QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const +{ + Q_UNUSED(family); + Q_UNUSED(styleHint); + + QStringList retList; + + size_t writingSystem = std::find(scriptForWritingSystem, + scriptForWritingSystem + QFontDatabase::WritingSystemsCount, + script) - scriptForWritingSystem; + if (writingSystem >= QFontDatabase::WritingSystemsCount) + writingSystem = QFontDatabase::Any; + + QFontDatabasePrivate *db = privateDb(); + for (int i = 0; i < db->count; ++i) { + QtFontFamily *f = db->families[i]; + + f->ensurePopulated(); + + if (writingSystem > QFontDatabase::Any && f->writingSystems[writingSystem] != QtFontFamily::Supported) + continue; + + for (int j = 0; j < f->count; ++j) { + QtFontFoundry *foundry = f->foundries[j]; + + for (int k = 0; k < foundry->count; ++k) { + if (style == foundry->styles[k]->key.style) { + if (foundry->name.isEmpty()) + retList.append(f->name); + else + retList.append(f->name + QLatin1String(" [") + foundry->name + QLatin1Char(']')); + break; + } + } + } + } + + return retList; +} + +QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) { // make sure that the db has all fallback families QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script); @@ -884,17 +926,19 @@ QFontEngine *loadEngine(int script, const QFontDef &request, QFontEngine *engine = loadSingleEngine(script, request, family, foundry, style, size); Q_ASSERT(!engine || engine->type() != QFontEngine::Multi); if (engine && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) { - QStringList fallbacks = request.fallBackFamilies; + QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); + QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script)); + if (!request.fallBackFamilies.isEmpty()) { + QStringList fallbacks = request.fallBackFamilies; - QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint); - if (styleHint == QFont::AnyStyle && request.fixedPitch) - styleHint = QFont::TypeWriter; + QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint); + if (styleHint == QFont::AnyStyle && request.fixedPitch) + styleHint = QFont::TypeWriter; - fallbacks += fallbackFamilies(family->name, QFont::Style(style->key.style), styleHint, QChar::Script(script)); + fallbacks += qt_fallbacksForFamily(family->name, QFont::Style(style->key.style), styleHint, QChar::Script(script)); - QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); - QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script)); - pfMultiEngine->setFallbackFamiliesList(fallbacks); + pfMultiEngine->setFallbackFamiliesList(fallbacks); + } engine = pfMultiEngine; // Cache Multi font engine as well in case we got the single @@ -2519,6 +2563,15 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script) QFontEngine *engine; +#if defined(QT_BUILD_INTERNAL) + // For testing purpose only, emulates an exact-matching monospace font + if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) { + engine = new QTestFontEngine(request.pixelSize); + engine->fontDef = request; + return engine; + } +#endif + // Until we specifically asked not to, try looking for Multi font engine // first, the last '1' indicates that we want Multi font engine instead // of single ones @@ -2534,12 +2587,6 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script) parseFontName(request.family, foundry_name, family_name); - if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) { - engine =new QTestFontEngine(request.pixelSize); - engine->fontDef = request; - return engine; - } - QtFontDesc desc; QList<int> blackListed; int index = match(script, request, family_name, foundry_name, &desc, blackListed); @@ -2560,10 +2607,10 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script) styleHint = QFont::TypeWriter; QStringList fallbacks = request.fallBackFamilies - + fallbackFamilies(request.family, - QFont::Style(request.style), - styleHint, - QChar::Script(script)); + + qt_fallbacksForFamily(request.family, + QFont::Style(request.style), + styleHint, + QChar::Script(script)); if (script > QChar::Script_Common) fallbacks += QString(); // Find the first font matching the specified script. diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index c5b28fb536..2087bad9f6 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1700,15 +1700,15 @@ QFontEngineMulti::~QFontEngineMulti() } } +QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script); + void QFontEngineMulti::ensureFallbackFamiliesQueried() { - if (QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration()) { - const QStringList fallbackFamilies = integration->fontDatabase()->fallbacksForFamily(fontDef.family, - QFont::Style(fontDef.style), - QFont::AnyStyle, - QChar::Script(m_script)); - setFallbackFamiliesList(fallbackFamilies); - } + QFont::StyleHint styleHint = QFont::StyleHint(fontDef.styleHint); + if (styleHint == QFont::AnyStyle && fontDef.fixedPitch) + styleHint = QFont::TypeWriter; + + setFallbackFamiliesList(qt_fallbacksForFamily(fontDef.family, QFont::Style(fontDef.style), styleHint, QChar::Script(m_script))); } void QFontEngineMulti::setFallbackFamiliesList(const QStringList &fallbackFamilies) diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index e351d4d2c5..5bc9fe3c7f 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -208,6 +208,11 @@ QFontMetrics &QFontMetrics::operator=(const QFontMetrics &fm) \since 5.2 */ +/*! + \fn QFontMetricsF &QFontMetricsF::operator=(QFontMetricsF &&other) + + Move-assigns \a other to this QFontMetricsF instance. +*/ /*! \fn void QFontMetrics::swap(QFontMetrics &other) diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp index 502348a79a..8764c8cebf 100644 --- a/src/gui/text/qplatformfontdatabase.cpp +++ b/src/gui/text/qplatformfontdatabase.cpp @@ -343,17 +343,15 @@ QFontEngine *QPlatformFontDatabase::fontEngine(const QByteArray &fontData, qreal } /*! + \fn QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const + Returns a list of alternative fonts for the specified \a family and \a style and \a script using the \a styleHint given. + + Default implementation returns a list of fonts for which \a style and \a script support + has been reported during the font database population. */ -QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const -{ - Q_UNUSED(family); - Q_UNUSED(style); - Q_UNUSED(styleHint); - Q_UNUSED(script); - return QStringList(); -} +// implemented in qfontdatabase.cpp /*! Adds an application font described by the font contained supplied \a fontData diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index d3b70aaf26..29e00d481e 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -135,9 +135,8 @@ bool Qt::mightBeRichText(const QString& text) return false; } -/*! - \fn QString Qt::convertFromPlainText(const QString &plain, WhiteSpaceMode mode) +/*! Converts the plain text string \a plain to an HTML-formatted paragraph while preserving most of its look. diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 7da3e84041..013cd8ae0f 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1605,8 +1605,8 @@ namespace { bool checkFullOtherwiseExtend(QScriptLine &line); QFixed calculateNewWidth(const QScriptLine &line) const { - return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth - - qMin(rightBearing, QFixed()); + return line.textWidth + tmpData.textWidth + spaceData.textWidth + + softHyphenWidth + negativeRightBearing(); } inline glyph_t currentGlyph() const @@ -1626,33 +1626,51 @@ namespace { } } - inline void adjustRightBearing(glyph_t glyph) + inline void calculateRightBearing(glyph_t glyph) { qreal rb; fontEngine->getGlyphBearings(glyph, 0, &rb); - rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); + + // We only care about negative right bearings, so we limit the range + // of the bearing here so that we can assume it's negative in the rest + // of the code, as well ase use QFixed(1) as a sentinel to represent + // the state where we have yet to compute the right bearing. + rightBearing = qMin(QFixed::fromReal(rb), QFixed(0)); } - inline void adjustRightBearing() + inline void calculateRightBearing() { if (currentPosition <= 0) return; - adjustRightBearing(currentGlyph()); + calculateRightBearing(currentGlyph()); } - inline void adjustPreviousRightBearing() + inline void calculateRightBearingForPreviousGlyph() { if (previousGlyph > 0) - adjustRightBearing(previousGlyph); + calculateRightBearing(previousGlyph); } + static const QFixed RightBearingNotCalculated; + inline void resetRightBearing() { - rightBearing = QFixed(1); // Any positive number is defined as invalid since only - // negative right bearings are interesting to us. + rightBearing = RightBearingNotCalculated; + } + + // We express the negative right bearing as an absolute number + // so that it can be applied to the width using addition. + inline QFixed negativeRightBearing() const + { + if (rightBearing == RightBearingNotCalculated) + return QFixed(0); + + return qAbs(rightBearing); } }; +const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1); + inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line) { LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal()); @@ -1805,7 +1823,7 @@ void QTextLine::layout_helper(int maxGlyphs) current, lbh.logClusters, lbh.glyphs); } else { lbh.tmpData.length++; - lbh.adjustPreviousRightBearing(); + lbh.calculateRightBearingForPreviousGlyph(); } line += lbh.tmpData; goto found; @@ -1887,22 +1905,29 @@ void QTextLine::layout_helper(int maxGlyphs) lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]]; } - // The actual width of the text needs to take the right bearing into account. The - // right bearing is left-ward, which means that if the rightmost pixel is to the right - // of the advance of the glyph, the bearing will be negative. We flip the sign - // for the code to be more readable. Logic borrowed from qfontmetrics.cpp. - // We ignore the right bearing if the minimum negative bearing is too little to - // expand the text beyond the edge. if (sb_or_ws|breakany) { - QFixed rightBearing = lbh.rightBearing; // store previous right bearing + // To compute the final width of the text we need to take negative right bearing + // into account (negative right bearing means the glyph has pixel data past the + // advance length). Note that the negative right bearing is an absolute number, + // so that we can apply it to the width using straight forward addition. + + // Store previous right bearing (for the already accepted glyph) in case we + // end up breaking due to the current glyph being too wide. + QFixed previousRightBearing = lbh.rightBearing; + + // We ignore the right bearing if the minimum negative bearing is too little to + // expand the text beyond the edge. if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width) - lbh.adjustRightBearing(); + lbh.calculateRightBearing(); + if (lbh.checkFullOtherwiseExtend(line)) { - // we are too wide, fix right bearing - if (rightBearing <= 0) - lbh.rightBearing = rightBearing; // take from cache + // We are too wide to accept the next glyph with its bearing, so we restore the + // right bearing to that of the previous glyph (the one that was already accepted), + // so that the bearing can be be applied to the final width of the text below. + if (previousRightBearing != LineBreakHelper::RightBearingNotCalculated) + lbh.rightBearing = previousRightBearing; else - lbh.adjustPreviousRightBearing(); + lbh.calculateRightBearingForPreviousGlyph(); if (!breakany) { line.textWidth += lbh.softHyphenWidth; @@ -1919,10 +1944,14 @@ void QTextLine::layout_helper(int maxGlyphs) LB_DEBUG("reached end of line"); lbh.checkFullOtherwiseExtend(line); found: - if (lbh.rightBearing > 0 && !lbh.whiteSpaceOrObject) // If right bearing has not yet been adjusted - lbh.adjustRightBearing(); line.textAdvance = line.textWidth; - line.textWidth -= qMin(QFixed(), lbh.rightBearing); + + // If right bearing has not been calculated yet, do that now + if (lbh.rightBearing == LineBreakHelper::RightBearingNotCalculated && !lbh.whiteSpaceOrObject) + lbh.calculateRightBearing(); + + // Then apply any negative right bearing + line.textWidth += lbh.negativeRightBearing(); if (line.length == 0) { LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", |