summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qfontdatabase.cpp85
-rw-r--r--src/gui/text/qfontengine.cpp14
-rw-r--r--src/gui/text/qfontmetrics.cpp5
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp14
-rw-r--r--src/gui/text/qtextdocument.cpp3
-rw-r--r--src/gui/text/qtextlayout.cpp81
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",