summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qfont.cpp240
-rw-r--r--src/gui/text/qfont.h1
-rw-r--r--src/gui/text/qfont_p.h2
-rw-r--r--src/gui/text/qfont_qpa.cpp95
-rw-r--r--src/gui/text/qfontdatabase.h2
-rw-r--r--src/gui/text/qfontengine.cpp115
-rw-r--r--src/gui/text/qfontengine_ft.cpp43
-rw-r--r--src/gui/text/qfontengine_ft_p.h12
-rw-r--r--src/gui/text/qfontengine_p.h31
-rw-r--r--src/gui/text/qfontengine_qpf2.cpp (renamed from src/gui/text/qfontengine_qpa.cpp)286
-rw-r--r--src/gui/text/qfontengine_qpf2_p.h (renamed from src/gui/text/qfontengine_qpa_p.h)49
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp18
-rw-r--r--src/gui/text/qrawfont.cpp18
-rw-r--r--src/gui/text/qrawfont_p.h3
-rw-r--r--src/gui/text/qrawfont_qpa.cpp70
-rw-r--r--src/gui/text/qstatictext_p.h5
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp2
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp27
-rw-r--r--src/gui/text/qtextengine.cpp266
-rw-r--r--src/gui/text/qtextengine_p.h41
-rw-r--r--src/gui/text/qtextlayout.cpp180
-rw-r--r--src/gui/text/text.pri6
22 files changed, 699 insertions, 813 deletions
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index cf40dd028d..cf64c89f2f 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -62,6 +62,8 @@
#include <limits.h>
#include <qpa/qplatformscreen.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformfontdatabase.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/QMutexLocker>
@@ -545,79 +547,6 @@ QFontEngineData::~QFontEngineData()
*/
/*!
- \fn QString QFont::rawName() const
- \deprecated
-
- Returns the name of the font within the underlying window system.
-
- On X11, this function will return an empty string.
-
- Using the return value of this function is usually \e not \e
- portable.
-
- \sa setRawName()
-*/
-
-/*!
- \fn void QFont::setRawName(const QString &name)
- \deprecated
-
- Sets a font by its system specific name.
-
- A font set with setRawName() is still a full-featured QFont. It can
- be queried (for example with italic()) or modified (for example with
- setItalic()) and is therefore also suitable for rendering rich text.
-
- If Qt's internal font database cannot resolve the raw name, the
- font becomes a raw font with \a name as its family.
-
- \sa rawName(), setRawMode(), setFamily()
-*/
-
-/*!
- \fn QString QFont::lastResortFamily() const
-
- Returns the "last resort" font family name.
-
- The current implementation tries a wide variety of common fonts,
- returning the first one it finds. Is is possible that no family is
- found in which case an empty string is returned.
-
- \sa lastResortFont()
-*/
-
-/*!
- \fn QString QFont::defaultFamily() const
-
- Returns the family name that corresponds to the current style
- hint.
-
- \sa StyleHint, styleHint(), setStyleHint()
-*/
-
-/*!
- \fn QString QFont::lastResortFont() const
-
- Returns a "last resort" font name for the font matching algorithm.
- This is used if the last resort family is not available. It will
- always return a name, if necessary returning something like
- "fixed" or "system".
-
- The current implementation tries a wide variety of common fonts,
- returning the first one it finds. The implementation may change
- at any time, but this function will always return a string
- containing something.
-
- It is theoretically possible that there really isn't a
- lastResortFont() in which case Qt will abort with an error
- message. We have not been able to identify a case where this
- happens. Please \l{bughowto.html}{report it as a bug} if
- it does, preferably with a list of the fonts you have installed.
-
- \sa lastResortFamily(), rawName()
-*/
-
-/*!
Constructs a font from \a font for use on the paint device \a pd.
*/
QFont::QFont(const QFont &font, QPaintDevice *pd)
@@ -1376,6 +1305,7 @@ QFont::StyleHint QFont::styleHint() const
\value PreferOutline prefers outline fonts (as opposed to bitmap fonts).
\value ForceOutline forces the use of outline fonts.
\value NoAntialias don't antialias the fonts.
+ \value NoSubpixelAntialias avoid subpixel antialiasing on the fonts if possible.
\value PreferAntialias antialias if possible.
\value OpenGLCompatible forces the use of OpenGL compatible
fonts.
@@ -1913,20 +1843,6 @@ void QFont::insertSubstitutions(const QString &familyName,
}
}
-/*! \fn void QFont::initialize()
- \internal
-
- Internal function that initializes the font system. The font cache
- and font dict do not alloc the keys. The key is a QString which is
- shared between QFontPrivate and QXFontName.
-*/
-
-/*! \fn void QFont::cleanup()
- \internal
-
- Internal function that cleans up the font system.
-*/
-
/*!
Removes all the substitutions for \a familyName.
@@ -2041,6 +1957,42 @@ static void set_extended_font_bits(quint8 bits, QFontPrivate *f)
}
#endif
+/*!
+ \fn QString QFont::rawName() const
+ \deprecated
+
+ Returns the name of the font within the underlying window system.
+
+ On X11, this function will return an empty string.
+
+ Using the return value of this function is usually \e not \e
+ portable.
+
+ \sa setRawName()
+*/
+QString QFont::rawName() const
+{
+ return QLatin1String("unknown");
+}
+
+/*!
+ \fn void QFont::setRawName(const QString &name)
+ \deprecated
+
+ Sets a font by its system specific name.
+
+ A font set with setRawName() is still a full-featured QFont. It can
+ be queried (for example with italic()) or modified (for example with
+ setItalic()) and is therefore also suitable for rendering rich text.
+
+ If Qt's internal font database cannot resolve the raw name, the
+ font becomes a raw font with \a name as its family.
+
+ \sa rawName(), setRawMode(), setFamily()
+*/
+void QFont::setRawName(const QString &)
+{
+}
/*!
Returns the font's key, a textual representation of a font. It is
@@ -2134,17 +2086,96 @@ bool QFont::fromString(const QString &descrip)
return true;
}
+/*! \fn void QFont::initialize()
+ \internal
+
+ Internal function that initializes the font system. The font cache
+ and font dict do not alloc the keys. The key is a QString which is
+ shared between QFontPrivate and QXFontName.
+*/
+void QFont::initialize()
+{
+}
+
+/*! \fn void QFont::cleanup()
+ \internal
+
+ Internal function that cleans up the font system.
+*/
+void QFont::cleanup()
+{
+ QFontCache::cleanup();
+}
+
/*! \internal
Internal function that dumps font cache statistics.
*/
void QFont::cacheStatistics()
{
+}
+
+/*!
+ \fn QString QFont::lastResortFamily() const
+
+ Returns the "last resort" font family name.
+
+ The current implementation tries a wide variety of common fonts,
+ returning the first one it finds. Is is possible that no family is
+ found in which case an empty string is returned.
+
+ \sa lastResortFont()
+*/
+QString QFont::lastResortFamily() const
+{
+ return QString::fromLatin1("helvetica");
+}
+/*!
+ \fn QString QFont::defaultFamily() const
+
+ Returns the family name that corresponds to the current style
+ hint.
+ \sa StyleHint, styleHint(), setStyleHint()
+*/
+QString QFont::defaultFamily() const
+{
+ QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
+ const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal
+ , QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
+ if (!fallbacks.isEmpty())
+ return fallbacks.first();
+ return QString();
}
+/*!
+ \fn QString QFont::lastResortFont() const
+ Returns a "last resort" font name for the font matching algorithm.
+ This is used if the last resort family is not available. It will
+ always return a name, if necessary returning something like
+ "fixed" or "system".
+
+ The current implementation tries a wide variety of common fonts,
+ returning the first one it finds. The implementation may change
+ at any time, but this function will always return a string
+ containing something.
+
+ It is theoretically possible that there really isn't a
+ lastResortFont() in which case Qt will abort with an error
+ message. We have not been able to identify a case where this
+ happens. Please \l{bughowto.html}{report it as a bug} if
+ it does, preferably with a list of the fonts you have installed.
+
+ \sa lastResortFamily(), rawName()
+*/
+QString QFont::lastResortFont() const
+{
+ qFatal("QFont::lastResortFont: Cannot find any reasonable font");
+ // Shut compiler up
+ return QString();
+}
/*****************************************************************************
QFont stream functions
@@ -2165,6 +2196,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << font.d->request.family.toLatin1();
} else {
s << font.d->request.family;
+ if (s.version() >= QDataStream::Qt_5_4)
+ s << font.d->request.styleName;
}
if (s.version() >= QDataStream::Qt_4_0) {
@@ -2185,8 +2218,14 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
}
s << (quint8) font.d->request.styleHint;
- if (s.version() >= QDataStream::Qt_3_1)
- s << (quint8) font.d->request.styleStrategy;
+ if (s.version() >= QDataStream::Qt_3_1) {
+ // Continue writing 8 bits for versions < 5.4 so that we don't write too much,
+ // even though we need 16 to store styleStrategy, so there is some data loss.
+ if (s.version() >= QDataStream::Qt_5_4)
+ s << (quint16) font.d->request.styleStrategy;
+ else
+ s << (quint8) font.d->request.styleStrategy;
+ }
s << (quint8) 0
<< (quint8) font.d->request.weight
<< get_font_bits(s.version(), font.d.data());
@@ -2198,6 +2237,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << font.d->letterSpacing.value();
s << font.d->wordSpacing.value();
}
+ if (s.version() >= QDataStream::Qt_5_4)
+ s << (quint8)font.d->request.hintingPreference;
return s;
}
@@ -2215,7 +2256,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d = new QFontPrivate;
font.resolve_mask = QFont::AllPropertiesResolved;
- quint8 styleHint, styleStrategy = QFont::PreferDefault, charSet, weight, bits;
+ quint8 styleHint, charSet, weight, bits;
+ quint16 styleStrategy = QFont::PreferDefault;
if (s.version() == 1) {
QByteArray fam;
@@ -2223,6 +2265,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d->request.family = QString::fromLatin1(fam);
} else {
s >> font.d->request.family;
+ if (s.version() >= QDataStream::Qt_5_4)
+ s >> font.d->request.styleName;
}
if (s.version() >= QDataStream::Qt_4_0) {
@@ -2242,8 +2286,15 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d->request.pixelSize = pixelSize;
}
s >> styleHint;
- if (s.version() >= QDataStream::Qt_3_1)
- s >> styleStrategy;
+ if (s.version() >= QDataStream::Qt_3_1) {
+ if (s.version() >= QDataStream::Qt_5_4) {
+ s >> styleStrategy;
+ } else {
+ quint8 tempStyleStrategy;
+ s >> tempStyleStrategy;
+ styleStrategy = tempStyleStrategy;
+ }
+ }
s >> charSet;
s >> weight;
@@ -2273,6 +2324,11 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
s >> value;
font.d->wordSpacing.setValue(value);
}
+ if (s.version() >= QDataStream::Qt_5_4) {
+ quint8 value;
+ s >> value;
+ font.d->request.hintingPreference = QFont::HintingPreference(value);
+ }
return s;
}
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index 7fbaf24861..f48f4cf4c5 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -83,6 +83,7 @@ public:
NoAntialias = 0x0100,
OpenGLCompatible = 0x0200,
ForceIntegerMetrics = 0x0400,
+ NoSubpixelAntialias = 0x0800,
NoFontMerging = 0x8000
};
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index 4d8712e76e..be0402b95a 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -92,7 +92,7 @@ struct QFontDef
uint weight : 7; // 0-99
uint fixedPitch : 1;
uint style : 2;
- uint stretch : 12; // 0-400
+ uint stretch : 12; // 0-4000
uint hintingPreference : 2;
uint ignorePitch : 1;
diff --git a/src/gui/text/qfont_qpa.cpp b/src/gui/text/qfont_qpa.cpp
deleted file mode 100644
index be432dc52f..0000000000
--- a/src/gui/text/qfont_qpa.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtGui/private/qguiapplication_p.h>
-#include <qpa/qplatformintegration.h>
-#include <qpa/qplatformfontdatabase.h>
-
-QT_BEGIN_NAMESPACE
-
-void QFont::initialize()
-{
-}
-
-void QFont::cleanup()
-{
- QFontCache::cleanup();
-}
-
-
-/*****************************************************************************
- QFont member functions
- *****************************************************************************/
-
-QString QFont::rawName() const
-{
- return QLatin1String("unknown");
-}
-
-void QFont::setRawName(const QString &)
-{
-}
-
-QString QFont::defaultFamily() const
-{
- QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
- const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal
- , QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
- if (!fallbacks.isEmpty())
- return fallbacks.first();
- return QString();
-}
-
-QString QFont::lastResortFamily() const
-{
- return QString::fromLatin1("helvetica");
-}
-
-QString QFont::lastResortFont() const
-{
- qFatal("QFont::lastResortFont: Cannot find any reasonable font");
- // Shut compiler up
- return QString();
-}
-
-
-QT_END_NAMESPACE
-
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index 833e574707..245d1cf81b 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -167,7 +167,7 @@ private:
friend class QFontPrivate;
friend class QFontDialog;
friend class QFontDialogPrivate;
- friend class QFontEngineMultiQPA;
+ friend class QFontEngineMultiBasicImpl;
QFontDatabasePrivate *d;
};
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 8adbb31a55..5f801c3bf4 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -42,6 +42,10 @@
#include <qdebug.h>
#include <private/qfontengine_p.h>
#include <private/qfontengineglyphcache_p.h>
+#include <private/qguiapplication_p.h>
+
+#include <qpa/qplatformfontdatabase.h>
+#include <qpa/qplatformintegration.h>
#include "qbitmap.h"
#include "qpainter.h"
@@ -2000,4 +2004,115 @@ QImage QFontEngineMulti::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosit
return engine(which)->alphaRGBMapForGlyph(stripped(glyph), subPixelPosition, t);
}
+/*
+ Creates a new multi engine.
+
+ This function takes ownership of the QFontEngine, increasing it's refcount.
+*/
+QFontEngineMultiBasicImpl::QFontEngineMultiBasicImpl(QFontEngine *fe, int _script, const QStringList &fallbacks)
+ : QFontEngineMulti(fallbacks.size() + 1),
+ fallbackFamilies(fallbacks), script(_script)
+ , fallbacksQueried(true)
+{
+ init(fe);
+}
+
+QFontEngineMultiBasicImpl::QFontEngineMultiBasicImpl(QFontEngine *fe, int _script)
+ : QFontEngineMulti(2)
+ , script(_script)
+ , fallbacksQueried(false)
+{
+ fallbackFamilies << QString();
+ init(fe);
+}
+
+void QFontEngineMultiBasicImpl::init(QFontEngine *fe)
+{
+ Q_ASSERT(fe && fe->type() != QFontEngine::Multi);
+ engines[0] = fe;
+ fe->ref.ref();
+ fontDef = engines[0]->fontDef;
+ cache_cost = fe->cache_cost;
+}
+
+void QFontEngineMultiBasicImpl::loadEngine(int at)
+{
+ ensureFallbackFamiliesQueried();
+ Q_ASSERT(at < engines.size());
+ Q_ASSERT(engines.at(at) == 0);
+ QFontDef request = fontDef;
+ request.styleStrategy |= QFont::NoFontMerging;
+ request.family = fallbackFamilies.at(at-1);
+ engines[at] = QFontDatabase::findFont(script,
+ /*fontprivate = */0,
+ request, /*multi = */false, true);
+ Q_ASSERT(engines[at]);
+ engines[at]->ref.ref();
+ engines[at]->fontDef = request;
+}
+void QFontEngineMultiBasicImpl::ensureFallbackFamiliesQueried()
+{
+ if (fallbacksQueried)
+ return;
+ QStringList fallbacks = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fallbacksForFamily(engine(0)->fontDef.family, QFont::Style(engine(0)->fontDef.style)
+ , QFont::AnyStyle, QChar::Script(script));
+ setFallbackFamiliesList(fallbacks);
+}
+
+void QFontEngineMultiBasicImpl::setFallbackFamiliesList(const QStringList &fallbacks)
+{
+ // Original FontEngine to restore after the fill.
+ QFontEngine *fe = engines[0];
+ fallbackFamilies = fallbacks;
+ if (!fallbackFamilies.isEmpty()) {
+ engines.fill(0, fallbackFamilies.size() + 1);
+ engines[0] = fe;
+ } else {
+ // Turns out we lied about having any fallback at all.
+ fallbackFamilies << fe->fontDef.family;
+ engines[1] = fe;
+ fe->ref.ref();
+ }
+ fallbacksQueried = true;
+}
+
+/*
+ This is used indirectly by Qt WebKit when using QTextLayout::setRawFont
+
+ The purpose of this is to provide the necessary font fallbacks when drawing complex
+ text. Since Qt WebKit ends up repeatedly creating QTextLayout instances and passing them
+ the same raw font over and over again, we want to cache the corresponding multi font engine
+ as it may contain fallback font engines already.
+*/
+QFontEngine* QFontEngineMultiBasicImpl::createMultiFontEngine(QFontEngine *fe, int script)
+{
+ QFontEngine *engine = 0;
+ QFontCache::Key key(fe->fontDef, script, /*multi = */true);
+ QFontCache *fc = QFontCache::instance();
+ // We can't rely on the fontDef (and hence the cache Key)
+ // alone to distinguish webfonts, since these should not be
+ // accidentally shared, even if the resulting fontcache key
+ // is strictly identical. See:
+ // http://www.w3.org/TR/css3-fonts/#font-face-rule
+ const bool faceIsLocal = !fe->faceId().filename.isEmpty();
+ QFontCache::EngineCache::Iterator it = fc->engineCache.find(key),
+ end = fc->engineCache.end();
+ while (it != end && it.key() == key) {
+ Q_ASSERT(it.value().data->type() == QFontEngine::Multi);
+ QFontEngineMulti *cachedEngine = static_cast<QFontEngineMulti *>(it.value().data);
+ if (fe == cachedEngine->engine(0) || (faceIsLocal && fe->faceId().filename == cachedEngine->engine(0)->faceId().filename)) {
+ engine = cachedEngine;
+ fc->updateHitCountAndTimeStamp(it.value());
+ break;
+ }
+ it++;
+ }
+ if (!engine) {
+ engine = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fontEngineMulti(fe, QChar::Script(script));
+ QFontCache::instance()->insertEngine(key, engine, /* insertMulti */ !faceIsLocal);
+ }
+ Q_ASSERT(engine);
+ return engine;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index f5ca559d62..0a22038bb4 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -132,6 +132,7 @@ static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *leng
return result;
}
+static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0};
// -------------------------- Freetype support ------------------------------
@@ -678,6 +679,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
const QByteArray env = qgetenv("QT_NO_FT_CACHE");
cacheEnabled = env.isEmpty() || env.toInt() == 0;
m_subPixelPositionCount = 4;
+ forceAutoHint = false;
}
QFontEngineFT::~QFontEngineFT()
@@ -813,11 +815,11 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
if (format == Format_Mono) {
load_target = FT_LOAD_TARGET_MONO;
} else if (format == Format_A32) {
- if (subpixelType == QFontEngineFT::Subpixel_RGB || subpixelType == QFontEngineFT::Subpixel_BGR) {
+ if (subpixelType == Subpixel_RGB || subpixelType == Subpixel_BGR) {
if (default_hint_style == HintFull)
load_target = FT_LOAD_TARGET_LCD;
hsubpixel = true;
- } else if (subpixelType == QFontEngineFT::Subpixel_VRGB || subpixelType == QFontEngineFT::Subpixel_VBGR) {
+ } else if (subpixelType == Subpixel_VRGB || subpixelType == Subpixel_VBGR) {
if (default_hint_style == HintFull)
load_target = FT_LOAD_TARGET_LCD_V;
vfactor = 3;
@@ -825,13 +827,16 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
}
if (set && set->outline_drawing)
- load_flags = FT_LOAD_NO_BITMAP;
+ load_flags |= FT_LOAD_NO_BITMAP;
if (default_hint_style == HintNone || (flags & DesignMetrics) || (set && set->outline_drawing))
load_flags |= FT_LOAD_NO_HINTING;
else
load_flags |= load_target;
+ if (forceAutoHint)
+ load_flags |= FT_LOAD_FORCE_AUTOHINT;
+
return load_flags;
}
@@ -854,6 +859,9 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
if (g && g->format == format && (fetchMetricsOnly || g->data))
return g;
+ if (!g && set && set->isGlyphMissing(glyph))
+ return &emptyGlyph;
+
QFontEngineFT::GlyphInfo info;
Q_ASSERT(format != Format_None);
@@ -890,8 +898,12 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
load_flags |= FT_LOAD_FORCE_AUTOHINT;
err = FT_Load_Glyph(face, glyph, load_flags);
}
- if (err != FT_Err_Ok)
+ if (err != FT_Err_Ok) {
qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
+ if (set)
+ set->setGlyphMissing(glyph);
+ return &emptyGlyph;
+ }
FT_GlyphSlot slot = face->glyph;
@@ -977,9 +989,9 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
glyph_buffer = new uchar[glyph_buffer_size];
if (hsubpixel)
- convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_RGB, false);
+ convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB, false);
else if (vfactor != 1)
- convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_VRGB, false);
+ convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB, false);
} else
#endif
{
@@ -1091,10 +1103,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
convoluteBitmap(bitmap.buffer, convoluted, bitmap.width, info.height, bitmap.pitch);
buffer = convoluted;
}
- convertRGBToARGB(buffer + 1, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_RGB, useLegacyLcdFilter);
+ convertRGBToARGB(buffer + 1, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != Subpixel_RGB, useLegacyLcdFilter);
delete [] convoluted;
} else if (vfactor != 1) {
- convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_VRGB, true);
+ convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != Subpixel_VRGB, true);
} else if (format == Format_A32 && bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
convertGRAYToARGB(bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch);
}
@@ -1629,9 +1641,12 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag
if (!face)
face = lockFace();
g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs->glyphs[i], 0, Format_None, true);
- glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10)
- : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
- if (!cacheEnabled)
+ if (g)
+ glyphs->advances[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
+ else
+ glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10)
+ : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
+ if (!cacheEnabled && g != &emptyGlyph)
delete g;
}
}
@@ -1670,7 +1685,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
xmax = qMax(xmax, x + g->width);
ymax = qMax(ymax, y + g->height);
overall.xoff += g->advance;
- if (!cacheEnabled)
+ if (!cacheEnabled && g != &emptyGlyph)
delete g;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
@@ -1713,7 +1728,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
overall.xoff = g->advance;
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
overall.xoff = overall.xoff.round();
- if (!cacheEnabled)
+ if (!cacheEnabled && g != &emptyGlyph)
delete g;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
@@ -1804,7 +1819,7 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe
overall.width = g->width;
overall.height = g->height;
overall.xoff = g->advance;
- if (!glyphSet)
+ if (!glyphSet && g != &emptyGlyph)
delete g;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 8bdf991174..e23024e472 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -150,14 +150,6 @@ public:
uchar *data;
};
- enum SubpixelAntialiasingType {
- Subpixel_None,
- Subpixel_RGB,
- Subpixel_BGR,
- Subpixel_VRGB,
- Subpixel_VBGR
- };
-
struct GlyphInfo {
unsigned short width;
unsigned short height;
@@ -195,8 +187,11 @@ public:
inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const;
void setGlyph(glyph_t index, QFixed spp, Glyph *glyph);
+ inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); }
+ inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); }
private:
mutable QHash<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data
+ mutable QSet<glyph_t> missing_glyphs;
mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
mutable int fast_glyph_count;
};
@@ -315,6 +310,7 @@ protected:
int lcdFilterType;
bool embeddedbitmap;
bool cacheEnabled;
+ bool forceAutoHint;
private:
friend class QFontEngineFTRawFont;
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index fc849d788f..bb05d12bbb 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -261,6 +261,14 @@ public:
};
virtual void setDefaultHintStyle(HintStyle) { }
+ enum SubpixelAntialiasingType {
+ Subpixel_None,
+ Subpixel_RGB,
+ Subpixel_BGR,
+ Subpixel_VRGB,
+ Subpixel_VBGR
+ };
+
private:
const Type m_type;
@@ -433,6 +441,29 @@ protected:
QVector<QFontEngine *> engines;
};
+class Q_GUI_EXPORT QFontEngineMultiBasicImpl : public QFontEngineMulti
+{
+public:
+ QFontEngineMultiBasicImpl(QFontEngine *fe, int script, const QStringList &fallbacks);
+ QFontEngineMultiBasicImpl(QFontEngine *fe, int script);
+
+ void loadEngine(int at);
+ static QFontEngine* createMultiFontEngine(QFontEngine *fe, int script);
+
+ int fallbackFamilyCount() const { return fallbackFamilies.size(); }
+ QString fallbackFamilyAt(int at) const { return fallbackFamilies.at(at); }
+
+ virtual void ensureFallbackFamiliesQueried();
+ virtual void setFallbackFamiliesList(const QStringList &fallbacks);
+
+private:
+ void init(QFontEngine *fe);
+
+ mutable QStringList fallbackFamilies;
+ int script;
+ mutable bool fallbacksQueried;
+};
+
class QTestFontEngine : public QFontEngineBox
{
public:
diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpf2.cpp
index a115d2a901..bcb128baac 100644
--- a/src/gui/text/qfontengine_qpa.cpp
+++ b/src/gui/text/qfontengine_qpf2.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include "qfontengine_qpa_p.h"
+#include "qfontengine_qpf2_p.h"
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
@@ -57,28 +57,28 @@ QT_BEGIN_NAMESPACE
//#define DEBUG_HEADER
//#define DEBUG_FONTENGINE
-static QFontEngineQPA::TagType tagTypes[QFontEngineQPA::NumTags] = {
- QFontEngineQPA::StringType, // FontName
- QFontEngineQPA::StringType, // FileName
- QFontEngineQPA::UInt32Type, // FileIndex
- QFontEngineQPA::UInt32Type, // FontRevision
- QFontEngineQPA::StringType, // FreeText
- QFontEngineQPA::FixedType, // Ascent
- QFontEngineQPA::FixedType, // Descent
- QFontEngineQPA::FixedType, // Leading
- QFontEngineQPA::FixedType, // XHeight
- QFontEngineQPA::FixedType, // AverageCharWidth
- QFontEngineQPA::FixedType, // MaxCharWidth
- QFontEngineQPA::FixedType, // LineThickness
- QFontEngineQPA::FixedType, // MinLeftBearing
- QFontEngineQPA::FixedType, // MinRightBearing
- QFontEngineQPA::FixedType, // UnderlinePosition
- QFontEngineQPA::UInt8Type, // GlyphFormat
- QFontEngineQPA::UInt8Type, // PixelSize
- QFontEngineQPA::UInt8Type, // Weight
- QFontEngineQPA::UInt8Type, // Style
- QFontEngineQPA::StringType, // EndOfHeader
- QFontEngineQPA::BitFieldType// WritingSystems
+static QFontEngineQPF2::TagType tagTypes[QFontEngineQPF2::NumTags] = {
+ QFontEngineQPF2::StringType, // FontName
+ QFontEngineQPF2::StringType, // FileName
+ QFontEngineQPF2::UInt32Type, // FileIndex
+ QFontEngineQPF2::UInt32Type, // FontRevision
+ QFontEngineQPF2::StringType, // FreeText
+ QFontEngineQPF2::FixedType, // Ascent
+ QFontEngineQPF2::FixedType, // Descent
+ QFontEngineQPF2::FixedType, // Leading
+ QFontEngineQPF2::FixedType, // XHeight
+ QFontEngineQPF2::FixedType, // AverageCharWidth
+ QFontEngineQPF2::FixedType, // MaxCharWidth
+ QFontEngineQPF2::FixedType, // LineThickness
+ QFontEngineQPF2::FixedType, // MinLeftBearing
+ QFontEngineQPF2::FixedType, // MinRightBearing
+ QFontEngineQPF2::FixedType, // UnderlinePosition
+ QFontEngineQPF2::UInt8Type, // GlyphFormat
+ QFontEngineQPF2::UInt8Type, // PixelSize
+ QFontEngineQPF2::UInt8Type, // Weight
+ QFontEngineQPF2::UInt8Type, // Style
+ QFontEngineQPF2::StringType, // EndOfHeader
+ QFontEngineQPF2::BitFieldType// WritingSystems
};
@@ -122,21 +122,21 @@ static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr)
quint16 tag, length;
READ_VERIFY(quint16, tag);
READ_VERIFY(quint16, length);
- if (tag == QFontEngineQPA::Tag_EndOfHeader)
+ if (tag == QFontEngineQPF2::Tag_EndOfHeader)
return endPtr;
- if (tag < QFontEngineQPA::NumTags) {
+ if (tag < QFontEngineQPF2::NumTags) {
switch (tagTypes[tag]) {
- case QFontEngineQPA::BitFieldType:
- case QFontEngineQPA::StringType:
+ case QFontEngineQPF2::BitFieldType:
+ case QFontEngineQPF2::StringType:
// can't do anything...
break;
- case QFontEngineQPA::UInt32Type:
+ case QFontEngineQPF2::UInt32Type:
VERIFY_TAG(length == sizeof(quint32));
break;
- case QFontEngineQPA::FixedType:
+ case QFontEngineQPF2::FixedType:
VERIFY_TAG(length == sizeof(quint32));
break;
- case QFontEngineQPA::UInt8Type:
+ case QFontEngineQPF2::UInt8Type:
VERIFY_TAG(length == sizeof(quint8));
break;
}
@@ -150,7 +150,7 @@ static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr)
return tagPtr + length;
}
-const QFontEngineQPA::Glyph *QFontEngineQPA::findGlyph(glyph_t g) const
+const QFontEngineQPF2::Glyph *QFontEngineQPF2::findGlyph(glyph_t g) const
{
if (!g || g >= glyphMapEntries)
return 0;
@@ -168,7 +168,7 @@ const QFontEngineQPA::Glyph *QFontEngineQPA::findGlyph(glyph_t g) const
return reinterpret_cast<const Glyph *>(fontData + glyphDataOffset + glyphPos);
}
-bool QFontEngineQPA::verifyHeader(const uchar *data, int size)
+bool QFontEngineQPF2::verifyHeader(const uchar *data, int size)
{
VERIFY(quintptr(data) % Q_ALIGNOF(Header) == 0);
VERIFY(size >= int(sizeof(Header)));
@@ -194,7 +194,7 @@ bool QFontEngineQPA::verifyHeader(const uchar *data, int size)
return true;
}
-QVariant QFontEngineQPA::extractHeaderField(const uchar *data, HeaderTag requestedTag)
+QVariant QFontEngineQPF2::extractHeaderField(const uchar *data, HeaderTag requestedTag)
{
const Header *header = reinterpret_cast<const Header *>(data);
const uchar *tagPtr = data + sizeof(Header);
@@ -226,7 +226,7 @@ QVariant QFontEngineQPA::extractHeaderField(const uchar *data, HeaderTag request
}
-QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data)
+QFontEngineQPF2::QFontEngineQPF2(const QFontDef &def, const QByteArray &data)
: QFontEngine(QPF2),
fontData(reinterpret_cast<const uchar *>(data.constData())), dataSize(data.size())
{
@@ -243,7 +243,7 @@ QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data)
readOnly = true;
#if defined(DEBUG_FONTENGINE)
- qDebug() << "QFontEngineQPA::QFontEngineQPA( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')';
+ qDebug() << "QFontEngineQPF2::QFontEngineQPF2( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')';
#endif
if (!verifyHeader(fontData, dataSize)) {
@@ -312,11 +312,11 @@ QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data)
#endif
}
-QFontEngineQPA::~QFontEngineQPA()
+QFontEngineQPF2::~QFontEngineQPF2()
{
}
-bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) const
+bool QFontEngineQPF2::getSfntTableData(uint tag, uchar *buffer, uint *length) const
{
if (tag != MAKE_TAG('c', 'm', 'a', 'p') || !cmap)
return false;
@@ -328,7 +328,7 @@ bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) con
return true;
}
-glyph_t QFontEngineQPA::glyphIndex(uint ucs4) const
+glyph_t QFontEngineQPF2::glyphIndex(uint ucs4) const
{
glyph_t glyph = getTrueTypeGlyphIndex(cmap, ucs4);
if (glyph == 0 && symbol && ucs4 < 0x100)
@@ -339,7 +339,7 @@ glyph_t QFontEngineQPA::glyphIndex(uint ucs4) const
return glyph;
}
-bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
+bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
if (*nglyphs < len) {
@@ -386,7 +386,7 @@ bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
return true;
}
-void QFontEngineQPA::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
+void QFontEngineQPF2::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
{
for (int i = 0; i < glyphs->numGlyphs; ++i) {
const Glyph *g = findGlyph(glyphs->glyphs[i]);
@@ -396,7 +396,7 @@ void QFontEngineQPA::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFla
}
}
-QImage QFontEngineQPA::alphaMapForGlyph(glyph_t g)
+QImage QFontEngineQPF2::alphaMapForGlyph(glyph_t g)
{
const Glyph *glyph = findGlyph(g);
if (!glyph)
@@ -409,12 +409,12 @@ QImage QFontEngineQPA::alphaMapForGlyph(glyph_t g)
return image;
}
-void QFontEngineQPA::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
+void QFontEngineQPF2::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
{
addBitmapFontToPath(x, y, glyphs, path, flags);
}
-glyph_metrics_t QFontEngineQPA::boundingBox(const QGlyphLayout &glyphs)
+glyph_metrics_t QFontEngineQPF2::boundingBox(const QGlyphLayout &glyphs)
{
glyph_metrics_t overall;
// initialize with line height, we get the same behaviour on all platforms
@@ -442,7 +442,7 @@ glyph_metrics_t QFontEngineQPA::boundingBox(const QGlyphLayout &glyphs)
return overall;
}
-glyph_metrics_t QFontEngineQPA::boundingBox(glyph_t glyph)
+glyph_metrics_t QFontEngineQPF2::boundingBox(glyph_t glyph)
{
glyph_metrics_t overall;
const Glyph *g = findGlyph(glyph);
@@ -456,107 +456,107 @@ glyph_metrics_t QFontEngineQPA::boundingBox(glyph_t glyph)
return overall;
}
-QFixed QFontEngineQPA::ascent() const
+QFixed QFontEngineQPF2::ascent() const
{
return QFixed::fromReal(extractHeaderField(fontData, Tag_Ascent).value<qreal>());
}
-QFixed QFontEngineQPA::descent() const
+QFixed QFontEngineQPF2::descent() const
{
return QFixed::fromReal(extractHeaderField(fontData, Tag_Descent).value<qreal>());
}
-QFixed QFontEngineQPA::leading() const
+QFixed QFontEngineQPF2::leading() const
{
return QFixed::fromReal(extractHeaderField(fontData, Tag_Leading).value<qreal>());
}
-qreal QFontEngineQPA::maxCharWidth() const
+qreal QFontEngineQPF2::maxCharWidth() const
{
return extractHeaderField(fontData, Tag_MaxCharWidth).value<qreal>();
}
-qreal QFontEngineQPA::minLeftBearing() const
+qreal QFontEngineQPF2::minLeftBearing() const
{
return extractHeaderField(fontData, Tag_MinLeftBearing).value<qreal>();
}
-qreal QFontEngineQPA::minRightBearing() const
+qreal QFontEngineQPF2::minRightBearing() const
{
return extractHeaderField(fontData, Tag_MinRightBearing).value<qreal>();
}
-QFixed QFontEngineQPA::underlinePosition() const
+QFixed QFontEngineQPF2::underlinePosition() const
{
return QFixed::fromReal(extractHeaderField(fontData, Tag_UnderlinePosition).value<qreal>());
}
-QFixed QFontEngineQPA::lineThickness() const
+QFixed QFontEngineQPF2::lineThickness() const
{
return QFixed::fromReal(extractHeaderField(fontData, Tag_LineThickness).value<qreal>());
}
-bool QFontEngineQPA::isValid() const
+bool QFontEngineQPF2::isValid() const
{
return fontData && dataSize && cmapOffset
&& glyphMapOffset && glyphDataOffset && glyphDataSize > 0;
}
-void QPAGenerator::generate()
+void QPF2Generator::generate()
{
writeHeader();
writeGMap();
- writeBlock(QFontEngineQPA::GlyphBlock, QByteArray());
+ writeBlock(QFontEngineQPF2::GlyphBlock, QByteArray());
dev->seek(4); // position of header.lock
writeUInt32(0);
}
-void QPAGenerator::writeHeader()
+void QPF2Generator::writeHeader()
{
- QFontEngineQPA::Header header;
+ QFontEngineQPF2::Header header;
header.magic[0] = 'Q';
header.magic[1] = 'P';
header.magic[2] = 'F';
header.magic[3] = '2';
header.lock = 1;
- header.majorVersion = QFontEngineQPA::CurrentMajorVersion;
- header.minorVersion = QFontEngineQPA::CurrentMinorVersion;
+ header.majorVersion = QFontEngineQPF2::CurrentMajorVersion;
+ header.minorVersion = QFontEngineQPF2::CurrentMinorVersion;
header.dataSize = 0;
dev->write((const char *)&header, sizeof(header));
- writeTaggedString(QFontEngineQPA::Tag_FontName, fe->fontDef.family.toUtf8());
+ writeTaggedString(QFontEngineQPF2::Tag_FontName, fe->fontDef.family.toUtf8());
QFontEngine::FaceId face = fe->faceId();
- writeTaggedString(QFontEngineQPA::Tag_FileName, face.filename);
- writeTaggedUInt32(QFontEngineQPA::Tag_FileIndex, face.index);
+ writeTaggedString(QFontEngineQPF2::Tag_FileName, face.filename);
+ writeTaggedUInt32(QFontEngineQPF2::Tag_FileIndex, face.index);
{
const QByteArray head = fe->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd'));
if (head.size() >= 4) {
const quint32 revision = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(head.constData()));
- writeTaggedUInt32(QFontEngineQPA::Tag_FontRevision, revision);
+ writeTaggedUInt32(QFontEngineQPF2::Tag_FontRevision, revision);
}
}
- writeTaggedQFixed(QFontEngineQPA::Tag_Ascent, fe->ascent());
- writeTaggedQFixed(QFontEngineQPA::Tag_Descent, fe->descent());
- writeTaggedQFixed(QFontEngineQPA::Tag_Leading, fe->leading());
- writeTaggedQFixed(QFontEngineQPA::Tag_XHeight, fe->xHeight());
- writeTaggedQFixed(QFontEngineQPA::Tag_AverageCharWidth, fe->averageCharWidth());
- writeTaggedQFixed(QFontEngineQPA::Tag_MaxCharWidth, QFixed::fromReal(fe->maxCharWidth()));
- writeTaggedQFixed(QFontEngineQPA::Tag_LineThickness, fe->lineThickness());
- writeTaggedQFixed(QFontEngineQPA::Tag_MinLeftBearing, QFixed::fromReal(fe->minLeftBearing()));
- writeTaggedQFixed(QFontEngineQPA::Tag_MinRightBearing, QFixed::fromReal(fe->minRightBearing()));
- writeTaggedQFixed(QFontEngineQPA::Tag_UnderlinePosition, fe->underlinePosition());
- writeTaggedUInt8(QFontEngineQPA::Tag_PixelSize, fe->fontDef.pixelSize);
- writeTaggedUInt8(QFontEngineQPA::Tag_Weight, fe->fontDef.weight);
- writeTaggedUInt8(QFontEngineQPA::Tag_Style, fe->fontDef.style);
-
- writeTaggedUInt8(QFontEngineQPA::Tag_GlyphFormat, QFontEngineQPA::AlphamapGlyphs);
-
- writeTaggedString(QFontEngineQPA::Tag_EndOfHeader, QByteArray());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_Ascent, fe->ascent());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_Descent, fe->descent());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_Leading, fe->leading());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_XHeight, fe->xHeight());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_AverageCharWidth, fe->averageCharWidth());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_MaxCharWidth, QFixed::fromReal(fe->maxCharWidth()));
+ writeTaggedQFixed(QFontEngineQPF2::Tag_LineThickness, fe->lineThickness());
+ writeTaggedQFixed(QFontEngineQPF2::Tag_MinLeftBearing, QFixed::fromReal(fe->minLeftBearing()));
+ writeTaggedQFixed(QFontEngineQPF2::Tag_MinRightBearing, QFixed::fromReal(fe->minRightBearing()));
+ writeTaggedQFixed(QFontEngineQPF2::Tag_UnderlinePosition, fe->underlinePosition());
+ writeTaggedUInt8(QFontEngineQPF2::Tag_PixelSize, fe->fontDef.pixelSize);
+ writeTaggedUInt8(QFontEngineQPF2::Tag_Weight, fe->fontDef.weight);
+ writeTaggedUInt8(QFontEngineQPF2::Tag_Style, fe->fontDef.style);
+
+ writeTaggedUInt8(QFontEngineQPF2::Tag_GlyphFormat, QFontEngineQPF2::AlphamapGlyphs);
+
+ writeTaggedString(QFontEngineQPF2::Tag_EndOfHeader, QByteArray());
align4();
const quint64 size = dev->pos();
@@ -566,11 +566,11 @@ void QPAGenerator::writeHeader()
dev->seek(size);
}
-void QPAGenerator::writeGMap()
+void QPF2Generator::writeGMap()
{
const quint16 glyphCount = fe->glyphCount();
- writeUInt16(QFontEngineQPA::GMapBlock);
+ writeUInt16(QFontEngineQPF2::GMapBlock);
writeUInt16(0); // padding
writeUInt32(glyphCount * 4);
@@ -582,7 +582,7 @@ void QPAGenerator::writeGMap()
dev->seek(pos + numBytes);
}
-void QPAGenerator::writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data)
+void QPF2Generator::writeBlock(QFontEngineQPF2::BlockTag tag, const QByteArray &data)
{
writeUInt16(tag);
writeUInt16(0); // padding
@@ -593,144 +593,32 @@ void QPAGenerator::writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &da
writeUInt8(0);
}
-void QPAGenerator::writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string)
+void QPF2Generator::writeTaggedString(QFontEngineQPF2::HeaderTag tag, const QByteArray &string)
{
writeUInt16(tag);
writeUInt16(string.length());
dev->write(string);
}
-void QPAGenerator::writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value)
+void QPF2Generator::writeTaggedUInt32(QFontEngineQPF2::HeaderTag tag, quint32 value)
{
writeUInt16(tag);
writeUInt16(sizeof(value));
writeUInt32(value);
}
-void QPAGenerator::writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value)
+void QPF2Generator::writeTaggedUInt8(QFontEngineQPF2::HeaderTag tag, quint8 value)
{
writeUInt16(tag);
writeUInt16(sizeof(value));
writeUInt8(value);
}
-void QPAGenerator::writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value)
+void QPF2Generator::writeTaggedQFixed(QFontEngineQPF2::HeaderTag tag, QFixed value)
{
writeUInt16(tag);
writeUInt16(sizeof(quint32));
writeUInt32(value.value());
}
-
-/*
- Creates a new multi QPA engine.
-
- This function takes ownership of the QFontEngine, increasing it's refcount.
-*/
-QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QStringList &fallbacks)
- : QFontEngineMulti(fallbacks.size() + 1),
- fallbackFamilies(fallbacks), script(_script)
- , fallbacksQueried(true)
-{
- init(fe);
-}
-
-QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script)
- : QFontEngineMulti(2)
- , script(_script)
- , fallbacksQueried(false)
-{
- fallbackFamilies << QString();
- init(fe);
-}
-
-void QFontEngineMultiQPA::init(QFontEngine *fe)
-{
- Q_ASSERT(fe && fe->type() != QFontEngine::Multi);
- engines[0] = fe;
- fe->ref.ref();
- fontDef = engines[0]->fontDef;
- cache_cost = fe->cache_cost;
-}
-
-void QFontEngineMultiQPA::loadEngine(int at)
-{
- ensureFallbackFamiliesQueried();
- Q_ASSERT(at < engines.size());
- Q_ASSERT(engines.at(at) == 0);
- QFontDef request = fontDef;
- request.styleStrategy |= QFont::NoFontMerging;
- request.family = fallbackFamilies.at(at-1);
- engines[at] = QFontDatabase::findFont(script,
- /*fontprivate = */0,
- request, /*multi = */false, true);
- Q_ASSERT(engines[at]);
- engines[at]->ref.ref();
- engines[at]->fontDef = request;
-}
-void QFontEngineMultiQPA::ensureFallbackFamiliesQueried()
-{
- if (fallbacksQueried)
- return;
- QStringList fallbacks = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fallbacksForFamily(engine(0)->fontDef.family, QFont::Style(engine(0)->fontDef.style)
- , QFont::AnyStyle, QChar::Script(script));
- setFallbackFamiliesList(fallbacks);
-}
-
-void QFontEngineMultiQPA::setFallbackFamiliesList(const QStringList &fallbacks)
-{
- // Original FontEngine to restore after the fill.
- QFontEngine *fe = engines[0];
- fallbackFamilies = fallbacks;
- if (!fallbackFamilies.isEmpty()) {
- engines.fill(0, fallbackFamilies.size() + 1);
- engines[0] = fe;
- } else {
- // Turns out we lied about having any fallback at all.
- fallbackFamilies << fe->fontDef.family;
- engines[1] = fe;
- fe->ref.ref();
- }
- fallbacksQueried = true;
-}
-
-/*
- This is used indirectly by Qt WebKit when using QTextLayout::setRawFont
-
- The purpose of this is to provide the necessary font fallbacks when drawing complex
- text. Since Qt WebKit ends up repeatedly creating QTextLayout instances and passing them
- the same raw font over and over again, we want to cache the corresponding multi font engine
- as it may contain fallback font engines already.
-*/
-QFontEngine* QFontEngineMultiQPA::createMultiFontEngine(QFontEngine *fe, int script)
-{
- QFontEngine *engine = 0;
- QFontCache::Key key(fe->fontDef, script, /*multi = */true);
- QFontCache *fc = QFontCache::instance();
- // We can't rely on the fontDef (and hence the cache Key)
- // alone to distinguish webfonts, since these should not be
- // accidentally shared, even if the resulting fontcache key
- // is strictly identical. See:
- // http://www.w3.org/TR/css3-fonts/#font-face-rule
- const bool faceIsLocal = !fe->faceId().filename.isEmpty();
- QFontCache::EngineCache::Iterator it = fc->engineCache.find(key),
- end = fc->engineCache.end();
- while (it != end && it.key() == key) {
- Q_ASSERT(it.value().data->type() == QFontEngine::Multi);
- QFontEngineMulti *cachedEngine = static_cast<QFontEngineMulti *>(it.value().data);
- if (faceIsLocal || fe == cachedEngine->engine(0)) {
- engine = cachedEngine;
- fc->updateHitCountAndTimeStamp(it.value());
- break;
- }
- it++;
- }
- if (!engine) {
- engine = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fontEngineMulti(fe, QChar::Script(script));
- QFontCache::instance()->insertEngine(key, engine, /* insertMulti */ !faceIsLocal);
- }
- Q_ASSERT(engine);
- return engine;
-}
-
QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengine_qpa_p.h b/src/gui/text/qfontengine_qpf2_p.h
index e84b067c68..a616cc3300 100644
--- a/src/gui/text/qfontengine_qpa_p.h
+++ b/src/gui/text/qfontengine_qpf2_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QFONTENGINE_QPA_P_H
-#define QFONTENGINE_QPA_P_H
+#ifndef QFONTENGINE_QPF2_P_H
+#define QFONTENGINE_QPF2_P_H
//
// W A R N I N G
@@ -67,7 +67,7 @@ class QFontEngine;
class QFreetypeFace;
class QBuffer;
-class Q_GUI_EXPORT QFontEngineQPA : public QFontEngine
+class Q_GUI_EXPORT QFontEngineQPF2 : public QFontEngine
{
public:
// if you add new tags please make sure to update the tables in
@@ -157,8 +157,8 @@ public:
qint8 advance;
};
- QFontEngineQPA(const QFontDef &def, const QByteArray &data);
- ~QFontEngineQPA();
+ QFontEngineQPF2(const QFontDef &def, const QByteArray &data);
+ ~QFontEngineQPF2();
FaceId faceId() const { return face_id; }
bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
@@ -211,20 +211,20 @@ private:
mutable bool kerning_pairs_loaded;
};
-struct QPAGenerator
+struct QPF2Generator
{
- QPAGenerator(QBuffer *device, QFontEngine *engine)
+ QPF2Generator(QBuffer *device, QFontEngine *engine)
: dev(device), fe(engine) {}
void generate();
void writeHeader();
void writeGMap();
- void writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data);
+ void writeBlock(QFontEngineQPF2::BlockTag tag, const QByteArray &data);
- void writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string);
- void writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value);
- void writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value);
- void writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value);
+ void writeTaggedString(QFontEngineQPF2::HeaderTag tag, const QByteArray &string);
+ void writeTaggedUInt32(QFontEngineQPF2::HeaderTag tag, quint32 value);
+ void writeTaggedUInt8(QFontEngineQPF2::HeaderTag tag, quint8 value);
+ void writeTaggedQFixed(QFontEngineQPF2::HeaderTag tag, QFixed value);
void writeUInt16(quint16 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); }
void writeUInt32(quint32 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); }
@@ -237,29 +237,6 @@ struct QPAGenerator
QFontEngine *fe;
};
-class Q_GUI_EXPORT QFontEngineMultiQPA : public QFontEngineMulti
-{
-public:
- QFontEngineMultiQPA(QFontEngine *fe, int script, const QStringList &fallbacks);
- QFontEngineMultiQPA(QFontEngine *fe, int script);
-
- void loadEngine(int at);
- static QFontEngine* createMultiFontEngine(QFontEngine *fe, int script);
-
- int fallbackFamilyCount() const { return fallbackFamilies.size(); }
- QString fallbackFamilyAt(int at) const { return fallbackFamilies.at(at); }
-
- virtual void ensureFallbackFamiliesQueried();
- virtual void setFallbackFamiliesList(const QStringList &fallbacks);
-
-private:
- void init(QFontEngine *fe);
-
- mutable QStringList fallbackFamilies;
- int script;
- mutable bool fallbacksQueried;
-};
-
QT_END_NAMESPACE
-#endif // QFONTENGINE_QPA_P_H
+#endif // QFONTENGINE_QPF2_P_H
diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp
index da44a275f8..e1d58a0d05 100644
--- a/src/gui/text/qplatformfontdatabase.cpp
+++ b/src/gui/text/qplatformfontdatabase.cpp
@@ -41,7 +41,7 @@
#include "qplatformfontdatabase.h"
#include <QtGui/private/qfontengine_p.h>
-#include <QtGui/private/qfontengine_qpa_p.h>
+#include <QtGui/private/qfontengine_qpf2_p.h>
#include <QtCore/QLibraryInfo>
#include <QtCore/QDir>
@@ -69,12 +69,12 @@ void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *
return;
const uchar *data = reinterpret_cast<const uchar *>(dataArray.constData());
- if (QFontEngineQPA::verifyHeader(data, dataArray.size())) {
- QString fontName = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_FontName).toString();
- int pixelSize = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_PixelSize).toInt();
- QVariant weight = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Weight);
- QVariant style = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Style);
- QByteArray writingSystemBits = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_WritingSystems).toByteArray();
+ if (QFontEngineQPF2::verifyHeader(data, dataArray.size())) {
+ QString fontName = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_FontName).toString();
+ int pixelSize = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_PixelSize).toInt();
+ QVariant weight = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_Weight);
+ QVariant style = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_Style);
+ QByteArray writingSystemBits = QFontEngineQPF2::extractHeaderField(data, QFontEngineQPF2::Tag_WritingSystems).toByteArray();
if (!fontName.isEmpty() && pixelSize) {
QFont::Weight fontWeight = QFont::Normal;
@@ -322,7 +322,7 @@ void QPlatformFontDatabase::invalidate()
*/
QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script)
{
- return new QFontEngineMultiQPA(fontEngine, script);
+ return new QFontEngineMultiBasicImpl(fontEngine, script);
}
/*!
@@ -332,7 +332,7 @@ QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine
QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{
QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
- QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr);
+ QFontEngineQPF2 *engine = new QFontEngineQPF2(fontDef,*fileDataPtr);
//qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family;
return engine;
}
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index f789ec596b..9b24742823 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -47,6 +47,10 @@
#include "qrawfont_p.h"
#include "qplatformfontdatabase.h"
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformfontdatabase.h>
+
#include <QtCore/qendian.h>
QT_BEGIN_NAMESPACE
@@ -252,7 +256,7 @@ void QRawFont::loadFromData(const QByteArray &fontData,
d->cleanUp();
d->hintingPreference = hintingPreference;
d->thread = QThread::currentThread();
- d->platformLoadFromData(fontData, pixelSize, hintingPreference);
+ d->loadFromData(fontData, pixelSize, hintingPreference);
}
/*!
@@ -735,7 +739,6 @@ void QRawFont::setPixelSize(qreal pixelSize)
*/
void QRawFontPrivate::cleanUp()
{
- platformCleanUp();
if (fontEngine != 0) {
if (!fontEngine->ref.deref())
delete fontEngine;
@@ -744,6 +747,17 @@ void QRawFontPrivate::cleanUp()
hintingPreference = QFont::PreferDefaultHinting;
}
+void QRawFontPrivate::loadFromData(const QByteArray &fontData, qreal pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ Q_ASSERT(fontEngine == 0);
+
+ QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
+ fontEngine = pfdb->fontEngine(fontData, pixelSize, hintingPreference);
+ if (fontEngine != 0)
+ fontEngine->ref.ref();
+}
+
/*!
Returns the smallest rectangle containing the glyph with the given \a glyphIndex.
diff --git a/src/gui/text/qrawfont_p.h b/src/gui/text/qrawfont_p.h
index c9c15717cc..b13454c391 100644
--- a/src/gui/text/qrawfont_p.h
+++ b/src/gui/text/qrawfont_p.h
@@ -95,8 +95,7 @@ public:
}
void cleanUp();
- void platformCleanUp();
- void platformLoadFromData(const QByteArray &fontData,
+ void loadFromData(const QByteArray &fontData,
qreal pixelSize,
QFont::HintingPreference hintingPreference);
diff --git a/src/gui/text/qrawfont_qpa.cpp b/src/gui/text/qrawfont_qpa.cpp
deleted file mode 100644
index 7de6ef0e8b..0000000000
--- a/src/gui/text/qrawfont_qpa.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/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 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
-
-#if !defined(QT_NO_RAWFONT)
-
-#include "qrawfont_p.h"
-#include <qpa/qplatformintegration.h>
-#include <qpa/qplatformfontdatabase.h>
-#include <private/qguiapplication_p.h>
-
-QT_BEGIN_NAMESPACE
-
-void QRawFontPrivate::platformCleanUp()
-{
-}
-
-void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, qreal pixelSize,
- QFont::HintingPreference hintingPreference)
-{
- Q_ASSERT(fontEngine == 0);
-
- QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
- fontEngine = pfdb->fontEngine(fontData, pixelSize, hintingPreference);
- if (fontEngine != 0)
- fontEngine->ref.ref();
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_RAWFONT
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
index 4451f27b27..fd920aaa52 100644
--- a/src/gui/text/qstatictext_p.h
+++ b/src/gui/text/qstatictext_p.h
@@ -79,7 +79,8 @@ class Q_GUI_EXPORT QStaticTextItem
{
public:
QStaticTextItem() : chars(0), numChars(0), useBackendOptimizations(false),
- userDataNeedsUpdate(0), m_fontEngine(0), m_userData(0) {}
+ userDataNeedsUpdate(0), usesRawFont(0),
+ m_fontEngine(0), m_userData(0) {}
QStaticTextItem(const QStaticTextItem &other)
{
@@ -97,6 +98,7 @@ public:
color = other.color;
useBackendOptimizations = other.useBackendOptimizations;
userDataNeedsUpdate = other.userDataNeedsUpdate;
+ usesRawFont = other.usesRawFont;
m_fontEngine = 0;
m_userData = 0;
@@ -145,6 +147,7 @@ public:
QColor color; // 10 bytes per item
char useBackendOptimizations : 1; // 1 byte per item
char userDataNeedsUpdate : 1; //
+ char usesRawFont : 1; //
// ================
// 51 bytes per item
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index 3bd1e2a801..896ba5c211 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -1142,7 +1142,7 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processBlockNode()
}
if (hasBlock) {
QTextBlockFormat fmt;
- fmt.setIndent(0);
+ fmt.setIndent(currentNode->blockFormat.indent());
cursor.mergeBlockFormat(fmt);
}
}
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index b2c82b8654..f1af362c80 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2080,15 +2080,32 @@ QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, in
QTextFrameData *fd = data(f);
QFixed newContentsWidth;
+ bool fullLayout = false;
{
QTextFrameFormat fformat = f->frameFormat();
// set sizes of this frame from the format
- fd->topMargin = QFixed::fromReal(fformat.topMargin());
- fd->bottomMargin = QFixed::fromReal(fformat.bottomMargin());
+ QFixed tm = QFixed::fromReal(fformat.topMargin());
+ if (tm != fd->topMargin) {
+ fd->topMargin = tm;
+ fullLayout = true;
+ }
+ QFixed bm = QFixed::fromReal(fformat.bottomMargin());
+ if (bm != fd->bottomMargin) {
+ fd->bottomMargin = bm;
+ fullLayout = true;
+ }
fd->leftMargin = QFixed::fromReal(fformat.leftMargin());
fd->rightMargin = QFixed::fromReal(fformat.rightMargin());
- fd->border = QFixed::fromReal(fformat.border());
- fd->padding = QFixed::fromReal(fformat.padding());
+ QFixed b = QFixed::fromReal(fformat.border());
+ if (b != fd->border) {
+ fd->border = b;
+ fullLayout = true;
+ }
+ QFixed p = QFixed::fromReal(fformat.padding());
+ if (p != fd->padding) {
+ fd->padding = p;
+ fullLayout = true;
+ }
QTextFrame *parent = f->parentFrame();
const QTextFrameData *pd = parent ? data(parent) : 0;
@@ -2143,7 +2160,7 @@ QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, in
layoutStruct.contentsWidth = 0;
layoutStruct.minimumWidth = 0;
layoutStruct.maximumWidth = QFIXED_MAX;
- layoutStruct.fullLayout = fd->oldContentsWidth != newContentsWidth;
+ layoutStruct.fullLayout = fullLayout || (fd->oldContentsWidth != newContentsWidth);
layoutStruct.updateRect = QRectF(QPointF(0, 0), QSizeF(qreal(INT_MAX), qreal(INT_MAX)));
LDEBUG << "layoutStruct: x_left" << layoutStruct.x_left << "x_right" << layoutStruct.x_right
<< "fullLayout" << layoutStruct.fullLayout;
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index fcf1a1468c..b192460f07 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -59,10 +59,6 @@
#include <algorithm>
#include <stdlib.h>
-#ifndef QT_NO_RAWFONT
-#include "qfontengine_qpa_p.h"
-#endif
-
QT_BEGIN_NAMESPACE
static const float smallCapsFraction = 0.7f;
@@ -88,7 +84,7 @@ public:
/// The caps parameter is used to choose the algoritm of splitting text and assiging roles to the textitems
void generate(int start, int length, QFont::Capitalization caps)
{
- if ((int)caps == (int)QFont::SmallCaps)
+ if (caps == QFont::SmallCaps)
generateScriptItemsSmallCaps(reinterpret_cast<const ushort *>(m_string.unicode()), start, length);
else if(caps == QFont::Capitalize)
generateScriptItemsCapitalize(start, length);
@@ -843,6 +839,81 @@ enum JustificationClass {
Justification_Arabic_Kashida = 13 // User-inserted Kashida(U+0640)
};
+#ifdef QT_ENABLE_HARFBUZZ_NG
+
+/*
+ Adds an inter character justification opportunity after the number or letter
+ character and a space justification opportunity after the space character.
+*/
+static inline void qt_getDefaultJustificationOpportunities(const ushort *string, int length, QGlyphLayout g, ushort *log_clusters, int spaceAs)
+{
+ int str_pos = 0;
+ while (str_pos < length) {
+ int glyph_pos = log_clusters[str_pos];
+
+ Q_ASSERT(glyph_pos < g.numGlyphs && g.attributes[glyph_pos].clusterStart);
+
+ uint ucs4 = string[str_pos];
+ if (QChar::isHighSurrogate(ucs4) && str_pos + 1 < length) {
+ ushort low = string[str_pos + 1];
+ if (QChar::isLowSurrogate(low)) {
+ ++str_pos;
+ ucs4 = QChar::surrogateToUcs4(ucs4, low);
+ }
+ }
+
+ // skip whole cluster
+ do {
+ ++str_pos;
+ } while (str_pos < length && log_clusters[str_pos] == glyph_pos);
+ do {
+ ++glyph_pos;
+ } while (glyph_pos < g.numGlyphs && !g.attributes[glyph_pos].clusterStart);
+ --glyph_pos;
+
+ // justification opportunity at the end of cluster
+ if (Q_LIKELY(QChar::isLetterOrNumber(ucs4)))
+ g.attributes[glyph_pos].justification = Justification_Character;
+ else if (Q_LIKELY(QChar::isSpace(ucs4)))
+ g.attributes[glyph_pos].justification = spaceAs;
+ }
+}
+
+static inline void qt_getJustificationOpportunities(const ushort *string, int length, const QScriptItem &si, QGlyphLayout g, ushort *log_clusters)
+{
+ Q_ASSERT(length > 0 && g.numGlyphs > 0);
+
+ for (int glyph_pos = 0; glyph_pos < g.numGlyphs; ++glyph_pos)
+ g.attributes[glyph_pos].justification = Justification_Prohibited;
+
+ int spaceAs;
+
+ switch (si.analysis.script) {
+ case QChar::Script_Nko:
+ case QChar::Script_Mandaic:
+ case QChar::Script_Mongolian:
+ case QChar::Script_PhagsPa:
+ // same as default but inter character justification takes precedence
+ spaceAs = Justification_Arabic_Space;
+ break;
+
+ case QChar::Script_Hiragana:
+ case QChar::Script_Katakana:
+ case QChar::Script_Han:
+ // same as default but inter character justification is the only option
+ spaceAs = Justification_Character;
+ break;
+
+ default:
+ spaceAs = Justification_Space;
+ break;
+ }
+
+ qt_getDefaultJustificationOpportunities(string, length, g, log_clusters, spaceAs);
+}
+
+#endif // QT_ENABLE_HARFBUZZ_NG
+
// shape all the items that intersect with the line, taking tab widths into account to find out what text actually fits in the line.
void QTextEngine::shapeLine(const QScriptLine &line)
@@ -853,7 +924,7 @@ void QTextEngine::shapeLine(const QScriptLine &line)
int item = findItem(line.from);
if (item == -1)
return;
- for (item = findItem(line.from); item <= end; ++item) {
+ for ( ; item <= end; ++item) {
QScriptItem &si = layoutData->items[item];
if (si.analysis.flags == QScriptAnalysis::Tab) {
ensureSpace(1);
@@ -1003,6 +1074,11 @@ void QTextEngine::shapeText(int item) const
QGlyphLayout glyphs = shapedGlyphs(&si);
+#ifdef QT_ENABLE_HARFBUZZ_NG
+ if (useHarfbuzzNG)
+ qt_getJustificationOpportunities(string, itemLength, si, glyphs, logClusters(&si));
+#endif
+
if (letterSpacing != 0) {
for (int i = 1; i < si.num_glyphs; ++i) {
if (glyphs.attributes[i].clusterStart) {
@@ -1082,7 +1158,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st
hb_buffer_set_segment_properties(buffer, &props);
hb_buffer_guess_segment_properties(buffer);
- uint buffer_flags = 0; // HB_BUFFER_FLAG_DEFAULT
+ uint buffer_flags = HB_BUFFER_FLAG_DEFAULT;
// Symbol encoding used to encode various crap in the 32..255 character code range,
// and thus might override U+00AD [SHY]; avoid hiding default ignorables
if (actualFontEngine->symbol)
@@ -1332,7 +1408,6 @@ void QTextEngine::init(QTextEngine *e)
e->minWidth = 0;
e->maxWidth = 0;
- e->underlinePositions = 0;
e->specialData = 0;
e->stackEngine = false;
#ifndef QT_NO_RAWFONT
@@ -1424,8 +1499,6 @@ void QTextEngine::invalidate()
freeMemory();
minWidth = 0;
maxWidth = 0;
- if (specialData)
- specialData->resolvedFormats.clear();
resetFontEngineCache();
}
@@ -1586,9 +1659,9 @@ void QTextEngine::itemize() const
}
Q_ASSERT(position <= length);
QFont::Capitalization capitalization =
- formats()->charFormat(format).hasProperty(QTextFormat::FontCapitalization)
- ? formats()->charFormat(format).fontCapitalization()
- : formats()->defaultFont().capitalization();
+ formatCollection()->charFormat(format).hasProperty(QTextFormat::FontCapitalization)
+ ? formatCollection()->charFormat(format).fontCapitalization()
+ : formatCollection()->defaultFont().capitalization();
itemizer.generate(prevPosition, position - prevPosition, capitalization);
if (it == end) {
if (position < length)
@@ -1605,8 +1678,8 @@ void QTextEngine::itemize() const
#ifndef QT_NO_RAWFONT
if (useRawFont && specialData) {
int lastIndex = 0;
- for (int i = 0; i < specialData->addFormats.size(); ++i) {
- const QTextLayout::FormatRange &range = specialData->addFormats.at(i);
+ for (int i = 0; i < specialData->formats.size(); ++i) {
+ const QTextLayout::FormatRange &range = specialData->formats.at(i);
const QTextCharFormat &format = range.format;
if (format.hasProperty(QTextFormat::FontCapitalization)) {
itemizer.generate(lastIndex, range.start - lastIndex, QFont::MixedCase);
@@ -1621,7 +1694,7 @@ void QTextEngine::itemize() const
}
addRequiredBoundaries();
- resolveAdditionalFormats();
+ resolveFormats();
}
bool QTextEngine::isRightToLeft() const
@@ -1646,6 +1719,9 @@ bool QTextEngine::isRightToLeft() const
int QTextEngine::findItem(int strPos) const
{
itemize();
+ if (strPos < 0 || strPos >= layoutData->string.size())
+ return -1;
+
int left = 1;
int right = layoutData->items.size()-1;
while(left <= right) {
@@ -1884,7 +1960,7 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
if (feCache.prevFontEngine && feCache.prevFontEngine->type() == QFontEngine::Multi && feCache.prevScript == script) {
engine = feCache.prevFontEngine;
} else {
- engine = QFontEngineMultiQPA::createMultiFontEngine(rawFont.d->fontEngine, script);
+ engine = QFontEngineMultiBasicImpl::createMultiFontEngine(rawFont.d->fontEngine, script);
feCache.prevFontEngine = engine;
feCache.prevScript = script;
engine->ref.ref();
@@ -1893,13 +1969,13 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
feCache.prevScaledFontEngine = 0;
}
}
- if (si.analysis.flags & QFont::SmallCaps) {
+ if (si.analysis.flags == QScriptAnalysis::SmallCaps) {
if (feCache.prevScaledFontEngine) {
scaledEngine = feCache.prevScaledFontEngine;
} else {
QFontEngine *scEngine = rawFont.d->fontEngine->cloneWithSize(smallCapsFraction * rawFont.pixelSize());
scEngine->ref.ref();
- scaledEngine = QFontEngineMultiQPA::createMultiFontEngine(scEngine, script);
+ scaledEngine = QFontEngineMultiBasicImpl::createMultiFontEngine(scEngine, script);
scaledEngine->ref.ref();
feCache.prevScaledFontEngine = scaledEngine;
// If scEngine is not ref'ed by scaledEngine, make sure it is deallocated and not leaked.
@@ -2065,7 +2141,8 @@ void QTextEngine::justify(const QScriptLine &line)
return;
int firstItem = findItem(line.from);
- int nItems = findItem(line.from + line_length - 1) - firstItem + 1;
+ int lastItem = findItem(line.from + line_length - 1);
+ int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0;
QVarLengthArray<QJustificationPoint> justificationPoints;
int nPoints = 0;
@@ -2309,8 +2386,7 @@ bool QTextEngine::LayoutData::reallocate(int totalGlyphs)
return false;
}
- void **newMem = memory;
- newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));
+ void **newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));
if (!newMem) {
layoutState = LayoutFailed;
return false;
@@ -2367,6 +2443,8 @@ void QTextEngine::freeMemory()
layoutData->haveCharAttributes = false;
layoutData->items.clear();
}
+ if (specialData)
+ specialData->resolvedFormats.clear();
for (int i = 0; i < lines.size(); ++i) {
lines[i].justified = 0;
lines[i].gridfitted = 0;
@@ -2376,7 +2454,7 @@ void QTextEngine::freeMemory()
int QTextEngine::formatIndex(const QScriptItem *si) const
{
if (specialData && !specialData->resolvedFormats.isEmpty()) {
- QTextFormatCollection *collection = formats();
+ QTextFormatCollection *collection = formatCollection();
Q_ASSERT(collection);
return collection->indexForFormat(specialData->resolvedFormats.at(si - &layoutData->items[0]));
}
@@ -2398,16 +2476,16 @@ int QTextEngine::formatIndex(const QScriptItem *si) const
QTextCharFormat QTextEngine::format(const QScriptItem *si) const
{
- if (const QTextFormatCollection *formats = this->formats())
- return formats->charFormat(formatIndex(si));
+ if (const QTextFormatCollection *collection = formatCollection())
+ return collection->charFormat(formatIndex(si));
return QTextCharFormat();
}
void QTextEngine::addRequiredBoundaries() const
{
if (specialData) {
- for (int i = 0; i < specialData->addFormats.size(); ++i) {
- const QTextLayout::FormatRange &r = specialData->addFormats.at(i);
+ for (int i = 0; i < specialData->formats.size(); ++i) {
+ const QTextLayout::FormatRange &r = specialData->formats.at(i);
setBoundary(r.start);
setBoundary(r.start + r.length);
//qDebug("adding boundaries %d %d", r.start, r.start+r.length);
@@ -2476,7 +2554,7 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText)
if (preeditText.isEmpty()) {
if (!specialData)
return;
- if (specialData->addFormats.isEmpty()) {
+ if (specialData->formats.isEmpty()) {
delete specialData;
specialData = 0;
} else {
@@ -2493,41 +2571,41 @@ void QTextEngine::setPreeditArea(int position, const QString &preeditText)
clearLineData();
}
-void QTextEngine::setAdditionalFormats(const QList<QTextLayout::FormatRange> &formatList)
+void QTextEngine::setFormats(const QList<QTextLayout::FormatRange> &formats)
{
- if (formatList.isEmpty()) {
+ if (formats.isEmpty()) {
if (!specialData)
return;
if (specialData->preeditText.isEmpty()) {
delete specialData;
specialData = 0;
} else {
- specialData->addFormats.clear();
+ specialData->formats.clear();
}
} else {
if (!specialData) {
specialData = new SpecialData;
specialData->preeditPosition = -1;
}
- specialData->addFormats = formatList;
- indexAdditionalFormats();
+ specialData->formats = formats;
+ indexFormats();
}
invalidate();
clearLineData();
}
-void QTextEngine::indexAdditionalFormats()
+void QTextEngine::indexFormats()
{
- QTextFormatCollection *collection = formats();
+ QTextFormatCollection *collection = formatCollection();
if (!collection) {
Q_ASSERT(!block.docHandle());
- specialData->formats.reset(new QTextFormatCollection);
- collection = specialData->formats.data();
+ specialData->formatCollection.reset(new QTextFormatCollection);
+ collection = specialData->formatCollection.data();
}
// replace with shared copies
- for (int i = 0; i < specialData->addFormats.count(); ++i) {
- QTextCharFormat &format = specialData->addFormats[i].format;
+ for (int i = 0; i < specialData->formats.size(); ++i) {
+ QTextCharFormat &format = specialData->formats[i].format;
format = collection->charFormat(collection->indexForFormat(format));
}
}
@@ -2755,64 +2833,17 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
return layoutData->string.mid(from, to - from);
}
-namespace {
-struct QScriptItemComparator {
- bool operator()(int p, const QScriptItem &b) { return p < b.position; }
-#if defined(Q_CC_MSVC) && _MSC_VER < 1600
-//The STL implementation of MSVC 2008 requires the definition
- bool operator()(const QScriptItem &a, int p) { return a.position < p; }
- bool operator()(const QScriptItem &a, const QScriptItem &b) { return a.position < b.position; }
-#endif
-};
-}
-
void QTextEngine::setBoundary(int strPos) const
{
- if (strPos <= 0 || strPos >= layoutData->string.length())
+ const int item = findItem(strPos);
+ if (item < 0)
return;
- const QScriptItem* it = std::upper_bound(layoutData->items.constBegin(), layoutData->items.constEnd(),
- strPos, QScriptItemComparator());
- Q_ASSERT(it > layoutData->items.constBegin());
- --it;
- if (it->position == strPos) {
- // already a split at the requested position
- return;
+ QScriptItem newItem = layoutData->items.at(item);
+ if (newItem.position != strPos) {
+ newItem.position = strPos;
+ layoutData->items.insert(item + 1, newItem);
}
- splitItem(it - layoutData->items.constBegin(), strPos - it->position);
-}
-
-void QTextEngine::splitItem(int item, int pos) const
-{
- if (pos <= 0)
- return;
-
- layoutData->items.insert(item + 1, layoutData->items[item]);
- QScriptItem &oldItem = layoutData->items[item];
- QScriptItem &newItem = layoutData->items[item+1];
- newItem.position += pos;
-
- if (oldItem.num_glyphs) {
- // already shaped, break glyphs aswell
- int breakGlyph = logClusters(&oldItem)[pos];
-
- newItem.num_glyphs = oldItem.num_glyphs - breakGlyph;
- oldItem.num_glyphs = breakGlyph;
- newItem.glyph_data_offset = oldItem.glyph_data_offset + breakGlyph;
-
- for (int i = 0; i < newItem.num_glyphs; i++)
- logClusters(&newItem)[i] -= breakGlyph;
-
- QFixed w = 0;
- const QGlyphLayout g = shapedGlyphs(&oldItem);
- for(int j = 0; j < breakGlyph; ++j)
- w += g.advances[j] * !g.attributes[j].dontPrint;
-
- newItem.width = oldItem.width - w;
- oldItem.width = w;
- }
-
-// qDebug("split at position %d itempos=%d", pos, item);
}
QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
@@ -2932,45 +2963,44 @@ public:
};
}
-void QTextEngine::resolveAdditionalFormats() const
+void QTextEngine::resolveFormats() const
{
- if (!specialData || specialData->addFormats.isEmpty()
- || !specialData->resolvedFormats.isEmpty())
+ if (!specialData || specialData->formats.isEmpty())
return;
+ Q_ASSERT(specialData->resolvedFormats.isEmpty());
- QTextFormatCollection *collection = formats();
+ QTextFormatCollection *collection = formatCollection();
- specialData->resolvedFormats.clear();
QVector<QTextCharFormat> resolvedFormats(layoutData->items.count());
- QVarLengthArray<int, 64> addFormatSortedByStart;
- addFormatSortedByStart.reserve(specialData->addFormats.count());
- for (int i = 0; i < specialData->addFormats.count(); ++i) {
- if (specialData->addFormats.at(i).length >= 0)
- addFormatSortedByStart.append(i);
+ QVarLengthArray<int, 64> formatsSortedByStart;
+ formatsSortedByStart.reserve(specialData->formats.size());
+ for (int i = 0; i < specialData->formats.size(); ++i) {
+ if (specialData->formats.at(i).length >= 0)
+ formatsSortedByStart.append(i);
}
- QVarLengthArray<int, 64> addFormatSortedByEnd = addFormatSortedByStart;
- std::sort(addFormatSortedByStart.begin(), addFormatSortedByStart.end(),
- FormatRangeComparatorByStart(specialData->addFormats));
- std::sort(addFormatSortedByEnd.begin(), addFormatSortedByEnd.end(),
- FormatRangeComparatorByEnd(specialData->addFormats));
+ QVarLengthArray<int, 64> formatsSortedByEnd = formatsSortedByStart;
+ std::sort(formatsSortedByStart.begin(), formatsSortedByStart.end(),
+ FormatRangeComparatorByStart(specialData->formats));
+ std::sort(formatsSortedByEnd.begin(), formatsSortedByEnd.end(),
+ FormatRangeComparatorByEnd(specialData->formats));
QVarLengthArray<int, 16> currentFormats;
- const int *startIt = addFormatSortedByStart.constBegin();
- const int *endIt = addFormatSortedByEnd.constBegin();
+ const int *startIt = formatsSortedByStart.constBegin();
+ const int *endIt = formatsSortedByEnd.constBegin();
for (int i = 0; i < layoutData->items.count(); ++i) {
const QScriptItem *si = &layoutData->items.at(i);
int end = si->position + length(si);
- while (startIt != addFormatSortedByStart.constEnd() &&
- specialData->addFormats.at(*startIt).start <= si->position) {
+ while (startIt != formatsSortedByStart.constEnd() &&
+ specialData->formats.at(*startIt).start <= si->position) {
currentFormats.insert(std::upper_bound(currentFormats.begin(), currentFormats.end(), *startIt),
*startIt);
++startIt;
}
- while (endIt != addFormatSortedByEnd.constEnd() &&
- specialData->addFormats.at(*endIt).start + specialData->addFormats.at(*endIt).length < end) {
+ while (endIt != formatsSortedByEnd.constEnd() &&
+ specialData->formats.at(*endIt).start + specialData->formats.at(*endIt).length < end) {
int *currentFormatIterator = std::lower_bound(currentFormats.begin(), currentFormats.end(), *endIt);
if (*endIt < *currentFormatIterator)
currentFormatIterator = currentFormats.end();
@@ -2986,7 +3016,7 @@ void QTextEngine::resolveAdditionalFormats() const
}
if (!currentFormats.isEmpty()) {
foreach (int cur, currentFormats) {
- const QTextLayout::FormatRange &range = specialData->addFormats.at(cur);
+ const QTextLayout::FormatRange &range = specialData->formats.at(cur);
Q_ASSERT(range.start <= si->position && range.start + range.length >= end);
format.merge(range.format);
}
@@ -3486,15 +3516,15 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co
logicalItem(-1),
item(-1),
visualOrder(nItems),
- levels(nItems),
selection(_selection)
{
- pos_x = x = QFixed::fromReal(pos.x());
+ x = QFixed::fromReal(pos.x());
x += line.x;
x += eng->alignLine(line);
+ QVarLengthArray<uchar> levels(nItems);
for (int i = 0; i < nItems; ++i)
levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
@@ -3565,7 +3595,7 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec
return false;
int start_glyph = logClusters[from];
- int end_glyph = (to == eng->length(item)) ? si->num_glyphs : logClusters[to];
+ int end_glyph = (to == itemLength) ? si->num_glyphs : logClusters[to];
QFixed soff;
QFixed swidth;
if (si->analysis.bidiLevel %2) {
@@ -3590,7 +3620,7 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec
// If the ending character is also part of a ligature, swidth does
// not contain that part yet, we also need to find out the width of
// that left part
- *selectionWidth += eng->offsetInLigature(si, to, eng->length(item), end_glyph);
+ *selectionWidth += eng->offsetInLigature(si, to, itemLength, end_glyph);
}
return true;
}
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 342a94de66..8ea2d5efb9 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -505,10 +505,10 @@ public:
void freeMemory();
int findItem(int strPos) const;
- inline QTextFormatCollection *formats() const {
+ inline QTextFormatCollection *formatCollection() const {
if (block.docHandle())
return block.docHandle()->formatCollection();
- return specialData ? specialData->formats.data() : 0;
+ return specialData ? specialData->formatCollection.data() : 0;
}
QTextCharFormat format(const QScriptItem *si) const;
inline QAbstractTextDocumentLayout *docLayout() const {
@@ -563,8 +563,6 @@ public:
uint useRawFont : 1;
#endif
- int *underlinePositions;
-
mutable LayoutData *layoutData;
ItemDecorationList underlineList;
@@ -572,19 +570,17 @@ public:
ItemDecorationList overlineList;
inline bool visualCursorMovement() const
- {
- return (visualMovement ||
- (block.docHandle() ? block.docHandle()->defaultCursorMoveStyle == Qt::VisualMoveStyle : false));
- }
+ { return visualMovement || (block.docHandle() && block.docHandle()->defaultCursorMoveStyle == Qt::VisualMoveStyle); }
inline int preeditAreaPosition() const { return specialData ? specialData->preeditPosition : -1; }
inline QString preeditAreaText() const { return specialData ? specialData->preeditText : QString(); }
void setPreeditArea(int position, const QString &text);
- inline bool hasFormats() const { return block.docHandle() || (specialData && !specialData->addFormats.isEmpty()); }
- inline QList<QTextLayout::FormatRange> additionalFormats() const
- { return specialData ? specialData->addFormats : QList<QTextLayout::FormatRange>(); }
- void setAdditionalFormats(const QList<QTextLayout::FormatRange> &formatList);
+ 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);
private:
static void init(QTextEngine *e);
@@ -592,15 +588,15 @@ private:
struct SpecialData {
int preeditPosition;
QString preeditText;
- QList<QTextLayout::FormatRange> addFormats;
+ QList<QTextLayout::FormatRange> formats;
QVector<QTextCharFormat> resolvedFormats;
// only used when no docHandle is available
- QScopedPointer<QTextFormatCollection> formats;
+ QScopedPointer<QTextFormatCollection> formatCollection;
};
SpecialData *specialData;
- void indexAdditionalFormats();
- void resolveAdditionalFormats() const;
+ void indexFormats();
+ void resolveFormats() const;
public:
bool atWordSeparator(int position) const;
@@ -643,7 +639,6 @@ private:
int shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const;
#endif
int shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const;
- void splitItem(int item, int pos) const;
int endOfLine(int lineNum);
int beginningOfLine(int lineNum);
@@ -676,15 +671,14 @@ struct QTextLineItemIterator
QTextEngine *eng;
QFixed x;
- QFixed pos_x;
const QScriptLine &line;
QScriptItem *si;
- int lineNum;
- int lineEnd;
- int firstItem;
- int lastItem;
- int nItems;
+ const int lineNum;
+ const int lineEnd;
+ const int firstItem;
+ const int lastItem;
+ const int nItems;
int logicalItem;
int item;
int itemLength;
@@ -697,7 +691,6 @@ struct QTextLineItemIterator
QFixed itemWidth;
QVarLengthArray<int> visualOrder;
- QVarLengthArray<uchar> levels;
const QTextLayout::FormatRange *selection;
};
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 8e605e4ae1..5056319b9d 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -505,7 +505,7 @@ QString QTextLayout::preeditAreaText() const
*/
void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
{
- d->setAdditionalFormats(formatList);
+ d->setFormats(formatList);
if (d->block.docHandle())
d->block.docHandle()->documentChange(d->block.position(), d->block.length());
@@ -518,7 +518,7 @@ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
*/
QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const
{
- return d->additionalFormats();
+ return d->formats();
}
/*!
@@ -567,7 +567,7 @@ bool QTextLayout::cacheEnabled() const
*/
void QTextLayout::setCursorMoveStyle(Qt::CursorMoveStyle style)
{
- d->visualMovement = style == Qt::VisualMoveStyle ? true : false;
+ d->visualMovement = style == Qt::VisualMoveStyle;
}
/*!
@@ -1735,6 +1735,7 @@ void QTextLine::layout_helper(int maxGlyphs)
int item = -1;
int newItem = eng->findItem(line.from);
+ Q_ASSERT(newItem >= 0);
LB_DEBUG("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal());
@@ -2020,79 +2021,6 @@ int QTextLine::textLength() const
return eng->lines[index].length + eng->lines[index].trailingSpaces;
}
-static void drawMenuText(QPainter *p, QFixed x, QFixed y, const QScriptItem &si, QTextItemInt &gf, QTextEngine *eng,
- int start, int glyph_start)
-{
- int ge = glyph_start + gf.glyphs.numGlyphs;
- int gs = glyph_start;
- int end = start + gf.num_chars;
- unsigned short *logClusters = eng->logClusters(&si);
- QGlyphLayout glyphs = eng->shapedGlyphs(&si);
- QFixed orig_width = gf.width;
-
- int *ul = eng->underlinePositions;
- if (ul)
- while (*ul != -1 && *ul < start)
- ++ul;
- bool rtl = si.analysis.bidiLevel % 2;
- if (rtl)
- x += si.width;
-
- do {
- int gtmp = ge;
- int stmp = end;
- if (ul && *ul != -1 && *ul < end) {
- stmp = *ul;
- gtmp = logClusters[*ul-si.position];
- }
-
- gf.glyphs = glyphs.mid(gs, gtmp - gs);
- gf.num_chars = stmp - start;
- gf.chars = eng->layoutData->string.unicode() + start;
- QFixed w = 0;
- while (gs < gtmp) {
- w += glyphs.effectiveAdvance(gs);
- ++gs;
- }
- start = stmp;
- gf.width = w;
- if (rtl)
- x -= w;
- if (gf.num_chars)
- QPainterPrivate::get(p)->drawTextItem(QPointF(x.toReal(), y.toReal()), gf, eng);
- if (!rtl)
- x += w;
- if (ul && *ul != -1 && *ul < end) {
- // draw underline
- gtmp = (*ul == end-1) ? ge : logClusters[*ul+1-si.position];
- ++stmp;
- gf.glyphs = glyphs.mid(gs, gtmp - gs);
- gf.num_chars = stmp - start;
- gf.chars = eng->layoutData->string.unicode() + start;
- gf.logClusters = logClusters + start - si.position;
- w = 0;
- while (gs < gtmp) {
- w += glyphs.effectiveAdvance(gs);
- ++gs;
- }
- ++start;
- gf.width = w;
- gf.underlineStyle = QTextCharFormat::SingleUnderline;
- if (rtl)
- x -= w;
- QPainterPrivate::get(p)->drawTextItem(QPointF(x.toReal(), y.toReal()), gf, eng);
- if (!rtl)
- x += w;
- gf.underlineStyle = QTextCharFormat::NoUnderline;
- ++gf.chars;
- ++ul;
- }
- } while (gs < ge);
-
- gf.width = orig_width;
-}
-
-
static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const QTextCharFormat &chf, const QRectF &r)
{
QBrush c = chf.foreground();
@@ -2212,14 +2140,10 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
if (si.analysis.flags >= QScriptAnalysis::TabOrObject)
continue;
- QPointF pos(iterator.x.toReal(), y);
- if (from >= 0 && length >= 0 &&
- (from >= si.position + eng->length(&si)
- || from + length <= si.position
- || from + length <= iterator.itemStart
- || from >= iterator.itemEnd)) {
+ if (from >= 0 && length >= 0 && (from >= iterator.itemEnd || from + length <= iterator.itemStart))
continue;
- }
+
+ QPointF pos(iterator.x.toReal(), y);
QFont font;
QGlyphRun::GlyphRunFlags flags;
@@ -2240,15 +2164,13 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
}
int relativeFrom = qMax(iterator.itemStart, from) - si.position;
- int relativeTo = qMin(iterator.itemEnd - 1, from + length - 1) - si.position;
+ int relativeTo = qMin(iterator.itemEnd, from + length) - 1 - si.position;
unsigned short *logClusters = eng->logClusters(&si);
int glyphsStart = logClusters[relativeFrom];
- int glyphsEnd = (relativeTo == eng->length(&si))
- ? si.num_glyphs - 1
- : logClusters[relativeTo];
+ int glyphsEnd = (relativeTo == iterator.itemLength) ? si.num_glyphs - 1 : logClusters[relativeTo];
// the glyph index right next to the requested range
- int nextGlyphIndex = relativeTo < eng->length(&si) - 1 ? logClusters[relativeTo + 1] : si.num_glyphs;
+ int nextGlyphIndex = (relativeTo < iterator.itemLength - 1) ? logClusters[relativeTo + 1] : si.num_glyphs;
if (nextGlyphIndex - 1 > glyphsEnd)
glyphsEnd = nextGlyphIndex - 1;
bool startsInsideLigature = relativeFrom > 0 && logClusters[relativeFrom - 1] == glyphsStart;
@@ -2488,52 +2410,48 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
Q_ASSERT(gf.fontEngine);
- if (eng->underlinePositions) {
- // can't have selections in this case
- drawMenuText(p, iterator.x, itemBaseLine, si, gf, eng, iterator.itemStart, iterator.glyphsStart);
- } else {
- QPointF pos(iterator.x.toReal(), itemBaseLine.toReal());
- if (format.penProperty(QTextFormat::TextOutline).style() != Qt::NoPen) {
- QPainterPath path;
- path.setFillRule(Qt::WindingFill);
-
- if (gf.glyphs.numGlyphs)
- gf.fontEngine->addOutlineToPath(pos.x(), pos.y(), gf.glyphs, &path, gf.flags);
- if (gf.flags) {
- const QFontEngine *fe = gf.fontEngine;
- const qreal lw = fe->lineThickness().toReal();
- if (gf.flags & QTextItem::Underline) {
- qreal offs = fe->underlinePosition().toReal();
- path.addRect(pos.x(), pos.y() + offs, gf.width.toReal(), lw);
- }
- if (gf.flags & QTextItem::Overline) {
- qreal offs = fe->ascent().toReal() + 1;
- path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
- }
- if (gf.flags & QTextItem::StrikeOut) {
- qreal offs = fe->ascent().toReal() / 3;
- path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
- }
+ QPointF pos(iterator.x.toReal(), itemBaseLine.toReal());
+ if (format.penProperty(QTextFormat::TextOutline).style() != Qt::NoPen) {
+ QPainterPath path;
+ path.setFillRule(Qt::WindingFill);
+
+ if (gf.glyphs.numGlyphs)
+ gf.fontEngine->addOutlineToPath(pos.x(), pos.y(), gf.glyphs, &path, gf.flags);
+ if (gf.flags) {
+ const QFontEngine *fe = gf.fontEngine;
+ const qreal lw = fe->lineThickness().toReal();
+ if (gf.flags & QTextItem::Underline) {
+ qreal offs = fe->underlinePosition().toReal();
+ path.addRect(pos.x(), pos.y() + offs, gf.width.toReal(), lw);
+ }
+ if (gf.flags & QTextItem::Overline) {
+ qreal offs = fe->ascent().toReal() + 1;
+ path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
+ }
+ if (gf.flags & QTextItem::StrikeOut) {
+ qreal offs = fe->ascent().toReal() / 3;
+ path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
}
-
- p->save();
- p->setRenderHint(QPainter::Antialiasing);
- //Currently QPen with a Qt::NoPen style still returns a default
- //QBrush which != Qt::NoBrush so we need this specialcase to reset it
- if (p->pen().style() == Qt::NoPen)
- p->setBrush(Qt::NoBrush);
- else
- p->setBrush(p->pen().brush());
-
- p->setPen(format.textOutline());
- p->drawPath(path);
- p->restore();
- } else {
- if (noText)
- gf.glyphs.numGlyphs = 0; // slightly less elegant than it should be
- QPainterPrivate::get(p)->drawTextItem(pos, gf, eng);
}
+
+ p->save();
+ p->setRenderHint(QPainter::Antialiasing);
+ //Currently QPen with a Qt::NoPen style still returns a default
+ //QBrush which != Qt::NoBrush so we need this specialcase to reset it
+ if (p->pen().style() == Qt::NoPen)
+ p->setBrush(Qt::NoBrush);
+ else
+ p->setBrush(p->pen().brush());
+
+ p->setPen(format.textOutline());
+ p->drawPath(path);
+ p->restore();
+ } else {
+ if (noText)
+ gf.glyphs.numGlyphs = 0; // slightly less elegant than it should be
+ QPainterPrivate::get(p)->drawTextItem(pos, gf, eng);
}
+
if (si.analysis.flags == QScriptAnalysis::Space
&& (eng->option.flags() & QTextOption::ShowTabsAndSpaces)) {
QBrush c = format.foreground();
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index c67769ad48..091129f5be 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -77,10 +77,8 @@ SOURCES += \
text/qdistancefield.cpp
SOURCES += \
- text/qfont_qpa.cpp \
- text/qfontengine_qpa.cpp \
- text/qplatformfontdatabase.cpp \
- text/qrawfont_qpa.cpp
+ text/qfontengine_qpf2.cpp \
+ text/qplatformfontdatabase.cpp
HEADERS += \
text/qplatformfontdatabase.h