summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Dzyubenko <denis.dzyubenko@nokia.com>2011-03-31 09:21:40 (GMT)
committerDenis Dzyubenko <denis.dzyubenko@nokia.com>2011-03-31 09:21:40 (GMT)
commitd43455eaa9106c63885fe04c39a7b2c7249f406f (patch)
tree1fc9d1355ac9654253503dd53f8c2dd9a5917e94
parent2e90e8dda26721dcab4842f9ac3eeadecfadd80f (diff)
parent7b18baf23b1e8c663872b2b25b1323798b1d09df (diff)
downloadQt-d43455eaa9106c63885fe04c39a7b2c7249f406f.zip
Qt-d43455eaa9106c63885fe04c39a7b2c7249f406f.tar.gz
Qt-d43455eaa9106c63885fe04c39a7b2c7249f406f.tar.bz2
Merge remote branch 'origin/master' into 4.8-earth
-rwxr-xr-xconfig.tests/unix/compile.test4
-rwxr-xr-xconfigure25
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp8
-rw-r--r--src/corelib/codecs/qiconvcodec.cpp38
-rw-r--r--src/corelib/plugin/qlibrary.cpp9
-rw-r--r--src/dbus/qdbusargument.cpp8
-rw-r--r--src/dbus/qdbusargument_p.h10
-rw-r--r--src/dbus/qdbusconnection.cpp50
-rw-r--r--src/dbus/qdbusconnection.h9
-rw-r--r--src/dbus/qdbusconnection_p.h1
-rw-r--r--src/dbus/qdbusdemarshaller.cpp8
-rw-r--r--src/dbus/qdbusintegrator.cpp16
-rw-r--r--src/dbus/qdbusmarshaller.cpp11
-rw-r--r--src/dbus/qdbusmessage.cpp17
-rw-r--r--src/dbus/qdbusmessage_p.h6
-rw-r--r--src/gui/kernel/qapplication_x11.cpp4
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp252
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h2
-rw-r--r--src/gui/painting/qpaintengine_x11.cpp2
-rw-r--r--src/gui/painting/qpainter.cpp15
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp17
-rw-r--r--src/gui/painting/qtransform.cpp3
-rw-r--r--src/gui/text/qfontdatabase_x11.cpp1
-rw-r--r--src/gui/text/qfontengine_ft.cpp173
-rw-r--r--src/gui/text/qfontengine_ft_p.h55
-rw-r--r--src/gui/text/qfontengine_qpf.cpp2
-rw-r--r--src/gui/text/qfontengine_x11.cpp23
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp9
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp15
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h2
-rw-r--r--src/opengl/qgl.cpp15
-rw-r--r--src/opengl/qgl_p.h1
32 files changed, 510 insertions, 301 deletions
diff --git a/config.tests/unix/compile.test b/config.tests/unix/compile.test
index 29ddea7..f4a7f29 100755
--- a/config.tests/unix/compile.test
+++ b/config.tests/unix/compile.test
@@ -11,9 +11,9 @@ TEST=$6
EXE=`basename "$6"`
DESCRIPTION=$7
shift 7
-LFLAGS=""
+LFLAGS="$SYSROOT_FLAG"
INCLUDEPATH=""
-CXXFLAGS=""
+CXXFLAGS="$SYSROOT_FLAG"
MAC_ARCH_CXXFLAGS=""
MAC_ARCH_LFLAGS=""
while [ "$#" -gt 0 ]; do
diff --git a/configure b/configure
index e88373e..382df60 100755
--- a/configure
+++ b/configure
@@ -1316,6 +1316,9 @@ while [ "$#" -gt 0 ]; do
qconfig)
CFG_QCONFIG="$VAL"
;;
+ sysroot)
+ CFG_SYSROOT="$VAL"
+ ;;
bindir)
QT_INSTALL_BINS="$VAL"
;;
@@ -3310,6 +3313,18 @@ if [ "$CFG_EMBEDDED" = "nacl" ]; then
TEST_COMPILER="nacl-gcc"
fi
+SYSROOT_FLAG=
+if [ -n "$CFG_SYSROOT" ]; then
+ if compilerSupportsFlag --sysroot="$CFG_SYSROOT"; then
+ [ "$OPT_VERBOSE" = "yes" ] && echo "Setting sysroot to: $CFG_SYSROOT"
+ SYSROOT_FLAG="--sysroot=$CFG_SYSROOT"
+ else
+ echo >&2 "The compiler doesn't support the --sysroot flag, I can't set the sysroot"
+ exit 1
+ fi
+fi
+export SYSROOT_FLAG # used by config.tests/unix/compile.test
+
# auto-detect precompiled header support
if [ "$CFG_PRECOMPILE" = "auto" ]; then
if [ `echo "$CFG_MAC_ARCHS" | wc -w` -gt 1 ]; then
@@ -8316,6 +8331,16 @@ QT_NAMESPACE = $QT_NAMESPACE
QT_NAMESPACE_MAC_CRC = $QT_NAMESPACE_MAC_CRC
EOF
+if [ -n "$CFG_SYSROOT" ]; then
+ echo "# sysroot" >>"$QTCONFIG.tmp"
+ echo `basename "$XQMAKESPEC"` \{ >>"$QTCONFIG.tmp"
+ echo " QT_SYSROOT += \$\$quote($CFG_SYSROOT)" >>"$QTCONFIG.tmp"
+ echo " QMAKE_CFLAGS += --sysroot=\$\$QT_SYSROOT" >>"$QTCONFIG.tmp"
+ echo " QMAKE_CXXFLAGS += --sysroot=\$\$QT_SYSROOT" >>"$QTCONFIG.tmp"
+ echo " QMAKE_LFLAGS += --sysroot=\$\$QT_SYSROOT" >>"$QTCONFIG.tmp"
+ echo "}" >> "$QTCONFIG.tmp"
+ echo >> "$QTCONFIG.tmp"
+fi
if [ "$CFG_RPATH" = "yes" ]; then
echo "QMAKE_RPATHDIR += \"$QT_INSTALL_LIBS\"" >> "$QTCONFIG.tmp"
fi
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
index 6c4d9f1..c202e1f 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
@@ -1052,16 +1052,16 @@ HB_Bool HB_SelectScript(HB_ShaperItem *shaper_item, const HB_OpenTypeFeature *fe
{
HB_Script script = shaper_item->item.script;
- if (!shaper_item->face->supported_scripts[script])
- return false;
-
HB_Face face = shaper_item->face;
if (face->current_script == script && face->current_flags == shaper_item->shaperFlags)
- return true;
+ return shaper_item->face->supported_scripts[script] ? true : false;
face->current_script = script;
face->current_flags = shaper_item->shaperFlags;
+ if (!shaper_item->face->supported_scripts[script])
+ return false;
+
assert(script < HB_ScriptCount);
// find script in our list of supported scripts.
unsigned int tag = ot_scripts[script].tag;
diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp
index 4497b8c..053b3d2 100644
--- a/src/corelib/codecs/qiconvcodec.cpp
+++ b/src/corelib/codecs/qiconvcodec.cpp
@@ -173,6 +173,7 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState
int invalidCount = 0;
int remainingCount = 0;
char *remainingBuffer = 0;
+ IconvState *temporaryState = 0;
IconvState **pstate;
if (convState) {
@@ -193,11 +194,11 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState
// we're running after the Q_GLOBAL_STATIC has been deleted
// or before the QCoreApplication initialization
// bad programmer, no cookie for you
- return QString::fromLatin1(chars, len);
+ pstate = &temporaryState;
+ } else {
+ // stateless conversion -- use thread-local data
+ pstate = &toUnicodeState()->localData();
}
-
- // stateless conversion -- use thread-local data
- pstate = &toUnicodeState()->localData();
}
if (!*pstate) {
@@ -280,6 +281,7 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState
iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft);
}
+ delete temporaryState;
return QString::fromLatin1(chars, len);
}
} while (inBytesLeft != 0);
@@ -294,6 +296,7 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState
iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft);
}
+ delete temporaryState;
return s;
}
@@ -337,30 +340,22 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
char **inBytesPtr = &inBytes;
#endif
+ IconvState *temporaryState = 0;
QThreadStorage<QIconvCodec::IconvState *> *ts = fromUnicodeState();
- if (!qt_locale_initialized || !ts) {
- // we're running after the Q_GLOBAL_STATIC has been deleted
- // or before the QCoreApplication initialization
- // bad programmer, no cookie for you
- if (!len)
- // this is a special case - zero-sized string should be
- // translated to empty but not-null QByteArray.
- return QByteArray("");
- return QString::fromRawData(uc, len).toLatin1();
- }
- IconvState *&state = ts->localData();
+ IconvState *&state = (qt_locale_initialized && ts) ? ts->localData() : temporaryState;
if (!state) {
- state = new IconvState(QIconvCodec::createIconv_t(0, UTF16));
- if (state->cd == reinterpret_cast<iconv_t>(-1)) {
- if (!setByteOrder(state->cd)) {
+ iconv_t cd = QIconvCodec::createIconv_t(0, UTF16);
+ if (cd != reinterpret_cast<iconv_t>(-1)) {
+ if (!setByteOrder(cd)) {
perror("QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv failed for BOM");
- iconv_close(state->cd);
- state->cd = reinterpret_cast<iconv_t>(-1);
+ iconv_close(cd);
+ cd = reinterpret_cast<iconv_t>(-1);
return QString(uc, len).toLatin1();
}
}
+ state = new IconvState(cd);
}
if (state->cd == reinterpret_cast<iconv_t>(-1)) {
static int reported = 0;
@@ -368,6 +363,7 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
fprintf(stderr,
"QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed\n");
}
+ delete temporaryState;
return QString(uc, len).toLatin1();
}
@@ -430,6 +426,7 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
// reset to initial state
iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft);
+ delete temporaryState;
return QString(uc, len).toLatin1();
}
}
@@ -445,6 +442,7 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
if (convState)
convState->invalidChars = invalidCount;
+ delete temporaryState;
return ba;
}
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index ecd1aac..80e927b 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -516,6 +516,8 @@ bool QLibraryPrivate::loadPlugin()
libraryUnloadCount.ref();
return true;
}
+ if (pluginState == IsNotAPlugin)
+ return false;
if (load()) {
instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance");
#if defined(Q_OS_SYMBIAN)
@@ -528,6 +530,9 @@ bool QLibraryPrivate::loadPlugin()
#endif
return instance;
}
+ if (qt_debug_component())
+ qWarning() << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
+ pluginState = IsNotAPlugin;
return false;
}
@@ -687,7 +692,7 @@ bool QLibraryPrivate::isPlugin(QSettings *settings)
.arg((QT_VERSION & 0xff00) >> 8)
.arg(QLIBRARY_AS_DEBUG ? QLatin1String("debug") : QLatin1String("false"))
.arg(fileName);
-#ifdef Q_WS_MAC
+#ifdef Q_WS_MAC
// On Mac, add the application arch to the reg key in order to
// cache plugin information separately for each arch. This prevents
// Qt from wrongly caching plugin load failures when the archs
@@ -702,7 +707,7 @@ bool QLibraryPrivate::isPlugin(QSettings *settings)
regkey += QLatin1String("-ppc");
#endif
#endif // Q_WS_MAC
-
+
QStringList reg;
#ifndef QT_NO_SETTINGS
if (!settings) {
diff --git a/src/dbus/qdbusargument.cpp b/src/dbus/qdbusargument.cpp
index 00f49ba..09f0e82 100644
--- a/src/dbus/qdbusargument.cpp
+++ b/src/dbus/qdbusargument.cpp
@@ -72,7 +72,7 @@ QByteArray QDBusArgumentPrivate::createSignature(int id)
return "";
QByteArray signature;
- QDBusMarshaller *marshaller = new QDBusMarshaller;
+ QDBusMarshaller *marshaller = new QDBusMarshaller(0);
marshaller->ba = &signature;
// run it
@@ -114,7 +114,7 @@ bool QDBusArgumentPrivate::checkWrite(QDBusArgumentPrivate *&d)
return false;
if (d->message && d->ref != 1) {
- QDBusMarshaller *dd = new QDBusMarshaller;
+ QDBusMarshaller *dd = new QDBusMarshaller(d->capabilities);
dd->message = q_dbus_message_copy(d->message);
q_dbus_message_iter_init_append(dd->message, &dd->iterator);
@@ -157,7 +157,7 @@ bool QDBusArgumentPrivate::checkReadAndDetach(QDBusArgumentPrivate *&d)
if (d->ref == 1)
return true; // no need to detach
- QDBusDemarshaller *dd = new QDBusDemarshaller;
+ QDBusDemarshaller *dd = new QDBusDemarshaller(d->capabilities);
dd->message = q_dbus_message_ref(d->message);
dd->iterator = static_cast<QDBusDemarshaller*>(d)->iterator;
@@ -295,7 +295,7 @@ QDBusArgument::QDBusArgument()
return;
}
- QDBusMarshaller *dd = new QDBusMarshaller;
+ QDBusMarshaller *dd = new QDBusMarshaller(0);
d = dd;
// create a new message with any type, we won't sent it anyways
diff --git a/src/dbus/qdbusargument_p.h b/src/dbus/qdbusargument_p.h
index fe3a9cd..89a383f 100644
--- a/src/dbus/qdbusargument_p.h
+++ b/src/dbus/qdbusargument_p.h
@@ -65,8 +65,8 @@ class QDBusDemarshaller;
class QDBusArgumentPrivate
{
public:
- inline QDBusArgumentPrivate()
- : message(0), ref(1)
+ inline QDBusArgumentPrivate(int flags = 0)
+ : message(0), ref(1), capabilities(flags)
{ }
~QDBusArgumentPrivate();
@@ -89,6 +89,7 @@ public:
public:
DBusMessage *message;
QAtomicInt ref;
+ int capabilities;
enum Direction {
Marshalling,
Demarshalling
@@ -98,7 +99,7 @@ public:
class QDBusMarshaller: public QDBusArgumentPrivate
{
public:
- QDBusMarshaller() : parent(0), ba(0), closeCode(0), ok(true)
+ QDBusMarshaller(int flags) : QDBusArgumentPrivate(flags), parent(0), ba(0), closeCode(0), ok(true)
{ direction = Marshalling; }
~QDBusMarshaller();
@@ -153,7 +154,8 @@ private:
class QDBusDemarshaller: public QDBusArgumentPrivate
{
public:
- inline QDBusDemarshaller() : parent(0) { direction = Demarshalling; }
+ inline QDBusDemarshaller(int flags) : QDBusArgumentPrivate(flags), parent(0)
+ { direction = Demarshalling; }
~QDBusDemarshaller();
QString currentSignature();
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp
index 3fb63eb..4883a4d 100644
--- a/src/dbus/qdbusconnection.cpp
+++ b/src/dbus/qdbusconnection.cpp
@@ -42,6 +42,7 @@
#include <qdebug.h>
#include <qcoreapplication.h>
#include <qstringlist.h>
+#include <qthread.h>
#include "qdbusconnection.h"
#include "qdbusconnectioninterface.h"
@@ -247,6 +248,17 @@ void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionP
*/
/*!
+ \since 4.8
+ \enum QDBusConnection::ConnectionCapabilities
+ The available capabilities for a D-Bus connection.
+
+ \value UnixFileDescriptorPassing passing of Unix file descriptors to other processes
+ (see QDBusUnixFileDescriptor)
+
+ \sa connectionCapabilities()
+*/
+
+/*!
Creates a QDBusConnection object attached to the connection with name \a name.
This does not open the connection. You have to call connectToBus() to open it.
@@ -873,6 +885,21 @@ QDBusConnectionInterface *QDBusConnection::interface() const
}
/*!
+ \internal
+ \since 4.8
+
+ Returns the internal, implementation-defined pointer for this
+ connection. Currently, this returns a DBusConnection* pointer,
+ without changing the reference count. It is the responsibility of
+ the caller to call dbus_connection_ref if it wants to store the
+ pointer.
+*/
+void *QDBusConnection::internalPointer() const
+{
+ return d ? d->connection : 0;
+}
+
+/*!
Returns true if this QDBusConnection object is connected.
*/
bool QDBusConnection::isConnected() const
@@ -932,6 +959,18 @@ QString QDBusConnection::name() const
}
/*!
+ \since 4.8
+
+ Returns the capabilities of this connection as negotiated with the bus
+ server or peer. If this QDBusConnection is not connected, this function
+ returns no capabilities.
+*/
+QDBusConnection::ConnectionCapabilities QDBusConnection::connectionCapabilities() const
+{
+ return d ? d->capabilities : ConnectionCapabilities(0);
+}
+
+/*!
Attempts to register the \a serviceName on the D-Bus server and
returns true if the registration succeeded. The registration will
fail if the name is already registered by another application.
@@ -972,7 +1011,16 @@ class QDBusDefaultConnection: public QDBusConnection
public:
inline QDBusDefaultConnection(BusType type, const char *name)
: QDBusConnection(connectToBus(type, QString::fromLatin1(name))), ownName(name)
- { }
+ {
+ // make sure this connection is running on the main thread
+ QCoreApplication *instance = QCoreApplication::instance();
+ if (!instance) {
+ qWarning("QDBusConnection: %s D-Bus connection created before QCoreApplication. Application may misbehave.",
+ type == SessionBus ? "session" : type == SystemBus ? "system" : "generic");
+ } else {
+ QDBusConnectionPrivate::d(*this)->moveToThread(instance->thread());
+ }
+ }
inline ~QDBusDefaultConnection()
{ disconnectFromBus(QString::fromLatin1(ownName)); }
diff --git a/src/dbus/qdbusconnection.h b/src/dbus/qdbusconnection.h
index ec59434..6ab0ea2 100644
--- a/src/dbus/qdbusconnection.h
+++ b/src/dbus/qdbusconnection.h
@@ -111,9 +111,13 @@ public:
UnregisterNode,
UnregisterTree
};
-
Q_DECLARE_FLAGS(RegisterOptions, RegisterOption)
+ enum ConnectionCapability {
+ UnixFileDescriptorPassing = 0x0001
+ };
+ Q_DECLARE_FLAGS(ConnectionCapabilities, ConnectionCapability)
+
QDBusConnection(const QString &name);
QDBusConnection(const QDBusConnection &other);
~QDBusConnection();
@@ -124,6 +128,7 @@ public:
QString baseService() const;
QDBusError lastError() const;
QString name() const;
+ ConnectionCapabilities connectionCapabilities() const;
bool send(const QDBusMessage &message) const;
bool callWithCallback(const QDBusMessage &message, QObject *receiver,
@@ -163,6 +168,8 @@ public:
QDBusConnectionInterface *interface() const;
+ void *internalPointer() const;
+
static QDBusConnection connectToBus(BusType type, const QString &name);
static QDBusConnection connectToBus(const QString &address, const QString &name);
static void disconnectFromBus(const QString &name);
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index 85308c1..36f7c53 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -262,6 +262,7 @@ signals:
public:
QAtomicInt ref;
+ QDBusConnection::ConnectionCapabilities capabilities;
QString name; // this connection's name
QString baseService; // this connection's base service
diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp
index 6638263..111122e 100644
--- a/src/dbus/qdbusdemarshaller.cpp
+++ b/src/dbus/qdbusdemarshaller.cpp
@@ -128,7 +128,7 @@ inline QDBusSignature QDBusDemarshaller::toSignature()
inline QDBusVariant QDBusDemarshaller::toVariant()
{
- QDBusDemarshaller sub;
+ QDBusDemarshaller sub(capabilities);
sub.message = q_dbus_message_ref(message);
q_dbus_message_iter_recurse(&iterator, &sub.iterator);
q_dbus_message_iter_next(&iterator);
@@ -249,7 +249,7 @@ QStringList QDBusDemarshaller::toStringList()
{
QStringList list;
- QDBusDemarshaller sub;
+ QDBusDemarshaller sub(capabilities);
q_dbus_message_iter_recurse(&iterator, &sub.iterator);
q_dbus_message_iter_next(&iterator);
while (!sub.atEnd())
@@ -297,7 +297,7 @@ inline QDBusDemarshaller *QDBusDemarshaller::beginMapEntry()
QDBusDemarshaller *QDBusDemarshaller::beginCommon()
{
- QDBusDemarshaller *d = new QDBusDemarshaller;
+ QDBusDemarshaller *d = new QDBusDemarshaller(capabilities);
d->parent = this;
d->message = q_dbus_message_ref(message);
@@ -336,7 +336,7 @@ QDBusDemarshaller *QDBusDemarshaller::endCommon()
QDBusArgument QDBusDemarshaller::duplicate()
{
- QDBusDemarshaller *d = new QDBusDemarshaller;
+ QDBusDemarshaller *d = new QDBusDemarshaller(capabilities);
d->iterator = iterator;
d->message = q_dbus_message_ref(message);
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 14138e0..ee917a5 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -535,7 +535,7 @@ qDBusSignalFilter(DBusConnection *connection, DBusMessage *message, void *data)
if (d->mode == QDBusConnectionPrivate::InvalidMode)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(message);
+ QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(message, d->capabilities);
qDBusDebug() << d << "got message (signal):" << amsg;
return d->handleMessage(amsg) ?
@@ -967,7 +967,7 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
extern bool qDBusInitThreads();
QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)
- : QObject(p), ref(1), mode(InvalidMode), connection(0), server(0), busService(0),
+ : QObject(p), ref(1), capabilities(0), mode(InvalidMode), connection(0), server(0), busService(0),
watchAndTimeoutLock(QMutex::Recursive),
rootNode(QString(QLatin1Char('/')))
{
@@ -1204,7 +1204,7 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in
QDBusMessagePrivate::setParametersValidated(message, true);
message.setArguments(args);
QDBusError error;
- DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error);
+ DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error);
if (!msg) {
qWarning("QDBusConnection: Could not emit signal %s.%s: %s", qPrintable(interface), memberName.constData(),
qPrintable(error.message()));
@@ -1754,7 +1754,7 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
if (call->pending) {
// decode the message
DBusMessage *reply = q_dbus_pending_call_steal_reply(call->pending);
- msg = QDBusMessagePrivate::fromDBusMessage(reply);
+ msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->capabilities);
q_dbus_message_unref(reply);
}
qDBusDebug() << connection << "got message reply (async):" << msg;
@@ -1805,7 +1805,7 @@ int QDBusConnectionPrivate::send(const QDBusMessage& message)
// through the d_ptr->localReply link
QDBusError error;
- DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error);
+ DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error);
if (!msg) {
if (message.type() == QDBusMessage::MethodCallMessage)
qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s",
@@ -1851,7 +1851,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,
if (!QCoreApplication::instance() || sendMode == QDBus::Block) {
QDBusError err;
- DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &err);
+ DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &err);
if (!msg) {
qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s",
qPrintable(message.service()), qPrintable(message.path()),
@@ -1872,7 +1872,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,
return QDBusMessage::createError(err);
}
- QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply);
+ QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply, capabilities);
q_dbus_message_unref(reply);
qDBusDebug() << this << "got message reply (blocking):" << amsg;
@@ -1948,7 +1948,7 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM
pcall->ref = 0;
QDBusError error;
- DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error);
+ DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error);
if (!msg) {
qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s",
qPrintable(message.service()), qPrintable(message.path()),
diff --git a/src/dbus/qdbusmarshaller.cpp b/src/dbus/qdbusmarshaller.cpp
index 15e56e7..76d76cc 100644
--- a/src/dbus/qdbusmarshaller.cpp
+++ b/src/dbus/qdbusmarshaller.cpp
@@ -188,7 +188,7 @@ inline bool QDBusMarshaller::append(const QDBusVariant &arg)
return false;
}
- QDBusMarshaller sub;
+ QDBusMarshaller sub(capabilities);
open(sub, DBUS_TYPE_VARIANT, signature);
bool isOk = sub.appendVariantInternal(value);
// don't call sub.close(): it auto-closes
@@ -203,7 +203,7 @@ inline void QDBusMarshaller::append(const QStringList &arg)
return;
}
- QDBusMarshaller sub;
+ QDBusMarshaller sub(capabilities);
open(sub, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING);
QStringList::ConstIterator it = arg.constBegin();
QStringList::ConstIterator end = arg.constEnd();
@@ -280,6 +280,7 @@ void QDBusMarshaller::open(QDBusMarshaller &sub, int code, const char *signature
sub.parent = this;
sub.ba = ba;
sub.ok = true;
+ sub.capabilities = capabilities;
if (ba)
switch (code) {
@@ -303,7 +304,7 @@ void QDBusMarshaller::open(QDBusMarshaller &sub, int code, const char *signature
QDBusMarshaller *QDBusMarshaller::beginCommon(int code, const char *signature)
{
- QDBusMarshaller *d = new QDBusMarshaller;
+ QDBusMarshaller *d = new QDBusMarshaller(capabilities);
open(*d, code, signature);
return d;
}
@@ -362,7 +363,7 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg)
if (!d->message)
return false; // can't append this one...
- QDBusDemarshaller demarshaller;
+ QDBusDemarshaller demarshaller(capabilities);
demarshaller.message = q_dbus_message_ref(d->message);
if (d->direction == Demarshalling) {
@@ -528,7 +529,7 @@ bool QDBusMarshaller::appendCrossMarshalling(QDBusDemarshaller *demarshaller)
// We have to recurse
QDBusDemarshaller *drecursed = demarshaller->beginCommon();
- QDBusMarshaller mrecursed; // create on the stack makes it autoclose
+ QDBusMarshaller mrecursed(capabilities); // create on the stack makes it autoclose
QByteArray subSignature;
const char *sig = 0;
if (code == DBUS_TYPE_VARIANT || code == DBUS_TYPE_ARRAY) {
diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp
index c13d483..bd77c77 100644
--- a/src/dbus/qdbusmessage.cpp
+++ b/src/dbus/qdbusmessage.cpp
@@ -95,14 +95,15 @@ QString QDBusMessage::errorMessage() const
/*!
\internal
- Constructs a DBusMessage object from this object. The returned value must be de-referenced
- with q_dbus_message_unref.
+ Constructs a DBusMessage object from \a message. The returned value must be de-referenced
+ with q_dbus_message_unref. The \a capabilities flags indicates which capabilities to use.
The \a error object is set to indicate the error if anything went wrong with the
marshalling. Usually, this error message will be placed in the reply, as if the call failed.
The \a error pointer must not be null.
*/
-DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDBusError *error)
+DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDBusConnection::ConnectionCapabilities capabilities,
+ QDBusError *error)
{
if (!qdbus_loadLibDBus()) {
*error = QDBusError(QDBusError::Failed, QLatin1String("Could not open lidbus-1 library"));
@@ -177,7 +178,7 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB
// we can record this fact
d_ptr->parametersValidated = true;
- QDBusMarshaller marshaller;
+ QDBusMarshaller marshaller(capabilities);
QVariantList::ConstIterator it = d_ptr->arguments.constBegin();
QVariantList::ConstIterator cend = d_ptr->arguments.constEnd();
q_dbus_message_iter_init_append(msg, &marshaller.iterator);
@@ -222,7 +223,7 @@ DBUS_DISABLE_CHECKS
\internal
Constructs a QDBusMessage by parsing the given DBusMessage object.
*/
-QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg)
+QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnection::ConnectionCapabilities capabilities)
{
QDBusMessage message;
if (!dmsg)
@@ -238,7 +239,7 @@ QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg)
message.d_ptr->signature = QString::fromUtf8(q_dbus_message_get_signature(dmsg));
message.d_ptr->msg = q_dbus_message_ref(dmsg);
- QDBusDemarshaller demarshaller;
+ QDBusDemarshaller demarshaller(capabilities);
demarshaller.message = q_dbus_message_ref(dmsg);
if (q_dbus_message_iter_init(demarshaller.message, &demarshaller.iterator))
while (!demarshaller.atEnd())
@@ -272,7 +273,7 @@ QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn,
// we must marshall and demarshall again so as to create QDBusArgument
// entries for the complex types
QDBusError error;
- DBusMessage *message = toDBusMessage(asSent, &error);
+ DBusMessage *message = toDBusMessage(asSent, conn.capabilities, &error);
if (!message) {
// failed to marshall, so it's a call error
return QDBusMessage::createError(error);
@@ -280,7 +281,7 @@ QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn,
q_dbus_message_set_sender(message, conn.baseService.toUtf8());
- QDBusMessage retval = fromDBusMessage(message);
+ QDBusMessage retval = fromDBusMessage(message, conn.capabilities);
retval.d_ptr->localMessage = true;
q_dbus_message_unref(message);
if (retval.d_ptr->service.isEmpty())
diff --git a/src/dbus/qdbusmessage_p.h b/src/dbus/qdbusmessage_p.h
index 6747976..52d4d25 100644
--- a/src/dbus/qdbusmessage_p.h
+++ b/src/dbus/qdbusmessage_p.h
@@ -56,6 +56,7 @@
#include <qatomic.h>
#include <qstring.h>
#include <qdbusmessage.h>
+#include <qdbusconnection.h>
struct DBusMessage;
@@ -92,8 +93,9 @@ public:
static void setParametersValidated(QDBusMessage &msg, bool enable)
{ msg.d_ptr->parametersValidated = enable; }
- static DBusMessage *toDBusMessage(const QDBusMessage &message, QDBusError *error);
- static QDBusMessage fromDBusMessage(DBusMessage *dmsg);
+ static DBusMessage *toDBusMessage(const QDBusMessage &message, QDBusConnection::ConnectionCapabilities capabilities,
+ QDBusError *error);
+ static QDBusMessage fromDBusMessage(DBusMessage *dmsg, QDBusConnection::ConnectionCapabilities capabilities);
static bool isLocal(const QDBusMessage &msg);
static QDBusMessage makeLocal(const QDBusConnectionPrivate &conn,
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 589b12e..31f70c7 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -1587,6 +1587,9 @@ static void getXDefault(const char *group, const char *key, int *val)
int v = strtol(str, &end, 0);
if (str != end)
*val = v;
+ // otherwise use fontconfig to convert the string to integer
+ else
+ FcNameConstant((FcChar8 *) str, val);
}
}
@@ -2237,6 +2240,7 @@ void qt_init(QApplicationPrivate *priv, int,
}
getXDefault("Xft", FC_ANTIALIAS, &X11->fc_antialias);
#ifdef FC_HINT_STYLE
+ X11->fc_hint_style = -1;
getXDefault("Xft", FC_HINT_STYLE, &X11->fc_hint_style);
#endif
#if 0
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 9242fb6..9f3b9b9 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -3076,65 +3076,150 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
blend(current, spans, &s->penData);
}
-void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
+bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
const QFixedPoint *positions, QFontEngine *fontEngine)
{
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
- QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(fontEngine->glyphFormat) : d->glyphCacheType;
+#if !defined(QT_NO_FREETYPE)
+ if (fontEngine->type() == QFontEngine::Freetype) {
+ QFontEngineFT *fe = static_cast<QFontEngineFT *>(fontEngine);
+ QFontEngineFT::GlyphFormat neededFormat =
+ painter()->device()->devType() == QInternal::Widget
+ ? fe->defaultGlyphFormat()
+ : QFontEngineFT::Format_A8;
+
+ if (d_func()->mono_surface
+ || fe->isBitmapFont() // alphaPenBlt can handle mono, too
+ )
+ neededFormat = QFontEngineFT::Format_Mono;
+
+ if (neededFormat == QFontEngineFT::Format_None)
+ neededFormat = QFontEngineFT::Format_A8;
+
+ QFontEngineFT::QGlyphSet *gset = fe->defaultGlyphs();
+ if (s->matrix.type() >= QTransform::TxScale) {
+ if (s->matrix.isAffine())
+ gset = fe->loadTransformedGlyphSet(s->matrix);
+ else
+ gset = 0;
+ }
- QImageTextureGlyphCache *cache =
- static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphType, s->matrix));
- if (!cache) {
- cache = new QImageTextureGlyphCache(glyphType, s->matrix);
- fontEngine->setGlyphCache(0, cache);
- }
+ if (!gset || gset->outline_drawing
+ || !fe->loadGlyphs(gset, glyphs, numGlyphs, positions, neededFormat))
+ return false;
+
+ FT_Face lockedFace = 0;
+
+ int depth;
+ switch (neededFormat) {
+ case QFontEngineFT::Format_Mono:
+ depth = 1;
+ break;
+ case QFontEngineFT::Format_A8:
+ depth = 8;
+ break;
+ case QFontEngineFT::Format_A32:
+ depth = 32;
+ break;
+ default:
+ Q_ASSERT(false);
+ depth = 0;
+ };
+
+ for (int i = 0; i < numGlyphs; i++) {
+ QFixed spp = fe->subPixelPositionForX(positions[i].x);
+ QFontEngineFT::Glyph *glyph = gset->getGlyph(glyphs[i], spp);
+
+ if (!glyph || glyph->format != neededFormat) {
+ if (!lockedFace)
+ lockedFace = fe->lockFace();
+ glyph = fe->loadGlyph(gset, glyphs[i], spp, neededFormat);
+ }
+
+ if (!glyph || !glyph->data)
+ continue;
+
+ int pitch;
+ switch (neededFormat) {
+ case QFontEngineFT::Format_Mono:
+ pitch = ((glyph->width + 31) & ~31) >> 3;
+ break;
+ case QFontEngineFT::Format_A8:
+ pitch = (glyph->width + 3) & ~3;
+ break;
+ case QFontEngineFT::Format_A32:
+ pitch = glyph->width * 4;
+ break;
+ default:
+ Q_ASSERT(false);
+ pitch = 0;
+ };
+
+ alphaPenBlt(glyph->data, pitch, depth,
+ qFloor(positions[i].x) + glyph->x,
+ qFloor(positions[i].y) - glyph->y,
+ glyph->width, glyph->height);
+ }
+ if (lockedFace)
+ fe->unlockFace();
+ } else
+#endif
+ {
+ QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(fontEngine->glyphFormat) : d->glyphCacheType;
- cache->populate(fontEngine, numGlyphs, glyphs, positions);
- cache->fillInPendingGlyphs();
+ QImageTextureGlyphCache *cache =
+ static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphType, s->matrix));
+ if (!cache) {
+ cache = new QImageTextureGlyphCache(glyphType, s->matrix);
+ fontEngine->setGlyphCache(0, cache);
+ }
- const QImage &image = cache->image();
- int bpl = image.bytesPerLine();
+ cache->populate(fontEngine, numGlyphs, glyphs, positions);
+ cache->fillInPendingGlyphs();
- int depth = image.depth();
- int rightShift = 0;
- int leftShift = 0;
- if (depth == 32)
- leftShift = 2; // multiply by 4
- else if (depth == 1)
- rightShift = 3; // divide by 8
+ const QImage &image = cache->image();
+ int bpl = image.bytesPerLine();
- int margin = cache->glyphMargin();
+ int depth = image.depth();
+ int rightShift = 0;
+ int leftShift = 0;
+ if (depth == 32)
+ leftShift = 2; // multiply by 4
+ else if (depth == 1)
+ rightShift = 3; // divide by 8
- bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions();
+ int margin = cache->glyphMargin();
- const uchar *bits = image.bits();
- for (int i=0; i<numGlyphs; ++i) {
+ bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions();
- QFixed subPixelPosition;
- if (supportsSubPixelPositions)
- subPixelPosition = cache->subPixelPositionForX(positions[i].x);
- QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition);
- const QTextureGlyphCache::Coord &c = cache->coords[glyph];
- if (c.isNull())
- continue;
+ const uchar *bits = image.bits();
+ for (int i=0; i<numGlyphs; ++i) {
- int x = qFloor(positions[i].x) + c.baseLineX - margin;
- int y = qFloor(positions[i].y) - c.baseLineY - margin;
+ QFixed subPixelPosition;
+ if (supportsSubPixelPositions)
+ subPixelPosition = cache->subPixelPositionForX(positions[i].x);
+ QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition);
+ const QTextureGlyphCache::Coord &c = cache->coords[glyph];
+ if (c.isNull())
+ continue;
-// printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n",
-// c.x, c.y,
-// c.w, c.h,
-// c.baseLineX, c.baseLineY,
-// glyphs[i],
-// x, y,
-// positions[i].x.toInt(), positions[i].y.toInt());
+ int x = qFloor(positions[i].x) + c.baseLineX - margin;
+ int y = qFloor(positions[i].y) - c.baseLineY - margin;
- alphaPenBlt(bits + ((c.x << leftShift) >> rightShift) + c.y * bpl, bpl, depth, x, y, c.w, c.h);
- }
+ // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n",
+ // c.x, c.y,
+ // c.w, c.h,
+ // c.baseLineX, c.baseLineY,
+ // glyphs[i],
+ // x, y,
+ // positions[i].x.toInt(), positions[i].y.toInt());
- return;
+ alphaPenBlt(bits + ((c.x << leftShift) >> rightShift) + c.y * bpl, bpl, depth, x, y, c.w, c.h);
+ }
+ }
+ return true;
}
#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
@@ -3445,91 +3530,10 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
if (glyphs.size() == 0)
return;
- // only use subpixel antialiasing when drawing to widgets
- QFontEngineFT::GlyphFormat neededFormat =
- painter()->device()->devType() == QInternal::Widget
- ? fe->defaultGlyphFormat()
- : QFontEngineFT::Format_A8;
-
- if (d_func()->mono_surface
- || fe->isBitmapFont() // alphaPenBlt can handle mono, too
- )
- neededFormat = QFontEngineFT::Format_Mono;
-
- if (neededFormat == QFontEngineFT::Format_None)
- neededFormat = QFontEngineFT::Format_A8;
-
- QFontEngineFT::QGlyphSet *gset = fe->defaultGlyphs();
- if (s->matrix.type() >= QTransform::TxScale) {
- if (s->matrix.isAffine())
- gset = fe->loadTransformedGlyphSet(s->matrix);
- else
- gset = 0;
-
- }
-
- if (!gset || gset->outline_drawing
- || !fe->loadGlyphs(gset, glyphs.data(), glyphs.size(), neededFormat))
- {
+ if (!drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), fontEngine))
QPaintEngine::drawTextItem(p, ti);
- return;
- }
-
- FT_Face lockedFace = 0;
-
- int depth;
- switch (neededFormat) {
- case QFontEngineFT::Format_Mono:
- depth = 1;
- break;
- case QFontEngineFT::Format_A8:
- depth = 8;
- break;
- case QFontEngineFT::Format_A32:
- depth = 32;
- break;
- default:
- Q_ASSERT(false);
- depth = 0;
- };
- for(int i = 0; i < glyphs.size(); i++) {
- QFontEngineFT::Glyph *glyph = gset->getGlyph(glyphs[i]);
-
- if (!glyph || glyph->format != neededFormat) {
- if (!lockedFace)
- lockedFace = fe->lockFace();
- glyph = fe->loadGlyph(gset, glyphs[i], neededFormat);
- }
-
- if (!glyph || !glyph->data)
- continue;
-
- int pitch;
- switch (neededFormat) {
- case QFontEngineFT::Format_Mono:
- pitch = ((glyph->width + 31) & ~31) >> 3;
- break;
- case QFontEngineFT::Format_A8:
- pitch = (glyph->width + 3) & ~3;
- break;
- case QFontEngineFT::Format_A32:
- pitch = glyph->width * 4;
- break;
- default:
- Q_ASSERT(false);
- pitch = 0;
- };
-
- alphaPenBlt(glyph->data, pitch, depth,
- qFloor(positions[i].x) + glyph->x,
- qFloor(positions[i].y) - glyph->y,
- glyph->width, glyph->height);
- }
- if (lockedFace)
- fe->unlockFace();
return;
-
#endif
#endif
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 7f902a8..52f51fa 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -261,7 +261,7 @@ private:
void fillRect(const QRectF &rect, QSpanData *data);
void drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fill);
- void drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions,
+ bool drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions,
QFontEngine *fontEngine);
#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp
index 8b71b83..94828fb 100644
--- a/src/gui/painting/qpaintengine_x11.cpp
+++ b/src/gui/painting/qpaintengine_x11.cpp
@@ -2385,7 +2385,7 @@ void QX11PaintEngine::drawFreetype(const QPointF &p, const QTextItemInt &ti)
set = ft->loadTransformedGlyphSet(d->matrix);
if (!set || set->outline_drawing
- || !ft->loadGlyphs(set, glyphs.data(), glyphs.size(), QFontEngineFT::Format_Render))
+ || !ft->loadGlyphs(set, glyphs.constData(), glyphs.size(), positions.constData(), QFontEngineFT::Format_Render))
{
QPaintEngine::drawTextItem(p, ti);
return;
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 2c25e70..14fb772 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -6463,7 +6463,7 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
pen.setWidthF(fe->lineThickness().toReal());
pen.setCapStyle(Qt::FlatCap);
- QLineF line(pos.x(), pos.y(), pos.x() + width, pos.y());
+ QLineF line(pos.x(), pos.y(), pos.x() + qFloor(width), pos.y());
const qreal underlineOffset = fe->underlinePosition().toReal();
// deliberately ceil the offset to avoid the underline coming too close to
@@ -8149,6 +8149,10 @@ start_lengthVariant:
engine.option.setTextDirection(layout_direction);
if (tf & Qt::AlignJustify)
engine.option.setAlignment(Qt::AlignJustify);
+ else if (tf & Qt::AlignRight)
+ engine.option.setAlignment(Qt::AlignRight);
+ else if (tf & Qt::AlignHCenter)
+ engine.option.setAlignment(Qt::AlignHCenter);
else
engine.option.setAlignment(Qt::AlignLeft); // do not do alignment twice
@@ -8244,14 +8248,7 @@ start_lengthVariant:
for (int i = 0; i < textLayout.lineCount(); i++) {
QTextLine line = textLayout.lineAt(i);
-
- qreal advance = line.horizontalAdvance();
- if (tf & Qt::AlignRight)
- xoff = r.width() - advance;
- else if (tf & Qt::AlignHCenter)
- xoff = (r.width() - advance)/2;
-
- line.draw(painter, QPointF(r.x() + xoff + line.x(), r.y() + yoff));
+ line.draw(painter, QPointF(r.x(), r.y() + yoff));
}
if (restore) {
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index e75c0f5..f0db805 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -134,9 +134,13 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
if (!supportsSubPixelPositions) {
m_subPixelPositionCount = 1;
} else {
+#if !defined(Q_WS_X11)
int i = 0;
while (m_subPixelPositionCount == 0 && i < numGlyphs)
m_subPixelPositionCount = calculateSubPixelPositionCount(glyphs[i++]);
+#else
+ m_subPixelPositionCount = 4;
+#endif
}
}
@@ -234,6 +238,11 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
}
}
+ if (maxTextureHeight() > 0 && m_cy + c.h > maxTextureHeight()) {
+ // We can't make a cache of the required size, so we bail out
+ return false;
+ }
+
c.x = m_cx;
c.y = m_cy;
@@ -307,9 +316,11 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition
QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_fontengine);
QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform);
+ QFixedPoint positions[1];
+ positions[0].x = subPixelPosition;
- if (gset && ft->loadGlyphs(gset, &g, 1, format)) {
- QFontEngineFT::Glyph *glyph = gset->getGlyph(g);
+ if (gset && ft->loadGlyphs(gset, &g, 1, positions, format)) {
+ QFontEngineFT::Glyph *glyph = gset->getGlyph(g, subPixelPosition);
const int bytesPerLine = (format == QFontEngineFT::Format_Mono ? ((glyph->width + 31) & ~31) >> 3
: (glyph->width + 3) & ~3);
return QImage(glyph->data, glyph->width, glyph->height, bytesPerLine, imageFormat);
@@ -356,7 +367,7 @@ void QImageTextureGlyphCache::createTextureData(int width, int height)
int QImageTextureGlyphCache::glyphMargin() const
{
-#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+#if (defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)) || defined(Q_WS_X11)
return 0;
#else
return m_type == QFontEngineGlyphCache::Raster_RGBMask ? 2 : 0;
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 4441b30..7d11e2f 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -1085,8 +1085,11 @@ QDebug operator<<(QDebug dbg, const QTransform &m)
"TxNone",
"TxTranslate",
"TxScale",
+ 0,
"TxRotate",
+ 0, 0, 0,
"TxShear",
+ 0, 0, 0, 0, 0, 0, 0,
"TxProject"
};
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
index 02b0148..0c0c4c8 100644
--- a/src/gui/text/qfontdatabase_x11.cpp
+++ b/src/gui/text/qfontdatabase_x11.cpp
@@ -746,6 +746,7 @@ QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &request)
QFontDef fontDef;
fontDef.styleStrategy = request.styleStrategy;
+ fontDef.hintingPreference = request.hintingPreference;
FcChar8 *value = 0;
if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) == FcResultMatch) {
fontDef.family = QString::fromUtf8(reinterpret_cast<const char *>(value));
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index f5e9e1c..db0156a 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -174,9 +174,7 @@ int QFreetypeFace::fsType() const
HB_Error QFreetypeFace::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
{
- int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
-
- if (HB_Error error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags))
+ if (HB_Error error = (HB_Error)FT_Load_Glyph(face, glyph, flags))
return error;
if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
@@ -760,12 +758,9 @@ void QFontEngineFT::setDefaultHintStyle(HintStyle style)
default_hint_style = style;
}
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const
+int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
+ bool &hsubpixel, int &vfactor) const
{
- Glyph *g = set->getGlyph(glyph);
- if (g && g->format == format)
- return g;
-
int load_flags = FT_LOAD_DEFAULT | default_load_flags;
int load_target = default_hint_style == HintLight
? FT_LOAD_TARGET_LIGHT
@@ -777,20 +772,35 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph
if (subpixelType == QFontEngineFT::Subpixel_RGB || subpixelType == QFontEngineFT::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) {
if (default_hint_style == HintFull)
load_target = FT_LOAD_TARGET_LCD_V;
+ vfactor = 3;
}
}
- if (set->outline_drawing)
+ if (set && set->outline_drawing)
load_flags = FT_LOAD_NO_BITMAP;
- if (default_hint_style == HintNone)
+ if (default_hint_style == HintNone || (flags & HB_ShaperFlag_UseDesignMetrics))
load_flags |= FT_LOAD_NO_HINTING;
else
load_flags |= load_target;
+ return load_flags;
+}
+
+QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const
+{
+ Glyph *g = set->getGlyph(glyph);
+ if (g && g->format == format)
+ return g;
+
+ bool hsubpixel = false;
+ int vfactor = 1;
+ int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor);
+
// apply our matrix to this, but note that the metrics will not be affected by this.
FT_Face face = lockFace();
FT_Matrix matrix = this->matrix;
@@ -881,7 +891,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph
return g;
}
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, GlyphFormat format, bool fetchMetricsOnly) const
+QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
+ QFixed subPixelPosition,
+ GlyphFormat format,
+ bool fetchMetricsOnly) const
{
// Q_ASSERT(freetype->lock == 1);
@@ -896,10 +909,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
}
}
- Glyph *g = set->getGlyph(glyph);
+ Glyph *g = set->getGlyph(glyph, subPixelPosition);
if (g && g->format == format) {
if (uploadToServer && !g->uploadedToServer) {
- set->setGlyph(glyph, 0);
+ set->setGlyph(glyph, subPixelPosition, 0);
delete g;
g = 0;
} else {
@@ -912,33 +925,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
Q_ASSERT(format != Format_None);
bool hsubpixel = false;
int vfactor = 1;
- int load_flags = FT_LOAD_DEFAULT | default_load_flags;
-
- int load_target = default_hint_style == HintLight
- ? FT_LOAD_TARGET_LIGHT
- : FT_LOAD_TARGET_NORMAL;
-
- if (set->outline_drawing)
- load_flags |= FT_LOAD_NO_BITMAP;
-
- 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 (default_hint_style == HintFull)
- load_target = FT_LOAD_TARGET_LCD;
- hsubpixel = true;
- } else if (subpixelType == QFontEngineFT::Subpixel_VRGB || subpixelType == QFontEngineFT::Subpixel_VBGR) {
- if (default_hint_style == HintFull)
- load_target = FT_LOAD_TARGET_LCD_V;
- vfactor = 3;
- }
- }
-
- if (default_hint_style == HintNone)
- load_flags |= FT_LOAD_NO_HINTING;
- else
- load_flags |= load_target;
+ int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor);
#ifndef Q_WS_QWS
if (format != Format_Mono && !embeddedbitmap)
@@ -955,6 +942,12 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
load_flags |= FT_LOAD_NO_BITMAP;
FT_Face face = freetype->face;
+
+ FT_Vector v;
+ v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.toReal() * 64);
+ v.y = 0;
+ FT_Set_Transform(face, &freetype->matrix, &v);
+
FT_Error err = FT_Load_Glyph(face, glyph, load_flags);
if (err && (load_flags & FT_LOAD_NO_BITMAP)) {
load_flags &= ~FT_LOAD_NO_BITMAP;
@@ -1055,6 +1048,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
top = CEIL(top);
int hpixels = TRUNC(right - left);
+ // subpixel position requires one more pixel
+ if (subPixelPosition > 0 && format != Format_Mono)
+ hpixels++;
+
if (hsubpixel)
hpixels = hpixels*3 + 8;
info.width = hpixels;
@@ -1197,7 +1194,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
uploadGlyphToServer(set, glyph, g, &info, glyph_buffer_size);
}
- set->setGlyph(glyph, g);
+ set->setGlyph(glyph, subPixelPosition, g);
return g;
}
@@ -1430,12 +1427,28 @@ QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(const QTransfor
return gs;
}
-bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format)
+QFixed QFontEngineFT::subPixelPositionForX(QFixed x)
+{
+ int m_subPixelPositionCount = 4;
+
+ QFixed subPixelPosition;
+ if (x != 0) {
+ subPixelPosition = x - x.floor();
+ QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();
+ subPixelPosition = fraction / QFixed(m_subPixelPositionCount);
+ }
+ return subPixelPosition;
+}
+
+bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,
+ const QFixedPoint *positions,
+ GlyphFormat format)
{
FT_Face face = 0;
for (int i = 0; i < num_glyphs; ++i) {
- Glyph *glyph = gs->getGlyph(glyphs[i]);
+ QFixed spp = subPixelPositionForX(positions[i].x);
+ Glyph *glyph = gs->getGlyph(glyphs[i], spp);
if (glyph == 0 || glyph->format != format) {
if (!face) {
face = lockFace();
@@ -1444,7 +1457,7 @@ bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, G
FT_Set_Transform(face, &m, 0);
freetype->matrix = m;
}
- if (!loadGlyph(gs, glyphs[i], format)) {
+ if (!loadGlyph(gs, glyphs[i], spp, format)) {
unlockFace();
return false;
}
@@ -1668,32 +1681,23 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs
void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
{
FT_Face face = 0;
- if (flags & QTextEngine::DesignMetrics) {
- for (int i = 0; i < glyphs->numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
- if (g) {
- glyphs->advances_x[i] = QFixed::fromFixed(g->linearAdvance);
- } else {
- if (!face)
- face = lockFace();
- g = loadGlyph(glyphs->glyphs[i], Format_None, true);
- glyphs->advances_x[i] = QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10);
- }
- glyphs->advances_y[i] = 0;
- }
- } else {
- for (int i = 0; i < glyphs->numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
- if (g) {
- glyphs->advances_x[i] = QFixed(g->advance);
- } else {
- if (!face)
- face = lockFace();
- g = loadGlyph(glyphs->glyphs[i], Format_None, true);
- glyphs->advances_x[i] = QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
- }
- glyphs->advances_y[i] = 0;
+ bool design = (default_hint_style == HintNone ||
+ default_hint_style == HintLight ||
+ (flags & HB_ShaperFlag_UseDesignMetrics));
+ for (int i = 0; i < glyphs->numGlyphs; i++) {
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
+ if (g) {
+ glyphs->advances_x[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
+ } else {
+ if (!face)
+ face = lockFace();
+ g = loadGlyph(glyphs->glyphs[i], 0, Format_None, true);
+ glyphs->advances_x[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10)
+ : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
}
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ glyphs->advances_x[i] = glyphs->advances_x[i].round();
+ glyphs->advances_y[i] = 0;
}
if (face)
unlockFace();
@@ -1716,7 +1720,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
if (!g) {
if (!face)
face = lockFace();
- g = loadGlyph(glyphs.glyphs[i], Format_None, true);
+ g = loadGlyph(glyphs.glyphs[i], 0, Format_None, true);
}
if (g) {
QFixed x = overall.xoff + glyphs.offsets[i].x + g->x;
@@ -1757,7 +1761,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
Glyph *g = defaultGlyphSet.getGlyph(glyph);
if (!g) {
face = lockFace();
- g = loadGlyph(glyph, Format_None, true);
+ g = loadGlyph(glyph, 0, Format_None, true);
}
if (g) {
overall.x = g->x;
@@ -1765,6 +1769,8 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
overall.width = g->width;
overall.height = g->height;
overall.xoff = g->advance;
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ overall.xoff = overall.xoff.round();
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
@@ -1860,13 +1866,13 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, const QTransfo
return overall;
}
-QImage QFontEngineFT::alphaMapForGlyph(glyph_t g)
+QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
{
lockFace();
GlyphFormat glyph_format = antialias ? Format_A8 : Format_Mono;
- Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, glyph_format);
+ Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, subPixelPosition, glyph_format);
if (!glyph) {
unlockFace();
return QFontEngine::alphaMapForGlyph(g);
@@ -1905,7 +1911,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, in
GlyphFormat glyph_format = Format_A32;
- Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, glyph_format);
+ Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, subPixelPosition, glyph_format);
if (!glyph) {
unlockFace();
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
@@ -1920,7 +1926,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, in
void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
{
- defaultGlyphSet.removeGlyphFromCache(glyph);
+ defaultGlyphSet.removeGlyphFromCache(glyph, 0);
}
int QFontEngineFT::glyphCount() const
@@ -2000,9 +2006,9 @@ void QFontEngineFT::QGlyphSet::clear()
glyph_data.clear();
}
-void QFontEngineFT::QGlyphSet::removeGlyphFromCache(int index)
+void QFontEngineFT::QGlyphSet::removeGlyphFromCache(glyph_t index, QFixed subPixelPosition)
{
- if (index < 256) {
+ if (useFastGlyphData(index, subPixelPosition)) {
if (fast_glyph_data[index]) {
delete fast_glyph_data[index];
fast_glyph_data[index] = 0;
@@ -2010,18 +2016,18 @@ void QFontEngineFT::QGlyphSet::removeGlyphFromCache(int index)
--fast_glyph_count;
}
} else {
- delete glyph_data.take(index);
+ delete glyph_data.take(GlyphAndSubPixelPosition(index, subPixelPosition));
}
}
-void QFontEngineFT::QGlyphSet::setGlyph(int index, Glyph *glyph)
+void QFontEngineFT::QGlyphSet::setGlyph(glyph_t index, QFixed subPixelPosition, Glyph *glyph)
{
- if (index < 256) {
+ if (useFastGlyphData(index, subPixelPosition)) {
if (!fast_glyph_data[index])
++fast_glyph_count;
fast_glyph_data[index] = glyph;
} else {
- glyph_data.insert(index, glyph);
+ glyph_data.insert(GlyphAndSubPixelPosition(index, subPixelPosition), glyph);
}
}
@@ -2038,7 +2044,10 @@ void QFontEngineFT::freeServerGlyphSet(unsigned long id)
HB_Error QFontEngineFT::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
{
lockFace();
- HB_Error result = freetype->getPointInOutline(glyph, flags, point, xpos, ypos, nPoints);
+ bool hsubpixel = true;
+ int vfactor = 1;
+ int load_flags = loadFlags(0, Format_A8, flags, hsubpixel, vfactor);
+ HB_Error result = freetype->getPointInOutline(glyph, load_flags, point, xpos, ypos, nPoints);
unlockFace();
return result;
}
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index abdbd20..fc3ac82 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -166,6 +166,19 @@ public:
};
#endif
+ struct GlyphAndSubPixelPosition
+ {
+ GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {}
+
+ bool operator==(const GlyphAndSubPixelPosition &other) const
+ {
+ return glyph == other.glyph && subPixelPosition == other.subPixelPosition;
+ }
+
+ glyph_t glyph;
+ QFixed subPixelPosition;
+ };
+
struct QGlyphSet
{
QGlyphSet();
@@ -174,18 +187,21 @@ public:
unsigned long id; // server sided id, GlyphSet for X11
bool outline_drawing;
- void removeGlyphFromCache(int index);
+ void removeGlyphFromCache(glyph_t index, QFixed subPixelPosition);
void clear();
- inline Glyph *getGlyph(int index) const
+ inline bool useFastGlyphData(glyph_t index, QFixed subPixelPosition) const {
+ return (index < 256 && subPixelPosition == 0);
+ }
+ inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const
{
- if (index < 256)
+ if (useFastGlyphData(index, subPixelPosition))
return fast_glyph_data[index];
- return glyph_data.value(index);
+ return glyph_data.value(GlyphAndSubPixelPosition(index, subPixelPosition));
}
- void setGlyph(int index, Glyph *glyph);
+ void setGlyph(glyph_t index, QFixed spp, Glyph *glyph);
private:
- mutable QHash<int, Glyph *> glyph_data; // maps from glyph index to glyph data
+ mutable QHash<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data
mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
mutable int fast_glyph_count;
};
@@ -193,6 +209,11 @@ private:
virtual QFontEngine::FaceId faceId() const;
virtual QFontEngine::Properties properties() const;
virtual QFixed emSquareSize() const;
+ virtual bool supportsSubPixelPositions() const
+ {
+ return default_hint_style == HintLight ||
+ default_hint_style == HintNone;
+ }
virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
virtual int synthesized() const;
@@ -233,7 +254,8 @@ private:
virtual glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix);
virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const;
- virtual QImage alphaMapForGlyph(glyph_t);
+ virtual QImage alphaMapForGlyph(glyph_t g) { return alphaMapForGlyph(g, 0); }
+ virtual QImage alphaMapForGlyph(glyph_t, QFixed);
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t);
virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QTransform &matrix,
QFontEngine::GlyphFormat format);
@@ -254,17 +276,20 @@ private:
inline bool invalid() const { return xsize == 0 && ysize == 0; }
inline bool isBitmapFont() const { return defaultFormat == Format_Mono; }
- inline Glyph *loadGlyph(uint glyph, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
- { return loadGlyph(&defaultGlyphSet, glyph, format, fetchMetricsOnly); }
- Glyph *loadGlyph(QGlyphSet *set, uint glyph, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
+ inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
+ { return loadGlyph(&defaultGlyphSet, glyph, subPixelPosition, format, fetchMetricsOnly); }
+ Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
QGlyphSet *defaultGlyphs() { return &defaultGlyphSet; }
GlyphFormat defaultGlyphFormat() const { return defaultFormat; }
- inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.getGlyph(g); }
+ inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.getGlyph(g, 0); }
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
- bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format = Format_Render);
+ QFixed subPixelPositionForX(QFixed x);
+ bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,
+ const QFixedPoint *positions,
+ GlyphFormat format = Format_Render);
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
virtual void draw(QPaintEngine * /*p*/, qreal /*x*/, qreal /*y*/, const QTextItemInt & /*si*/) {}
@@ -309,6 +334,7 @@ protected:
private:
QFontEngineFT::Glyph *loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const;
+ int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
GlyphFormat defaultFormat;
FT_Matrix matrix;
@@ -330,6 +356,11 @@ private:
mutable bool kerning_pairs_loaded;
};
+inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g)
+{
+ return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_FREETYPE
diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp
index 2fd4716..d35bbe5 100644
--- a/src/gui/text/qfontengine_qpf.cpp
+++ b/src/gui/text/qfontengine_qpf.cpp
@@ -306,6 +306,8 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
glyphMapEntries = 0;
glyphDataOffset = 0;
glyphDataSize = 0;
+ if (renderingFontEngine)
+ glyphFormat = renderingFontEngine->glyphFormat;
kerning_pairs_loaded = false;
readOnly = true;
diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp
index d5ec584..9f3f8d3 100644
--- a/src/gui/text/qfontengine_x11.cpp
+++ b/src/gui/text/qfontengine_x11.cpp
@@ -1012,10 +1012,29 @@ QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int s
}
}
+ if (fd.hintingPreference != QFont::PreferDefaultHinting) {
+ switch (fd.hintingPreference) {
+ case QFont::PreferNoHinting:
+ default_hint_style = HintNone;
+ break;
+ case QFont::PreferVerticalHinting:
+ default_hint_style = HintLight;
+ break;
+ case QFont::PreferFullHinting:
+ default:
+ default_hint_style = HintFull;
+ break;
+ }
+ }
#ifdef FC_HINT_STYLE
- {
+ else {
int hint_style = 0;
- if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch)
+ // Try to use Xft.hintstyle from XDefaults first if running in GNOME, to match
+ // the behavior of cairo
+ if (X11->fc_hint_style > -1 && X11->desktopEnvironment == DE_GNOME)
+ hint_style = X11->fc_hint_style;
+ else if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch
+ && X11->fc_hint_style > -1)
hint_style = X11->fc_hint_style;
switch (hint_style) {
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index ad77d7f..6678522 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -1577,8 +1577,13 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
// cache so this text is performed before we test if the cache size has changed.
if (recreateVertexArrays) {
cache->setPaintEnginePrivate(this);
- cache->populate(staticTextItem->fontEngine(), staticTextItem->numGlyphs,
- staticTextItem->glyphs, staticTextItem->glyphPositions);
+ if (!cache->populate(staticTextItem->fontEngine(), staticTextItem->numGlyphs,
+ staticTextItem->glyphs, staticTextItem->glyphPositions)) {
+ // No space for glyphs in cache. We need to reset it and try again.
+ cache->clear();
+ cache->populate(staticTextItem->fontEngine(), staticTextItem->numGlyphs,
+ staticTextItem->glyphs, staticTextItem->glyphPositions);
+ }
cache->fillInPendingGlyphs();
}
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index 9e8e828..c867d60 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -378,4 +378,19 @@ int QGLTextureGlyphCache::maxTextureHeight() const
else
return ctx->d_ptr->maxTextureSize();
}
+
+void QGLTextureGlyphCache::clear()
+{
+ if (ctx != 0) {
+ m_textureResource.cleanup(ctx);
+
+ m_w = 0;
+ m_h = 0;
+ m_cx = 0;
+ m_cy = 0;
+ m_currentRowHeight = 0;
+ coords.clear();
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
index cc6de28..133289e 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
@@ -142,6 +142,8 @@ public:
FilterMode filterMode() const { return m_filterMode; }
void setFilterMode(FilterMode m) { m_filterMode = m; }
+ void clear();
+
void freeResource(void *) { ctx = 0; }
private:
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 19858e7..4698a5c 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -5606,6 +5606,21 @@ void *QGLContextGroupResourceBase::value(const QGLContext *context)
return group->m_resources.value(this, 0);
}
+void QGLContextGroupResourceBase::cleanup(const QGLContext *ctx)
+{
+ void *resource = value(ctx);
+
+ if (resource != 0) {
+ QGLShareContextScope scope(ctx);
+ freeResource(resource);
+
+ QGLContextGroup *group = QGLContextPrivate::contextGroup(ctx);
+ group->m_resources.remove(this);
+ m_groups.removeOne(group);
+ active.deref();
+ }
+}
+
void QGLContextGroupResourceBase::cleanup(const QGLContext *ctx, void *value)
{
#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 5a5e5cc..b2261a2 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -687,6 +687,7 @@ public:
virtual ~QGLContextGroupResourceBase();
void insert(const QGLContext *context, void *value);
void *value(const QGLContext *context);
+ void cleanup(const QGLContext *context);
void cleanup(const QGLContext *context, void *value);
virtual void freeResource(void *value) = 0;