summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qabstracttextdocumentlayout.cpp9
-rw-r--r--src/gui/text/qabstracttextdocumentlayout.h4
-rw-r--r--src/gui/text/qabstracttextdocumentlayout_p.h3
-rw-r--r--src/gui/text/qcssparser.cpp1
-rw-r--r--src/gui/text/qfont.cpp21
-rw-r--r--src/gui/text/qfontdatabase.cpp97
-rw-r--r--src/gui/text/qfontengine.cpp112
-rw-r--r--src/gui/text/qfontengine_ft.cpp188
-rw-r--r--src/gui/text/qfontengine_ft_p.h99
-rw-r--r--src/gui/text/qfontengine_p.h21
-rw-r--r--src/gui/text/qfontengineglyphcache.cpp43
-rw-r--r--src/gui/text/qfontengineglyphcache_p.h4
-rw-r--r--src/gui/text/qfontmetrics.h10
-rw-r--r--src/gui/text/qfontsubset.cpp41
-rw-r--r--src/gui/text/qfontsubset_p.h2
-rw-r--r--src/gui/text/qglyphrun.cpp1
-rw-r--r--src/gui/text/qglyphrun.h8
-rw-r--r--src/gui/text/qharfbuzzng.cpp10
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp15
-rw-r--r--src/gui/text/qplatformfontdatabase.h2
-rw-r--r--src/gui/text/qrawfont.cpp1
-rw-r--r--src/gui/text/qrawfont.h10
-rw-r--r--src/gui/text/qstatictext.cpp8
-rw-r--r--src/gui/text/qstatictext.h7
-rw-r--r--src/gui/text/qstatictext_p.h5
-rw-r--r--src/gui/text/qsyntaxhighlighter.cpp8
-rw-r--r--src/gui/text/qtextcursor.h8
-rw-r--r--src/gui/text/qtextcursor_p.h3
-rw-r--r--src/gui/text/qtextdocument.cpp29
-rw-r--r--src/gui/text/qtextdocument.h18
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp18
-rw-r--r--src/gui/text/qtextengine.cpp63
-rw-r--r--src/gui/text/qtextengine_p.h33
-rw-r--r--src/gui/text/qtextformat.cpp8
-rw-r--r--src/gui/text/qtextformat_p.h1
-rw-r--r--src/gui/text/qtextimagehandler.cpp36
-rw-r--r--src/gui/text/qtextlayout.cpp127
-rw-r--r--src/gui/text/qtextlayout.h24
-rw-r--r--src/gui/text/qtextobject.cpp5
-rw-r--r--src/gui/text/qtextobject.h6
-rw-r--r--src/gui/text/qtextodfwriter.cpp11
-rw-r--r--src/gui/text/qtextodfwriter_p.h2
-rw-r--r--src/gui/text/qtextoption.cpp6
-rw-r--r--src/gui/text/qtexttable.cpp17
-rw-r--r--src/gui/text/qtexttable.h4
-rw-r--r--src/gui/text/qzip.cpp83
-rw-r--r--src/gui/text/qzipreader_p.h18
-rw-r--r--src/gui/text/text.pri2
48 files changed, 798 insertions, 454 deletions
diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp
index 70be92535d..7735fd6b46 100644
--- a/src/gui/text/qabstracttextdocumentlayout.cpp
+++ b/src/gui/text/qabstracttextdocumentlayout.cpp
@@ -40,6 +40,15 @@
QT_BEGIN_NAMESPACE
+QAbstractTextDocumentLayoutPrivate::~QAbstractTextDocumentLayoutPrivate()
+{
+}
+
+QTextObjectInterface::~QTextObjectInterface()
+{
+ // must be empty until ### Qt 6
+}
+
/*!
\class QAbstractTextDocumentLayout
\reentrant
diff --git a/src/gui/text/qabstracttextdocumentlayout.h b/src/gui/text/qabstracttextdocumentlayout.h
index 27135b0476..cdcfed7535 100644
--- a/src/gui/text/qabstracttextdocumentlayout.h
+++ b/src/gui/text/qabstracttextdocumentlayout.h
@@ -90,7 +90,7 @@ public:
QTextDocument *document() const;
void registerHandler(int objectType, QObject *component);
- void unregisterHandler(int objectType, QObject *component = 0);
+ void unregisterHandler(int objectType, QObject *component = Q_NULLPTR);
QTextObjectInterface *handlerForObject(int objectType) const;
Q_SIGNALS:
@@ -126,7 +126,7 @@ private:
class Q_GUI_EXPORT QTextObjectInterface
{
public:
- virtual ~QTextObjectInterface() {}
+ virtual ~QTextObjectInterface();
virtual QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format) = 0;
virtual void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format) = 0;
};
diff --git a/src/gui/text/qabstracttextdocumentlayout_p.h b/src/gui/text/qabstracttextdocumentlayout_p.h
index 505135fa4b..a7f28ebf96 100644
--- a/src/gui/text/qabstracttextdocumentlayout_p.h
+++ b/src/gui/text/qabstracttextdocumentlayout_p.h
@@ -58,13 +58,14 @@ struct QTextObjectHandler
};
typedef QHash<int, QTextObjectHandler> HandlerHash;
-class QAbstractTextDocumentLayoutPrivate : public QObjectPrivate
+class Q_GUI_EXPORT QAbstractTextDocumentLayoutPrivate : public QObjectPrivate
{
public:
Q_DECLARE_PUBLIC(QAbstractTextDocumentLayout)
inline QAbstractTextDocumentLayoutPrivate()
: paintDevice(0) {}
+ ~QAbstractTextDocumentLayoutPrivate();
inline void setDocument(QTextDocument *doc) {
document = doc;
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 3c98cb568d..adbb3df3bf 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -461,6 +461,7 @@ void ValueExtractor::lengthValues(const Declaration &decl, int *m)
}
QList<QVariant> v;
+ v.reserve(4);
for (i = 0; i < 4; i++) {
v += QVariant::fromValue<LengthData>(datas[i]);
m[i] = lengthValueFromData(datas[i], f);
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 16550c0b3c..bc9da5b564 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -1860,14 +1860,9 @@ void QFont::removeSubstitutions(const QString &familyName)
*/
QStringList QFont::substitutions()
{
- typedef QFontSubst::const_iterator QFontSubstConstIterator;
-
QFontSubst *fontSubst = globalFontSubst();
Q_ASSERT(fontSubst != 0);
- QStringList ret;
- const QFontSubstConstIterator cend = fontSubst->constEnd();
- for (QFontSubstConstIterator it = fontSubst->constBegin(); it != cend; ++it)
- ret.append(it.key());
+ QStringList ret = fontSubst->keys();
ret.sort();
return ret;
@@ -2115,6 +2110,9 @@ QString QFont::lastResortFamily() const
return QString::fromLatin1("helvetica");
}
+extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
+ QFont::StyleHint styleHint, QChar::Script script);
+
/*!
\fn QString QFont::defaultFamily() const
@@ -2125,8 +2123,7 @@ QString QFont::lastResortFamily() const
*/
QString QFont::defaultFamily() const
{
- QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
- const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal
+ const QStringList fallbacks = qt_fallbacksForFamily(QString(), QFont::StyleNormal
, QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
if (!fallbacks.isEmpty())
return fallbacks.first();
@@ -2223,6 +2220,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
}
if (s.version() >= QDataStream::Qt_5_4)
s << (quint8)font.d->request.hintingPreference;
+ if (s.version() >= QDataStream::Qt_5_6)
+ s << (quint8)font.d->capital;
return s;
}
@@ -2313,7 +2312,11 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
s >> value;
font.d->request.hintingPreference = QFont::HintingPreference(value);
}
-
+ if (s.version() >= QDataStream::Qt_5_6) {
+ quint8 value;
+ s >> value;
+ font.d->capital = QFont::Capitalization(value);
+ }
return s;
}
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 85a804acfe..aae84dc988 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -47,6 +47,7 @@
#include <qpa/qplatformfontdatabase.h>
#include <qpa/qplatformtheme.h>
+#include <QtCore/qcache.h>
#include <QtCore/qmath.h>
#include <stdlib.h>
@@ -413,11 +414,45 @@ void QtFontFamily::ensurePopulated()
Q_ASSERT_X(populated, Q_FUNC_INFO, qPrintable(name));
}
+
+struct FallbacksCacheKey {
+ QString family;
+ QFont::Style style;
+ QFont::StyleHint styleHint;
+ QChar::Script script;
+};
+
+inline bool operator==(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
+{
+ return lhs.script == rhs.script &&
+ lhs.styleHint == rhs.styleHint &&
+ lhs.style == rhs.style &&
+ lhs.family == rhs.family;
+}
+
+inline bool operator!=(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
+{
+ return !operator==(lhs, rhs);
+}
+
+inline uint qHash(const FallbacksCacheKey &key, uint seed = 0) Q_DECL_NOTHROW
+{
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, key.family);
+ seed = hash(seed, int(key.style));
+ seed = hash(seed, int(key.styleHint));
+ seed = hash(seed, int(key.script));
+ return seed;
+}
+
+
class QFontDatabasePrivate
{
public:
QFontDatabasePrivate()
- : count(0), families(0), reregisterAppFonts(false)
+ : count(0), families(0),
+ fallbacksCache(64),
+ reregisterAppFonts(false)
{ }
~QFontDatabasePrivate() {
@@ -443,6 +478,7 @@ public:
int count;
QtFontFamily **families;
+ QCache<FallbacksCacheKey, QStringList> fallbacksCache;
struct ApplicationFont {
@@ -461,6 +497,8 @@ public:
void QFontDatabasePrivate::invalidate()
{
QFontCache::instance()->clear();
+
+ fallbacksCache.clear();
free();
QGuiApplicationPrivate::platformIntegration()->fontDatabase()->invalidate();
emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged();
@@ -680,8 +718,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive))
void qt_cleanupFontDatabase()
{
QFontDatabasePrivate *db = privateDb();
- if (db)
+ if (db) {
+ db->fallbacksCache.clear();
db->free();
+ }
}
// used in qfontengine_x11.cpp
@@ -798,11 +838,17 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
return retList;
}
-QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
+static QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
{
+ QFontDatabasePrivate *db = privateDb();
+
+ const FallbacksCacheKey cacheKey = { family, style, styleHint, script };
+
+ if (const QStringList *fallbacks = db->fallbacksCache.object(cacheKey))
+ return *fallbacks;
+
// make sure that the db has all fallback families
QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
- QFontDatabasePrivate *db = privateDb();
QStringList::iterator i;
for (i = retList.begin(); i != retList.end(); ++i) {
@@ -818,9 +864,18 @@ QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFo
--i;
}
}
+
+ db->fallbacksCache.insert(cacheKey, new QStringList(retList));
+
return retList;
}
+QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
+{
+ QMutexLocker locker(fontDatabaseMutex());
+ return fallbacksForFamily(family, style, styleHint, script);
+}
+
static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt);
static void initializeDb()
@@ -935,7 +990,7 @@ QFontEngine *loadEngine(int script, const QFontDef &request,
if (styleHint == QFont::AnyStyle && request.fixedPitch)
styleHint = QFont::TypeWriter;
- fallbacks += qt_fallbacksForFamily(family->name, QFont::Style(style->key.style), styleHint, QChar::Script(script));
+ fallbacks += fallbacksForFamily(family->name, QFont::Style(style->key.style), styleHint, QChar::Script(script));
pfMultiEngine->setFallbackFamiliesList(fallbacks);
}
@@ -1413,22 +1468,30 @@ QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems() const
QT_PREPEND_NAMESPACE(load)();
- QList<WritingSystem> list;
+ quint64 writingSystemsFound = 0;
+ Q_STATIC_ASSERT(WritingSystemsCount < 64);
+
for (int i = 0; i < d->count; ++i) {
QtFontFamily *family = d->families[i];
family->ensurePopulated();
if (family->count == 0)
continue;
- for (int x = Latin; x < WritingSystemsCount; ++x) {
- const WritingSystem writingSystem = WritingSystem(x);
- if (!(family->writingSystems[writingSystem] & QtFontFamily::Supported))
- continue;
- if (!list.contains(writingSystem))
- list.append(writingSystem);
+ for (uint x = Latin; x < uint(WritingSystemsCount); ++x) {
+ if (family->writingSystems[x] & QtFontFamily::Supported)
+ writingSystemsFound |= quint64(1) << x;
}
}
- std::sort(list.begin(), list.end());
+
+ // mutex protection no longer needed - just working on local data now:
+ locker.unlock();
+
+ QList<WritingSystem> list;
+ list.reserve(qPopulationCount(writingSystemsFound));
+ for (uint x = Latin ; x < uint(WritingSystemsCount); ++x) {
+ if (writingSystemsFound & (quint64(1) << x))
+ list.push_back(WritingSystem(x));
+ }
return list;
}
@@ -2607,10 +2670,10 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script)
styleHint = QFont::TypeWriter;
QStringList fallbacks = request.fallBackFamilies
- + qt_fallbacksForFamily(request.family,
- QFont::Style(request.style),
- styleHint,
- QChar::Script(script));
+ + 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 2087bad9f6..f267b2d147 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -54,6 +54,7 @@
#include <private/qharfbuzz_p.h>
#include <algorithm>
+#include <limits.h>
QT_BEGIN_NAMESPACE
@@ -235,10 +236,14 @@ Q_AUTOTEST_EXPORT QList<QFontEngine *> QFontEngine_stopCollectingEngines()
// QFontEngine
+#define kBearingNotInitialized std::numeric_limits<qreal>::max()
+
QFontEngine::QFontEngine(Type type)
: m_type(type), ref(0),
font_(0), font_destroy_func(0),
- face_(0), face_destroy_func(0)
+ face_(0), face_destroy_func(0),
+ m_minLeftBearing(kBearingNotInitialized),
+ m_minRightBearing(kBearingNotInitialized)
{
faceData.user_data = this;
faceData.get_font_table = qt_get_font_table_default;
@@ -365,17 +370,15 @@ bool QFontEngine::supportsScript(QChar::Script script) const
return true;
}
-#ifdef Q_OS_MAC
- {
+#ifdef QT_ENABLE_HARFBUZZ_NG
+ if (qt_useHarfbuzzNG()) {
+#if defined(Q_OS_DARWIN)
// in AAT fonts, 'gsub' table is effectively replaced by 'mort'/'morx' table
uint len;
if (getSfntTableData(MAKE_TAG('m','o','r','t'), 0, &len) || getSfntTableData(MAKE_TAG('m','o','r','x'), 0, &len))
return true;
- }
#endif
-#ifdef QT_ENABLE_HARFBUZZ_NG
- if (qt_useHarfbuzzNG()) {
bool ret = false;
if (hb_face_t *face = hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this))) {
hb_tag_t script_tag_1, script_tag_2;
@@ -562,11 +565,91 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
{
glyph_metrics_t gi = boundingBox(glyph);
- bool isValid = gi.isValid();
if (leftBearing != 0)
- *leftBearing = isValid ? gi.x.toReal() : 0.0;
+ *leftBearing = gi.leftBearing().toReal();
if (rightBearing != 0)
- *rightBearing = isValid ? (gi.xoff - gi.x - gi.width).toReal() : 0.0;
+ *rightBearing = gi.rightBearing().toReal();
+}
+
+qreal QFontEngine::minLeftBearing() const
+{
+ if (m_minLeftBearing == kBearingNotInitialized)
+ minRightBearing(); // Initializes both (see below)
+
+ return m_minLeftBearing;
+}
+
+#define q16Dot16ToFloat(i) ((i) / 65536.0)
+
+#define kMinLeftSideBearingOffset 12
+#define kMinRightSideBearingOffset 14
+
+qreal QFontEngine::minRightBearing() const
+{
+ if (m_minRightBearing == kBearingNotInitialized) {
+
+ // Try the 'hhea' font table first, which covers the entire font
+ QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a'));
+ if (hheaTable.size() >= int(kMinRightSideBearingOffset + sizeof(qint16))) {
+ const uchar *tableData = reinterpret_cast<const uchar *>(hheaTable.constData());
+ Q_ASSERT(q16Dot16ToFloat(qFromBigEndian<quint32>(tableData)) == 1.0);
+
+ qint16 minLeftSideBearing = qFromBigEndian<qint16>(tableData + kMinLeftSideBearingOffset);
+ qint16 minRightSideBearing = qFromBigEndian<qint16>(tableData + kMinRightSideBearingOffset);
+
+ // The table data is expressed as FUnits, meaning we have to take the number
+ // of units per em into account. Since pixelSize already has taken DPI into
+ // account we can use that directly instead of the point size.
+ int unitsPerEm = emSquareSize().toInt();
+ qreal funitToPixelFactor = fontDef.pixelSize / unitsPerEm;
+
+ // Some fonts on OS X (such as Gurmukhi Sangam MN, Khmer MN, Lao Sangam MN, etc.), have
+ // invalid values for their NBSPACE left bearing, causing the 'hhea' minimum bearings to
+ // be way off. We detect this by assuming that the minimum bearsings are within a certain
+ // range of the em square size.
+ static const int largestValidBearing = 4 * unitsPerEm;
+
+ if (qAbs(minLeftSideBearing) < largestValidBearing)
+ m_minLeftBearing = minLeftSideBearing * funitToPixelFactor;
+ if (qAbs(minRightSideBearing) < largestValidBearing)
+ m_minRightBearing = minRightSideBearing * funitToPixelFactor;
+ }
+
+ // Fallback in case of missing 'hhea' table (bitmap fonts e.g.) or broken 'hhea' values
+ if (m_minLeftBearing == kBearingNotInitialized || m_minRightBearing == kBearingNotInitialized) {
+
+ // To balance performance and correctness we only look at a subset of the
+ // possible glyphs in the font, based on which characters are more likely
+ // to have a left or right bearing.
+ static const ushort characterSubset[] = {
+ '(', 'C', 'F', 'K', 'V', 'X', 'Y', ']', '_', 'f', 'r', '|',
+ 127, 205, 645, 884, 922, 1070, 12386
+ };
+
+ // The font may have minimum bearings larger than 0, so we have to start at the max
+ m_minLeftBearing = m_minRightBearing = std::numeric_limits<qreal>::max();
+
+ for (uint i = 0; i < (sizeof(characterSubset) / sizeof(ushort)); ++i) {
+ const glyph_t glyph = glyphIndex(characterSubset[i]);
+ if (!glyph)
+ continue;
+
+ glyph_metrics_t glyphMetrics = const_cast<QFontEngine *>(this)->boundingBox(glyph);
+
+ // Glyphs with no contours shouldn't contribute to bearings
+ if (!glyphMetrics.width || !glyphMetrics.height)
+ continue;
+
+ m_minLeftBearing = qMin(m_minLeftBearing, glyphMetrics.leftBearing().toReal());
+ m_minRightBearing = qMin(m_minRightBearing, glyphMetrics.rightBearing().toReal());
+ }
+ }
+
+ if (m_minLeftBearing == kBearingNotInitialized || m_minRightBearing == kBearingNotInitialized)
+ qWarning() << "Failed to compute left/right minimum bearings for" << fontDef.family;
+ }
+
+ return m_minRightBearing;
}
glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs)
@@ -875,7 +958,8 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph)
pt.x = -glyph_x;
pt.y = -glyph_y; // the baseline
QPainterPath path;
- QImage im(glyph_width + 4, glyph_height, QImage::Format_ARGB32_Premultiplied);
+ path.setFillRule(Qt::WindingFill);
+ QImage im(glyph_width, glyph_height, QImage::Format_ARGB32_Premultiplied);
im.fill(Qt::transparent);
QPainter p(&im);
p.setRenderHint(QPainter::Antialiasing);
@@ -1469,8 +1553,7 @@ QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round)
glyph_t glyph = glyphs.glyphs[glyphs.numGlyphs - 1];
glyph_metrics_t gi = boundingBox(glyph);
if (gi.isValid())
- return round ? QFixed(qRound(gi.xoff - gi.x - gi.width))
- : QFixed(gi.xoff - gi.x - gi.width);
+ return round ? qRound(gi.rightBearing()) : gi.rightBearing();
}
return 0;
}
@@ -1752,7 +1835,10 @@ QFontEngine *QFontEngineMulti::loadEngine(int at)
request.family = fallbackFamilyAt(at - 1);
if (QFontEngine *engine = QFontDatabase::findFont(request, m_script)) {
- engine->fontDef = request;
+ if (request.weight > QFont::Normal)
+ engine->fontDef.weight = request.weight;
+ if (request.style > QFont::StyleNormal)
+ engine->fontDef.style = request.style;
return engine;
}
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 1177305f6e..de5bec6f93 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -99,6 +99,13 @@ static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *leng
static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0};
+static const QFontEngine::HintStyle ftInitialDefaultHintStyle =
+#ifdef Q_OS_WIN
+ QFontEngineFT::HintFull;
+#else
+ QFontEngineFT::HintNone;
+#endif
+
// -------------------------- Freetype support ------------------------------
class QtFreetypeData
@@ -527,69 +534,87 @@ QFontEngineFT::Glyph::~Glyph()
delete [] data;
}
-static const uint subpixel_filter[3][3] = {
- { 180, 60, 16 },
- { 38, 180, 38 },
- { 16, 60, 180 }
+struct LcdFilterDummy
+{
+ static inline void filterPixel(uchar &, uchar &, uchar &)
+ {}
};
-static inline uint filterPixel(uint red, uint green, uint blue, bool legacyFilter)
+struct LcdFilterLegacy
{
- uint res;
- if (legacyFilter) {
- uint high = (red*subpixel_filter[0][0] + green*subpixel_filter[0][1] + blue*subpixel_filter[0][2]) >> 8;
- uint mid = (red*subpixel_filter[1][0] + green*subpixel_filter[1][1] + blue*subpixel_filter[1][2]) >> 8;
- uint low = (red*subpixel_filter[2][0] + green*subpixel_filter[2][1] + blue*subpixel_filter[2][2]) >> 8;
- res = (mid << 24) + (high << 16) + (mid << 8) + low;
- } else {
- uint alpha = green;
- res = (alpha << 24) + (red << 16) + (green << 8) + blue;
+ static inline void filterPixel(uchar &red, uchar &green, uchar &blue)
+ {
+ uint r = red, g = green, b = blue;
+ // intra-pixel filter used by the legacy filter (adopted from _ft_lcd_filter_legacy)
+ red = (r * uint(65538 * 9/13) + g * uint(65538 * 1/6) + b * uint(65538 * 1/13)) / 65536;
+ green = (r * uint(65538 * 3/13) + g * uint(65538 * 4/6) + b * uint(65538 * 3/13)) / 65536;
+ blue = (r * uint(65538 * 1/13) + g * uint(65538 * 1/6) + b * uint(65538 * 9/13)) / 65536;
}
- return res;
-}
+};
-static void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
+template <typename LcdFilter>
+static void convertRGBToARGB_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
{
- int h = height;
const int offs = bgr ? -1 : 1;
const int w = width * 3;
- while (h--) {
+ while (height--) {
uint *dd = dst;
for (int x = 0; x < w; x += 3) {
- uint red = src[x+1-offs];
- uint green = src[x+1];
- uint blue = src[x+1+offs];
- *dd = filterPixel(red, green, blue, legacyFilter);
- ++dd;
+ uchar red = src[x + 1 - offs];
+ uchar green = src[x + 1];
+ uchar blue = src[x + 1 + offs];
+ LcdFilter::filterPixel(red, green, blue);
+ // alpha = green
+ *dd++ = (green << 24) | (red << 16) | (green << 8) | blue;
}
dst += width;
src += src_pitch;
}
}
-static void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
+static inline void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
+{
+ if (!legacyFilter)
+ convertRGBToARGB_helper<LcdFilterDummy>(src, dst, width, height, src_pitch, bgr);
+ else
+ convertRGBToARGB_helper<LcdFilterLegacy>(src, dst, width, height, src_pitch, bgr);
+}
+
+template <typename LcdFilter>
+static void convertRGBToARGB_V_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
{
- int h = height;
const int offs = bgr ? -src_pitch : src_pitch;
- while (h--) {
+ while (height--) {
for (int x = 0; x < width; x++) {
- uint red = src[x+src_pitch-offs];
- uint green = src[x+src_pitch];
- uint blue = src[x+src_pitch+offs];
- dst[x] = filterPixel(red, green, blue, legacyFilter);
+ uchar red = src[x + src_pitch - offs];
+ uchar green = src[x + src_pitch];
+ uchar blue = src[x + src_pitch + offs];
+ LcdFilter::filterPixel(red, green, blue);
+ // alpha = green
+ *dst++ = (green << 24) | (red << 16) | (green << 8) | blue;
}
- dst += width;
src += 3*src_pitch;
}
}
-static void convertGRAYToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch) {
- for (int y = 0; y < height; ++y) {
- int readpos = (y * src_pitch);
- int writepos = (y * width);
- for (int x = 0; x < width; ++x) {
- dst[writepos + x] = (0xFF << 24) + (src[readpos + x] << 16) + (src[readpos + x] << 8) + src[readpos + x];
+static inline void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
+{
+ if (!legacyFilter)
+ convertRGBToARGB_V_helper<LcdFilterDummy>(src, dst, width, height, src_pitch, bgr);
+ else
+ convertRGBToARGB_V_helper<LcdFilterLegacy>(src, dst, width, height, src_pitch, bgr);
+}
+
+static inline void convertGRAYToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch)
+{
+ while (height--) {
+ const uchar *p = src;
+ const uchar * const e = p + width;
+ while (p < e) {
+ uchar gray = *p++;
+ *dst++ = (0xFF << 24) | (gray << 16) | (gray << 8) | gray;
}
+ src += src_pitch;
}
}
@@ -629,11 +654,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
antialias = true;
freetype = 0;
default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
-#ifndef Q_OS_WIN
- default_hint_style = HintNone;
-#else
- default_hint_style = HintFull;
-#endif
+ default_hint_style = ftInitialDefaultHintStyle;
subpixelType = Subpixel_None;
lcdFilterType = 0;
#if defined(FT_LCD_FILTER_H)
@@ -685,7 +706,6 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive));
}
- lbearing = rbearing = SHRT_MIN;
freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing);
FT_Face face = lockFace();
@@ -697,8 +717,12 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
FT_Set_Transform(face, &matrix, 0);
freetype->matrix = matrix;
// fake bold
- if ((fontDef.weight >= QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face))
- embolden = true;
+ if ((fontDef.weight >= QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face)) {
+ if (const TT_OS2 *os2 = reinterpret_cast<const TT_OS2 *>(FT_Get_Sfnt_Table(face, ft_sfnt_os2))) {
+ if (os2->usWeightClass < 750)
+ embolden = true;
+ }
+ }
// underline metrics
line_thickness = QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale));
underline_position = QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale));
@@ -760,6 +784,24 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
return true;
}
+void QFontEngineFT::setQtDefaultHintStyle(QFont::HintingPreference hintingPreference)
+{
+ switch (hintingPreference) {
+ case QFont::PreferNoHinting:
+ setDefaultHintStyle(HintNone);
+ break;
+ case QFont::PreferFullHinting:
+ setDefaultHintStyle(HintFull);
+ break;
+ case QFont::PreferVerticalHinting:
+ setDefaultHintStyle(HintLight);
+ break;
+ case QFont::PreferDefaultHinting:
+ setDefaultHintStyle(ftInitialDefaultHintStyle);
+ break;
+ }
+}
+
void QFontEngineFT::setDefaultHintStyle(HintStyle style)
{
default_hint_style = style;
@@ -1213,7 +1255,7 @@ QFixed QFontEngineFT::xHeight() const
TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
if (os2 && os2->sxHeight) {
lockFace();
- QFixed answer = QFixed(os2->sxHeight*freetype->face->size->metrics.y_ppem)/freetype->face->units_per_EM;
+ QFixed answer = QFixed(os2->sxHeight * freetype->face->size->metrics.y_ppem) / emSquareSize();
unlockFace();
return answer;
}
@@ -1225,7 +1267,7 @@ QFixed QFontEngineFT::averageCharWidth() const
TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
if (os2 && os2->xAvgCharWidth) {
lockFace();
- QFixed answer = QFixed(os2->xAvgCharWidth*freetype->face->size->metrics.x_ppem)/freetype->face->units_per_EM;
+ QFixed answer = QFixed(os2->xAvgCharWidth * freetype->face->size->metrics.x_ppem) / emSquareSize();
unlockFace();
return answer;
}
@@ -1237,54 +1279,6 @@ qreal QFontEngineFT::maxCharWidth() const
return metrics.max_advance >> 6;
}
-static const ushort char_table[] = {
- 40,
- 67,
- 70,
- 75,
- 86,
- 88,
- 89,
- 91,
- 95,
- 102,
- 114,
- 124,
- 127,
- 205,
- 645,
- 884,
- 922,
- 1070,
- 12386
-};
-
-static const int char_table_entries = sizeof(char_table)/sizeof(ushort);
-
-
-qreal QFontEngineFT::minLeftBearing() const
-{
- if (lbearing == SHRT_MIN)
- (void) minRightBearing(); // calculates both
- return lbearing.toReal();
-}
-
-qreal QFontEngineFT::minRightBearing() const
-{
- if (rbearing == SHRT_MIN) {
- lbearing = rbearing = 0;
- for (int i = 0; i < char_table_entries; ++i) {
- const glyph_t glyph = glyphIndex(char_table[i]);
- if (glyph != 0) {
- glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyph);
- lbearing = qMin(lbearing, gi.x);
- rbearing = qMin(rbearing, (gi.xoff - gi.x - gi.width));
- }
- }
- }
- return rbearing.toReal();
-}
-
QFixed QFontEngineFT::lineThickness() const
{
return line_thickness;
@@ -1301,7 +1295,7 @@ void QFontEngineFT::doKerning(QGlyphLayout *g, QFontEngine::ShaperFlags flags) c
kerning_pairs_loaded = true;
lockFace();
if (freetype->face->size->metrics.x_ppem != 0) {
- QFixed scalingFactor(freetype->face->units_per_EM/freetype->face->size->metrics.x_ppem);
+ QFixed scalingFactor = emSquareSize() / QFixed(freetype->face->size->metrics.x_ppem);
unlockFace();
const_cast<QFontEngineFT *>(this)->loadKerningPairs(scalingFactor);
} else {
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 7b28a4064f..6f05645a3f 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -189,67 +189,65 @@ private:
mutable int fast_glyph_count;
};
- virtual QFontEngine::FaceId faceId() const Q_DECL_OVERRIDE;
- virtual QFontEngine::Properties properties() const Q_DECL_OVERRIDE;
- virtual QFixed emSquareSize() const Q_DECL_OVERRIDE;
- virtual bool supportsSubPixelPositions() const Q_DECL_OVERRIDE
+ QFontEngine::FaceId faceId() const Q_DECL_OVERRIDE;
+ QFontEngine::Properties properties() const Q_DECL_OVERRIDE;
+ QFixed emSquareSize() const Q_DECL_OVERRIDE;
+ bool supportsSubPixelPositions() const Q_DECL_OVERRIDE
{
return default_hint_style == HintLight ||
default_hint_style == HintNone;
}
- virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const Q_DECL_OVERRIDE;
- virtual int synthesized() const Q_DECL_OVERRIDE;
+ bool getSfntTableData(uint tag, uchar *buffer, uint *length) const Q_DECL_OVERRIDE;
+ int synthesized() const Q_DECL_OVERRIDE;
- virtual QFixed ascent() const Q_DECL_OVERRIDE;
- virtual QFixed descent() const Q_DECL_OVERRIDE;
- virtual QFixed leading() const Q_DECL_OVERRIDE;
- virtual QFixed xHeight() const Q_DECL_OVERRIDE;
- virtual QFixed averageCharWidth() const Q_DECL_OVERRIDE;
+ QFixed ascent() const Q_DECL_OVERRIDE;
+ QFixed descent() const Q_DECL_OVERRIDE;
+ QFixed leading() const Q_DECL_OVERRIDE;
+ QFixed xHeight() const Q_DECL_OVERRIDE;
+ QFixed averageCharWidth() const Q_DECL_OVERRIDE;
- virtual qreal maxCharWidth() const Q_DECL_OVERRIDE;
- virtual qreal minLeftBearing() const Q_DECL_OVERRIDE;
- virtual qreal minRightBearing() const Q_DECL_OVERRIDE;
- virtual QFixed lineThickness() const Q_DECL_OVERRIDE;
- virtual QFixed underlinePosition() const Q_DECL_OVERRIDE;
+ qreal maxCharWidth() const Q_DECL_OVERRIDE;
+ QFixed lineThickness() const Q_DECL_OVERRIDE;
+ QFixed underlinePosition() const Q_DECL_OVERRIDE;
- virtual glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE;
+ glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE;
void doKerning(QGlyphLayout *, ShaperFlags) const Q_DECL_OVERRIDE;
- virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) Q_DECL_OVERRIDE;
+ void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) Q_DECL_OVERRIDE;
- virtual bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE;
+ bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE;
- virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
- QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
- virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
- QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
+ void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
+ QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
+ void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
+ QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
- virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const Q_DECL_OVERRIDE;
+ bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const Q_DECL_OVERRIDE;
- virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE;
- virtual glyph_metrics_t boundingBox(glyph_t glyph) Q_DECL_OVERRIDE;
- virtual glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix) Q_DECL_OVERRIDE;
+ glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE;
+ glyph_metrics_t boundingBox(glyph_t glyph) Q_DECL_OVERRIDE;
+ glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix) Q_DECL_OVERRIDE;
- virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const Q_DECL_OVERRIDE;
- virtual QImage alphaMapForGlyph(glyph_t g) Q_DECL_OVERRIDE { return alphaMapForGlyph(g, 0); }
- virtual QImage alphaMapForGlyph(glyph_t, QFixed) Q_DECL_OVERRIDE;
+ void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const Q_DECL_OVERRIDE;
+ QImage alphaMapForGlyph(glyph_t g) Q_DECL_OVERRIDE { return alphaMapForGlyph(g, 0); }
+ QImage alphaMapForGlyph(glyph_t, QFixed) Q_DECL_OVERRIDE;
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
- virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
- virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
- QFixed subPixelPosition,
- const QTransform &matrix,
- QFontEngine::GlyphFormat format) Q_DECL_OVERRIDE;
- virtual QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
- GlyphFormat neededFormat, const QTransform &t,
- QPoint *offset) Q_DECL_OVERRIDE;
- virtual bool hasInternalCaching() const Q_DECL_OVERRIDE { return cacheEnabled; }
- virtual void unlockAlphaMapForGlyph() Q_DECL_OVERRIDE;
-
- virtual void removeGlyphFromCache(glyph_t glyph) Q_DECL_OVERRIDE;
- virtual int glyphMargin(QFontEngine::GlyphFormat /* format */) Q_DECL_OVERRIDE { return 0; }
-
- virtual int glyphCount() const Q_DECL_OVERRIDE;
+ QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
+ glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
+ QFixed subPixelPosition,
+ const QTransform &matrix,
+ QFontEngine::GlyphFormat format) Q_DECL_OVERRIDE;
+ QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
+ GlyphFormat neededFormat, const QTransform &t,
+ QPoint *offset) Q_DECL_OVERRIDE;
+ bool hasInternalCaching() const Q_DECL_OVERRIDE { return cacheEnabled; }
+ void unlockAlphaMapForGlyph() Q_DECL_OVERRIDE;
+
+ void removeGlyphFromCache(glyph_t glyph) Q_DECL_OVERRIDE;
+ int glyphMargin(QFontEngine::GlyphFormat /* format */) Q_DECL_OVERRIDE { return 0; }
+
+ int glyphCount() const Q_DECL_OVERRIDE;
enum Scaling {
Scaled,
@@ -279,12 +277,12 @@ private:
bool init(FaceId faceId, bool antialias, GlyphFormat format,
QFreetypeFace *freetypeFace);
- virtual int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) Q_DECL_OVERRIDE;
+ int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) Q_DECL_OVERRIDE;
+ void setQtDefaultHintStyle(QFont::HintingPreference hintingPreference);
+ void setDefaultHintStyle(HintStyle style) Q_DECL_OVERRIDE;
- virtual void setDefaultHintStyle(HintStyle style) Q_DECL_OVERRIDE;
-
- virtual QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE;
+ QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE;
bool initFromFontEngine(const QFontEngineFT *fontEngine);
HintStyle defaultHintStyle() const { return default_hint_style; }
@@ -307,6 +305,7 @@ private:
friend class QFontEngineFTRawFont;
friend class QFontconfigDatabase;
friend class QBasicFontDatabase;
+ friend class QCoreTextFontDatabase;
friend class QFontEngineMultiFontConfig;
int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
@@ -323,8 +322,6 @@ private:
int xsize;
int ysize;
- mutable QFixed lbearing;
- mutable QFixed rbearing;
QFixed line_thickness;
QFixed underline_position;
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 6f4fabe1f6..be9eaa5020 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -49,6 +49,7 @@
#include "QtCore/qatomic.h"
#include <QtCore/qvarlengtharray.h>
#include <QtCore/QLinkedList>
+#include <QtCore/qhashfunctions.h>
#include "private/qtextengine_p.h"
#include "private/qfont_p.h"
@@ -213,8 +214,8 @@ public:
virtual QFixed underlinePosition() const;
virtual qreal maxCharWidth() const = 0;
- virtual qreal minLeftBearing() const { return qreal(); }
- virtual qreal minRightBearing() const { return qreal(); }
+ virtual qreal minLeftBearing() const;
+ virtual qreal minRightBearing() const;
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
@@ -322,18 +323,28 @@ private:
private:
QVariant m_userData;
+
+ mutable qreal m_minLeftBearing;
+ mutable qreal m_minRightBearing;
+
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFontEngine::ShaperFlags)
inline bool operator ==(const QFontEngine::FaceId &f1, const QFontEngine::FaceId &f2)
{
- return (f1.index == f2.index) && (f1.encoding == f2.encoding) && (f1.filename == f2.filename);
+ return f1.index == f2.index && f1.encoding == f2.encoding && f1.filename == f2.filename && f1.uuid == f2.uuid;
}
-inline uint qHash(const QFontEngine::FaceId &f)
+inline uint qHash(const QFontEngine::FaceId &f, uint seed = 0)
+ Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(f.filename)))
{
- return qHash((f.index << 16) + f.encoding) + qHash(f.filename + f.uuid);
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, f.filename);
+ seed = hash(seed, f.uuid);
+ seed = hash(seed, f.index);
+ seed = hash(seed, f.encoding);
+ return seed;
}
diff --git a/src/gui/text/qfontengineglyphcache.cpp b/src/gui/text/qfontengineglyphcache.cpp
new file mode 100644
index 0000000000..f6fdfa3ce3
--- /dev/null
+++ b/src/gui/text/qfontengineglyphcache.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qfontengineglyphcache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// out-of-line to avoid vtable duplication, breaking e.g. RTTI
+QFontEngineGlyphCache::~QFontEngineGlyphCache()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h
index 6cf4d2f1ba..def42c22a3 100644
--- a/src/gui/text/qfontengineglyphcache_p.h
+++ b/src/gui/text/qfontengineglyphcache_p.h
@@ -56,7 +56,7 @@
QT_BEGIN_NAMESPACE
-class QFontEngineGlyphCache: public QSharedData
+class Q_GUI_EXPORT QFontEngineGlyphCache: public QSharedData
{
public:
QFontEngineGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) : m_format(format), m_transform(matrix)
@@ -64,7 +64,7 @@ public:
Q_ASSERT(m_format != QFontEngine::Format_None);
}
- virtual ~QFontEngineGlyphCache() { }
+ virtual ~QFontEngineGlyphCache();
QFontEngine::GlyphFormat glyphFormat() const { return m_format; }
const QTransform &transform() const { return m_transform; }
diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h
index 2031f022d4..4c2c6317ba 100644
--- a/src/gui/text/qfontmetrics.h
+++ b/src/gui/text/qfontmetrics.h
@@ -93,11 +93,11 @@ public:
QRect boundingRect(QChar) const;
QRect boundingRect(const QString &text) const;
- QRect boundingRect(const QRect &r, int flags, const QString &text, int tabstops=0, int *tabarray=0) const;
+ QRect boundingRect(const QRect &r, int flags, const QString &text, int tabstops = 0, int *tabarray = Q_NULLPTR) const;
inline QRect boundingRect(int x, int y, int w, int h, int flags, const QString &text,
- int tabstops=0, int *tabarray=0) const
+ int tabstops = 0, int *tabarray = Q_NULLPTR) const
{ return boundingRect(QRect(x, y, w, h), flags, text, tabstops, tabarray); }
- QSize size(int flags, const QString& str, int tabstops=0, int *tabarray=0) const;
+ QSize size(int flags, const QString& str, int tabstops = 0, int *tabarray = Q_NULLPTR) const;
QRect tightBoundingRect(const QString &text) const;
@@ -161,8 +161,8 @@ public:
QRectF boundingRect(const QString &string) const;
QRectF boundingRect(QChar) const;
- QRectF boundingRect(const QRectF &r, int flags, const QString& string, int tabstops=0, int *tabarray=0) const;
- QSizeF size(int flags, const QString& str, int tabstops=0, int *tabarray=0) const;
+ QRectF boundingRect(const QRectF &r, int flags, const QString& string, int tabstops = 0, int *tabarray = Q_NULLPTR) const;
+ QSizeF size(int flags, const QString& str, int tabstops = 0, int *tabarray = Q_NULLPTR) const;
QRectF tightBoundingRect(const QString &text) const;
diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp
index 9f652084be..dc32405f36 100644
--- a/src/gui/text/qfontsubset.cpp
+++ b/src/gui/text/qfontsubset.cpp
@@ -350,6 +350,7 @@ struct qttf_head_table {
quint16 macStyle;
qint16 indexToLocFormat;
};
+Q_DECLARE_TYPEINFO(qttf_head_table, Q_PRIMITIVE_TYPE);
struct qttf_hhea_table {
@@ -362,6 +363,7 @@ struct qttf_hhea_table {
qint16 xMaxExtent;
quint16 numberOfHMetrics;
};
+Q_DECLARE_TYPEINFO(qttf_hhea_table, Q_PRIMITIVE_TYPE);
struct qttf_maxp_table {
@@ -373,6 +375,7 @@ struct qttf_maxp_table {
quint16 maxComponentElements;
quint16 maxComponentDepth;
};
+Q_DECLARE_TYPEINFO(qttf_maxp_table, Q_PRIMITIVE_TYPE);
struct qttf_name_table {
QString copyright;
@@ -380,6 +383,7 @@ struct qttf_name_table {
QString subfamily;
QString postscript_name;
};
+Q_DECLARE_TYPEINFO(qttf_name_table, Q_MOVABLE_TYPE);
static QTtfTable generateHead(const qttf_head_table &head);
@@ -411,9 +415,9 @@ Q_DECLARE_TYPEINFO(QTtfGlyph, Q_MOVABLE_TYPE);
static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem);
// generates glyf, loca and hmtx
-static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs);
+static QVector<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QVector<QTtfGlyph> &_glyphs);
-static QByteArray bindFont(const QList<QTtfTable>& _tables);
+static QByteArray bindFont(const QVector<QTtfTable>& _tables);
static quint32 checksum(const QByteArray &table)
@@ -607,12 +611,13 @@ struct QTtfNameRecord {
quint16 nameId;
QString value;
};
+Q_DECLARE_TYPEINFO(QTtfNameRecord, Q_MOVABLE_TYPE);
-static QTtfTable generateName(const QList<QTtfNameRecord> &name);
+static QTtfTable generateName(const QVector<QTtfNameRecord> &name);
static QTtfTable generateName(const qttf_name_table &name)
{
- QList<QTtfNameRecord> list;
+ QVector<QTtfNameRecord> list;
QTtfNameRecord rec;
rec.nameId = 0;
rec.value = name.copyright;
@@ -636,7 +641,7 @@ static QTtfTable generateName(const qttf_name_table &name)
}
// ####### should probably generate Macintosh/Roman name entries as well
-static QTtfTable generateName(const QList<QTtfNameRecord> &name)
+static QTtfTable generateName(const QVector<QTtfNameRecord> &name)
{
const int char_size = 2;
@@ -707,7 +712,7 @@ struct TTF_POINT {
};
Q_DECLARE_TYPEINFO(TTF_POINT, Q_PRIMITIVE_TYPE);
-static void convertPath(const QPainterPath &path, QList<TTF_POINT> *points, QList<int> *endPoints, qreal ppem)
+static void convertPath(const QPainterPath &path, QVector<TTF_POINT> *points, QVector<int> *endPoints, qreal ppem)
{
int numElements = path.elementCount();
for (int i = 0; i < numElements - 1; ++i) {
@@ -829,7 +834,7 @@ static void convertPath(const QPainterPath &path, QList<TTF_POINT> *points, QLis
endPoints->append(points->size() - 1);
}
-static void getBounds(const QList<TTF_POINT> &points, qint16 *xmin, qint16 *xmax, qint16 *ymin, qint16 *ymax)
+static void getBounds(const QVector<TTF_POINT> &points, qint16 *xmin, qint16 *xmax, qint16 *ymin, qint16 *ymax)
{
*xmin = points.at(0).x;
*xmax = *xmin;
@@ -844,7 +849,7 @@ static void getBounds(const QList<TTF_POINT> &points, qint16 *xmin, qint16 *xmax
}
}
-static int convertToRelative(QList<TTF_POINT> *points)
+static int convertToRelative(QVector<TTF_POINT> *points)
{
// convert points to relative and setup flags
// qDebug() << "relative points:";
@@ -897,7 +902,7 @@ static int convertToRelative(QList<TTF_POINT> *points)
return point_array_size;
}
-static void getGlyphData(QTtfGlyph *glyph, const QList<TTF_POINT> &points, const QList<int> &endPoints, int point_array_size)
+static void getGlyphData(QTtfGlyph *glyph, const QVector<TTF_POINT> &points, const QVector<int> &endPoints, int point_array_size)
{
const int max_size = 5*sizeof(qint16) // header
+ endPoints.size()*sizeof(quint16) // end points of contours
@@ -947,8 +952,8 @@ static void getGlyphData(QTtfGlyph *glyph, const QList<TTF_POINT> &points, const
static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem)
{
- QList<TTF_POINT> points;
- QList<int> endPoints;
+ QVector<TTF_POINT> points;
+ QVector<int> endPoints;
QTtfGlyph glyph;
glyph.index = index;
glyph.advanceWidth = qRound(advance * 2048. / ppem);
@@ -983,10 +988,10 @@ static bool operator <(const QTtfGlyph &g1, const QTtfGlyph &g2)
return g1.index < g2.index;
}
-static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs)
+static QVector<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QVector<QTtfGlyph> &_glyphs)
{
const int max_size_small = 65536*2;
- QList<QTtfGlyph> glyphs = _glyphs;
+ QVector<QTtfGlyph> glyphs = _glyphs;
std::sort(glyphs.begin(), glyphs.end());
Q_ASSERT(tables.maxp.numGlyphs == glyphs.at(glyphs.size()-1).index + 1);
@@ -1049,7 +1054,7 @@ static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QLis
Q_ASSERT(loca.data.size() == ls.offset());
Q_ASSERT(hmtx.data.size() == hs.offset());
- QList<QTtfTable> list;
+ QVector<QTtfTable> list;
list.append(glyf);
list.append(loca);
list.append(hmtx);
@@ -1061,9 +1066,9 @@ static bool operator <(const QTtfTable &t1, const QTtfTable &t2)
return t1.tag < t2.tag;
}
-static QByteArray bindFont(const QList<QTtfTable>& _tables)
+static QByteArray bindFont(const QVector<QTtfTable>& _tables)
{
- QList<QTtfTable> tables = _tables;
+ QVector<QTtfTable> tables = _tables;
std::sort(tables.begin(), tables.end());
@@ -1154,7 +1159,7 @@ QByteArray QFontSubset::toTruetype() const
qreal ppem = fontEngine->fontDef.pixelSize;
#define TO_TTF(x) qRound(x * 2048. / ppem)
- QList<QTtfGlyph> glyphs;
+ QVector<QTtfGlyph> glyphs;
QFontEngine::Properties properties = fontEngine->properties();
// initialize some stuff needed in createWidthArray
@@ -1225,7 +1230,7 @@ QByteArray QFontSubset::toTruetype() const
}
- QList<QTtfTable> tables = generateGlyphTables(font, glyphs);
+ QVector<QTtfTable> tables = generateGlyphTables(font, glyphs);
tables.append(generateHead(font.head));
tables.append(generateHhea(font.hhea));
tables.append(generateMaxp(font.maxp));
diff --git a/src/gui/text/qfontsubset_p.h b/src/gui/text/qfontsubset_p.h
index da8589de3f..4abdb48c0d 100644
--- a/src/gui/text/qfontsubset_p.h
+++ b/src/gui/text/qfontsubset_p.h
@@ -79,7 +79,7 @@ public:
const int object_id;
bool noEmbed;
QFontEngine *fontEngine;
- QList<int> glyph_indices;
+ QVector<int> glyph_indices;
mutable int downloaded_glyphs;
mutable bool standard_font;
int nGlyphs() const { return glyph_indices.size(); }
diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp
index e6d6863134..642313d340 100644
--- a/src/gui/text/qglyphrun.cpp
+++ b/src/gui/text/qglyphrun.cpp
@@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE
\ingroup text
\ingroup shared
- \mainclass
When Qt displays a string of text encoded in Unicode, it will first convert the Unicode points
into a list of glyph indexes and a list of positions based on one or more fonts. The Unicode
diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h
index d3034b7546..9f51a49a6d 100644
--- a/src/gui/text/qglyphrun.h
+++ b/src/gui/text/qglyphrun.h
@@ -59,9 +59,13 @@ public:
QGlyphRun();
QGlyphRun(const QGlyphRun &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ QGlyphRun &operator=(QGlyphRun &&other) Q_DECL_NOTHROW { swap(other); return *this; }
+#endif
+ QGlyphRun &operator=(const QGlyphRun &other);
~QGlyphRun();
- void swap(QGlyphRun &other) { qSwap(d, other.d); }
+ void swap(QGlyphRun &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
QRawFont rawFont() const;
void setRawFont(const QRawFont &rawFont);
@@ -78,8 +82,6 @@ public:
void clear();
- QGlyphRun &operator=(const QGlyphRun &other);
-
bool operator==(const QGlyphRun &other) const;
inline bool operator!=(const QGlyphRun &other) const
{ return !operator==(other); }
diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp
index 102c62ea8a..b2edfc00a0 100644
--- a/src/gui/text/qharfbuzzng.cpp
+++ b/src/gui/text/qharfbuzzng.cpp
@@ -188,7 +188,15 @@ static const hb_script_t _qtscript_to_hbscript[] = {
HB_SCRIPT_SIDDHAM,
HB_SCRIPT_KHUDAWADI,
HB_SCRIPT_TIRHUTA,
- HB_SCRIPT_WARANG_CITI
+ HB_SCRIPT_WARANG_CITI,
+
+ // Unicode 8.0 additions
+ HB_SCRIPT_AHOM,
+ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS,
+ HB_SCRIPT_HATRAN,
+ HB_SCRIPT_MULTANI,
+ HB_SCRIPT_OLD_HUNGARIAN,
+ HB_SCRIPT_SIGNWRITING
};
Q_STATIC_ASSERT(QChar::ScriptCount == sizeof(_qtscript_to_hbscript) / sizeof(_qtscript_to_hbscript[0]));
diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp
index 8764c8cebf..0695c2eff4 100644
--- a/src/gui/text/qplatformfontdatabase.cpp
+++ b/src/gui/text/qplatformfontdatabase.cpp
@@ -40,6 +40,9 @@
#include <QtCore/QLibraryInfo>
#include <QtCore/QDir>
+#include <algorithm>
+#include <iterator>
+
QT_BEGIN_NAMESPACE
void qt_registerFont(const QString &familyname, const QString &stylename,
@@ -450,11 +453,11 @@ bool QPlatformFontDatabase::fontsAlwaysScalable() const
QList<int> QPlatformFontDatabase::standardSizes() const
{
QList<int> ret;
- static const unsigned short standard[] =
- { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 };
- ret.reserve(int(sizeof(standard) / sizeof(standard[0])));
- const unsigned short *sizes = standard;
- while (*sizes) ret << *sizes++;
+ static const quint8 standard[] =
+ { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 };
+ static const int num_standards = int(sizeof standard / sizeof *standard);
+ ret.reserve(num_standards);
+ std::copy(standard, standard + num_standards, std::back_inserter(ret));
return ret;
}
@@ -471,7 +474,7 @@ QFontEngine::SubpixelAntialiasingType QPlatformFontDatabase::subpixelAntialiasin
// ### copied to tools/makeqpf/qpf2.cpp
// see the Unicode subset bitfields in the MSDN docs
-static const ushort requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
+static const quint8 requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
{ 127, 127 }, // Any
{ 0, 127 }, // Latin
{ 7, 127 }, // Greek
diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h
index 0615df65d6..3331d96f8b 100644
--- a/src/gui/text/qplatformfontdatabase.h
+++ b/src/gui/text/qplatformfontdatabase.h
@@ -47,7 +47,9 @@
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QList>
+#if QT_DEPRECATED_SINCE(5, 5)
#include <QtCore/QHash>
+#endif
#include <QtGui/QFontDatabase>
#include <QtGui/private/qfontengine_p.h>
#include <QtGui/private/qfont_p.h>
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index fedf58872b..0fd5f510c7 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE
\ingroup text
\ingroup shared
- \mainclass
\note QRawFont is a low level class. For most purposes QFont is a more appropriate class.
diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h
index 3798555de5..d710658a9b 100644
--- a/src/gui/text/qrawfont.h
+++ b/src/gui/text/qrawfont.h
@@ -72,13 +72,15 @@ public:
qreal pixelSize,
QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
QRawFont(const QRawFont &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ QRawFont &operator=(QRawFont &&other) Q_DECL_NOTHROW { swap(other); return *this; }
+#endif
+ QRawFont &operator=(const QRawFont &other);
~QRawFont();
- bool isValid() const;
+ void swap(QRawFont &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
- QRawFont &operator=(const QRawFont &other);
-
- void swap(QRawFont &other) { qSwap(d, other.d); }
+ bool isValid() const;
bool operator==(const QRawFont &other) const;
inline bool operator!=(const QRawFont &other) const
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
index fc95a859e7..74f4b10305 100644
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -39,6 +39,10 @@
QT_BEGIN_NAMESPACE
+QStaticTextUserData::~QStaticTextUserData()
+{
+}
+
/*!
\class QStaticText
\brief The QStaticText class enables optimized drawing of text when the text and its layout
@@ -49,7 +53,6 @@ QT_BEGIN_NAMESPACE
\ingroup multimedia
\ingroup text
\ingroup shared
- \mainclass
QStaticText provides a way to cache layout data for a block of text so that it can be drawn
more efficiently than by using QPainter::drawText() in which the layout information is
@@ -555,6 +558,9 @@ namespace {
case PdmDevicePixelRatio:
val = 1;
break;
+ case PdmDevicePixelRatioScaled:
+ val = devicePixelRatioFScale();
+ break;
default:
val = 0;
qWarning("DrawTextItemDevice::metric: Invalid metric command");
diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h
index d2825e73ac..0a1d9429b4 100644
--- a/src/gui/text/qstatictext.h
+++ b/src/gui/text/qstatictext.h
@@ -57,9 +57,13 @@ public:
QStaticText();
QStaticText(const QString &text);
QStaticText(const QStaticText &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ QStaticText &operator=(QStaticText &&other) Q_DECL_NOTHROW { swap(other); return *this; }
+#endif
+ QStaticText &operator=(const QStaticText &);
~QStaticText();
- void swap(QStaticText &other) { qSwap(data, other.data); }
+ void swap(QStaticText &other) Q_DECL_NOTHROW { qSwap(data, other.data); }
void setText(const QString &text);
QString text() const;
@@ -80,7 +84,6 @@ public:
void setPerformanceHint(PerformanceHint performanceHint);
PerformanceHint performanceHint() const;
- QStaticText &operator=(const QStaticText &);
bool operator==(const QStaticText &) const;
bool operator!=(const QStaticText &) const;
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
index 088e49e2fc..49ca24d51c 100644
--- a/src/gui/text/qstatictext_p.h
+++ b/src/gui/text/qstatictext_p.h
@@ -52,7 +52,8 @@
QT_BEGIN_NAMESPACE
-class QStaticTextUserData
+// ### Qt 6: Unexport again, if QOpenGLStaticTextUserData (the one from QtOpenGL) is gone by then
+class Q_GUI_EXPORT QStaticTextUserData
{
public:
enum Type {
@@ -61,7 +62,7 @@ public:
};
QStaticTextUserData(Type t) : ref(0), type(t) {}
- virtual ~QStaticTextUserData() {}
+ virtual ~QStaticTextUserData();
QAtomicInt ref;
Type type;
diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp
index 162c646a98..f180a839b7 100644
--- a/src/gui/text/qsyntaxhighlighter.cpp
+++ b/src/gui/text/qsyntaxhighlighter.cpp
@@ -90,13 +90,13 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
QTextLayout *layout = currentBlock.layout();
- QList<QTextLayout::FormatRange> ranges = layout->additionalFormats();
+ QVector<QTextLayout::FormatRange> ranges = layout->formats();
const int preeditAreaStart = layout->preeditAreaPosition();
const int preeditAreaLength = layout->preeditAreaText().length();
if (preeditAreaLength != 0) {
- QList<QTextLayout::FormatRange>::Iterator it = ranges.begin();
+ QVector<QTextLayout::FormatRange>::Iterator it = ranges.begin();
while (it != ranges.end()) {
if (it->start >= preeditAreaStart
&& it->start + it->length <= preeditAreaStart + preeditAreaLength) {
@@ -142,7 +142,7 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
}
if (formatsChanged) {
- layout->setAdditionalFormats(ranges);
+ layout->setFormats(ranges);
doc->markContentsDirty(currentBlock.position(), currentBlock.length());
}
}
@@ -329,7 +329,7 @@ void QSyntaxHighlighter::setDocument(QTextDocument *doc)
QTextCursor cursor(d->doc);
cursor.beginEditBlock();
for (QTextBlock blk = d->doc->begin(); blk.isValid(); blk = blk.next())
- blk.layout()->clearAdditionalFormats();
+ blk.layout()->clearFormats();
cursor.endEditBlock();
}
d->doc = doc;
diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h
index f04055603c..d42d7a1a70 100644
--- a/src/gui/text/qtextcursor.h
+++ b/src/gui/text/qtextcursor.h
@@ -62,14 +62,17 @@ public:
QTextCursor();
explicit QTextCursor(QTextDocument *document);
QTextCursor(QTextDocumentPrivate *p, int pos);
+ explicit QTextCursor(QTextCursorPrivate *d);
explicit QTextCursor(QTextFrame *frame);
explicit QTextCursor(const QTextBlock &block);
- explicit QTextCursor(QTextCursorPrivate *d);
QTextCursor(const QTextCursor &cursor);
+#ifdef Q_COMPILER_RVALUE_REFS
+ QTextCursor &operator=(QTextCursor &&other) Q_DECL_NOTHROW { swap(other); return *this; }
+#endif
QTextCursor &operator=(const QTextCursor &other);
~QTextCursor();
- void swap(QTextCursor &other) { qSwap(d, other.d); }
+ void swap(QTextCursor &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
bool isNull() const;
@@ -220,6 +223,7 @@ public:
private:
QSharedDataPointer<QTextCursorPrivate> d;
friend class QTextCursorPrivate;
+ friend class QTextDocumentPrivate;
friend class QTextDocumentFragmentPrivate;
friend class QTextCopyHelper;
friend class QWidgetTextControlPrivate;
diff --git a/src/gui/text/qtextcursor_p.h b/src/gui/text/qtextcursor_p.h
index 51fb92d37c..d3cb52d94f 100644
--- a/src/gui/text/qtextcursor_p.h
+++ b/src/gui/text/qtextcursor_p.h
@@ -100,6 +100,9 @@ public:
void aboutToRemoveCell(int from, int to);
+ static QTextCursor fromPosition(QTextDocumentPrivate *d, int pos)
+ { return QTextCursor(d, pos); }
+
QTextDocumentPrivate *priv;
qreal x;
int position;
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 29e00d481e..3edf652f35 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -33,6 +33,7 @@
#include "qtextdocument.h"
#include <qtextformat.h>
+#include "qtextcursor_p.h"
#include "qtextdocumentlayout_p.h"
#include "qtextdocumentfragment.h"
#include "qtextdocumentfragment_p.h"
@@ -532,7 +533,7 @@ QTextOption QTextDocument::defaultTextOption() const
/*!
\since 4.3
- Sets the default text option.
+ Sets the default text option to \a option.
*/
void QTextDocument::setDefaultTextOption(const QTextOption &option)
{
@@ -1273,7 +1274,7 @@ static bool findInBlock(const QTextBlock &block, const QString &expression, int
}
}
//we have a hit, return the cursor for that.
- *cursor = QTextCursor(block.docHandle(), block.position() + idx);
+ *cursor = QTextCursorPrivate::fromPosition(block.docHandle(), block.position() + idx);
cursor->setPosition(cursor->position() + expression.length(), QTextCursor::KeepAnchor);
return true;
}
@@ -1391,7 +1392,7 @@ static bool findInBlock(const QTextBlock &block, const QRegExp &expression, int
}
}
//we have a hit, return the cursor for that.
- *cursor = QTextCursor(block.docHandle(), block.position() + idx);
+ *cursor = QTextCursorPrivate::fromPosition(block.docHandle(), block.position() + idx);
cursor->setPosition(cursor->position() + expr.matchedLength(), QTextCursor::KeepAnchor);
return true;
}
@@ -1401,7 +1402,9 @@ static bool findInBlock(const QTextBlock &block, const QRegExp &expression, int
/*!
\overload
- Finds the next occurrence, matching the regular expression, \a expr, in the document.
+ Finds the next occurrence that matches the given regular expression,
+ \a expr, within the same paragraph in the document.
+
The search starts at the given \a from position, and proceeds forwards
through the document unless specified otherwise in the search options.
The \a options control the type of search performed. The FindCaseSensitively
@@ -1454,7 +1457,9 @@ QTextCursor QTextDocument::find(const QRegExp & expr, int from, FindFlags option
/*!
\overload
- Finds the next occurrence, matching the regular expression, \a expr, in the document.
+ Finds the next occurrence that matches the given regular expression,
+ \a expr, within the same paragraph in the document.
+
The search starts at the position of the given from \a cursor, and proceeds
forwards through the document unless specified otherwise in the search
options. The \a options control the type of search performed. The FindCaseSensitively
@@ -1463,7 +1468,7 @@ QTextCursor QTextDocument::find(const QRegExp & expr, int from, FindFlags option
Returns a cursor with the match selected if a match was found; otherwise
returns a null cursor.
- If the given \a from cursor has a selection, the search begins after the
+ If the given \a cursor has a selection, the search begins after the
selection; otherwise it begins at the cursor's position.
By default the search is case-sensitive, and can match text anywhere in the
@@ -1515,7 +1520,7 @@ static bool findInBlock(const QTextBlock &block, const QRegularExpression &expre
}
}
//we have a hit, return the cursor for that.
- *cursor = QTextCursor(block.docHandle(), block.position() + idx);
+ *cursor = QTextCursorPrivate::fromPosition(block.docHandle(), block.position() + idx);
cursor->setPosition(cursor->position() + match.capturedLength(), QTextCursor::KeepAnchor);
return true;
}
@@ -1525,7 +1530,9 @@ static bool findInBlock(const QTextBlock &block, const QRegularExpression &expre
/*!
\since 5.5
- Finds the next occurrence, matching the regular expression, \a expr, in the document.
+ Finds the next occurrence that matches the given regular expression,
+ \a expr, within the same paragraph in the document.
+
The search starts at the given \a from position, and proceeds forwards
through the document unless specified otherwise in the search options.
The \a options control the type of search performed.
@@ -1578,7 +1585,9 @@ QTextCursor QTextDocument::find(const QRegularExpression &expr, int from, FindFl
/*!
\since 5.5
- Finds the next occurrence, matching the regular expression, \a expr, in the document.
+ Finds the next occurrence that matches the given regular expression,
+ \a expr, within the same paragraph in the document.
+
The search starts at the position of the given \a cursor, and proceeds
forwards through the document unless specified otherwise in the search
options. The \a options control the type of search performed.
@@ -1948,7 +1957,7 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
for (QTextBlock srcBlock = firstBlock(), dstBlock = clonedDoc->firstBlock();
srcBlock.isValid() && dstBlock.isValid();
srcBlock = srcBlock.next(), dstBlock = dstBlock.next()) {
- dstBlock.layout()->setAdditionalFormats(srcBlock.layout()->additionalFormats());
+ dstBlock.layout()->setFormats(srcBlock.layout()->formats());
}
QAbstractTextDocumentLayout *layout = doc->documentLayout();
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index ca80a88033..f05b624704 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -109,11 +109,11 @@ class Q_GUI_EXPORT QTextDocument : public QObject
Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl NOTIFY baseUrlChanged)
public:
- explicit QTextDocument(QObject *parent = 0);
- explicit QTextDocument(const QString &text, QObject *parent = 0);
+ explicit QTextDocument(QObject *parent = Q_NULLPTR);
+ explicit QTextDocument(const QString &text, QObject *parent = Q_NULLPTR);
~QTextDocument();
- QTextDocument *clone(QObject *parent = 0) const;
+ QTextDocument *clone(QObject *parent = Q_NULLPTR) const;
bool isEmpty() const;
virtual void clear();
@@ -157,17 +157,17 @@ public:
};
Q_DECLARE_FLAGS(FindFlags, FindFlag)
- QTextCursor find(const QString &subString, int from = 0, FindFlags options = 0) const;
- QTextCursor find(const QString &subString, const QTextCursor &cursor, FindFlags options = 0) const;
+ QTextCursor find(const QString &subString, int from = 0, FindFlags options = FindFlags()) const;
+ QTextCursor find(const QString &subString, const QTextCursor &cursor, FindFlags options = FindFlags()) const;
#ifndef QT_NO_REGEXP
- QTextCursor find(const QRegExp &expr, int from = 0, FindFlags options = 0) const;
- QTextCursor find(const QRegExp &expr, const QTextCursor &cursor, FindFlags options = 0) const;
+ QTextCursor find(const QRegExp &expr, int from = 0, FindFlags options = FindFlags()) const;
+ QTextCursor find(const QRegExp &expr, const QTextCursor &cursor, FindFlags options = FindFlags()) const;
#endif
#ifndef QT_NO_REGULAREXPRESSION
- QTextCursor find(const QRegularExpression &expr, int from = 0, FindFlags options = 0) const;
- QTextCursor find(const QRegularExpression &expr, const QTextCursor &cursor, FindFlags options = 0) const;
+ QTextCursor find(const QRegularExpression &expr, int from = 0, FindFlags options = FindFlags()) const;
+ QTextCursor find(const QRegularExpression &expr, const QTextCursor &cursor, FindFlags options = FindFlags()) const;
#endif
QTextFrame *frameAt(int pos) const;
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 5864ca0b1a..c7bbcea4f4 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -106,7 +106,7 @@ public:
bool sizeDirty;
bool layoutDirty;
- QList<QPointer<QTextFrame> > floats;
+ QVector<QPointer<QTextFrame> > floats;
};
QTextFrameData::QTextFrameData()
@@ -467,9 +467,9 @@ public:
void drawFlow(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context,
QTextFrame::Iterator it, const QList<QTextFrame *> &floats, QTextBlock *cursorBlockNeedingRepaint) const;
void drawBlock(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context,
- QTextBlock bl, bool inRootFrame) const;
+ const QTextBlock &bl, bool inRootFrame) const;
void drawListItem(const QPointF &offset, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context,
- QTextBlock bl, const QTextCharFormat *selectionFormat) const;
+ const QTextBlock &bl, const QTextCharFormat *selectionFormat) const;
void drawTableCell(const QRectF &cellRect, QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &cell_context,
QTextTable *table, QTextTableData *td, int r, int c,
QTextBlock *cursorBlockNeedingRepaint, QPointF *cursorBlockOffset) const;
@@ -487,7 +487,7 @@ public:
HitPoint hitTest(QTextFrame::Iterator it, HitPoint hit, const QFixedPoint &p,
int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const;
HitPoint hitTest(QTextTable *table, const QFixedPoint &point, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const;
- HitPoint hitTest(QTextBlock bl, const QFixedPoint &point, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const;
+ HitPoint hitTest(const QTextBlock &bl, const QFixedPoint &point, int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const;
QTextLayoutStruct layoutCell(QTextTable *t, const QTextTableCell &cell, QFixed width,
int layoutFrom, int layoutTo, QTextTableData *tableData, QFixed absoluteTableY,
@@ -749,7 +749,7 @@ QTextDocumentLayoutPrivate::hitTest(QTextTable *table, const QFixedPoint &point,
}
QTextDocumentLayoutPrivate::HitPoint
-QTextDocumentLayoutPrivate::hitTest(QTextBlock bl, const QFixedPoint &point, int *position, QTextLayout **l,
+QTextDocumentLayoutPrivate::hitTest(const QTextBlock &bl, const QFixedPoint &point, int *position, QTextLayout **l,
Qt::HitTestAccuracy accuracy) const
{
QTextLayout *tl = bl.layout();
@@ -1071,7 +1071,9 @@ void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *pain
it = frameIteratorForYPosition(QFixed::fromReal(context.clip.top()));
QList<QTextFrame *> floats;
- for (int i = 0; i < fd->floats.count(); ++i)
+ const int numFloats = fd->floats.count();
+ floats.reserve(numFloats);
+ for (int i = 0; i < numFloats; ++i)
floats.append(fd->floats.at(i));
drawFlow(off, painter, context, it, floats, &cursorBlockNeedingRepaint);
@@ -1283,7 +1285,7 @@ void QTextDocumentLayoutPrivate::drawFlow(const QPointF &offset, QPainter *paint
void QTextDocumentLayoutPrivate::drawBlock(const QPointF &offset, QPainter *painter,
const QAbstractTextDocumentLayout::PaintContext &context,
- QTextBlock bl, bool inRootFrame) const
+ const QTextBlock &bl, bool inRootFrame) const
{
const QTextLayout *tl = bl.layout();
QRectF r = tl->boundingRect();
@@ -1377,7 +1379,7 @@ void QTextDocumentLayoutPrivate::drawBlock(const QPointF &offset, QPainter *pain
void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *painter,
const QAbstractTextDocumentLayout::PaintContext &context,
- QTextBlock bl, const QTextCharFormat *selectionFormat) const
+ const QTextBlock &bl, const QTextCharFormat *selectionFormat) const
{
Q_Q(const QTextDocumentLayout);
const QTextBlockFormat blockFormat = bl.blockFormat();
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 29a633f350..1c924175e2 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -918,10 +918,11 @@ void QTextEngine::shapeLine(const QScriptLine &line)
{
QFixed x;
bool first = true;
- const int end = findItem(line.from + line.length - 1);
int item = findItem(line.from);
if (item == -1)
return;
+
+ const int end = findItem(line.from + line.length - 1, item);
for ( ; item <= end; ++item) {
QScriptItem &si = layoutData->items[item];
if (si.analysis.flags == QScriptAnalysis::Tab) {
@@ -1172,7 +1173,23 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
};
const int num_features = 1;
- bool shapedOk = hb_shape_full(hb_font, buffer, features, num_features, 0);
+ const char *const *shaper_list = Q_NULLPTR;
+#if defined(Q_OS_DARWIN)
+ // What's behind QFontEngine::FaceData::user_data isn't compatible between different font engines
+ // - specifically functions in hb-coretext.cc would run into undefined behavior with data
+ // from non-CoreText engine. The other shapers works with that engine just fine.
+ if (actualFontEngine->type() != QFontEngine::Mac) {
+ static const char *s_shaper_list_without_coretext[] = {
+ "graphite2",
+ "ot",
+ "fallback",
+ Q_NULLPTR
+ };
+ shaper_list = s_shaper_list_without_coretext;
+ }
+#endif
+
+ bool shapedOk = hb_shape_full(hb_font, buffer, features, num_features, shaper_list);
if (Q_UNLIKELY(!shapedOk)) {
hb_buffer_destroy(buffer);
return 0;
@@ -1251,21 +1268,22 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
g.glyphs[i] |= (engineIdx << 24);
}
-#ifdef Q_OS_MAC
- // CTRunGetPosition has a bug which applies matrix on 10.6, so we disable
- // scaling the advances for this particular version
- if (actualFontEngine->fontDef.stretch != 100
- && QSysInfo::MacintoshVersion != QSysInfo::MV_10_6) {
- QFixed stretch = QFixed(int(actualFontEngine->fontDef.stretch)) / QFixed(100);
- for (uint i = 0; i < num_glyphs; ++i)
- g.advances[i] *= stretch;
+#ifdef Q_OS_DARWIN
+ if (actualFontEngine->type() == QFontEngine::Mac) {
+ // CTRunGetPosition has a bug which applies matrix on 10.6, so we disable
+ // scaling the advances for this particular version
+ if (QSysInfo::MacintoshVersion != QSysInfo::MV_10_6 && actualFontEngine->fontDef.stretch != 100) {
+ QFixed stretch = QFixed(int(actualFontEngine->fontDef.stretch)) / QFixed(100);
+ for (uint i = 0; i < num_glyphs; ++i)
+ g.advances[i] *= stretch;
+ }
}
+#endif
- if (actualFontEngine->fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ if (!actualFontEngine->supportsSubPixelPositions() || (actualFontEngine->fontDef.styleStrategy & QFont::ForceIntegerMetrics)) {
for (uint i = 0; i < num_glyphs; ++i)
g.advances[i] = g.advances[i].round();
}
-#endif
glyphs_shaped += num_glyphs;
}
@@ -1730,13 +1748,13 @@ bool QTextEngine::isRightToLeft() const
}
-int QTextEngine::findItem(int strPos) const
+int QTextEngine::findItem(int strPos, int firstItem) const
{
itemize();
- if (strPos < 0 || strPos >= layoutData->string.size())
+ if (strPos < 0 || strPos >= layoutData->string.size() || firstItem < 0)
return -1;
- int left = 1;
+ int left = firstItem + 1;
int right = layoutData->items.size()-1;
while(left <= right) {
int middle = ((right-left)/2)+left;
@@ -2155,7 +2173,7 @@ void QTextEngine::justify(const QScriptLine &line)
return;
int firstItem = findItem(line.from);
- int lastItem = findItem(line.from + line_length - 1);
+ int lastItem = findItem(line.from + line_length - 1, firstItem);
int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
QVarLengthArray<QJustificationPoint> justificationPoints;
@@ -2571,7 +2589,7 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText)
clearLineData();
}
-void QTextEngine::setFormats(const QList<QTextLayout::FormatRange> &formats)
+void QTextEngine::setFormats(const QVector<QTextLayout::FormatRange> &formats)
{
if (formats.isEmpty()) {
if (!specialData)
@@ -2863,6 +2881,7 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
if (!tabArray.isEmpty()) {
if (isRightToLeft()) { // rebase the tabArray positions.
QList<QTextOption::Tab> newTabs;
+ newTabs.reserve(tabArray.count());
QList<QTextOption::Tab>::Iterator iter = tabArray.begin();
while(iter != tabArray.end()) {
QTextOption::Tab tab = *iter;
@@ -2946,17 +2965,17 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
namespace {
class FormatRangeComparatorByStart {
- const QList<QTextLayout::FormatRange> &list;
+ const QVector<QTextLayout::FormatRange> &list;
public:
- FormatRangeComparatorByStart(const QList<QTextLayout::FormatRange> &list) : list(list) { }
+ FormatRangeComparatorByStart(const QVector<QTextLayout::FormatRange> &list) : list(list) { }
bool operator()(int a, int b) {
return list.at(a).start < list.at(b).start;
}
};
class FormatRangeComparatorByEnd {
- const QList<QTextLayout::FormatRange> &list;
+ const QVector<QTextLayout::FormatRange> &list;
public:
- FormatRangeComparatorByEnd(const QList<QTextLayout::FormatRange> &list) : list(list) { }
+ FormatRangeComparatorByEnd(const QVector<QTextLayout::FormatRange> &list) : list(list) { }
bool operator()(int a, int b) {
return list.at(a).start + list.at(a).length < list.at(b).start + list.at(b).length;
}
@@ -3511,7 +3530,7 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co
lineNum(_lineNum),
lineEnd(line.from + line.length),
firstItem(eng->findItem(line.from)),
- lastItem(eng->findItem(lineEnd - 1)),
+ lastItem(eng->findItem(lineEnd - 1, firstItem)),
nItems((firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0),
logicalItem(-1),
item(-1),
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 39b9e0cb5a..39c228fd52 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -107,6 +107,22 @@ struct Q_GUI_EXPORT glyph_metrics_t
glyph_metrics_t transformed(const QTransform &xform) const;
inline bool isValid() const {return x != 100000 && y != 100000;}
+
+ inline QFixed leftBearing() const
+ {
+ if (!isValid())
+ return QFixed();
+
+ return x;
+ }
+
+ inline QFixed rightBearing() const
+ {
+ if (!isValid())
+ return QFixed();
+
+ return xoff - x - width;
+ }
};
Q_DECLARE_TYPEINFO(glyph_metrics_t, Q_PRIMITIVE_TYPE);
@@ -351,8 +367,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine
uint leadingIncluded : 1;
QFixed height() const { return ascent + descent
+ (leadingIncluded? qMax(QFixed(),leading) : QFixed()); }
- QFixed base() const { return ascent
- + (leadingIncluded ? qMax(QFixed(),leading) : QFixed()); }
+ QFixed base() const { return ascent; }
void setDefaultHeight(QTextEngine *eng);
void operator+=(const QScriptLine &other);
};
@@ -400,6 +415,7 @@ public:
};
struct ItemDecoration {
+ ItemDecoration() {} // for QVector, don't use
ItemDecoration(qreal x1, qreal x2, qreal y, const QPen &pen):
x1(x1), x2(x2), y(y), pen(pen) {}
@@ -409,7 +425,7 @@ public:
QPen pen;
};
- typedef QList<ItemDecoration> ItemDecorationList;
+ typedef QVector<ItemDecoration> ItemDecorationList;
QTextEngine();
QTextEngine(const QString &str, const QFont &f);
@@ -496,7 +512,7 @@ public:
void freeMemory();
- int findItem(int strPos) const;
+ int findItem(int strPos, int firstItem = 0) const;
inline QTextFormatCollection *formatCollection() const {
if (block.docHandle())
return block.docHandle()->formatCollection();
@@ -570,9 +586,9 @@ public:
inline bool hasFormats() const
{ return block.docHandle() || (specialData && !specialData->formats.isEmpty()); }
- inline QList<QTextLayout::FormatRange> formats() const
- { return specialData ? specialData->formats : QList<QTextLayout::FormatRange>(); }
- void setFormats(const QList<QTextLayout::FormatRange> &formats);
+ inline QVector<QTextLayout::FormatRange> formats() const
+ { return specialData ? specialData->formats : QVector<QTextLayout::FormatRange>(); }
+ void setFormats(const QVector<QTextLayout::FormatRange> &formats);
private:
static void init(QTextEngine *e);
@@ -580,7 +596,7 @@ private:
struct SpecialData {
int preeditPosition;
QString preeditText;
- QList<QTextLayout::FormatRange> formats;
+ QVector<QTextLayout::FormatRange> formats;
QVector<QTextCharFormat> resolvedFormats;
// only used when no docHandle is available
QScopedPointer<QTextFormatCollection> formatCollection;
@@ -643,6 +659,7 @@ public:
LayoutData _layoutData;
void *_memory[MemSize];
};
+Q_DECLARE_TYPEINFO(QTextEngine::ItemDecoration, Q_MOVABLE_TYPE);
struct QTextLineItemIterator
{
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index ba4bdcc5ad..7dcd060ba1 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -38,7 +38,7 @@
#include <qdatastream.h>
#include <qdebug.h>
#include <qmap.h>
-#include <qhash.h>
+#include <qhashfunctions.h>
QT_BEGIN_NAMESPACE
@@ -1115,7 +1115,9 @@ void QTextFormat::setProperty(int propertyId, const QVector<QTextLength> &value)
if (!d)
d = new QTextFormatPrivate;
QVariantList list;
- for (int i=0; i<value.size(); ++i)
+ const int numValues = value.size();
+ list.reserve(numValues);
+ for (int i = 0; i < numValues; ++i)
list << value.at(i);
d->insertProperty(propertyId, list);
}
@@ -2041,6 +2043,7 @@ QTextBlockFormat::QTextBlockFormat(const QTextFormat &fmt)
void QTextBlockFormat::setTabPositions(const QList<QTextOption::Tab> &tabs)
{
QList<QVariant> list;
+ list.reserve(tabs.count());
QList<QTextOption::Tab>::ConstIterator iter = tabs.constBegin();
while (iter != tabs.constEnd()) {
QVariant v;
@@ -2065,6 +2068,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
QList<QTextOption::Tab> answer;
QList<QVariant> variantsList = qvariant_cast<QList<QVariant> >(variant);
QList<QVariant>::Iterator iter = variantsList.begin();
+ answer.reserve(variantsList.count());
while(iter != variantsList.end()) {
answer.append( qvariant_cast<QTextOption::Tab>(*iter));
++iter;
diff --git a/src/gui/text/qtextformat_p.h b/src/gui/text/qtextformat_p.h
index 29656bbafe..928cef6488 100644
--- a/src/gui/text/qtextformat_p.h
+++ b/src/gui/text/qtextformat_p.h
@@ -47,7 +47,6 @@
#include "QtGui/qtextformat.h"
#include "QtCore/qvector.h"
-#include "QtCore/qhash.h"
QT_BEGIN_NAMESPACE
diff --git a/src/gui/text/qtextimagehandler.cpp b/src/gui/text/qtextimagehandler.cpp
index e85890baf2..16d81a7d6d 100644
--- a/src/gui/text/qtextimagehandler.cpp
+++ b/src/gui/text/qtextimagehandler.cpp
@@ -44,7 +44,10 @@
QT_BEGIN_NAMESPACE
-static QString resolveFileName(QString fileName, QUrl *url, qreal targetDevicePixelRatio)
+extern QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio,
+ qreal *sourceDevicePixelRatio);
+static QString resolveFileName(QString fileName, QUrl *url, qreal targetDevicePixelRatio,
+ qreal *sourceDevicePixelRatio)
{
// We might use the fileName for loading if url loading fails
// try to make sure it is a valid file path.
@@ -62,19 +65,8 @@ static QString resolveFileName(QString fileName, QUrl *url, qreal targetDevicePi
if (targetDevicePixelRatio <= 1.0)
return fileName;
- // try to find a 2x version
-
- const int dotIndex = fileName.lastIndexOf(QLatin1Char('.'));
- if (dotIndex != -1) {
- QString at2xfileName = fileName;
- at2xfileName.insert(dotIndex, QStringLiteral("@2x"));
- if (QFile::exists(at2xfileName)) {
- fileName = at2xfileName;
- *url = QUrl(fileName);
- }
- }
-
- return fileName;
+ // try to find a Nx version
+ return qt_findAtNxFile(fileName, targetDevicePixelRatio, sourceDevicePixelRatio);
}
@@ -86,7 +78,8 @@ static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format, con
if (name.startsWith(QLatin1String(":/"))) // auto-detect resources and convert them to url
name.prepend(QLatin1String("qrc"));
QUrl url = QUrl(name);
- name = resolveFileName(name, &url, devicePixelRatio);
+ qreal sourcePixelRatio = 1.0;
+ name = resolveFileName(name, &url, devicePixelRatio, &sourcePixelRatio);
const QVariant data = doc->resource(QTextDocument::ImageResource, url);
if (data.type() == QVariant::Pixmap || data.type() == QVariant::Image) {
pm = qvariant_cast<QPixmap>(data);
@@ -112,7 +105,7 @@ static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format, con
}
if (name.contains(QStringLiteral("@2x")))
- pm.setDevicePixelRatio(2.0);
+ pm.setDevicePixelRatio(sourcePixelRatio);
return pm;
}
@@ -167,7 +160,8 @@ static QImage getImage(QTextDocument *doc, const QTextImageFormat &format, const
if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
name.prepend(QLatin1String("qrc"));
QUrl url = QUrl(name);
- name = resolveFileName(name, &url, devicePixelRatio);
+ qreal sourcePixelRatio = 1.0;
+ name = resolveFileName(name, &url, devicePixelRatio, &sourcePixelRatio);
const QVariant data = doc->resource(QTextDocument::ImageResource, url);
if (data.type() == QVariant::Image) {
image = qvariant_cast<QImage>(data);
@@ -191,8 +185,8 @@ static QImage getImage(QTextDocument *doc, const QTextImageFormat &format, const
doc->addResource(QTextDocument::ImageResource, url, image);
}
- if (name.contains(QStringLiteral("@2x")))
- image.setDevicePixelRatio(2.0);
+ if (sourcePixelRatio != 1.0)
+ image.setDevicePixelRatio(sourcePixelRatio);
return image;
}
@@ -256,10 +250,10 @@ void QTextImageHandler::drawObject(QPainter *p, const QRectF &rect, QTextDocumen
const QTextImageFormat imageFormat = format.toImageFormat();
if (QCoreApplication::instance()->thread() != QThread::currentThread()) {
- const QImage image = getImage(doc, imageFormat, p->device()->devicePixelRatio());
+ const QImage image = getImage(doc, imageFormat, p->device()->devicePixelRatioF());
p->drawImage(rect, image, image.rect());
} else {
- const QPixmap pixmap = getPixmap(doc, imageFormat, p->device()->devicePixelRatio());
+ const QPixmap pixmap = getPixmap(doc, imageFormat, p->device()->devicePixelRatioF());
p->drawPixmap(rect, pixmap, pixmap.rect());
}
}
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 013cd8ae0f..9e2a23a7f7 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE
for a specified area in the text layout's content.
\inmodule QtGui
- \sa QTextLayout::setAdditionalFormats(), QTextLayout::draw()
+ \sa QTextLayout::setFormats(), QTextLayout::draw()
*/
/*!
@@ -87,6 +87,20 @@ QT_BEGIN_NAMESPACE
Specifies the format to apply.
*/
+/*! \fn bool operator==(const FormatRange &lhs, const FormatRange &rhs)
+ \relates QTextLayout::FormatRange
+
+ Returns true if the \c {start}, \c {length}, and \c {format} fields
+ in \a lhs and \a rhs contain the same values respectively.
+ */
+
+/*! \fn bool operator!=(const FormatRange &lhs, const FormatRange &rhs)
+ \relates QTextLayout::FormatRange
+
+ Returns true if any of the \c {start}, \c {length}, or \c {format} fields
+ in \a lhs and \a rhs contain different values respectively.
+ */
+
/*!
\class QTextInlineObject
\reentrant
@@ -485,39 +499,76 @@ QString QTextLayout::preeditAreaText() const
return d->preeditAreaText();
}
+#if QT_DEPRECATED_SINCE(5, 6)
+/*!
+ \obsolete Use setFormats() instead.
+*/
+void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
+{
+ setFormats(formatList.toVector());
+}
+#endif // deprecated since 5.6
/*!
- Sets the additional formats supported by the text layout to \a formatList.
+ \since 5.6
+
+ Sets the additional formats supported by the text layout to \a formats.
The formats are applied with preedit area text in place.
- \sa additionalFormats(), clearAdditionalFormats()
+ \sa formats(), clearFormats()
*/
-void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
+void QTextLayout::setFormats(const QVector<FormatRange> &formats)
{
- d->setFormats(formatList);
+ d->setFormats(formats);
if (d->block.docHandle())
d->block.docHandle()->documentChange(d->block.position(), d->block.length());
}
+#if QT_DEPRECATED_SINCE(5, 6)
/*!
- Returns the list of additional formats supported by the text layout.
+ \obsolete Use formats() instead.
\sa setAdditionalFormats(), clearAdditionalFormats()
*/
QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const
{
+ return formats().toList();
+}
+#endif // deprecated since 5.6
+
+/*!
+ \since 5.6
+
+ Returns the list of additional formats supported by the text layout.
+
+ \sa setFormats(), clearFormats()
+*/
+QVector<QTextLayout::FormatRange> QTextLayout::formats() const
+{
return d->formats();
}
+#if QT_DEPRECATED_SINCE(5, 6)
/*!
+ \obsolete Use clearFormats() instead.
+*/
+void QTextLayout::clearAdditionalFormats()
+{
+ clearFormats();
+}
+#endif // deprecated since 5.6
+
+/*!
+ \since 5.6
+
Clears the list of additional formats supported by the text layout.
- \sa additionalFormats(), setAdditionalFormats()
+ \sa formats(), setFormats()
*/
-void QTextLayout::clearAdditionalFormats()
+void QTextLayout::clearFormats()
{
- setAdditionalFormats(QList<FormatRange>());
+ setFormats(QVector<FormatRange>());
}
/*!
@@ -1007,12 +1058,15 @@ QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const
QVector<quint32> indexes = oldGlyphRun.glyphIndexes();
QVector<QPointF> positions = oldGlyphRun.positions();
+ QRectF boundingRect = oldGlyphRun.boundingRect();
indexes += glyphRun.glyphIndexes();
positions += glyphRun.positions();
+ boundingRect = boundingRect.united(glyphRun.boundingRect());
oldGlyphRun.setGlyphIndexes(indexes);
oldGlyphRun.setPositions(positions);
+ oldGlyphRun.setBoundingRect(boundingRect);
} else {
glyphRunHash[key] = glyphRun;
}
@@ -1915,9 +1969,16 @@ void QTextLine::layout_helper(int maxGlyphs)
// 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)
+ // We skip calculating the right bearing if the minimum negative bearing is too
+ // small to possibly expand the text beyond the edge. Note that this optimization
+ // will in some cases fail, as the minimum right bearing reported by the font
+ // engine may not cover all the glyphs in the font. The result is that we think
+ // we don't need to break at the current glyph (because the right bearing is 0),
+ // and when we then end up breaking on the next glyph we compute the right bearing
+ // and end up with a line width that is slightly larger width than what was requested.
+ // Unfortunately we can't remove this optimization as it will slow down text
+ // layouting significantly, so we accept the slight correctnes issue.
+ if ((lbh.calculateNewWidth(line) + qAbs(lbh.minimumRightBearing)) > line.width)
lbh.calculateRightBearing();
if (lbh.checkFullOtherwiseExtend(line)) {
@@ -2559,33 +2620,31 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
inside the line, taking account of the \a edge.
If \a cursorPos is not a valid cursor position, the nearest valid
- cursor position will be used instead, and cpos will be modified to
+ cursor position will be used instead, and \a cursorPos will be modified to
point to this valid cursor position.
\sa xToCursor()
*/
qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
{
- if (!eng->layoutData)
- eng->itemize();
-
const QScriptLine &line = eng->lines[index];
bool lastLine = index >= eng->lines.size() - 1;
- QFixed x = line.x;
- x += eng->alignLine(line) - eng->leadingSpaceWidth(line);
+ QFixed x = line.x + eng->alignLine(line) - eng->leadingSpaceWidth(line);
- if (!index && !eng->layoutData->items.size()) {
- *cursorPos = 0;
+ if (!eng->layoutData)
+ eng->itemize();
+ if (!eng->layoutData->items.size()) {
+ *cursorPos = line.from;
return x.toReal();
}
int lineEnd = line.from + line.length + line.trailingSpaces;
- int pos = qBound(0, *cursorPos, lineEnd);
+ int pos = qBound(line.from, *cursorPos, lineEnd);
int itm;
const QCharAttributes *attributes = eng->attributes();
if (!attributes) {
- *cursorPos = 0;
+ *cursorPos = line.from;
return x.toReal();
}
while (pos < lineEnd && !attributes[pos].graphemeBoundary)
@@ -2597,7 +2656,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
else
itm = eng->findItem(pos);
if (itm < 0) {
- *cursorPos = 0;
+ *cursorPos = line.from;
return x.toReal();
}
eng->shapeLine(line);
@@ -2605,18 +2664,14 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
const QScriptItem *si = &eng->layoutData->items[itm];
if (!si->num_glyphs)
eng->shape(itm);
- pos -= si->position;
+
+ const int l = eng->length(itm);
+ pos = qBound(0, pos - si->position, l);
QGlyphLayout glyphs = eng->shapedGlyphs(si);
unsigned short *logClusters = eng->logClusters(si);
Q_ASSERT(logClusters);
- int l = eng->length(itm);
- if (pos > l)
- pos = l;
- if (pos < 0)
- pos = 0;
-
int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos];
if (edge == Trailing && glyph_pos < si->num_glyphs) {
// trailing edge is leading edge of next cluster
@@ -2625,13 +2680,13 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
glyph_pos++;
}
- bool reverse = eng->layoutData->items[itm].analysis.bidiLevel % 2;
+ bool reverse = si->analysis.bidiLevel % 2;
// add the items left of the cursor
int firstItem = eng->findItem(line.from);
- int lastItem = eng->findItem(lineEnd - 1);
+ int lastItem = eng->findItem(lineEnd - 1, itm);
int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
QVarLengthArray<int> visualOrder(nItems);
@@ -2652,13 +2707,15 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
x += si.width;
continue;
}
+
+ const int itemLength = eng->length(item);
int start = qMax(line.from, si.position);
- int end = qMin(lineEnd, si.position + eng->length(item));
+ int end = qMin(lineEnd, si.position + itemLength);
logClusters = eng->logClusters(&si);
int gs = logClusters[start-si.position];
- int ge = (end == si.position + eng->length(item)) ? si.num_glyphs-1 : logClusters[end-si.position-1];
+ int ge = (end == si.position + itemLength) ? si.num_glyphs-1 : logClusters[end-si.position-1];
QGlyphLayout glyphs = eng->shapedGlyphs(&si);
@@ -2730,7 +2787,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
return line.from;
int firstItem = eng->findItem(line.from);
- int lastItem = eng->findItem(line.from + line_length - 1);
+ int lastItem = eng->findItem(line.from + line_length - 1, firstItem);
int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
if (!nItems)
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index 47dcd388e2..f74d4d4229 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -62,7 +62,7 @@ class Q_GUI_EXPORT QTextInlineObject
{
public:
QTextInlineObject(int i, QTextEngine *e) : itm(i), eng(e) {}
- inline QTextInlineObject() : itm(0), eng(0) {}
+ inline QTextInlineObject() : itm(0), eng(Q_NULLPTR) {}
inline bool isValid() const { return eng; }
QRectF rect() const;
@@ -100,7 +100,7 @@ public:
// does itemization
QTextLayout();
QTextLayout(const QString& text);
- QTextLayout(const QString& text, const QFont &font, QPaintDevice *paintdevice = 0);
+ QTextLayout(const QString& text, const QFont &font, QPaintDevice *paintdevice = Q_NULLPTR);
QTextLayout(const QTextBlock &b);
~QTextLayout();
@@ -125,10 +125,20 @@ public:
int start;
int length;
QTextCharFormat format;
+
+ friend bool operator==(const FormatRange &lhs, const FormatRange &rhs)
+ { return lhs.start == rhs.start && lhs.length == rhs.length && lhs.format == rhs.format; }
+ friend bool operator!=(const FormatRange &lhs, const FormatRange &rhs)
+ { return !operator==(lhs, rhs); }
};
- void setAdditionalFormats(const QList<FormatRange> &overrides);
- QList<FormatRange> additionalFormats() const;
- void clearAdditionalFormats();
+#if QT_DEPRECATED_SINCE(5, 6)
+ QT_DEPRECATED_X("Use setFormats()") void setAdditionalFormats(const QList<FormatRange> &overrides);
+ QT_DEPRECATED_X("Use formats()") QList<FormatRange> additionalFormats() const;
+ QT_DEPRECATED_X("Use clearFormats()") void clearAdditionalFormats();
+#endif
+ void setFormats(const QVector<FormatRange> &overrides);
+ QVector<FormatRange> formats() const;
+ void clearFormats();
void setCacheEnabled(bool enable);
bool cacheEnabled() const;
@@ -192,7 +202,7 @@ private:
class Q_GUI_EXPORT QTextLine
{
public:
- inline QTextLine() : index(0), eng(0) {}
+ inline QTextLine() : index(0), eng(Q_NULLPTR) {}
inline bool isValid() const { return eng; }
QRectF rect() const;
@@ -237,7 +247,7 @@ public:
int lineNumber() const { return index; }
- void draw(QPainter *p, const QPointF &point, const QTextLayout::FormatRange *selection = 0) const;
+ void draw(QPainter *p, const QPointF &point, const QTextLayout::FormatRange *selection = Q_NULLPTR) const;
#if !defined(QT_NO_RAWFONT)
QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const;
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index df7c8b9c71..e70b8ed300 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -33,6 +33,7 @@
#include "qtextobject.h"
#include "qtextobject_p.h"
+#include "qtextcursor_p.h"
#include "qtextdocument.h"
#include "qtextformat_p.h"
#include "qtextdocument_p.h"
@@ -461,7 +462,7 @@ QTextFrame *QTextFrame::parentFrame() const
QTextCursor QTextFrame::firstCursorPosition() const
{
Q_D(const QTextFrame);
- return QTextCursor(d->pieceTable, firstPosition());
+ return QTextCursorPrivate::fromPosition(d->pieceTable, firstPosition());
}
/*!
@@ -472,7 +473,7 @@ QTextCursor QTextFrame::firstCursorPosition() const
QTextCursor QTextFrame::lastCursorPosition() const
{
Q_D(const QTextFrame);
- return QTextCursor(d->pieceTable, lastPosition());
+ return QTextCursorPrivate::fromPosition(d->pieceTable, lastPosition());
}
/*!
diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h
index 9ad912d992..fbb90e42b0 100644
--- a/src/gui/text/qtextobject.h
+++ b/src/gui/text/qtextobject.h
@@ -190,7 +190,7 @@ class Q_GUI_EXPORT QTextBlock
friend class QSyntaxHighlighter;
public:
inline QTextBlock(QTextDocumentPrivate *priv, int b) : p(priv), n(b) {}
- inline QTextBlock() : p(0), n(0) {}
+ inline QTextBlock() : p(Q_NULLPTR), n(0) {}
inline QTextBlock(const QTextBlock &o) : p(o.p), n(o.n) {}
inline QTextBlock &operator=(const QTextBlock &o) { p = o.p; n = o.n; return *this; }
@@ -247,7 +247,7 @@ public:
friend class QTextBlock;
iterator(const QTextDocumentPrivate *priv, int begin, int end, int f) : p(priv), b(begin), e(end), n(f) {}
public:
- iterator() : p(0), b(0), e(0), n(0) {}
+ iterator() : p(Q_NULLPTR), b(0), e(0), n(0) {}
iterator(const iterator &o) : p(o.p), b(o.b), e(o.e), n(o.n) {}
QTextFragment fragment() const;
@@ -289,7 +289,7 @@ class Q_GUI_EXPORT QTextFragment
{
public:
inline QTextFragment(const QTextDocumentPrivate *priv, int f, int fe) : p(priv), n(f), ne(fe) {}
- inline QTextFragment() : p(0), n(0), ne(0) {}
+ inline QTextFragment() : p(Q_NULLPTR), n(0), ne(0) {}
inline QTextFragment(const QTextFragment &o) : p(o.p), n(o.n), ne(o.ne) {}
inline QTextFragment &operator=(const QTextFragment &o) { p = o.p; n = o.n; ne = o.ne; return *this; }
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp
index 6b17a264b1..1fd20cfbef 100644
--- a/src/gui/text/qtextodfwriter.cpp
+++ b/src/gui/text/qtextodfwriter.cpp
@@ -279,6 +279,12 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
writer.writeAttribute(textNS, QString::fromLatin1("style-name"), QString::fromLatin1("p%1")
.arg(block.blockFormatIndex()));
for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) {
+ bool isHyperlink = frag.fragment().charFormat().hasProperty(QTextFormat::AnchorHref);
+ if (isHyperlink) {
+ QString value = frag.fragment().charFormat().property(QTextFormat::AnchorHref).toString();
+ writer.writeStartElement(textNS, QString::fromLatin1("a"));
+ writer.writeAttribute(xlinkNS, QString::fromLatin1("href"), value);
+ }
writer.writeCharacters(QString()); // Trick to make sure that the span gets no linefeed in front of it.
writer.writeStartElement(textNS, QString::fromLatin1("span"));
@@ -335,6 +341,9 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
writer.writeCharacters(fragmentText.mid(exportedIndex));
writer.writeEndElement(); // span
+ writer.writeCharacters(QString()); // Trick to make sure that the span gets no linefeed behind it.
+ if (isHyperlink)
+ writer.writeEndElement(); // a
}
writer.writeCharacters(QString()); // Trick to make sure that the span gets no linefeed behind it.
writer.writeEndElement(); // p
@@ -396,7 +405,7 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
writer.writeEndElement(); // frame
}
-void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, QSet<int> formats) const
+void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, const QSet<int> &formats) const
{
writer.writeStartElement(officeNS, QString::fromLatin1("automatic-styles"));
QVector<QTextFormat> allStyles = m_document->allFormats();
diff --git a/src/gui/text/qtextodfwriter_p.h b/src/gui/text/qtextodfwriter_p.h
index 20805a8d27..15a4b40796 100644
--- a/src/gui/text/qtextodfwriter_p.h
+++ b/src/gui/text/qtextodfwriter_p.h
@@ -83,7 +83,7 @@ public:
bool createArchive() const { return m_createArchive; }
void writeBlock(QXmlStreamWriter &writer, const QTextBlock &block);
- void writeFormats(QXmlStreamWriter &writer, QSet<int> formatIds) const;
+ void writeFormats(QXmlStreamWriter &writer, const QSet<int> &formatIds) const;
void writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat format, int formatIndex) const;
void writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFormat format, int formatIndex) const;
void writeListFormat(QXmlStreamWriter &writer, QTextListFormat format, int formatIndex) const;
diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp
index dbafcfd58e..5a4f6b7954 100644
--- a/src/gui/text/qtextoption.cpp
+++ b/src/gui/text/qtextoption.cpp
@@ -146,6 +146,7 @@ void QTextOption::setTabArray(const QList<qreal> &tabStops)
d = new QTextOptionPrivate;
QList<QTextOption::Tab> tabs;
QTextOption::Tab tab;
+ tabs.reserve(tabStops.count());
foreach (qreal pos, tabStops) {
tab.position = pos;
tabs.append(tab);
@@ -174,10 +175,11 @@ void QTextOption::setTabs(const QList<QTextOption::Tab> &tabStops)
*/
QList<qreal> QTextOption::tabArray() const
{
+ QList<qreal> answer;
if (!d)
- return QList<qreal>();
+ return answer;
- QList<qreal> answer;
+ answer.reserve(d->tabStops.count());
QList<QTextOption::Tab>::ConstIterator iter = d->tabStops.constBegin();
while(iter != d->tabStops.constEnd()) {
answer.append( (*iter).position);
diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp
index a75a1aae54..553dc3c772 100644
--- a/src/gui/text/qtexttable.cpp
+++ b/src/gui/text/qtexttable.cpp
@@ -35,6 +35,7 @@
#include "qtextcursor.h"
#include "qtextformat.h"
#include <qdebug.h>
+#include "qtextcursor_p.h"
#include "qtexttable_p.h"
#include "qvarlengtharray.h"
@@ -220,7 +221,7 @@ int QTextTableCell::columnSpan() const
*/
QTextCursor QTextTableCell::firstCursorPosition() const
{
- return QTextCursor(table->d_func()->pieceTable, firstPosition());
+ return QTextCursorPrivate::fromPosition(table->d_func()->pieceTable, firstPosition());
}
/*!
@@ -230,7 +231,7 @@ QTextCursor QTextTableCell::firstCursorPosition() const
*/
QTextCursor QTextTableCell::lastCursorPosition() const
{
- return QTextCursor(table->d_func()->pieceTable, lastPosition());
+ return QTextCursorPrivate::fromPosition(table->d_func()->pieceTable, lastPosition());
}
@@ -986,8 +987,8 @@ void QTextTable::removeColumns(int pos, int num)
Merges the cell at the specified \a row and \a column with the adjacent cells
into one cell. The new cell will span \a numRows rows and \a numCols columns.
- If \a numRows or \a numCols is less than the current number of rows or columns
- the cell spans then this method does nothing.
+ This method does nothing if \a numRows or \a numCols is less than the current
+ number of rows or columns spanned by the cell.
\sa splitCell()
*/
@@ -1103,10 +1104,10 @@ void QTextTable::mergeCells(int row, int column, int numRows, int numCols)
if (nextPos > pos) {
if (needsParagraph) {
needsParagraph = false;
- QTextCursor(p, insertPos++).insertBlock();
+ QTextCursorPrivate::fromPosition(p, insertPos++).insertBlock();
p->move(pos + 1, insertPos, nextPos - pos);
} else if (rowHasText) {
- QTextCursor(p, insertPos++).insertText(QLatin1String(" "));
+ QTextCursorPrivate::fromPosition(p, insertPos++).insertText(QLatin1String(" "));
p->move(pos + 1, insertPos, nextPos - pos);
} else {
p->move(pos, insertPos, nextPos - pos);
@@ -1282,7 +1283,7 @@ QTextCursor QTextTable::rowStart(const QTextCursor &c) const
int row = cell.row();
QTextDocumentPrivate *p = d->pieceTable;
QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), d->grid[row*d->nCols]);
- return QTextCursor(p, it.position());
+ return QTextCursorPrivate::fromPosition(p, it.position());
}
/*!
@@ -1304,7 +1305,7 @@ QTextCursor QTextTable::rowEnd(const QTextCursor &c) const
int fragment = row < d->nRows ? d->grid[row*d->nCols] : d->fragment_end;
QTextDocumentPrivate *p = d->pieceTable;
QTextDocumentPrivate::FragmentIterator it(&p->fragmentMap(), fragment);
- return QTextCursor(p, it.position() - 1);
+ return QTextCursorPrivate::fromPosition(p, it.position() - 1);
}
/*!
diff --git a/src/gui/text/qtexttable.h b/src/gui/text/qtexttable.h
index 6ceb1fdd0f..4ff7d19e85 100644
--- a/src/gui/text/qtexttable.h
+++ b/src/gui/text/qtexttable.h
@@ -48,7 +48,7 @@ class QTextTablePrivate;
class Q_GUI_EXPORT QTextTableCell
{
public:
- QTextTableCell() : table(0) {}
+ QTextTableCell() : table(Q_NULLPTR) {}
~QTextTableCell() {}
QTextTableCell(const QTextTableCell &o) : table(o.table), fragment(o.fragment) {}
QTextTableCell &operator=(const QTextTableCell &o)
@@ -63,7 +63,7 @@ public:
int rowSpan() const;
int columnSpan() const;
- inline bool isValid() const { return table != 0; }
+ inline bool isValid() const { return table != Q_NULLPTR; }
QTextCursor firstCursorPosition() const;
QTextCursor lastCursorPosition() const;
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index 1d621db0e6..31ef8f87be 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -243,11 +243,11 @@ static QFile::Permissions modeToPermissions(quint32 mode)
static quint32 permissionsToMode(QFile::Permissions perms)
{
quint32 mode = 0;
- if (mode & (QFile::ReadOwner | QFile::ReadUser))
+ if (perms & (QFile::ReadOwner | QFile::ReadUser))
mode |= UnixFileAttributes::ReadUser;
- if (mode & (QFile::WriteOwner | QFile::WriteUser))
+ if (perms & (QFile::WriteOwner | QFile::WriteUser))
mode |= UnixFileAttributes::WriteUser;
- if (mode & (QFile::ExeOwner | QFile::ExeUser))
+ if (perms & (QFile::ExeOwner | QFile::ExeUser))
mode |= UnixFileAttributes::WriteUser;
if (perms & QFile::ReadGroup)
mode |= UnixFileAttributes::ReadGroup;
@@ -303,6 +303,7 @@ enum HostOS {
HostOS400 = 18,
HostOSX = 19
};
+Q_DECLARE_TYPEINFO(HostOS, Q_PRIMITIVE_TYPE);
enum GeneralPurposeFlag {
Encrypted = 0x01,
@@ -314,6 +315,7 @@ enum GeneralPurposeFlag {
Utf8Names = 0x0800,
CentralDirectoryEncrypted = 0x2000
};
+Q_DECLARE_TYPEINFO(GeneralPurposeFlag, Q_PRIMITIVE_TYPE);
enum CompressionMethod {
CompressionMethodStored = 0,
@@ -340,6 +342,7 @@ enum CompressionMethod {
CompressionMethodPPMd = 98,
CompressionMethodWzAES = 99
};
+Q_DECLARE_TYPEINFO(CompressionMethod, Q_PRIMITIVE_TYPE);
struct LocalFileHeader
{
@@ -354,6 +357,7 @@ struct LocalFileHeader
uchar file_name_length[2];
uchar extra_field_length[2];
};
+Q_DECLARE_TYPEINFO(LocalFileHeader, Q_PRIMITIVE_TYPE);
struct DataDescriptor
{
@@ -361,6 +365,7 @@ struct DataDescriptor
uchar compressed_size[4];
uchar uncompressed_size[4];
};
+Q_DECLARE_TYPEINFO(DataDescriptor, Q_PRIMITIVE_TYPE);
struct CentralFileHeader
{
@@ -382,6 +387,7 @@ struct CentralFileHeader
uchar offset_local_header[4];
LocalFileHeader toLocalHeader() const;
};
+Q_DECLARE_TYPEINFO(CentralFileHeader, Q_PRIMITIVE_TYPE);
struct EndOfDirectory
{
@@ -394,6 +400,7 @@ struct EndOfDirectory
uchar dir_start_offset[4];
uchar comment_length[2];
};
+Q_DECLARE_TYPEINFO(EndOfDirectory, Q_PRIMITIVE_TYPE);
struct FileHeader
{
@@ -402,38 +409,7 @@ struct FileHeader
QByteArray extra_field;
QByteArray file_comment;
};
-
-QZipReader::FileInfo::FileInfo()
- : isDir(false), isFile(false), isSymLink(false), crc(0), size(0)
-{
-}
-
-QZipReader::FileInfo::~FileInfo()
-{
-}
-
-QZipReader::FileInfo::FileInfo(const FileInfo &other)
-{
- operator=(other);
-}
-
-QZipReader::FileInfo& QZipReader::FileInfo::operator=(const FileInfo &other)
-{
- filePath = other.filePath;
- isDir = other.isDir;
- isFile = other.isFile;
- isSymLink = other.isSymLink;
- permissions = other.permissions;
- crc = other.crc;
- size = other.size;
- lastModified = other.lastModified;
- return *this;
-}
-
-bool QZipReader::FileInfo::isValid() const
-{
- return isDir || isFile || isSymLink;
-}
+Q_DECLARE_TYPEINFO(FileHeader, Q_MOVABLE_TYPE);
class QZipPrivate
{
@@ -449,18 +425,19 @@ public:
delete device;
}
- void fillFileInfo(int index, QZipReader::FileInfo &fileInfo) const;
+ QZipReader::FileInfo fillFileInfo(int index) const;
QIODevice *device;
bool ownDevice;
bool dirtyFileTree;
- QList<FileHeader> fileHeaders;
+ QVector<FileHeader> fileHeaders;
QByteArray comment;
uint start_of_directory;
};
-void QZipPrivate::fillFileInfo(int index, QZipReader::FileInfo &fileInfo) const
+QZipReader::FileInfo QZipPrivate::fillFileInfo(int index) const
{
+ QZipReader::FileInfo fileInfo;
FileHeader header = fileHeaders.at(index);
quint32 mode = readUInt(header.h.external_file_attributes);
const HostOS hostOS = HostOS(readUShort(header.h.version_made) >> 8);
@@ -502,7 +479,7 @@ void QZipPrivate::fillFileInfo(int index, QZipReader::FileInfo &fileInfo) const
break;
default:
qWarning("QZip: Zip entry format at %d is not supported.", index);
- return; // we don't support anything else
+ return fileInfo; // we don't support anything else
}
ushort general_purpose_bits = readUShort(header.h.general_purpose_bits);
@@ -519,6 +496,8 @@ void QZipPrivate::fillFileInfo(int index, QZipReader::FileInfo &fileInfo) const
fileInfo.filePath = fileInfo.filePath.mid(1);
while (!fileInfo.filePath.isEmpty() && fileInfo.filePath.at(fileInfo.filePath.size() - 1) == QLatin1Char('/'))
fileInfo.filePath.chop(1);
+
+ return fileInfo;
}
class QZipReaderPrivate : public QZipPrivate
@@ -816,12 +795,6 @@ void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const
*/
/*!
- \variable FileInfo::d
- \internal
- private pointer.
-*/
-
-/*!
\class QZipReader
\internal
\since 4.5
@@ -913,15 +886,14 @@ bool QZipReader::exists() const
/*!
Returns the list of files the archive contains.
*/
-QList<QZipReader::FileInfo> QZipReader::fileInfoList() const
+QVector<QZipReader::FileInfo> QZipReader::fileInfoList() const
{
d->scanFiles();
- QList<QZipReader::FileInfo> files;
- for (int i = 0; i < d->fileHeaders.size(); ++i) {
- QZipReader::FileInfo fi;
- d->fillFileInfo(i, fi);
- files.append(fi);
- }
+ QVector<FileInfo> files;
+ const int numFileHeaders = d->fileHeaders.size();
+ files.reserve(numFileHeaders);
+ for (int i = 0; i < numFileHeaders; ++i)
+ files.append(d->fillFileInfo(i));
return files;
}
@@ -945,10 +917,9 @@ int QZipReader::count() const
QZipReader::FileInfo QZipReader::entryInfoAt(int index) const
{
d->scanFiles();
- QZipReader::FileInfo fi;
if (index >= 0 && index < d->fileHeaders.count())
- d->fillFileInfo(index, fi);
- return fi;
+ return d->fillFileInfo(index);
+ return QZipReader::FileInfo();
}
/*!
@@ -1044,7 +1015,7 @@ bool QZipReader::extractAll(const QString &destinationDir) const
QDir baseDir(destinationDir);
// create directories first
- QList<FileInfo> allFiles = fileInfoList();
+ const QVector<FileInfo> allFiles = fileInfoList();
foreach (const FileInfo &fi, allFiles) {
const QString absPath = destinationDir + QDir::separator() + fi.filePath;
if (fi.isDir) {
diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h
index df7e2d26e9..7f26bfb184 100644
--- a/src/gui/text/qzipreader_p.h
+++ b/src/gui/text/qzipreader_p.h
@@ -70,13 +70,14 @@ public:
bool isReadable() const;
bool exists() const;
- struct Q_GUI_EXPORT FileInfo
+ struct FileInfo
{
- FileInfo();
- FileInfo(const FileInfo &other);
- ~FileInfo();
- FileInfo &operator=(const FileInfo &other);
- bool isValid() const;
+ FileInfo() Q_DECL_NOTHROW
+ : isDir(false), isFile(false), isSymLink(false), crc(0), size(0)
+ {}
+
+ bool isValid() const Q_DECL_NOTHROW { return isDir || isFile || isSymLink; }
+
QString filePath;
uint isDir : 1;
uint isFile : 1;
@@ -85,10 +86,9 @@ public:
uint crc;
qint64 size;
QDateTime lastModified;
- void *d;
};
- QList<FileInfo> fileInfoList() const;
+ QVector<FileInfo> fileInfoList() const;
int count() const;
FileInfo entryInfoAt(int index) const;
@@ -111,6 +111,8 @@ private:
QZipReaderPrivate *d;
Q_DISABLE_COPY(QZipReader)
};
+Q_DECLARE_TYPEINFO(QZipReader::FileInfo, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QZipReader::Status, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index 61e239f678..be60ba72cc 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -21,6 +21,7 @@ HEADERS += \
text/qtextdocument_p.h \
text/qtexthtmlparser_p.h \
text/qabstracttextdocumentlayout.h \
+ text/qabstracttextdocumentlayout_p.h \
text/qtextdocumentlayout_p.h \
text/qtextcursor.h \
text/qtextcursor_p.h \
@@ -47,6 +48,7 @@ HEADERS += \
SOURCES += \
text/qfont.cpp \
text/qfontengine.cpp \
+ text/qfontengineglyphcache.cpp \
text/qfontsubset.cpp \
text/qfontmetrics.cpp \
text/qfontdatabase.cpp \