From de66ffa4d7d057f0c782edc45374ad58322a0c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Thu, 26 Aug 2010 09:55:31 +0200 Subject: Remove listing all platform plugins on load --- src/gui/kernel/qplatformintegrationfactory_qpa.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/kernel/qplatformintegrationfactory_qpa.cpp b/src/gui/kernel/qplatformintegrationfactory_qpa.cpp index 4f2bfa5..9122e1a 100644 --- a/src/gui/kernel/qplatformintegrationfactory_qpa.cpp +++ b/src/gui/kernel/qplatformintegrationfactory_qpa.cpp @@ -61,7 +61,6 @@ QPlatformIntegration *QPlatformIntegrationFactory::create(const QString& key) QString platform = paramList.takeFirst().toLower(); #if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) - qDebug() << loader()->keys(); if (QPlatformIntegrationFactoryInterface *factory = qobject_cast(loader()->instance(platform))) ret = factory->create(platform, paramList); #endif -- cgit v0.12 From 5e7fdcc7a4a2bb070ad7ece920ac5db81e3e6f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 20 Aug 2010 12:33:33 +0200 Subject: Initial pluggable fontdatabase QPlatformFontDatabase added. QPlatformIntegration now has a new virtual function: QPlatformDatabase::fontDatabase() const. Most unix platform plugins wants to follow the pattern implemented in directfb, linuxfb, vnc etc. In the pro file do: include(../fontdatabases/genericunix/genericunix.pri) In the QPlatformIntegration class do: and instansiate a QGenericFontDatabase in the constructor and return it in the getter function. --- configure | 24 + lib/fonts/dejavu_sans_11_50.qpf2 | Bin 0 -> 405944 bytes src/gui/kernel/qplatformintegration_qpa.cpp | 11 + src/gui/kernel/qplatformintegration_qpa.h | 4 + src/gui/painting/qpaintengine.h | 2 +- src/gui/painting/qpaintengine_raster.cpp | 31 +- src/gui/painting/qpdf.cpp | 2 +- src/gui/text/qfont.h | 4 +- src/gui/text/qfont_qpa.cpp | 114 ++++ src/gui/text/qfontdatabase.cpp | 67 ++- src/gui/text/qfontdatabase.h | 1 + src/gui/text/qfontdatabase_qpa.cpp | 392 +++++++++++++ src/gui/text/qfontengine.cpp | 2 +- src/gui/text/qfontengine_ft.cpp | 7 +- src/gui/text/qfontengine_ft_p.h | 16 +- src/gui/text/qfontengine_p.h | 2 +- src/gui/text/qfontengine_qpa.cpp | 650 +++++++++++++++++++++ src/gui/text/qfontengine_qpa_p.h | 262 +++++++++ src/gui/text/qplatformfontdatabase_qpa.cpp | 195 +++++++ src/gui/text/qplatformfontdatabase_qpa.h | 65 +++ src/gui/text/text.pri | 22 +- src/plugins/platforms/directfb/directfb.pro | 2 + .../platforms/directfb/qdirectfbintegration.cpp | 7 +- .../platforms/directfb/qdirectfbintegration.h | 4 +- src/plugins/platforms/eglfs/eglfs.pro | 2 + src/plugins/platforms/eglfs/qeglfsintegration.cpp | 8 + src/plugins/platforms/eglfs/qeglfsintegration.h | 3 + .../fontdatabases/basicunix/basicunix.pri | 82 +++ .../basicunix/qbasicunixfontdatabase.cpp | 281 +++++++++ .../basicunix/qbasicunixfontdatabase.h | 26 + .../fontdatabases/fontconfig/fontconfig.pri | 12 + .../fontconfig/qfontconfigdatabase.cpp | 528 +++++++++++++++++ .../fontdatabases/fontconfig/qfontconfigdatabase.h | 15 + .../fontdatabases/genericunix/genericunix.pri | 10 + .../genericunix/qgenericunixfontdatabase.h | 12 + src/plugins/platforms/linuxfb/linuxfb.pro | 1 + .../platforms/linuxfb/qlinuxfbintegration.cpp | 7 + .../platforms/linuxfb/qlinuxfbintegration.h | 3 + src/plugins/platforms/platforms.pro | 12 +- src/plugins/platforms/qvfb/qvfb.pro | 2 + src/plugins/platforms/qvfb/qvfbintegration.cpp | 8 + src/plugins/platforms/qvfb/qvfbintegration.h | 3 + .../platforms/testlite/qtestliteintegration.cpp | 8 +- .../platforms/testlite/qtestliteintegration.h | 3 + src/plugins/platforms/testlite/qtestlitewindow.cpp | 10 +- src/plugins/platforms/testlite/testlite.pro | 21 +- src/plugins/platforms/vnc/qvncintegration.cpp | 8 +- src/plugins/platforms/vnc/qvncintegration.h | 4 + src/plugins/platforms/vnc/vnc.pro | 1 + 49 files changed, 2894 insertions(+), 62 deletions(-) create mode 100644 lib/fonts/dejavu_sans_11_50.qpf2 create mode 100644 src/gui/text/qfont_qpa.cpp create mode 100644 src/gui/text/qfontdatabase_qpa.cpp create mode 100644 src/gui/text/qfontengine_qpa.cpp create mode 100644 src/gui/text/qfontengine_qpa_p.h create mode 100644 src/gui/text/qplatformfontdatabase_qpa.cpp create mode 100644 src/gui/text/qplatformfontdatabase_qpa.h create mode 100644 src/plugins/platforms/fontdatabases/basicunix/basicunix.pri create mode 100644 src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp create mode 100644 src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h create mode 100644 src/plugins/platforms/fontdatabases/fontconfig/fontconfig.pri create mode 100644 src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp create mode 100644 src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h create mode 100644 src/plugins/platforms/fontdatabases/genericunix/genericunix.pri create mode 100644 src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h diff --git a/configure b/configure index bdf4588..94a0c0f 100755 --- a/configure +++ b/configure @@ -6093,6 +6093,30 @@ if [ "$PLATFORM_QPA" = "yes" ]; then exit 1 fi fi + + # auto-detect FontConfig support + if [ "$CFG_FONTCONFIG" != "no" ]; then + if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists fontconfig --exists freetype2 2>/dev/null; then + QT_CFLAGS_FONTCONFIG=`$PKG_CONFIG --cflags fontconfig --cflags freetype2 2>/dev/null` + QT_LIBS_FONTCONFIG=`$PKG_CONFIG --libs fontconfig --libs freetype2 2>/dev/null` + else + QT_CFLAGS_FONTCONFIG= + QT_LIBS_FONTCONFIG="-lfreetype -lfontconfig" + fi + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/x11/fontconfig "FontConfig" $L_FLAGS $I_FLAGS $l_FLAGS $X11TESTS_FLAGS $QT_CFLAGS_FONTCONFIG $QT_LIBS_FONTCONFIG; then + QT_CONFIG="$QT_CONFIG fontconfig" + QMakeVar set QMAKE_CFLAGS_FONTCONFIG "$QT_CFLAGS_FONTCONFIG" + QMakeVar set QMAKE_LIBS_FONTCONFIG "$QT_LIBS_FONTCONFIG" + CFG_LIBFREETYPE=system + fi + fi + + # MIT_SHM is required for testlite + if [ "$CFG_MITSHM" != "no" ]; then + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/x11/mitshm "mitshm" $L_FLAGS $I_FLAGS $l_FLAGS $X11TESTS_FLAGS; then + QT_CONFIG="$QT_CONFIG mitshm" + fi + fi fi diff --git a/lib/fonts/dejavu_sans_11_50.qpf2 b/lib/fonts/dejavu_sans_11_50.qpf2 new file mode 100644 index 0000000..c88d099 Binary files /dev/null and b/lib/fonts/dejavu_sans_11_50.qpf2 differ diff --git a/src/gui/kernel/qplatformintegration_qpa.cpp b/src/gui/kernel/qplatformintegration_qpa.cpp index b4987f2..e2a493d 100644 --- a/src/gui/kernel/qplatformintegration_qpa.cpp +++ b/src/gui/kernel/qplatformintegration_qpa.cpp @@ -41,6 +41,8 @@ #include "qplatformintegration_qpa.h" +#include + QT_BEGIN_NAMESPACE QPixmap QPlatformIntegration::grabWindow(WId window, int x, int y, int width, int height) const @@ -63,4 +65,13 @@ bool QPlatformIntegration::hasOpenGL() const return false; } +QPlatformFontDatabase *QPlatformIntegration::fontDatabase() const +{ + static QPlatformFontDatabase *db = 0; + if (!db) { + db = new QPlatformFontDatabase; + } + return db; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformintegration_qpa.h b/src/gui/kernel/qplatformintegration_qpa.h index 9460910..b1f4e5f 100644 --- a/src/gui/kernel/qplatformintegration_qpa.h +++ b/src/gui/kernel/qplatformintegration_qpa.h @@ -58,6 +58,7 @@ class QWindowSurface; class QBlittable; class QWidget; class QPlatformEventLoopIntegration; +class QPlatformFontDatabase; class Q_GUI_EXPORT QPlatformIntegration { @@ -75,6 +76,9 @@ public: virtual bool isVirtualDesktop() { return false; } virtual QPixmap grabWindow(WId window, int x, int y, int width, int height) const; +//Fontdatabase integration. + virtual QPlatformFontDatabase *fontDatabase() const; + // Experimental in mainthread eventloop integration // This should only be used if it is only possible to do window system event processing in // the gui thread. All of the functions in QWindowSystemInterface are thread safe. diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h index ddb6195..ee9b457 100644 --- a/src/gui/painting/qpaintengine.h +++ b/src/gui/painting/qpaintengine.h @@ -272,7 +272,7 @@ private: friend class QProxyFontEngine; #endif #ifdef Q_WS_QPA - friend class QProxyFontEngine; + friend class QFontEngineQPA; #endif friend class QPainter; friend class QPainterPrivate; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index df32ea8..7dee7e4 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3396,9 +3396,36 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte } #endif // Q_WS_QWS -#if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) || defined(Q_WS_QPA)) && !defined(QT_NO_FREETYPE) +#ifdef Q_WS_QPA + if (s->matrix.type() < QTransform::TxScale) { -#if (defined(Q_WS_QWS) || defined(Q_WS_QPA)) && !defined(QT_NO_QWS_QPF2) + QVarLengthArray positions; + QVarLengthArray glyphs; + QTransform matrix = state()->transform(); + + qreal _x = qFloor(p.x() + aliasedCoordinateDelta); + qreal _y = qFloor(p.y() + aliasedCoordinateDelta); + matrix.translate(_x, _y); + + fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); + if (glyphs.size() == 0) + return; + + for(int i = 0; i < glyphs.size(); i++) { + QImage img = fontEngine->alphaMapForGlyph(glyphs[i]); + glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]); + alphaPenBlt(img.bits(), img.bytesPerLine(), img.depth(), + qRound(positions[i].x + metrics.x), + qRound(positions[i].y + metrics.y), + img.width(), img.height()); + } + return; + } +#endif //Q_WS_QPA + +#if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) + +#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2) if (fontEngine->type() == QFontEngine::QPF2) { QFontEngine *renderingEngine = static_cast(fontEngine)->renderingEngine(); if (renderingEngine) diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 6e02435..fdb84e0 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -916,7 +916,7 @@ const char *QPdf::paperSizeToString(QPrinter::PaperSize paperSize) } -QByteArray QPdf::stripSpecialCharacters(const QByteArray &string) +Q_GUI_EXPORT QByteArray QPdf::stripSpecialCharacters(const QByteArray &string) { QByteArray s = string; s.replace(' ', ""); diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index fd1a2dd..2cc41e1 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -46,7 +46,7 @@ #include #include -#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) typedef struct FT_FaceRec_* FT_Face; #endif @@ -236,7 +236,7 @@ public: #ifdef Q_WS_MAC quint32 macFontID() const; #endif -#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) FT_Face freetypeFace() const; #endif diff --git a/src/gui/text/qfont_qpa.cpp b/src/gui/text/qfont_qpa.cpp new file mode 100644 index 0000000..5fed18b --- /dev/null +++ b/src/gui/text/qfont_qpa.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +QT_BEGIN_NAMESPACE + +void QFont::initialize() +{ + QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase(); +} + +void QFont::cleanup() +{ + QFontCache::cleanup(); +} + + +/***************************************************************************** + QFont member functions + *****************************************************************************/ + +Qt::HANDLE QFont::handle() const +{ + return 0; +} + +QString QFont::rawName() const +{ + return QLatin1String("unknown"); +} + +void QFont::setRawName(const QString &) +{ +} + +QString QFont::defaultFamily() const +{ + QString familyName; + switch(d->request.styleHint) { + case QFont::Times: + familyName = QString::fromLatin1("times"); + case QFont::Courier: + case QFont::Monospace: + familyName = QString::fromLatin1("monospace"); + case QFont::Decorative: + familyName = QString::fromLatin1("old english"); + case QFont::Helvetica: + case QFont::System: + default: + familyName = QString::fromLatin1("helvetica"); + } + + QStringList list = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(familyName,QFont::StyleNormal,QUnicodeTables::Common); + if (list.size()) { + familyName = list.at(0); + } + return familyName; +} + +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.cpp b/src/gui/text/qfontdatabase.cpp index 7ece6ea..72ffb1c 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -50,13 +50,19 @@ #include "private/qunicodetables_p.h" #include "qfontengine_p.h" +#ifdef Q_WS_QPA +#include +#include +#include "qabstractfileengine.h" +#endif + #ifdef Q_WS_X11 #include #endif #include #include -#if (defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) +#if (defined(Q_WS_QWS)|| defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) # include # include FT_TRUETYPE_TABLES_H #endif @@ -143,7 +149,7 @@ struct QtFontEncoding uchar pitch : 8; }; -struct QtFontSize +struct QtFontSize { #ifdef Q_WS_X11 QtFontEncoding *encodings; @@ -152,10 +158,13 @@ struct QtFontSize unsigned short count : 16; #endif // Q_WS_X11 -#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QByteArray fileName; int fileIndex; #endif // defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QPA) + void *handle; +#endif unsigned short pixelSize : 16; }; @@ -238,9 +247,15 @@ struct QtFontStyle #ifdef Q_WS_X11 free(pixelSizes[count].encodings); #endif -#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) pixelSizes[count].fileName.~QByteArray(); #endif +#if defined (Q_WS_QPA) + QPlatformIntegration *integration = QApplicationPrivate::platformIntegration(); + if (integration) { //on shut down there will be some that we don't release. + integration->fontDatabase()->releaseHandle(pixelSizes[count].handle); + } +#endif } #endif free(pixelSizes); @@ -302,10 +317,13 @@ QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add) pixelSizes[count].count = 0; pixelSizes[count].encodings = 0; #endif -#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) new (&pixelSizes[count].fileName) QByteArray; pixelSizes[count].fileIndex = 0; #endif +#if defined(Q_WS_QPA) + pixelSizes[count].handle = 0; +#endif return pixelSizes + (count++); } @@ -362,7 +380,7 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create) } -struct QtFontFamily +struct QtFontFamily { enum WritingSystemStatus { Unknown = 0, @@ -391,6 +409,9 @@ struct QtFontFamily #if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) , bogusWritingSystems(false) #endif +#if defined(Q_WS_QPA) + , askedForFallback(false) +#endif { memset(writingSystems, 0, sizeof(writingSystems)); } @@ -432,6 +453,9 @@ struct QtFontFamily bool bogusWritingSystems; QStringList fallbackFamilies; #endif +#if defined (Q_WS_QPA) + bool askedForFallback; +#endif unsigned char writingSystems[QFontDatabase::WritingSystemsCount]; QtFontFoundry *foundry(const QString &f, bool = false); @@ -475,7 +499,7 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) // ### copied to tools/makeqpf/qpf2.cpp -#if ((defined(Q_WS_QWS) || defined(Q_WS_QPA)) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)) +#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)) // see the Unicode subset bitfields in the MSDN docs static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { @@ -617,7 +641,7 @@ class QFontDatabasePrivate public: QFontDatabasePrivate() : count(0), families(0), reregisterAppFonts(false) -#if defined(Q_WS_QWS) || defined(Q_WS_QPA) +#if defined(Q_WS_QWS) , stream(0) #endif #if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) @@ -665,11 +689,11 @@ public: void invalidate(); -#if defined(Q_WS_QWS) || defined(Q_WS_QPA) +#if defined(Q_WS_QWS) bool loadFromCache(const QString &fontPath); void addQPF2File(const QByteArray &file); #endif // Q_WS_QWS -#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) void addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, const QByteArray &file, int fileIndex, bool antialiased, @@ -678,12 +702,14 @@ public: QStringList addTTFile(const QByteArray &file, const QByteArray &fontData = QByteArray()); #endif // QT_NO_FREETYPE #endif -#if defined(Q_WS_QWS) || defined (Q_WS_QPA) +#if defined(Q_WS_QWS) QDataStream *stream; - QStringList fallbackFamilies; #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) const QSymbianFontDatabaseExtras *symbianExtras; #endif +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) + QStringList fallbackFamilies; +#endif }; void QFontDatabasePrivate::invalidate() @@ -732,7 +758,7 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) return families[pos]; } -#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, const QByteArray &file, int fileIndex, bool antialiased, const QList &writingSystems) @@ -763,7 +789,7 @@ void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundr size->fileName = file; size->fileIndex = fileIndex; -#if defined(Q_WS_QWS) || defined(Q_WS_QPA) +#if defined(Q_WS_QWS) if (stream) { *stream << familyname << foundry->name << weight << quint8(italic) << pixelSize << file << fileIndex << quint8(antialiased); @@ -778,7 +804,7 @@ void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundr } #endif -#if (defined(Q_WS_QWS) || defined (Q_WS_QPA) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) +#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData) { QStringList families; @@ -891,7 +917,7 @@ static const int scriptForWritingSystem[] = { }; -#if defined Q_WS_QWS || defined(Q_WS_QPA) || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)) || defined(Q_WS_WIN) +#if defined Q_WS_QWS || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)) || defined(Q_WS_WIN) static inline bool requiresOpenType(int writingSystem) { return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) @@ -994,7 +1020,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe #endif #endif -#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || defined(Q_WS_QPA) static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key) { // look for the requested font in the engine data cache @@ -1053,8 +1079,10 @@ QT_BEGIN_INCLUDE_NAMESPACE # include "qfontdatabase_mac.cpp" #elif defined(Q_WS_WIN) # include "qfontdatabase_win.cpp" -#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) +#elif defined(Q_WS_QWS) # include "qfontdatabase_qws.cpp" +#elif defined(Q_WS_QPA) +# include "qfontdatabase_qpa.cpp" #elif defined(Q_OS_SYMBIAN) # include "qfontdatabase_s60.cpp" #endif @@ -1340,6 +1368,7 @@ static void match(int script, const QFontDef &request, styleKey.stretch = request.stretch; char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p'; + FM_DEBUG("QFontDatabase::match\n" " request:\n" " family: %s [%s], script: %d\n" @@ -2485,7 +2514,7 @@ void QFontDatabase::createDatabase() { initializeDb(); } // used from qfontengine_ft.cpp -QByteArray qt_fontdata_from_index(int index) +Q_GUI_EXPORT QByteArray qt_fontdata_from_index(int index) { QMutexLocker locker(fontDatabaseMutex()); return privateDb()->applicationFonts.value(index).data; diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index 6a09b77..f31c19c 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -167,6 +167,7 @@ private: friend class QFontEngineMultiXLFD; friend class QFontEngineMultiQWS; friend class QFontEngineMultiS60; + friend class QFontEngineMultiQPA; QFontDatabasePrivate *d; }; diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp new file mode 100644 index 0000000..53594aa --- /dev/null +++ b/src/gui/text/qfontdatabase_qpa.cpp @@ -0,0 +1,392 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlibraryinfo.h" +#include + +#include "qfontengine_qpa_p.h" +#include "qplatformdefs.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &foundryname, int weight, + QFont::Style style, int stretch, bool antialiased, bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *handle) +{ + QFontDatabasePrivate *d = privateDb(); + // qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased; + QtFontStyle::Key styleKey; + styleKey.style = style; + styleKey.weight = weight; + styleKey.stretch = stretch; + QtFontFamily *f = d->family(familyName, true); + + for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { + if (writingSystems.supported(QFontDatabase::WritingSystem(i))) { + f->writingSystems[i] = QtFontFamily::Supported; + } else { + f->writingSystems[i] = QtFontFamily::Unsupported; + } + } + + QtFontFoundry *foundry = f->foundry(foundryname, true); + QtFontStyle *fontStyle = foundry->style(styleKey, true); + fontStyle->smoothScalable = scalable; + fontStyle->antialiased = antialiased; + QtFontSize *size = fontStyle->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true); + size->handle = handle; +} + +static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QUnicodeTables::Script &script) +{ + QStringList retList = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,script); + QFontDatabasePrivate *db = privateDb(); + + QStringList::iterator i; + for (i = retList.begin(); i != retList.end(); ++i) { + bool contains = false; + for (int j = 0; j < db->count; j++) { + QtFontFamily *qtFamily = db->families[j]; + if (!(i->compare(qtFamily->name,Qt::CaseInsensitive))) { + contains = true; + break; + } + } + if (!contains) { + i = retList.erase(i); + i--; + } + } + return retList; +} + +static void initializeDb() +{ + static int initialized = false; + + if (!initialized) { + //init by asking for the platformfontdb for the first time :) + QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase(); + initialized = true; + } +} + +#ifndef QT_NO_SETTINGS +// called from qapplication_qws.cpp +void qt_applyFontDatabaseSettings(const QSettings &settings) +{ + initializeDb(); + QFontDatabasePrivate *db = privateDb(); + for (int i = 0; i < db->count; ++i) { + QtFontFamily *family = db->families[i]; + if (settings.contains(family->name)) + family->fallbackFamilies = settings.value(family->name).toStringList(); + } + + if (settings.contains(QLatin1String("Global Fallbacks"))) + db->fallbackFamilies = settings.value(QLatin1String("Global Fallbacks")).toStringList(); +} +#endif // QT_NO_SETTINGS + +static inline void load(const QString & = QString(), int = -1) +{ + initializeDb(); +} + +static +QFontEngine *loadSingleEngine(int script, + const QFontDef &request, + QtFontFoundry *foundry, + QtFontStyle *style, QtFontSize *size) +{ + Q_UNUSED(foundry); + + Q_ASSERT(size); + int pixelSize = size->pixelSize; + if (!pixelSize || (style->smoothScalable && pixelSize == SMOOTH_SCALABLE)) + pixelSize = request.pixelSize; + + QFontDef def = request; + def.pixelSize = pixelSize; + + QFontCache::Key key(def,script); + QFontEngine *engine = QFontCache::instance()->findEngine(key); + if (!engine) { + QPlatformFontDatabase *pfdb = QApplicationPrivate::platformIntegration()->fontDatabase(); + if (size->handle) { + engine = pfdb->fontEngine(def,QUnicodeTables::Script(script),size->handle); + if (engine) { + QFontCache::Key key(def,script); + QFontCache::instance()->instance()->insertEngine(key,engine); + } + } + + } + return engine; +} + +static +QFontEngine *loadEngine(int script, const QFontDef &request, + QtFontFamily *family, QtFontFoundry *foundry, + QtFontStyle *style, QtFontSize *size) +{ + + QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size); + //make sure that the db has all fallback families + if (engine + && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) { + + if (family && !family->askedForFallback) { + family->fallbackFamilies = fallbackFamilies(family->name,QFont::Style(style->key.style),QUnicodeTables::Script(script)); + + family->askedForFallback = true; + } + + QStringList fallbacks = privateDb()->fallbackFamilies; + if (family && !family->fallbackFamilies.isEmpty()) + fallbacks = family->fallbackFamilies; + + engine = new QFontEngineMultiQPA(engine, script, fallbacks); + } + + return engine; +} + +static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) +{ + QFontDatabasePrivate *db = privateDb(); + + QApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName); + db->reregisterAppFonts = true; +} + +bool QFontDatabase::removeApplicationFont(int handle) +{ + QMutexLocker locker(fontDatabaseMutex()); + + QFontDatabasePrivate *db = privateDb(); + if (handle < 0 || handle >= db->applicationFonts.count()) + return false; + + db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); + + db->reregisterAppFonts = true; + db->invalidate(); + return true; +} + +bool QFontDatabase::removeAllApplicationFonts() +{ + QMutexLocker locker(fontDatabaseMutex()); + + QFontDatabasePrivate *db = privateDb(); + if (db->applicationFonts.isEmpty()) + return false; + + db->applicationFonts.clear(); + db->invalidate(); + return true; +} + +bool QFontDatabase::supportsThreadedFontRendering() +{ + return true; +} + +/*! + \internal +*/ +QFontEngine * +QFontDatabase::findFont(int script, const QFontPrivate *fp, + const QFontDef &request) +{ + QMutexLocker locker(fontDatabaseMutex()); + + const int force_encoding_id = -1; + + if (!privateDb()->count) + initializeDb(); + + QFontEngine *engine; + QFontCache::Key key(request, script); + engine = QFontCache::instance()->findEngine(key); + if (engine) { + qDebug() << "Cache hit level 1"; + return engine; + } + + QString family_name, foundry_name; + + parseFontName(request.family, foundry_name, family_name); + + if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) { + engine =new QTestFontEngine(request.pixelSize); + engine->fontDef = request; + } + + QtFontDesc desc; + match(script, request, family_name, foundry_name, force_encoding_id, &desc); + if (desc.family != 0 && desc.foundry != 0 && desc.style != 0) { + engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size); + } else { + FM_DEBUG(" NO MATCH FOUND\n"); + } + + if (engine) { + initFontDef(desc, request, &engine->fontDef); + + if (fp) { + QFontDef def = request; + if (def.family.isEmpty()) { + def.family = fp->request.family; + def.family = def.family.left(def.family.indexOf(QLatin1Char(','))); + } + } + } + + if (!engine) { + if (!request.family.isEmpty()) { + QStringList fallbacks = fallbackFamilies(request.family,QFont::Style(request.style),QUnicodeTables::Script(script)); + for (int i = 0; i < fallbacks.size(); i++) { + QFontDef def = request; + def.family = fallbacks.at(i); + QFontCache::Key key(def,script); + engine = QFontCache::instance()->findEngine(key); + if (!engine) { + QtFontDesc desc; + match(script, def, def.family, QLatin1String(""), 0, &desc); + if (desc.family == 0 && desc.foundry == 0 && desc.style == 0) { + continue; + } + engine = loadEngine(script, def, desc.family, desc.foundry, desc.style, desc.size); + if (engine) { + initFontDef(desc, def, &engine->fontDef); + break; + } + } + } + } + + if (!engine) + engine = new QFontEngineBox(request.pixelSize); + + FM_DEBUG("returning box engine"); + } + + if (fp && fp->dpi > 0) { + engine->fontDef.pointSize = qreal(double((engine->fontDef.pixelSize * 72) / fp->dpi)); + } else { + engine->fontDef.pointSize = request.pointSize; + } + + return engine; +} + +void QFontDatabase::load(const QFontPrivate *d, int script) +{ + QFontDef req = d->request; + + if (req.pixelSize == -1) { + req.pixelSize = floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100; + req.pixelSize = qRound(req.pixelSize); + } + if (req.pointSize < 0) + req.pointSize = req.pixelSize*72.0/d->dpi; + if (req.weight == 0) + req.weight = QFont::Normal; + if (req.stretch == 0) + req.stretch = 100; + + QFontCache::Key key(req, script); + + if (!d->engineData) + getEngineData(d, key); + + // the cached engineData could have already loaded the engine we want + if (d->engineData->engines[script]) + return; + + QFontEngine *fe = QFontCache::instance()->findEngine(key); + + // list of families to try + QStringList family_list; + + if (!req.family.isEmpty()) { + family_list = familyList(req); + + // add the default family + QString defaultFamily = QApplication::font().family(); + if (! family_list.contains(defaultFamily)) + family_list << defaultFamily; + + } + + // null family means find the first font matching the specified script + family_list << QString(); + + QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd(); + for (; !fe && it != end; ++it) { + req.family = *it; + + fe = QFontDatabase::findFont(script, d, req); + if (fe && (fe->type()==QFontEngine::Box) && !req.family.isEmpty()) + fe = 0; + } + + if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) { + for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) { + if (!d->engineData->engines[i]) { + d->engineData->engines[i] = fe; + fe->ref.ref(); + } + } + } else { + d->engineData->engines[script] = fe; + fe->ref.ref(); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index fdb86ce..1c705ae 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -481,7 +481,7 @@ static void collectSingleContour(qreal x0, qreal y0, uint *grid, int x, int y, i path->closeSubpath(); } -void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path) +Q_GUI_EXPORT void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path) { uint *grid = new uint[(w+1)*(h+1)]; // set up edges diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 2c4fbab..1ee7144 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -717,7 +717,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format) metrics = face->size->metrics; -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) /* TrueType fonts with embedded bitmaps may have a bitmap font specific ascent/descent in the EBLC table. There is no direct public API @@ -749,6 +749,11 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format) return true; } +void QFontEngineFT::setDefaultHintStyle(HintStyle style) +{ + default_hint_style = style; +} + QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph) const { Glyph *g = set->getGlyph(glyph); diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 372ad0c..f40ce04 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -271,7 +271,7 @@ private: QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix); bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format = Format_Render); -#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) virtual void draw(QPaintEngine * /*p*/, qreal /*x*/, qreal /*y*/, const QTextItemInt & /*si*/) {} #endif @@ -282,6 +282,14 @@ private: virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints); + enum HintStyle { + HintNone, + HintLight, + HintMedium, + HintFull + }; + + void setDefaultHintStyle(HintStyle style); protected: void freeGlyphSets(); @@ -293,12 +301,6 @@ protected: QFreetypeFace *freetype; int default_load_flags; - enum HintStyle { - HintNone, - HintLight, - HintMedium, - HintFull - }; HintStyle default_hint_style; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index fb4556b..897f76f 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -168,7 +168,7 @@ public: virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const {} virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const; -#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN) +#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(Q_WS_QPA) virtual void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si) = 0; #endif virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp new file mode 100644 index 0000000..910bbfe --- /dev/null +++ b/src/gui/text/qfontengine_qpa.cpp @@ -0,0 +1,650 @@ +#include "qfontengine_qpa_p.h" + +#include +#include +#include +#include + +#include +#include +#include + +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 +}; + + +#if defined(DEBUG_HEADER) +# define DEBUG_VERIFY qDebug +#else +# define DEBUG_VERIFY if (0) qDebug +#endif + +#define READ_VERIFY(type, variable) \ + if (tagPtr + sizeof(type) > endPtr) { \ + DEBUG_VERIFY() << "read verify failed in line" << __LINE__; \ + return 0; \ + } \ + variable = qFromBigEndian(tagPtr); \ + DEBUG_VERIFY() << "read value" << variable << "of type " #type; \ + tagPtr += sizeof(type) + +template +T readValue(const uchar *&data) +{ + T value = qFromBigEndian(data); + data += sizeof(T); + return value; +} + +#define VERIFY(condition) \ + if (!(condition)) { \ + DEBUG_VERIFY() << "condition " #condition " failed in line" << __LINE__; \ + return 0; \ + } + +#define VERIFY_TAG(condition) \ + if (!(condition)) { \ + DEBUG_VERIFY() << "verifying tag condition " #condition " failed in line" << __LINE__ << "with tag" << tag; \ + return 0; \ + } + +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) + return endPtr; + if (tag < QFontEngineQPA::NumTags) { + switch (tagTypes[tag]) { + case QFontEngineQPA::BitFieldType: + case QFontEngineQPA::StringType: + // can't do anything... + break; + case QFontEngineQPA::UInt32Type: + VERIFY_TAG(length == sizeof(quint32)); + break; + case QFontEngineQPA::FixedType: + VERIFY_TAG(length == sizeof(quint32)); + break; + case QFontEngineQPA::UInt8Type: + VERIFY_TAG(length == sizeof(quint8)); + break; + } +#if defined(DEBUG_HEADER) + if (length == 1) + qDebug() << "tag data" << hex << *tagPtr; + else if (length == 4) + qDebug() << "tag data" << hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3]; +#endif + } + return tagPtr + length; +} + +const QFontEngineQPA::Glyph *QFontEngineQPA::findGlyph(glyph_t g) const +{ + if (!g || g >= glyphMapEntries) + return 0; + const quint32 *gmapPtr = reinterpret_cast(fontData + glyphMapOffset); + quint32 glyphPos = qFromBigEndian(gmapPtr[g]); + if (glyphPos > glyphDataSize) { + if (glyphPos == 0xffffffff) + return 0; +#if defined(DEBUG_FONTENGINE) + qDebug() << "glyph" << g << "outside of glyphData, remapping font file"; +#endif + if (glyphPos > glyphDataSize) + return 0; + } + return reinterpret_cast(fontData + glyphDataOffset + glyphPos); +} + +bool QFontEngineQPA::verifyHeader(const uchar *data, int size) +{ + VERIFY(size >= int(sizeof(Header))); + const Header *header = reinterpret_cast(data); + if (header->magic[0] != 'Q' + || header->magic[1] != 'P' + || header->magic[2] != 'F' + || header->magic[3] != '2') + return false; + + VERIFY(header->majorVersion <= CurrentMajorVersion); + const quint16 dataSize = qFromBigEndian(header->dataSize); + VERIFY(size >= int(sizeof(Header)) + dataSize); + + const uchar *tagPtr = data + sizeof(Header); + const uchar *tagEndPtr = tagPtr + dataSize; + while (tagPtr < tagEndPtr - 3) { + tagPtr = verifyTag(tagPtr, tagEndPtr); + VERIFY(tagPtr); + } + + VERIFY(tagPtr <= tagEndPtr); + return true; +} + +QVariant QFontEngineQPA::extractHeaderField(const uchar *data, HeaderTag requestedTag) +{ + const Header *header = reinterpret_cast(data); + const uchar *tagPtr = data + sizeof(Header); + const uchar *endPtr = tagPtr + qFromBigEndian(header->dataSize); + while (tagPtr < endPtr - 3) { + quint16 tag = readValue(tagPtr); + quint16 length = readValue(tagPtr); + if (tag == requestedTag) { + switch (tagTypes[requestedTag]) { + case StringType: + return QVariant(QString::fromUtf8(reinterpret_cast(tagPtr), length)); + case UInt32Type: + return QVariant(readValue(tagPtr)); + case UInt8Type: + return QVariant(uint(*tagPtr)); + case FixedType: + return QVariant(QFixed::fromFixed(readValue(tagPtr)).toReal()); + case BitFieldType: + return QVariant(QByteArray(reinterpret_cast(tagPtr), length)); + } + return QVariant(); + } else if (tag == Tag_EndOfHeader) { + break; + } + tagPtr += length; + } + + return QVariant(); +} + + + +static inline unsigned int getChar(const QChar *str, int &i, const int len) +{ + unsigned int uc = str[i].unicode(); + if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { + uint low = str[i+1].unicode(); + if (low >= 0xdc00 && low < 0xe000) { + uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + ++i; + } + } + return uc; +} + +QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data) + : fontData(reinterpret_cast(data.constData())), dataSize(data.size()) +{ + fontDef = def; + cache_cost = 100; + externalCMap = 0; + cmapOffset = 0; + cmapSize = 0; + glyphMapOffset = 0; + glyphMapEntries = 0; + glyphDataOffset = 0; + glyphDataSize = 0; + kerning_pairs_loaded = false; + readOnly = true; + +#if defined(DEBUG_FONTENGINE) + qDebug() << "QFontEngineQPA::QFontEngineQPA( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')'; +#endif + + if (!verifyHeader(fontData, dataSize)) { +#if defined(DEBUG_FONTENGINE) + qDebug() << "verifyHeader failed!"; +#endif + return; + } + + const Header *header = reinterpret_cast(fontData); + + readOnly = (header->lock == 0xffffffff); + + const uchar *imgData = fontData + sizeof(Header) + qFromBigEndian(header->dataSize); + const uchar *endPtr = fontData + dataSize; + while (imgData <= endPtr - 8) { + quint16 blockTag = readValue(imgData); + imgData += 2; // skip padding + quint32 blockSize = readValue(imgData); + + if (blockTag == CMapBlock) { + cmapOffset = imgData - fontData; + cmapSize = blockSize; + } else if (blockTag == GMapBlock) { + glyphMapOffset = imgData - fontData; + glyphMapEntries = blockSize / 4; + } else if (blockTag == GlyphBlock) { + glyphDataOffset = imgData - fontData; + glyphDataSize = blockSize; + } + + imgData += blockSize; + } + + face_id.filename = QFile::encodeName(extractHeaderField(fontData, Tag_FileName).toString()); + face_id.index = extractHeaderField(fontData, Tag_FileIndex).toInt(); + + // get the real cmap + if (cmapOffset) { + int tableSize = cmapSize; + const uchar *cmapPtr = getCMap(fontData + cmapOffset, tableSize, &symbol, &cmapSize); + if (cmapPtr) + cmapOffset = cmapPtr - fontData; + else + cmapOffset = 0; + } else if (externalCMap) { + int tableSize = cmapSize; + externalCMap = getCMap(externalCMap, tableSize, &symbol, &cmapSize); + } + + // verify all the positions in the glyphMap + if (glyphMapOffset) { + const quint32 *gmapPtr = reinterpret_cast(fontData + glyphMapOffset); + for (uint i = 0; i < glyphMapEntries; ++i) { + quint32 glyphDataPos = qFromBigEndian(gmapPtr[i]); + if (glyphDataPos == 0xffffffff) + continue; + if (glyphDataPos >= glyphDataSize) { + // error + glyphMapOffset = 0; + glyphMapEntries = 0; + break; + } + } + } + +#if defined(DEBUG_FONTENGINE) + if (!isValid()) + qDebug() << "fontData" << fontData << "dataSize" << dataSize + << "externalCMap" << externalCMap << "cmapOffset" << cmapOffset + << "glyphMapOffset" << glyphMapOffset << "glyphDataOffset" << glyphDataOffset + << "fd" << fd << "glyphDataSize" << glyphDataSize; +#endif +} + +QFontEngineQPA::~QFontEngineQPA() +{ +} + +bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) const +{ + Q_UNUSED(tag); + Q_UNUSED(buffer); + *length = 0; + return false; +} + +bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const +{ + if (*nglyphs < len) { + *nglyphs = len; + return false; + } + +#if defined(DEBUG_FONTENGINE) + QSet seenGlyphs; +#endif + + const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset); + + bool mirrored = flags & QTextEngine::RightToLeft; + int glyph_pos = 0; + if (symbol) { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(str, i, len); + if (mirrored) + uc = QChar::mirroredChar(uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + if(!glyphs->glyphs[glyph_pos] && uc < 0x100) + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + ++glyph_pos; + } + } else { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(str, i, len); + if (mirrored) + uc = QChar::mirroredChar(uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); +#if 0 && defined(DEBUG_FONTENGINE) + QChar c(uc); + if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) + qDebug() << "glyph for character" << c << '/' << hex << uc << "is" << dec << glyphs[glyph_pos].glyph; + + seenGlyphs.insert(c); +#endif + ++glyph_pos; + } + } + + *nglyphs = glyph_pos; + glyphs->numGlyphs = glyph_pos; + recalcAdvances(glyphs, flags); + return true; +} + +void QFontEngineQPA::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags) const +{ + for (int i = 0; i < glyphs->numGlyphs; ++i) { + const Glyph *g = findGlyph(glyphs->glyphs[i]); + if (!g) { + glyphs->glyphs[i] = 0; + continue; + } + glyphs->advances_x[i] = g->advance; + glyphs->advances_y[i] = 0; + } +} + +QImage QFontEngineQPA::alphaMapForGlyph(glyph_t g) +{ + const Glyph *glyph = findGlyph(g); + if (!glyph) + return QImage(); + + const uchar *bits = ((const uchar *) glyph) + sizeof(Glyph); + + QImage image(bits,glyph->width, glyph->height, glyph->bytesPerLine, QImage::Format_Indexed8); + + return image; +} + +void QFontEngineQPA::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 overall; + // initialize with line height, we get the same behaviour on all platforms + overall.y = -ascent(); + overall.height = ascent() + descent() + 1; + + QFixed ymax = 0; + QFixed xmax = 0; + for (int i = 0; i < glyphs.numGlyphs; i++) { + const Glyph *g = findGlyph(glyphs.glyphs[i]); + if (!g) + continue; + + QFixed x = overall.xoff + glyphs.offsets[i].x + g->x; + QFixed y = overall.yoff + glyphs.offsets[i].y + g->y; + overall.x = qMin(overall.x, x); + overall.y = qMin(overall.y, y); + xmax = qMax(xmax, x + g->width); + ymax = qMax(ymax, y + g->height); + overall.xoff += g->advance; + } + overall.height = qMax(overall.height, ymax - overall.y); + overall.width = xmax - overall.x; + + return overall; +} + +glyph_metrics_t QFontEngineQPA::boundingBox(glyph_t glyph) +{ + glyph_metrics_t overall; + const Glyph *g = findGlyph(glyph); + if (!g) + return overall; + overall.x = g->x; + overall.y = g->y; + overall.width = g->width; + overall.height = g->height; + overall.xoff = g->advance; + return overall; +} + +QFixed QFontEngineQPA::ascent() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_Ascent).value()); +} + +QFixed QFontEngineQPA::descent() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_Descent).value()); +} + +QFixed QFontEngineQPA::leading() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_Leading).value()); +} + +qreal QFontEngineQPA::maxCharWidth() const +{ + return extractHeaderField(fontData, Tag_MaxCharWidth).value(); +} + +qreal QFontEngineQPA::minLeftBearing() const +{ + return extractHeaderField(fontData, Tag_MinLeftBearing).value(); +} + +qreal QFontEngineQPA::minRightBearing() const +{ + return extractHeaderField(fontData, Tag_MinRightBearing).value(); +} + +QFixed QFontEngineQPA::underlinePosition() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_UnderlinePosition).value()); +} + +QFixed QFontEngineQPA::lineThickness() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_LineThickness).value()); +} + +QFontEngine::Type QFontEngineQPA::type() const +{ + return QFontEngine::QPF2; +} + +bool QFontEngineQPA::canRender(const QChar *string, int len) +{ + const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset); + + if (symbol) { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(string, i, len); + glyph_t g = getTrueTypeGlyphIndex(cmap, uc); + if(!g && uc < 0x100) + g = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + if (!g) + return false; + } + } else { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(string, i, len); + if (!getTrueTypeGlyphIndex(cmap, uc)) + return false; + } + } + return true; +} + +bool QFontEngineQPA::isValid() const +{ + return fontData && dataSize && (cmapOffset || externalCMap) + && glyphMapOffset && glyphDataOffset && glyphDataSize > 0; +} + +void QPAGenerator::generate() +{ + writeHeader(); + writeGMap(); + writeBlock(QFontEngineQPA::GlyphBlock, QByteArray()); + + dev->seek(4); // position of header.lock + writeUInt32(0); +} + +void QPAGenerator::writeHeader() +{ + QFontEngineQPA::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.dataSize = 0; + dev->write((const char *)&header, sizeof(header)); + + writeTaggedString(QFontEngineQPA::Tag_FontName, fe->fontDef.family.toUtf8()); + + QFontEngine::FaceId face = fe->faceId(); + writeTaggedString(QFontEngineQPA::Tag_FileName, face.filename); + writeTaggedUInt32(QFontEngineQPA::Tag_FileIndex, face.index); + + { + uchar data[4]; + uint len = 4; + bool ok = fe->getSfntTableData(MAKE_TAG('h', 'e', 'a', 'd'), data, &len); + if (ok) { + const quint32 revision = qFromBigEndian(data); + writeTaggedUInt32(QFontEngineQPA::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()); + align4(); + + const quint64 size = dev->pos(); + header.dataSize = qToBigEndian(size - sizeof(header)); + dev->seek(0); + dev->write((const char *)&header, sizeof(header)); + dev->seek(size); +} + +void QPAGenerator::writeGMap() +{ + const quint16 glyphCount = fe->glyphCount(); + + writeUInt16(QFontEngineQPA::GMapBlock); + writeUInt16(0); // padding + writeUInt32(glyphCount * 4); + + QByteArray &buffer = dev->buffer(); + const int numBytes = glyphCount * sizeof(quint32); + qint64 pos = buffer.size(); + buffer.resize(pos + numBytes); + qMemSet(buffer.data() + pos, 0xff, numBytes); + dev->seek(pos + numBytes); +} + +void QPAGenerator::writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data) +{ + writeUInt16(tag); + writeUInt16(0); // padding + const int padSize = ((data.size() + 3) / 4) * 4 - data.size(); + writeUInt32(data.size() + padSize); + dev->write(data); + for (int i = 0; i < padSize; ++i) + writeUInt8(0); +} + +void QPAGenerator::writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string) +{ + writeUInt16(tag); + writeUInt16(string.length()); + dev->write(string); +} + +void QPAGenerator::writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value) +{ + writeUInt16(tag); + writeUInt16(sizeof(value)); + writeUInt32(value); +} + +void QPAGenerator::writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value) +{ + writeUInt16(tag); + writeUInt16(sizeof(value)); + writeUInt8(value); +} + +void QPAGenerator::writeTaggedQFixed(QFontEngineQPA::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) +{ + engines[0] = fe; + fe->ref.ref(); + fontDef = engines[0]->fontDef; +} + +void QFontEngineMultiQPA::loadEngine(int at) +{ + 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); + Q_ASSERT(engines[at]); + engines[at]->ref.ref(); + engines[at]->fontDef = request; +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_qpa_p.h b/src/gui/text/qfontengine_qpa_p.h new file mode 100644 index 0000000..467fca6 --- /dev/null +++ b/src/gui/text/qfontengine_qpa_p.h @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFONTENGINE_QPA_P_H +#define QFONTENGINE_QPA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +#include +#include +#include +#include + +#include "qfontengine_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QFontEngine; +class QFreetypeFace; +class QBuffer; + +class Q_GUI_EXPORT QFontEngineQPA : public QFontEngine +{ +public: + // if you add new tags please make sure to update the tables in + // qpfutil.cpp and tools/makeqpf/qpf2.cpp + enum HeaderTag { + Tag_FontName, // 0 string + Tag_FileName, // 1 string + Tag_FileIndex, // 2 quint32 + Tag_FontRevision, // 3 quint32 + Tag_FreeText, // 4 string + Tag_Ascent, // 5 QFixed + Tag_Descent, // 6 QFixed + Tag_Leading, // 7 QFixed + Tag_XHeight, // 8 QFixed + Tag_AverageCharWidth, // 9 QFixed + Tag_MaxCharWidth, // 10 QFixed + Tag_LineThickness, // 11 QFixed + Tag_MinLeftBearing, // 12 QFixed + Tag_MinRightBearing, // 13 QFixed + Tag_UnderlinePosition, // 14 QFixed + Tag_GlyphFormat, // 15 quint8 + Tag_PixelSize, // 16 quint8 + Tag_Weight, // 17 quint8 + Tag_Style, // 18 quint8 + Tag_EndOfHeader, // 19 string + Tag_WritingSystems, // 20 bitfield + + NumTags + }; + + enum TagType { + StringType, + FixedType, + UInt8Type, + UInt32Type, + BitFieldType + }; + + struct Tag + { + quint16 tag; + quint16 size; + }; + + enum GlyphFormat { + BitmapGlyphs = 1, + AlphamapGlyphs = 8 + }; + + enum { + CurrentMajorVersion = 2, + CurrentMinorVersion = 0 + }; + + // The CMap is identical to the TrueType CMap table format + // The GMap table is a normal array with the total number of + // covered glyphs in the TrueType font + enum BlockTag { + CMapBlock, + GMapBlock, + GlyphBlock + }; + + struct Q_PACKED Header + { + char magic[4]; // 'QPF2' + quint32 lock; // values: 0 = unlocked, 0xffffffff = read-only, otherwise qws client id of locking process + quint8 majorVersion; + quint8 minorVersion; + quint16 dataSize; + }; + + struct Q_PACKED Block + { + quint16 tag; + quint16 pad; + quint32 dataSize; + }; + + struct Q_PACKED Glyph + { + quint8 width; + quint8 height; + quint8 bytesPerLine; + qint8 x; + qint8 y; + qint8 advance; + }; + + QFontEngineQPA(const QFontDef &def, const QByteArray &data); + ~QFontEngineQPA(); + + FaceId faceId() const { return face_id; } + bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; + + bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; + void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; + + void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags); + QImage alphaMapForGlyph(glyph_t t); + + glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); + glyph_metrics_t boundingBox(glyph_t glyph); + + QFixed ascent() const; + QFixed descent() const; + QFixed leading() const; + qreal maxCharWidth() const; + qreal minLeftBearing() const; + qreal minRightBearing() const; + QFixed underlinePosition() const; + QFixed lineThickness() const; + + Type type() const; + + bool canRender(const QChar *string, int len); + inline const char *name() const { return "QPF2"; } + + virtual int glyphCount() const { return glyphMapEntries; } + + bool isValid() const; + + const Glyph *findGlyph(glyph_t g) const; + + static bool verifyHeader(const uchar *data, int size); + static QVariant extractHeaderField(const uchar *data, HeaderTag tag); + +private: + + const uchar *fontData; + int dataSize; + const uchar *externalCMap; + quint32 cmapOffset; + int cmapSize; + quint32 glyphMapOffset; + quint32 glyphMapEntries; + quint32 glyphDataOffset; + quint32 glyphDataSize; + QString internalFileName; + QString encodedFileName; + bool readOnly; + + FaceId face_id; + QByteArray freetypeCMapTable; + mutable bool kerning_pairs_loaded; +}; + +struct QPAGenerator +{ + QPAGenerator(QBuffer *device, QFontEngine *engine) + : dev(device), fe(engine) {} + + void generate(); + void writeHeader(); + void writeGMap(); + void writeBlock(QFontEngineQPA::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 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)); } + void writeUInt8(quint8 value) { dev->write((const char *)&value, sizeof(value)); } + void writeInt8(qint8 value) { dev->write((const char *)&value, sizeof(value)); } + + void align4() { while (dev->pos() & 3) { dev->putChar('\0'); } } + + QBuffer *dev; + QFontEngine *fe; +}; + +class QFontEngineMultiQPA : public QFontEngineMulti +{ +public: + QFontEngineMultiQPA(QFontEngine *fe, int script, const QStringList &fallbacks); + + void loadEngine(int at); + +private: + QStringList fallbackFamilies; + int script; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QFONTENGINE_QPA_P_H diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp new file mode 100644 index 0000000..7bb1f9a --- /dev/null +++ b/src/gui/text/qplatformfontdatabase_qpa.cpp @@ -0,0 +1,195 @@ +#include "qplatformfontdatabase_qpa.h" +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +extern void qt_registerFont(const QString &familyname, const QString &foundryname, int weight, + QFont::Style style, int stretch, bool antialiased,bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *hanlde); + +void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle) +{ + if (dataArray.size() == 0) + return; + + const uchar *data = reinterpret_cast(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 (!fontName.isEmpty() && pixelSize) { + int fontWeight = 50; + if (weight.type() == QVariant::Int || weight.type() == QVariant::UInt) + fontWeight = weight.toInt(); + + QFont::Style fontStyle = static_cast(style.toInt()); + + QSupportedWritingSystems writingSystems; + for (int i = 0; i < writingSystemBits.count(); ++i) { + uchar currentByte = writingSystemBits.at(i); + for (int j = 0; j < 8; ++j) { + if (currentByte & 1) + writingSystems.setSupported(QFontDatabase::WritingSystem(i * 8 + j)); + currentByte >>= 1; + } + } + + registerFont(fontName,QString(),fontWeight,fontStyle,100,true,false,pixelSize,writingSystems,handle); + } + } else { + qDebug() << "header verification of QPF2 font failed. maybe it is corrupt?"; + } +} + +void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &foundryname, int weight, + QFont::Style style, int stretch, bool antialiased, bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *usrPtr) +{ + if (scalable) + pixelSize = 0; + qt_registerFont(familyname,foundryname,weight,style,stretch,antialiased,scalable,pixelSize,writingSystems,usrPtr); +} + +class QWritingSystemsPrivate +{ +public: + QWritingSystemsPrivate() + : ref(1) + , vector(QFontDatabase::WritingSystemsCount,false) + { + } + + QWritingSystemsPrivate(const QWritingSystemsPrivate *other) + : ref(1) + , vector(other->vector) + { + } + + QAtomicInt ref; + QVector vector; +}; + +QSupportedWritingSystems::QSupportedWritingSystems() +{ + d = new QWritingSystemsPrivate; +} + +QSupportedWritingSystems::QSupportedWritingSystems(const QSupportedWritingSystems &other) +{ + d = other.d; + d->ref.ref(); +} + +QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWritingSystems &other) +{ + if (d != other.d) { + other.d->ref.ref(); + if (!d->ref.deref()) + delete d; + d = other.d; + } + return *this; +} + +QSupportedWritingSystems::~QSupportedWritingSystems() +{ + if (!d->ref.deref()) + delete d; +} + +void QSupportedWritingSystems::detach() +{ + if (d->ref != 1) { + QWritingSystemsPrivate *newd = new QWritingSystemsPrivate(d); + if (!d->ref.deref()) + delete d; + d = newd; + } +} + +void QSupportedWritingSystems::setSupported(QFontDatabase::WritingSystem writingSystem, bool support) +{ + detach(); + d->vector[writingSystem] = support; +} + +bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSystem) const +{ + return d->vector.at(writingSystem); +} + +void QPlatformFontDatabase::populateFontDatabase() +{ + QString fontpath = fontDir(); + + if(!QFile::exists(fontpath)) { + qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?", + qPrintable(fontpath)); + } + + QDir dir(fontpath); + dir.setNameFilters(QStringList() << QLatin1String("*.qpf2")); + dir.refresh(); + for (int i = 0; i < int(dir.count()); ++i) { + const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i])); + QFile file(QString::fromLocal8Bit(fileName)); + if (file.open(QFile::ReadOnly)) { + const QByteArray fileData = file.readAll(); + QByteArray *fileDataPtr = new QByteArray(fileData); + registerQPF2Font(fileData, fileDataPtr); + } + } +} + +QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle) +{ + Q_UNUSED(script); + Q_UNUSED(handle); + QByteArray *fileDataPtr = static_cast(handle); + QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr); + qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family << script; + return engine; +} + +QStringList QPlatformFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +{ + Q_UNUSED(family); + Q_UNUSED(style); + Q_UNUSED(script); + return QStringList(); +} + +void QPlatformFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) +{ + Q_UNUSED(fontData); + Q_UNUSED(fileName); + + qWarning("This plugin does not support application fonts"); +} + +void QPlatformFontDatabase::releaseHandle(void *handle) +{ + QByteArray *fileDataPtr = static_cast(handle); + delete fileDataPtr; +} + +QString QPlatformFontDatabase::fontDir() const +{ + QString fontpath = QString::fromLocal8Bit(qgetenv("QT_QPA_FONTDIR")); + if (fontpath.isEmpty()) { +#ifndef QT_NO_SETTINGS + fontpath = QLibraryInfo::location(QLibraryInfo::LibrariesPath); + fontpath += QLatin1String("/fonts"); +#endif + } + + return fontpath; +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qplatformfontdatabase_qpa.h b/src/gui/text/qplatformfontdatabase_qpa.h new file mode 100644 index 0000000..a34033f --- /dev/null +++ b/src/gui/text/qplatformfontdatabase_qpa.h @@ -0,0 +1,65 @@ +#ifndef QPLATFORMFONTDATABASE_QPA_H +#define QPLATFORMFONTDATABASE_QPA_H + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QWritingSystemsPrivate; + +class Q_GUI_EXPORT QSupportedWritingSystems +{ +public: + + QSupportedWritingSystems(); + QSupportedWritingSystems(const QSupportedWritingSystems &other); + QSupportedWritingSystems &operator=(const QSupportedWritingSystems &other); + ~QSupportedWritingSystems(); + + void setSupported(QFontDatabase::WritingSystem, bool supported = true); + bool supported(QFontDatabase::WritingSystem) const; + +private: + void detach(); + + QWritingSystemsPrivate *d; + + friend Q_GUI_EXPORT bool operator==(const QSupportedWritingSystems &, const QSupportedWritingSystems &); + friend Q_GUI_EXPORT bool operator!=(const QSupportedWritingSystems &, const QSupportedWritingSystems &); +}; + +Q_GUI_EXPORT bool operator==(const QSupportedWritingSystems &, const QSupportedWritingSystems &); +Q_GUI_EXPORT bool operator!=(const QSupportedWritingSystems &, const QSupportedWritingSystems &); + +class QFontRequestPrivate; + +class Q_GUI_EXPORT QPlatformFontDatabase +{ +public: + virtual void populateFontDatabase(); + virtual QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); + virtual QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const; + virtual void addApplicationFont(const QByteArray &fontData, const QString &fileName); + virtual void releaseHandle(void *handle); + + virtual QString fontDir() const; + + //callback + static void registerQPF2Font(const QByteArray &dataArray, void *handle); + static void registerFont(const QString &familyname, const QString &foundryname, int weight, + QFont::Style style, int stetch, bool antialiased, bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *handle); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMFONTDATABASE_QPA_H diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index 1040ad8..8721d80 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -25,7 +25,7 @@ HEADERS += \ text/qabstracttextdocumentlayout.h \ text/qtextdocumentlayout_p.h \ text/qtextcursor.h \ - text/qtextcursor_p.h \ + text/qtextcursor_p.h \ text/qtextdocumentfragment.h \ text/qtextdocumentfragment_p.h \ text/qtextimagehandler_p.h \ @@ -39,7 +39,7 @@ HEADERS += \ text/qzipwriter_p.h \ text/qtextodfwriter_p.h \ text/qstatictext_p.h \ - text/qstatictext.h + text/qstatictext.h SOURCES += \ text/qfont.cpp \ @@ -69,7 +69,7 @@ SOURCES += \ text/qcssparser.cpp \ text/qzip.cpp \ text/qtextodfwriter.cpp \ - text/qstatictext.cpp + text/qstatictext.cpp win32 { SOURCES += \ @@ -112,15 +112,15 @@ embedded { qpa { SOURCES += \ - text/qfont_qws.cpp \ - text/qfontengine_ft.cpp \ - text/qfontengine_qpf.cpp \ - text/qabstractfontengine_qws.cpp + text/qfont_qpa.cpp \ + text/qfontengine_qpa.cpp \ + text/qplatformfontdatabase_qpa.cpp + HEADERS += \ - text/qfontengine_ft_p.h \ - text/qabstractfontengine_qws.h \ - text/qabstractfontengine_p.h + text/qplatformfontdatabase_qpa.h + DEFINES += QT_NO_FONTCONFIG + DEFINES += QT_NO_FREETYPE } symbian { @@ -142,6 +142,7 @@ symbian { } } +!qpa { contains(QT_CONFIG, freetype) { SOURCES += \ ../3rdparty/freetype/src/base/ftbase.c \ @@ -215,6 +216,7 @@ contains(QT_CONFIG, freetype) { contains(QT_CONFIG, fontconfig) { CONFIG += opentype } +}#!qpa DEFINES += QT_NO_OPENTYPE INCLUDEPATH += ../3rdparty/harfbuzz/src diff --git a/src/plugins/platforms/directfb/directfb.pro b/src/plugins/platforms/directfb/directfb.pro index f81ec31..48128fb 100644 --- a/src/plugins/platforms/directfb/directfb.pro +++ b/src/plugins/platforms/directfb/directfb.pro @@ -27,5 +27,7 @@ HEADERS = qdirectfbintegration.h \ qdirectfbinput.h \ qdirectfbcursor.h \ qdirectfbwindow.h + +include(../fontdatabases/genericunix/genericunix.pri) target.path += $$[QT_INSTALL_PLUGINS]/platforms INSTALLS += target diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.cpp b/src/plugins/platforms/directfb/qdirectfbintegration.cpp index b19a1d9..64b98db 100644 --- a/src/plugins/platforms/directfb/qdirectfbintegration.cpp +++ b/src/plugins/platforms/directfb/qdirectfbintegration.cpp @@ -46,6 +46,8 @@ #include "qdirectfbcursor.h" #include "qdirectfbwindow.h" +#include "qgenericunixfontdatabase.h" + #include #include @@ -80,6 +82,7 @@ QDirectFbScreen::~QDirectFbScreen() } QDirectFbIntegration::QDirectFbIntegration() + : mFontDb(new QGenericUnixFontDatabase()) { const QStringList args = QCoreApplication::arguments(); int argc = args.size(); @@ -133,9 +136,9 @@ QWindowSurface *QDirectFbIntegration::createWindowSurface(QWidget *widget, WId w return new QDirectFbWindowSurface(widget,winId); } -QBlittable *QDirectFbIntegration::createBlittable(const QSize &size) const +QPlatformFontDatabase *QDirectFbIntegration::fontDatabase() const { - return new QDirectFbBlitter(size); + return mFontDb; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.h b/src/plugins/platforms/directfb/qdirectfbintegration.h index 27847e2..d2d8367 100644 --- a/src/plugins/platforms/directfb/qdirectfbintegration.h +++ b/src/plugins/platforms/directfb/qdirectfbintegration.h @@ -87,14 +87,16 @@ public: QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; - QBlittable *createBlittable(const QSize &size) const; QList screens() const { return mScreens; } + QPlatformFontDatabase *fontDatabase() const; + private: QList mScreens; QDirectFbInput *mInput; QThread *mInputRunner; + QPlatformFontDatabase *mFontDb; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/eglfs.pro b/src/plugins/platforms/eglfs/eglfs.pro index 5d1318a..7ad8fd9 100644 --- a/src/plugins/platforms/eglfs/eglfs.pro +++ b/src/plugins/platforms/eglfs/eglfs.pro @@ -25,5 +25,7 @@ HEADERS = qeglfsintegration.h \ qeglfswindowsurface.h \ qeglfsscreen.h +include(../fontdatabases/genericunix/genericunix.pri) + target.path += $$[QT_INSTALL_PLUGINS]/platforms INSTALLS += target diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 2b673ae..07605ec 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -48,11 +48,14 @@ #include #include +#include "qgenericunixfontdatabase.h" + #include QT_BEGIN_NAMESPACE QEglFSIntegration::QEglFSIntegration() + mFontDb(new QGenericUnixFontDatabase()) { m_primaryScreen = new QEglFSScreen(EGL_DEFAULT_DISPLAY); @@ -90,4 +93,9 @@ QWindowSurface *QEglFSIntegration::createWindowSurface(QWidget *widget, WId winI return new QEglFSWindowSurface(m_primaryScreen,widget); } +QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const +{ + return mFontDb; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h index f15b6b2..0342539 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -62,7 +62,10 @@ public: QList screens() const { return mScreens; } + QPlatformFontDatabase *fontDatabase() const; + private: + QPlatformFontDatabase *mFontDb; QList mScreens; QEglFSScreen *m_primaryScreen; }; diff --git a/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri b/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri new file mode 100644 index 0000000..21aedba --- /dev/null +++ b/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri @@ -0,0 +1,82 @@ +DEFINES += QT_NO_FONTCONFIG +HEADERS += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h \ + $$QT_SOURCE_TREE/src/gui/text/qfontengine_ft_p.h + +SOURCES += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp \ + $$QT_SOURCE_TREE/src/gui/text/qfontengine_ft.cpp + +INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src + +INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/basicunix + +CONFIG += opentype + +contains(QT_CONFIG, freetype) { + SOURCES += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftbase.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftbbox.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftdebug.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftglyph.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftinit.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftmm.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/fttype1.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftsynth.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftbitmap.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/bdf/bdf.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/cache/ftcache.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/cff/cff.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/cid/type1cid.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/gzip/ftgzip.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/pcf/pcf.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/pfr/pfr.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/psaux/psaux.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/pshinter/pshinter.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/psnames/psmodule.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/raster/raster.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/sfnt/sfnt.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/smooth/smooth.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/truetype/truetype.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/type1/type1.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/type42/type42.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/winfonts/winfnt.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/lzw/ftlzw.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvalid.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvbase.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvgdef.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvjstf.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvcommn.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvgpos.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvgsub.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvmod.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afangles.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afglobal.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/aflatin.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afmodule.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afdummy.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afhints.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afloader.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/autofit.c + + symbian { + SOURCES += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftsystem.c + } else { + SOURCES += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/builds/unix/ftsystem.c + INCLUDEPATH += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/builds/unix + } + + INCLUDEPATH += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/include + + DEFINES += FT2_BUILD_LIBRARY FT_CONFIG_OPTION_SYSTEM_ZLIB + } else:contains(QT_CONFIG, system-freetype) { + # pull in the proper freetype2 include directory + include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri) + LIBS_PRIVATE += -lfreetype + } + diff --git a/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp new file mode 100644 index 0000000..5b8ca63 --- /dev/null +++ b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp @@ -0,0 +1,281 @@ +#include "qbasicunixfontdatabase.h" + +#include +#include + +#include +#include +#include + +#undef QT_NO_FREETYPE +#include +#include + +#include +#include FT_TRUETYPE_TABLES_H + +#define SimplifiedChineseCsbBit 18 +#define TraditionalChineseCsbBit 20 +#define JapaneseCsbBit 17 +#define KoreanCsbBit 21 + +static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { + // Any, + { 127, 127 }, + // Latin, + { 0, 127 }, + // Greek, + { 7, 127 }, + // Cyrillic, + { 9, 127 }, + // Armenian, + { 10, 127 }, + // Hebrew, + { 11, 127 }, + // Arabic, + { 13, 127 }, + // Syriac, + { 71, 127 }, + //Thaana, + { 72, 127 }, + //Devanagari, + { 15, 127 }, + //Bengali, + { 16, 127 }, + //Gurmukhi, + { 17, 127 }, + //Gujarati, + { 18, 127 }, + //Oriya, + { 19, 127 }, + //Tamil, + { 20, 127 }, + //Telugu, + { 21, 127 }, + //Kannada, + { 22, 127 }, + //Malayalam, + { 23, 127 }, + //Sinhala, + { 73, 127 }, + //Thai, + { 24, 127 }, + //Lao, + { 25, 127 }, + //Tibetan, + { 70, 127 }, + //Myanmar, + { 74, 127 }, + // Georgian, + { 26, 127 }, + // Khmer, + { 80, 127 }, + // SimplifiedChinese, + { 126, 127 }, + // TraditionalChinese, + { 126, 127 }, + // Japanese, + { 126, 127 }, + // Korean, + { 56, 127 }, + // Vietnamese, + { 0, 127 }, // same as latin1 + // Other, + { 126, 127 }, + // Ogham, + { 78, 127 }, + // Runic, + { 79, 127 }, + // Nko, + { 14, 127 }, +}; + +static QSupportedWritingSystems determineWritingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2]) +{ + QSupportedWritingSystems writingSystems; + bool hasScript = false; + + int i; + for(i = 0; i < QFontDatabase::WritingSystemsCount; i++) { + int bit = requiredUnicodeBits[i][0]; + int index = bit/32; + int flag = 1 << (bit&31); + if (bit != 126 && unicodeRange[index] & flag) { + bit = requiredUnicodeBits[i][1]; + index = bit/32; + + flag = 1 << (bit&31); + if (bit == 127 || unicodeRange[index] & flag) { + writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + hasScript = true; + // qDebug("font %s: index=%d, flag=%8x supports script %d", familyName.latin1(), index, flag, i); + } + } + } + if(codePageRange[0] & (1 << SimplifiedChineseCsbBit)) { + writingSystems.setSupported(QFontDatabase::SimplifiedChinese); + hasScript = true; + //qDebug("font %s supports Simplified Chinese", familyName.latin1()); + } + if(codePageRange[0] & (1 << TraditionalChineseCsbBit)) { + writingSystems.setSupported(QFontDatabase::TraditionalChinese); + hasScript = true; + //qDebug("font %s supports Traditional Chinese", familyName.latin1()); + } + if(codePageRange[0] & (1 << JapaneseCsbBit)) { + writingSystems.setSupported(QFontDatabase::Japanese); + hasScript = true; + //qDebug("font %s supports Japanese", familyName.latin1()); + } + if(codePageRange[0] & (1 << KoreanCsbBit)) { + writingSystems.setSupported(QFontDatabase::Korean); + hasScript = true; + //qDebug("font %s supports Korean", familyName.latin1()); + } + if (!hasScript) + writingSystems.setSupported(QFontDatabase::Symbol); + + return writingSystems; +} + +static inline bool scriptRequiresOpenType(int script) +{ + return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala) + || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko); +} + +void QBasicUnixFontDatabase::populateFontDatabase() +{ + QPlatformFontDatabase::populateFontDatabase(); + QString fontpath = fontDir(); + + if(!QFile::exists(fontpath)) { + qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?", + qPrintable(fontpath)); + } + + QDir dir(fontpath); + dir.setNameFilters(QStringList() << QLatin1String("*.ttf") + << QLatin1String("*.ttc") << QLatin1String("*.pfa") + << QLatin1String("*.pfb")); + dir.refresh(); + for (int i = 0; i < int(dir.count()); ++i) { + const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); +// qDebug() << "looking at" << file; + addTTFile(QByteArray(), file); + } +} + +QFontEngine *QBasicUnixFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *usrPtr) +{ + QFontEngineFT *engine; + FontFile *fontfile = static_cast (usrPtr); + QFontEngine::FaceId fid; + fid.filename = fontfile->fileName.toLocal8Bit(); + fid.index = fontfile->indexValue; + engine = new QFontEngineFT(fontDef); + + bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; + if (!engine->init(fid,antialias,format)) { + delete engine; + engine = 0; + return engine; + } + if (engine->invalid()) { + delete engine; + engine = 0; + } else if (scriptRequiresOpenType(script)) { + HB_Face hbFace = engine->harfbuzzFace(); + if (!hbFace || !hbFace->supported_scripts[script]) { + delete engine; + engine = 0; + } + } + + return engine; +} + +QStringList QBasicUnixFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +{ + Q_UNUSED(family); + Q_UNUSED(style); + Q_UNUSED(script); + return QStringList(); +} + +void QBasicUnixFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) +{ + addTTFile(fontData,fileName.toLocal8Bit()); +} + +void QBasicUnixFontDatabase::releaseHandle(void *handle) +{ + FontFile *file = static_cast(handle); + delete file; +} + +void QBasicUnixFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file) +{ + extern FT_Library qt_getFreetype(); + FT_Library library = qt_getFreetype(); + + int index = 0; + int numFaces = 0; + do { + FT_Face face; + FT_Error error; + if (!fontData.isEmpty()) { + error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face); + } else { + error = FT_New_Face(library, file.constData(), index, &face); + } + if (error != FT_Err_Ok) { + qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error; + break; + } + numFaces = face->num_faces; + + int weight = QFont::Normal; + + QFont::Style style = QFont::StyleNormal; + if (face->style_flags & FT_STYLE_FLAG_ITALIC) + style = QFont::StyleItalic; + + if (face->style_flags & FT_STYLE_FLAG_BOLD) + weight = QFont::Bold; + + QSupportedWritingSystems writingSystems; + // detect symbol fonts + for (int i = 0; i < face->num_charmaps; ++i) { + FT_CharMap cm = face->charmaps[i]; + if (cm->encoding == ft_encoding_adobe_custom + || cm->encoding == ft_encoding_symbol) { + writingSystems.setSupported(QFontDatabase::Symbol); + break; + } + } + + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); + if (os2) { + quint32 unicodeRange[4] = { + os2->ulUnicodeRange1, os2->ulUnicodeRange2, os2->ulUnicodeRange3, os2->ulUnicodeRange4 + }; + quint32 codePageRange[2] = { + os2->ulCodePageRange1, os2->ulCodePageRange2 + }; + + writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); + } + + QString family = QString::fromAscii(face->family_name); + FontFile *fontFile = new FontFile; + fontFile->fileName = file; + fontFile->indexValue = index; + + registerFont(family,"",weight,style,100,true,true,0,writingSystems,fontFile); + + FT_Done_Face(face); + ++index; + } while (index < numFaces); +} diff --git a/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h new file mode 100644 index 0000000..401a4aa --- /dev/null +++ b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h @@ -0,0 +1,26 @@ +#ifndef QBASICUNIXFONTDATABASE_H +#define QBASICUNIXFONTDATABASE_H + +#include +#include +#include + +struct FontFile +{ + QString fileName; + int indexValue; +}; + +class QBasicUnixFontDatabase : public QPlatformFontDatabase +{ +public: + void populateFontDatabase(); + QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); + QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const; + void addApplicationFont(const QByteArray &fontData, const QString &fileName); + void releaseHandle(void *handle); + + static void addTTFile(const QByteArray &fontData, const QByteArray &file); +}; + +#endif // QBASICUNIXFONTDATABASE_H diff --git a/src/plugins/platforms/fontdatabases/fontconfig/fontconfig.pri b/src/plugins/platforms/fontdatabases/fontconfig/fontconfig.pri new file mode 100644 index 0000000..19c74ed --- /dev/null +++ b/src/plugins/platforms/fontdatabases/fontconfig/fontconfig.pri @@ -0,0 +1,12 @@ +include(../basicunix/basicunix.pri) + +HEADERS += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h + +SOURCES += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp + +INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/fontconfig +LIBS_PRIVATE += -lfontconfig + + diff --git a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp new file mode 100644 index 0000000..562cb2d --- /dev/null +++ b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -0,0 +1,528 @@ +#include "qfontconfigdatabase.h" + +#include +#include + +#include + +#include +#include + +#include +#include + + + +#include +#include FT_TRUETYPE_TABLES_H + +#include + +#define SimplifiedChineseCsbBit 18 +#define TraditionalChineseCsbBit 20 +#define JapaneseCsbBit 17 +#define KoreanCsbBit 21 + +static inline bool requiresOpenType(int writingSystem) +{ + return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) + || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); +} +static inline bool scriptRequiresOpenType(int script) +{ + return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala) + || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko); +} + +static int getFCWeight(int fc_weight) +{ + int qtweight = QFont::Black; + if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2) + qtweight = QFont::Light; + else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2) + qtweight = QFont::Normal; + else if (fc_weight <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2) + qtweight = QFont::DemiBold; + else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2) + qtweight = QFont::Bold; + + return qtweight; +} + +static const char *specialLanguages[] = { + "en", // Common + "el", // Greek + "ru", // Cyrillic + "hy", // Armenian + "he", // Hebrew + "ar", // Arabic + "syr", // Syriac + "div", // Thaana + "hi", // Devanagari + "bn", // Bengali + "pa", // Gurmukhi + "gu", // Gujarati + "or", // Oriya + "ta", // Tamil + "te", // Telugu + "kn", // Kannada + "ml", // Malayalam + "si", // Sinhala + "th", // Thai + "lo", // Lao + "bo", // Tibetan + "my", // Myanmar + "ka", // Georgian + "ko", // Hangul + "", // Ogham + "", // Runic + "km", // Khmer + "" // N'Ko +}; +enum { SpecialLanguageCount = sizeof(specialLanguages) / sizeof(const char *) }; + +static const ushort specialChars[] = { + 0, // English + 0, // Greek + 0, // Cyrillic + 0, // Armenian + 0, // Hebrew + 0, // Arabic + 0, // Syriac + 0, // Thaana + 0, // Devanagari + 0, // Bengali + 0, // Gurmukhi + 0, // Gujarati + 0, // Oriya + 0, // Tamil + 0xc15, // Telugu + 0xc95, // Kannada + 0xd15, // Malayalam + 0xd9a, // Sinhala + 0, // Thai + 0, // Lao + 0, // Tibetan + 0x1000, // Myanmar + 0, // Georgian + 0, // Hangul + 0x1681, // Ogham + 0x16a0, // Runic + 0, // Khmer + 0x7ca // N'Ko +}; +enum { SpecialCharCount = sizeof(specialChars) / sizeof(ushort) }; + +// this could become a list of all languages used for each writing +// system, instead of using the single most common language. +static const char *languageForWritingSystem[] = { + 0, // Any + "en", // Latin + "el", // Greek + "ru", // Cyrillic + "hy", // Armenian + "he", // Hebrew + "ar", // Arabic + "syr", // Syriac + "div", // Thaana + "hi", // Devanagari + "bn", // Bengali + "pa", // Gurmukhi + "gu", // Gujarati + "or", // Oriya + "ta", // Tamil + "te", // Telugu + "kn", // Kannada + "ml", // Malayalam + "si", // Sinhala + "th", // Thai + "lo", // Lao + "bo", // Tibetan + "my", // Myanmar + "ka", // Georgian + "km", // Khmer + "zh-cn", // SimplifiedChinese + "zh-tw", // TraditionalChinese + "ja", // Japanese + "ko", // Korean + "vi", // Vietnamese + 0, // Symbol + 0, // Ogham + 0, // Runic + 0 // N'Ko +}; +enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) }; + +// Unfortunately FontConfig doesn't know about some languages. We have to test these through the +// charset. The lists below contain the systems where we need to do this. +static const ushort sampleCharForWritingSystem[] = { + 0, // Any + 0, // Latin + 0, // Greek + 0, // Cyrillic + 0, // Armenian + 0, // Hebrew + 0, // Arabic + 0, // Syriac + 0, // Thaana + 0, // Devanagari + 0, // Bengali + 0, // Gurmukhi + 0, // Gujarati + 0, // Oriya + 0, // Tamil + 0xc15, // Telugu + 0xc95, // Kannada + 0xd15, // Malayalam + 0xd9a, // Sinhala + 0, // Thai + 0, // Lao + 0, // Tibetan + 0x1000, // Myanmar + 0, // Georgian + 0, // Khmer + 0, // SimplifiedChinese + 0, // TraditionalChinese + 0, // Japanese + 0, // Korean + 0, // Vietnamese + 0, // Symbol + 0x1681, // Ogham + 0x16a0, // Runic + 0x7ca // N'Ko +}; +enum { SampleCharCount = sizeof(sampleCharForWritingSystem) / sizeof(ushort) }; + +// Newer FontConfig let's us sort out fonts that contain certain glyphs, but no +// open type tables for is directly. Do this so we don't pick some strange +// pseudo unicode font +static const char *openType[] = { + 0, // Any + 0, // Latin + 0, // Greek + 0, // Cyrillic + 0, // Armenian + 0, // Hebrew + 0, // Arabic + "syrc", // Syriac + "thaa", // Thaana + "deva", // Devanagari + "beng", // Bengali + "guru", // Gurmukhi + "gurj", // Gujarati + "orya", // Oriya + "taml", // Tamil + "telu", // Telugu + "knda", // Kannada + "mlym", // Malayalam + "sinh", // Sinhala + 0, // Thai + 0, // Lao + "tibt", // Tibetan + "mymr", // Myanmar + 0, // Georgian + "khmr", // Khmer + 0, // SimplifiedChinese + 0, // TraditionalChinese + 0, // Japanese + 0, // Korean + 0, // Vietnamese + 0, // Symbol + 0, // Ogham + 0, // Runic + "nko " // N'Ko +}; + +void QFontconfigDatabase::populateFontDatabase() +{ + FcFontSet *fonts; + + QString familyName; + FcChar8 *value = 0; + int weight_value; + int slant_value; + int spacing_value; + FcChar8 *file_value; + int indexValue; + FcChar8 *foundry_value; + FcBool scalable; + FcBool antialias; + + { + FcObjectSet *os = FcObjectSetCreate(); + FcPattern *pattern = FcPatternCreate(); + const char *properties [] = { + FC_FAMILY, FC_WEIGHT, FC_SLANT, + FC_SPACING, FC_FILE, FC_INDEX, + FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT, + FC_WIDTH, +#if FC_VERSION >= 20297 + FC_CAPABILITY, +#endif + (const char *)0 + }; + const char **p = properties; + while (*p) { + FcObjectSetAdd(os, *p); + ++p; + } + fonts = FcFontList(0, pattern, os); + FcObjectSetDestroy(os); + FcPatternDestroy(pattern); + } + + for (int i = 0; i < fonts->nfont; i++) { + if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) + continue; + // capitalize(value); + familyName = QString::fromUtf8((const char *)value); + slant_value = FC_SLANT_ROMAN; + weight_value = FC_WEIGHT_MEDIUM; + spacing_value = FC_PROPORTIONAL; + file_value = 0; + indexValue = 0; + scalable = FcTrue; + + + if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch) + slant_value = FC_SLANT_ROMAN; + if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch) + weight_value = FC_WEIGHT_MEDIUM; + if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch) + spacing_value = FC_PROPORTIONAL; + if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch) + file_value = 0; + if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &indexValue) != FcResultMatch) + indexValue = 0; + if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch) + scalable = FcTrue; + if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) + foundry_value = 0; + if(FcPatternGetBool(fonts->fonts[i],FC_ANTIALIAS,0,&antialias) != FcResultMatch) + antialias = true; + + QSupportedWritingSystems writingSystems; + FcLangSet *langset = 0; + FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset); + if (res == FcResultMatch) { + for (int i = 1; i < LanguageCount; ++i) { + const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i]; + if (lang) { + FcLangResult langRes = FcLangSetHasLang(langset, lang); + if (langRes != FcLangDifferentLang) + writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + } + } + } else { + // we set Other to supported for symbol fonts. It makes no + // sense to merge these with other ones, as they are + // special in a way. + writingSystems.setSupported(QFontDatabase::Other); + } + + FcCharSet *cs = 0; + res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, &cs); + if (res == FcResultMatch) { + // some languages are not supported by FontConfig, we rather check the + // charset to detect these + for (int i = 1; i < SampleCharCount; ++i) { + if (!sampleCharForWritingSystem[i]) + continue; + if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i])) + writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + } + } + +#if FC_VERSION >= 20297 + for (int j = 1; j < LanguageCount; ++j) { + if (writingSystems.supported(QFontDatabase::WritingSystem(j)) + && requiresOpenType(j) && openType[j]) { + FcChar8 *cap; + res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap); + if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) + writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); + } + } +#endif + + FontFile *fontFile = new FontFile; + fontFile->fileName = QLatin1String((const char *)file_value); + fontFile->indexValue = indexValue; + + QFont::Style style = (slant_value == FC_SLANT_ITALIC) + ? QFont::StyleItalic + : ((slant_value == FC_SLANT_OBLIQUE) + ? QFont::StyleOblique + : QFont::StyleNormal); + int weight = getFCWeight(weight_value); + + double pixel_size = 0; + if (!scalable) { + int width = 100; + FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width); + FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size); + } + + QPlatformFontDatabase::registerFont(familyName,QLatin1String((const char *)foundry_value),weight,style,100,antialias,scalable,pixel_size,writingSystems,fontFile); +// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; + } + + FcFontSetDestroy (fonts); + + struct FcDefaultFont { + const char *qtname; + const char *rawname; + bool fixed; + }; + const FcDefaultFont defaults[] = { + { "Serif", "serif", false }, + { "Sans Serif", "sans-serif", false }, + { "Monospace", "monospace", true }, + { 0, 0, false } + }; + const FcDefaultFont *f = defaults; + // aliases only make sense for 'common', not for any of the specials + QSupportedWritingSystems ws; + ws.setSupported(QFontDatabase::Latin); + + while (f->qtname) { + registerFont(f->qtname,"",50,QFont::StyleNormal,100,true,true,0,ws,0); + registerFont(f->qtname,"",50,QFont::StyleItalic,100,true,true,0,ws,0); + registerFont(f->qtname,"",50,QFont::StyleOblique,100,true,true,0,ws,0); + ++f; + } + + const FcDefaultFont *s = defaults; + QFont font("Sans Serif"); + font.setPointSize(9); + QApplication::setFont(font); +} + +QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables::Script script, void *usrPtr) +{ + QFontDef fontDef = f; + + QFontEngineFT *engine; + FontFile *fontfile = static_cast (usrPtr); + QFontEngine::FaceId fid; + fid.filename = fontfile->fileName.toLocal8Bit(); + fid.index = fontfile->indexValue; + + //try and get the pattern + FcPattern *pattern = FcPatternCreate(); + + bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; + + engine = new QFontEngineFT(fontDef); + + FcValue value; + value.type = FcTypeString; + QByteArray cs = fontDef.family.toUtf8(); + value.u.s = (const FcChar8 *)cs.data(); + FcPatternAdd(pattern,FC_FAMILY,value,true); + + + value.u.s = (const FcChar8 *)fid.filename.data(); + FcPatternAdd(pattern,FC_FILE,value,true); + + value.type = FcTypeInteger; + value.u.i = fid.index; + FcPatternAdd(pattern,FC_INDEX,value,true); + + QFontEngineFT::HintStyle default_hint_style; + + if (FcConfigSubstitute(0,pattern,FcMatchPattern)) { + + //hinting + int hint_style = 0; + if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) + hint_style = QFontEngineFT::HintFull; + switch (hint_style) { + case FC_HINT_NONE: + default_hint_style = QFontEngineFT::HintNone; + break; + case FC_HINT_SLIGHT: + default_hint_style = QFontEngineFT::HintLight; + break; + case FC_HINT_MEDIUM: + default_hint_style = QFontEngineFT::HintMedium; + break; + default: + default_hint_style = QFontEngineFT::HintFull; + break; + } + } + + engine->setDefaultHintStyle(default_hint_style); + if (!engine->init(fid,antialias,format)) { + delete engine; + engine = 0; + return engine; + } + if (engine->invalid()) { + delete engine; + engine = 0; + } else if (scriptRequiresOpenType(script)) { + HB_Face hbFace = engine->harfbuzzFace(); + if (!hbFace || !hbFace->supported_scripts[script]) { + delete engine; + engine = 0; + } + } + + return engine; +} + +QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +{ + QStringList fallbackFamilies; + FcPattern *pattern = FcPatternCreate(); + if (!pattern) + return fallbackFamilies; + + FcValue value; + value.type = FcTypeString; + QByteArray cs = family.toUtf8(); + value.u.s = (const FcChar8 *)cs.data(); + FcPatternAdd(pattern,FC_FAMILY,value,true); + + int slant_value = FC_SLANT_ROMAN; + if (style == QFont::StyleItalic) + slant_value = FC_SLANT_ITALIC; + else if (style == QFont::StyleOblique) + slant_value = FC_SLANT_OBLIQUE; + FcPatternAddInteger(pattern, FC_SLANT, slant_value); + + if (script != QUnicodeTables::Common && *specialLanguages[script] != '\0') { + Q_ASSERT(script < QUnicodeTables::ScriptCount); + FcLangSet *ls = FcLangSetCreate(); + FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); + FcPatternAddLangSet(pattern, FC_LANG, ls); + FcLangSetDestroy(ls); + } + + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcConfigSubstitute(0, pattern, FcMatchFont); + + FcResult result = FcResultMatch; + FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result); + + if (fontSet && result == FcResultMatch) + { + for (int i = 0; i < fontSet->nfont; i++) { + FcChar8 *value = 0; + if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) + continue; + // capitalize(value); + QString familyName = QString::fromUtf8((const char *)value); + if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive)) { + fallbackFamilies << familyName; + } + + } + } +// qDebug() << "fallbackFamilies for:" << family << fallbackFamilies; + + return fallbackFamilies; +} diff --git a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h new file mode 100644 index 0000000..5945b6e --- /dev/null +++ b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h @@ -0,0 +1,15 @@ +#ifndef QFONTCONFIGDATABASE_H +#define QFONTCONFIGDATABASE_H + +#include +#include "qbasicunixfontdatabase.h" + +class QFontconfigDatabase : public QBasicUnixFontDatabase +{ +public: + void populateFontDatabase(); + QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); + QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const; +}; + +#endif // QFONTCONFIGDATABASE_H diff --git a/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri b/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri new file mode 100644 index 0000000..dbcfbce --- /dev/null +++ b/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri @@ -0,0 +1,10 @@ +contains(QT_CONFIG, fontconfig) { + include(../fontconfig/fontconfig.pri) + DEFINES += Q_FONTCONFIGDATABASE +} else { + include(../basicunix/basicunix.pri) +} + +INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix +HEADERS += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h diff --git a/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h b/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h new file mode 100644 index 0000000..ec083f8 --- /dev/null +++ b/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h @@ -0,0 +1,12 @@ +#ifndef QGENERICUNIXFONTDATABASE_H +#define QGENERICUNIXFONTDATABASE_H + +#ifdef Q_FONTCONFIGDATABASE +#include "qfontconfigdatabase.h" +typedef QFontconfigDatabase QGenericUnixFontDatabase; +#else +#include "qbasicunixfontdatabase.h" +typedef QBasicUnixFontDatabase QGenericUnixFontDatabase; +#endif //Q_FONTCONFIGDATABASE + +#endif // QGENERICUNIXFONTDATABASE_H diff --git a/src/plugins/platforms/linuxfb/linuxfb.pro b/src/plugins/platforms/linuxfb/linuxfb.pro index 8d4b6d7..216b899 100644 --- a/src/plugins/platforms/linuxfb/linuxfb.pro +++ b/src/plugins/platforms/linuxfb/linuxfb.pro @@ -7,6 +7,7 @@ SOURCES = main.cpp qlinuxfbintegration.cpp HEADERS = qlinuxfbintegration.h include(../fb_base/fb_base.pri) +include(../fontdatabases/genericunix/genericunix.pri) target.path += $$[QT_INSTALL_PLUGINS]/platforms INSTALLS += target diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp index 437af81..aa1d401 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -41,6 +41,7 @@ #include "qlinuxfbintegration.h" #include "../fb_base/fb_base.h" +#include "qgenericunixfontdatabase.h" #include #include // overrides QT_OPEN #include @@ -156,6 +157,7 @@ void QLinuxFbIntegrationPrivate::closeTty() } QLinuxFbIntegration::QLinuxFbIntegration() + :fontDb(new QGenericUnixFontDatabase()) { d_ptr = new QLinuxFbIntegrationPrivate(); @@ -799,6 +801,11 @@ QPlatformWindow *QLinuxFbIntegration::createPlatformWindow(QWidget *widget, WId return w; } +QPlatformFontDatabase *QLinuxFbIntegration::fontDatabase() const +{ + return fontDb; +} + QLinuxFbScreen::QLinuxFbScreen(uchar * d, int w, int h, int lstep, QImage::Format screenFormat) : compositePainter(0) { diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h index dc61df5..a5d7abd 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h @@ -82,6 +82,8 @@ public: QList screens() const { return mScreens; } + QPlatformFontDatabase *fontDatabase() const; + private: QLinuxFbScreen *mPrimaryScreen; QList mScreens; @@ -122,6 +124,7 @@ private: void setPixelFormat(struct fb_var_screeninfo); void createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo); void blank(bool on); + QPlatformFontDatabase *fontDb; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index b68230c..3446e81 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -5,7 +5,15 @@ contains(QT_CONFIG, openvg):contains(QT_CONFIG, egl) { SUBDIRS += minimal -#this don't work. but leave it for now -qpa:x11 { +contains(QT_CONFIG, mitshm) { SUBDIRS += testlite } + +linux { + SUBDIRS += linuxfb +} + +unix { + SUBDIRS += vnc \ + qvfb +} diff --git a/src/plugins/platforms/qvfb/qvfb.pro b/src/plugins/platforms/qvfb/qvfb.pro index a560755..d2b332a 100644 --- a/src/plugins/platforms/qvfb/qvfb.pro +++ b/src/plugins/platforms/qvfb/qvfb.pro @@ -7,5 +7,7 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms SOURCES = main.cpp qvfbintegration.cpp qvfbwindowsurface.cpp HEADERS = qvfbintegration.h qvfbwindowsurface.h +include(../fontdatabases/genericunix/genericunix.pri) + target.path += $$[QT_INSTALL_PLUGINS]/platforms INSTALLS += target diff --git a/src/plugins/platforms/qvfb/qvfbintegration.cpp b/src/plugins/platforms/qvfb/qvfbintegration.cpp index a50763a..0cc3938 100644 --- a/src/plugins/platforms/qvfb/qvfbintegration.cpp +++ b/src/plugins/platforms/qvfb/qvfbintegration.cpp @@ -62,6 +62,8 @@ #include #include +#include "qgenericunixfontdatabase.h" + QT_BEGIN_NAMESPACE @@ -409,6 +411,7 @@ QImage *QVFbScreen::screenImage() } QVFbIntegration::QVFbIntegration(const QStringList ¶mList) + : mFontDb(new QGenericUnixFontDatabase()) { int displayId = 0; if (paramList.length() > 0) @@ -435,6 +438,11 @@ QPlatformWindow *QVFbIntegration::createPlatformWindow(QWidget *widget, WId) con return new QVFbWindow(mPrimaryScreen, widget); } +QPlatformFontDatabase *QVFbIntegration::fontDatabase() const +{ + return mFontDb; +} + QT_END_NAMESPACE #include "qvfbintegration.moc" diff --git a/src/plugins/platforms/qvfb/qvfbintegration.h b/src/plugins/platforms/qvfb/qvfbintegration.h index e46e0da..198a45c 100644 --- a/src/plugins/platforms/qvfb/qvfbintegration.h +++ b/src/plugins/platforms/qvfb/qvfbintegration.h @@ -84,9 +84,12 @@ public: QList screens() const { return mScreens; } + QPlatformFontDatabase *fontDatabase() const; + private: QVFbScreen *mPrimaryScreen; QList mScreens; + QPlatformFontDatabase *mFontDb; }; diff --git a/src/plugins/platforms/testlite/qtestliteintegration.cpp b/src/plugins/platforms/testlite/qtestliteintegration.cpp index a8e0fa7..68e9051 100644 --- a/src/plugins/platforms/testlite/qtestliteintegration.cpp +++ b/src/plugins/platforms/testlite/qtestliteintegration.cpp @@ -49,6 +49,7 @@ #include #include "qtestlitewindow.h" +#include "qgenericunixfontdatabase.h" #ifndef QT_NO_OPENGL #include @@ -84,8 +85,8 @@ public: QTestLiteIntegration::QTestLiteIntegration(bool useOpenGL) : mUseOpenGL(useOpenGL) + , mFontDb(new QGenericUnixFontDatabase()) { - xd = new MyDisplay; mPrimaryScreen = new QTestLiteScreen(); @@ -136,6 +137,11 @@ QPixmap QTestLiteIntegration::grabWindow(WId window, int x, int y, int width, in return QPixmap::fromImage(img); } +QPlatformFontDatabase *QTestLiteIntegration::fontDatabase() const +{ + return mFontDb; +} + bool QTestLiteIntegration::hasOpenGL() const { #ifndef QT_NO_OPENGL diff --git a/src/plugins/platforms/testlite/qtestliteintegration.h b/src/plugins/platforms/testlite/qtestliteintegration.h index ac10841..8286ef0 100644 --- a/src/plugins/platforms/testlite/qtestliteintegration.h +++ b/src/plugins/platforms/testlite/qtestliteintegration.h @@ -84,6 +84,8 @@ public: QList screens() const { return mScreens; } + QPlatformFontDatabase *fontDatabase() const; + bool hasOpenGL() const; MyDisplay *xd; @@ -92,6 +94,7 @@ private: bool mUseOpenGL; QTestLiteScreen *mPrimaryScreen; QList mScreens; + QPlatformFontDatabase *mFontDb; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp index 1f477db..1de4b9d 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -622,7 +622,7 @@ void QTestLiteWindow::handleKeyEvent(QEvent::Type type, void *ev) int qtcode = chars.toUpper()[0]; //Not exactly right... if (modifiers & Qt::ControlModifier && qtcode < ' ') qtcode = chars[0] + '@'; - QWindowSystemInterface::handleKeyEvent(widget(), e->time, type, qtcode, modifiers, QString::fromLatin1(chars)); + QWindowSystemInterface::handleKeyEvent(0, e->time, type, qtcode, modifiers, QString::fromLatin1(chars)); } else { qWarning() << "unknown X keycode" << hex << e->keycode << keySym; } @@ -647,9 +647,9 @@ WId QTestLiteWindow::winId() const void QTestLiteWindow::setParent(const QPlatformWindow *window) { - QPoint point = widget()->mapTo(widget()->nativeParentWidget(),QPoint()); - XReparentWindow(xd->display,x_window,window->winId(),point.x(),point.y()); - XMapWindow(xd->display, x_window); + QPoint point = widget()->mapTo(widget()->nativeParentWidget(),QPoint()); + XReparentWindow(xd->display,x_window,window->winId(),point.x(),point.y()); + XMapWindow(xd->display, x_window); } void QTestLiteWindow::raise() @@ -1441,7 +1441,7 @@ bool MyDisplay::handleEvent(XEvent *xe) xw->handleMouseEvent(QEvent::MouseMove, &xe->xbutton); break; - case XKeyPress: + case XKeyPress: xw->handleKeyEvent(QEvent::KeyPress, &xe->xkey); break; diff --git a/src/plugins/platforms/testlite/testlite.pro b/src/plugins/platforms/testlite/testlite.pro index 0a5ebb2..05bd384 100644 --- a/src/plugins/platforms/testlite/testlite.pro +++ b/src/plugins/platforms/testlite/testlite.pro @@ -1,18 +1,29 @@ -TARGET = qtestlitegraphicssystem -include(../../qpluginbase.pri) +TARGET = qtestlite +include(../../qpluginbase.pri) QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms -SOURCES = main.cpp qtestliteintegration.cpp qtestlitewindowsurface.cpp qtestlitewindow.cpp -HEADERS = qtestliteintegration.h qtestlitewindowsurface.h qtestlitewindow.h +SOURCES = \ + main.cpp \ + qtestliteintegration.cpp \ + qtestlitewindowsurface.cpp \ + qtestlitewindow.cpp + +HEADERS = \ + qtestliteintegration.h \ + qtestlitewindowsurface.h \ + qtestlitewindow.h + LIBS += -lX11 -lXext +include (../fontdatabases/genericunix/genericunix.pri) + contains(QT_CONFIG, opengl) { QT += opengl HEADERS += qglxintegration.h SOURCES += qglxintegration.cpp } -target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +target.path += $$[QT_INSTALL_PLUGINS]/platforms INSTALLS += target diff --git a/src/plugins/platforms/vnc/qvncintegration.cpp b/src/plugins/platforms/vnc/qvncintegration.cpp index 331c16a..b36ff33 100644 --- a/src/plugins/platforms/vnc/qvncintegration.cpp +++ b/src/plugins/platforms/vnc/qvncintegration.cpp @@ -49,6 +49,7 @@ #include #include +#include "qgenericunixfontdatabase.h" QVNCScreen::QVNCScreen(QRect screenSize, int screenId) : QFbScreen::QFbScreen() @@ -100,7 +101,7 @@ static void usage() } QVNCIntegration::QVNCIntegration(const QStringList& paramList) - : virtualDesktop(false) + : virtualDesktop(false), fontDb(new QGenericUnixFontDatabase()) { int sizeX = defaultWidth(); int sizeY = defaultHeight(); @@ -234,3 +235,8 @@ void QVNCIntegration::moveToScreen(QWidget *window, int screen) window->platformWindow()->setGeometry(window->geometry()); // this should be unified elsewhere newScreen->addWindow(static_cast(window->platformWindow())); } + +QPlatformFontDatabase *QVNCIntegration::fontDatabase() const +{ + return fontDb; +} diff --git a/src/plugins/platforms/vnc/qvncintegration.h b/src/plugins/platforms/vnc/qvncintegration.h index 241993d..dfc0e6b 100644 --- a/src/plugins/platforms/vnc/qvncintegration.h +++ b/src/plugins/platforms/vnc/qvncintegration.h @@ -45,6 +45,7 @@ #include "qvnccursor.h" #include "../fb_base/fb_base.h" #include +#include "qgenericunixfontdatabase.h" QT_BEGIN_NAMESPACE @@ -91,10 +92,13 @@ public: bool isVirtualDesktop() { return virtualDesktop; } void moveToScreen(QWidget *window, int screen); + QPlatformFontDatabase *fontDatabase() const; + private: QVNCScreen *mPrimaryScreen; QList mScreens; bool virtualDesktop; + QPlatformFontDatabase *fontDb; }; diff --git a/src/plugins/platforms/vnc/vnc.pro b/src/plugins/platforms/vnc/vnc.pro index 65824a2..6c448f5 100644 --- a/src/plugins/platforms/vnc/vnc.pro +++ b/src/plugins/platforms/vnc/vnc.pro @@ -13,6 +13,7 @@ HEADERS += qvnccursor.h SOURCES += qvnccursor.cpp include(../fb_base/fb_base.pri) +include(../fontdatabases/genericunix/genericunix.pri) target.path += $$[QT_INSTALL_PLUGINS]/platforms -- cgit v0.12 From 4e630e3af2f33a123abb58f15f95d640d9054cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Thu, 2 Sep 2010 15:27:27 +0200 Subject: Lighthouse: Move shared context init so it is not created untill anyone asks for it. --- src/plugins/platforms/testlite/qglxintegration.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/testlite/qglxintegration.cpp b/src/plugins/platforms/testlite/qglxintegration.cpp index fbffcab..e262d5b 100644 --- a/src/plugins/platforms/testlite/qglxintegration.cpp +++ b/src/plugins/platforms/testlite/qglxintegration.cpp @@ -241,18 +241,18 @@ QGLXGLContext::QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindow , m_drawable((Drawable)window) , m_context(0) { - if (!QPlatformGLContext::defaultSharedContext()) { - if (m_defaultSharedContextMutex.tryLock()){ - createDefaultSharedContex(xd); - m_defaultSharedContextMutex.unlock(); - } else { - m_defaultSharedContextMutex.lock(); //wait to the the shared context is created - m_defaultSharedContextMutex.unlock(); - } - } QPlatformGLContext *sharePlatformContext; if (format.useDefaultSharedContext()) { + if (!QPlatformGLContext::defaultSharedContext()) { + if (m_defaultSharedContextMutex.tryLock()){ + createDefaultSharedContex(xd); + m_defaultSharedContextMutex.unlock(); + } else { + m_defaultSharedContextMutex.lock(); //wait to the the shared context is created + m_defaultSharedContextMutex.unlock(); + } + } sharePlatformContext = QPlatformGLContext::defaultSharedContext(); } else { sharePlatformContext = format.sharedGLContext(); @@ -309,9 +309,6 @@ void QGLXGLContext::createDefaultSharedContex(MyDisplay *xd) } else { qWarning("Warning no shared context created"); } - - - } void QGLXGLContext::makeCurrent() -- cgit v0.12 From 975490d721ca98251aefa7e7f50e6e54e63b79c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 3 Sep 2010 09:27:44 +0200 Subject: Lighthouse: Fix eventhandling for when widgets are in destructor This is a problem when you send events from a seperate thread --- src/gui/kernel/qwindowsysteminterface_qpa.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp index c49bd36..f10c038 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -61,6 +61,10 @@ extern QPointer qt_last_mouse_receiver; void QWindowSystemInterface::handleEnterEvent(QWidget *tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + if (tlw) { QWindowSystemInterfacePrivate::EnterEvent *e = new QWindowSystemInterfacePrivate::EnterEvent(tlw); QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); @@ -69,12 +73,20 @@ void QWindowSystemInterface::handleEnterEvent(QWidget *tlw) void QWindowSystemInterface::handleLeaveEvent(QWidget *tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(tlw); QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); } void QWindowSystemInterface::handleGeometryChange(QWidget *tlw, const QRect &newRect) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw,newRect); QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); } @@ -102,6 +114,9 @@ void QWindowSystemInterface::handleMouseEvent(QWidget *w, const QPoint & local, void QWindowSystemInterface::handleMouseEvent(QWidget *tlw, ulong timestamp, const QPoint & local, const QPoint & global, Qt::MouseButtons b) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; QWindowSystemInterfacePrivate::MouseEvent * e = new QWindowSystemInterfacePrivate::MouseEvent(tlw, timestamp, local, global, b); QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); @@ -114,6 +129,10 @@ void QWindowSystemInterface::handleKeyEvent(QWidget *w, QEvent::Type t, int k, Q void QWindowSystemInterface::handleKeyEvent(QWidget *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + QWindowSystemInterfacePrivate::KeyEvent * e = new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count); QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); @@ -126,6 +145,10 @@ void QWindowSystemInterface::handleWheelEvent(QWidget *w, const QPoint & local, void QWindowSystemInterface::handleWheelEvent(QWidget *tlw, ulong timestamp, const QPoint & local, const QPoint & global, int d, Qt::Orientation o) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + QWindowSystemInterfacePrivate::WheelEvent *e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, d, o); QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); -- cgit v0.12 From 136c32ddb97a12eefcbbfebf63075237c07d4cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 3 Sep 2010 12:53:14 +0200 Subject: Lighthouse: Added QDirectFbGlContext This is untested since I have no HW to test on, but its in the public api, so that we have something to build on. --- src/plugins/platforms/directfb/directfb.pro | 6 ++- .../platforms/directfb/qdirectfbglcontext.cpp | 58 ++++++++++++++++++++++ .../platforms/directfb/qdirectfbglcontext.h | 28 +++++++++++ src/plugins/platforms/directfb/qdirectfbwindow.cpp | 23 ++++++++- src/plugins/platforms/directfb/qdirectfbwindow.h | 3 ++ 5 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 src/plugins/platforms/directfb/qdirectfbglcontext.cpp create mode 100644 src/plugins/platforms/directfb/qdirectfbglcontext.h diff --git a/src/plugins/platforms/directfb/directfb.pro b/src/plugins/platforms/directfb/directfb.pro index 48128fb..65c49e3 100644 --- a/src/plugins/platforms/directfb/directfb.pro +++ b/src/plugins/platforms/directfb/directfb.pro @@ -19,14 +19,16 @@ SOURCES = main.cpp \ qdirectfbconvenience.cpp \ qdirectfbinput.cpp \ qdirectfbcursor.cpp \ - qdirectfbwindow.cpp + qdirectfbwindow.cpp \ + qdirectfbglcontext.cpp HEADERS = qdirectfbintegration.h \ qdirectfbwindowsurface.h \ qdirectfbblitter.h \ qdirectfbconvenience.h \ qdirectfbinput.h \ qdirectfbcursor.h \ - qdirectfbwindow.h + qdirectfbwindow.h \ + qdirectfbglcontext.h include(../fontdatabases/genericunix/genericunix.pri) target.path += $$[QT_INSTALL_PLUGINS]/platforms diff --git a/src/plugins/platforms/directfb/qdirectfbglcontext.cpp b/src/plugins/platforms/directfb/qdirectfbglcontext.cpp new file mode 100644 index 0000000..fe96efe --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbglcontext.cpp @@ -0,0 +1,58 @@ +#include "qdirectfbglcontext.h" + +#include + +#include + +QDirectFbGLContext::QDirectFbGLContext(IDirectFBGL *glContext) + : m_dfbGlContext(glContext) +{ + DFBResult result; + DFBGLAttributes glAttribs; + result = m_dfbGlContext->GetAttributes(glContext, &glAttribs); + if (result == DFB_OK) { + m_windowFormat.setDepthBufferSize(glAttribs.depth_size); + m_windowFormat.setStencilBufferSize(glAttribs.stencil_size); + + m_windowFormat.setRedBufferSize(glAttribs.red_size); + m_windowFormat.setGreenBufferSize(glAttribs.green_size); + m_windowFormat.setBlueBufferSize(glAttribs.blue_size); + m_windowFormat.setAlphaBufferSize(glAttribs.alpha_size); + + m_windowFormat.setAccumBufferSize(glAttribs.accum_red_size); + m_windowFormat.setAlpha(glAttribs.accum_alpha_size); + + m_windowFormat.setDoubleBuffer(glAttribs.double_buffer); + m_windowFormat.setStereo(glAttribs.stereo); + } +} + +void QDirectFbGLContext::makeCurrent() +{ + m_dfbGlContext->Lock(m_dfbGlContext); +} + +void QDirectFbGLContext::doneCurrent() +{ + m_dfbGlContext->Unlock(m_dfbGlContext); +} + +void *QDirectFbGLContext::getProcAddress(const QString &procName) +{ + void *proc; + DFBResult result = m_dfbGlContext->GetProcAddress(m_dfbGlContext,qPrintable(procName),&proc); + if (result == DFB_OK) + return proc; + return 0; +} + +void QDirectFbGLContext::swapBuffers() +{ +// m_dfbGlContext->Unlock(m_dfbGlContext); //maybe not in doneCurrent() + qDebug() << "Swap buffers"; +} + +QPlatformWindowFormat QDirectFbGLContext::platformWindowFormat() const +{ + return m_windowFormat; +} diff --git a/src/plugins/platforms/directfb/qdirectfbglcontext.h b/src/plugins/platforms/directfb/qdirectfbglcontext.h new file mode 100644 index 0000000..037587e --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbglcontext.h @@ -0,0 +1,28 @@ +#ifndef QDIRECTFBGLCONTEXT_H +#define QDIRECTFBGLCONTEXT_H + +#include + +#include "qdirectfbconvenience.h" + +class QDirectFbGLContext : public QPlatformGLContext +{ +public: + explicit QDirectFbGLContext(IDirectFBGL *glContext); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void *getProcAddress(const QString &procName); + + QPlatformWindowFormat platformWindowFormat() const; + + +private: + IDirectFBGL *m_dfbGlContext; + + QPlatformWindowFormat m_windowFormat; + +}; + +#endif // QDIRECTFBGLCONTEXT_H diff --git a/src/plugins/platforms/directfb/qdirectfbwindow.cpp b/src/plugins/platforms/directfb/qdirectfbwindow.cpp index 30e6f5a..f82fbd6 100644 --- a/src/plugins/platforms/directfb/qdirectfbwindow.cpp +++ b/src/plugins/platforms/directfb/qdirectfbwindow.cpp @@ -40,13 +40,14 @@ ****************************************************************************/ #include "qdirectfbwindow.h" #include "qdirectfbinput.h" +#include "qdirectfbglcontext.h" #include #include QDirectFbWindow::QDirectFbWindow(QWidget *tlw, QDirectFbInput *inputhandler) - : QPlatformWindow(tlw), m_inputHandler(inputhandler) + : QPlatformWindow(tlw), m_inputHandler(inputhandler), m_context(0) { IDirectFBDisplayLayer *layer = QDirectFbConvenience::dfbDisplayLayer(); DFBDisplayLayerConfig layerConfig; @@ -155,3 +156,23 @@ WId QDirectFbWindow::winId() const m_dfbWindow->GetID(m_dfbWindow, &id); return WId(id); } + +QPlatformGLContext *QDirectFbWindow::glContext() const +{ + if (!m_context) { + IDirectFBSurface *surface; + DFBResult result = m_dfbWindow->GetSurface(m_dfbWindow,&surface); + if (result != DFB_OK) { + qWarning("could not retrieve surface in QDirectFbWindow::glContext()"); + return 0; + } + IDirectFBGL *gl; + result = surface->GetGL(surface,&gl); + if (result != DFB_OK) { + qWarning("could not retrieve IDirectFBGL in QDirectFbWindow::glContext()"); + return 0; + } + const_cast(this)->m_context = new QDirectFbGLContext(gl); + } + return m_context; +} diff --git a/src/plugins/platforms/directfb/qdirectfbwindow.h b/src/plugins/platforms/directfb/qdirectfbwindow.h index b512afd..eaf5173 100644 --- a/src/plugins/platforms/directfb/qdirectfbwindow.h +++ b/src/plugins/platforms/directfb/qdirectfbwindow.h @@ -65,10 +65,13 @@ public: void lower(); WId winId() const; + QPlatformGLContext *glContext() const; + private: IDirectFBWindow *m_dfbWindow; QDirectFbInput *m_inputHandler; + QPlatformGLContext *m_context; }; QT_END_NAMESPACE -- cgit v0.12 From c5fe294667d9d8dfcec5c9529185a13ba5a47e91 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Mon, 6 Sep 2010 14:53:51 +0200 Subject: Send mouse release events for touch screens --- src/plugins/generic/linuxinput/qlinuxinput.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/generic/linuxinput/qlinuxinput.cpp b/src/plugins/generic/linuxinput/qlinuxinput.cpp index 32137ee..955aed9 100644 --- a/src/plugins/generic/linuxinput/qlinuxinput.cpp +++ b/src/plugins/generic/linuxinput/qlinuxinput.cpp @@ -155,6 +155,9 @@ void QLinuxInputMouseHandler::readMouseData() } } else if (data->type == EV_KEY && data->code == BTN_TOUCH) { m_buttons = data->value ? Qt::LeftButton : Qt::NoButton; + + QWindowSystemInterface::handleMouseEvent(0, QPoint(m_x, m_y), + QPoint(m_x, m_y), m_buttons); } else if (data->type == EV_KEY) { Qt::MouseButton button = Qt::NoButton; switch (data->code) { -- cgit v0.12 From 8a92433b5deb14a27457715241b14764c28ffb39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 3 Sep 2010 14:45:43 +0200 Subject: Make phonon gst backend build properly Only software rendering for now... also fix regression I made in QWindowSystemInterface. Its allowed to send in NULL pointers for tlw in some of the functions. So dont ask for the widget data of a NULL pointer. --- src/3rdparty/phonon/gstreamer/devicemanager.cpp | 4 +- src/3rdparty/phonon/gstreamer/videowidget.cpp | 4 ++ src/3rdparty/phonon/gstreamer/x11renderer.h | 4 -- src/gui/kernel/qwindowsysteminterface_qpa.cpp | 50 +++++++++++++--------- src/plugins/phonon/gstreamer/gstreamer.pro | 2 +- .../platforms/testlite/qtestlitewindowsurface.cpp | 2 +- 6 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/3rdparty/phonon/gstreamer/devicemanager.cpp b/src/3rdparty/phonon/gstreamer/devicemanager.cpp index c3826eb..518aa85 100644 --- a/src/3rdparty/phonon/gstreamer/devicemanager.cpp +++ b/src/3rdparty/phonon/gstreamer/devicemanager.cpp @@ -22,7 +22,9 @@ #include "videowidget.h" #include "glrenderer.h" #include "widgetrenderer.h" +#ifdef Q_WS_X11 #include "x11renderer.h" +#endif #include "artssink.h" #include "pulsesupport.h" @@ -264,7 +266,7 @@ AbstractRenderer *DeviceManager::createVideoRenderer(VideoWidget *parent) if (m_videoSinkWidget == "software") { return new WidgetRenderer(parent); } -#ifndef Q_WS_QWS +#ifdef Q_WS_X11 else if (m_videoSinkWidget == "xwindow") { return new X11Renderer(parent); } else { diff --git a/src/3rdparty/phonon/gstreamer/videowidget.cpp b/src/3rdparty/phonon/gstreamer/videowidget.cpp index e1f0ec9..a4c6f79 100644 --- a/src/3rdparty/phonon/gstreamer/videowidget.cpp +++ b/src/3rdparty/phonon/gstreamer/videowidget.cpp @@ -31,7 +31,9 @@ #include "glrenderer.h" #include "widgetrenderer.h" +#ifdef Q_WS_X11 #include "x11renderer.h" +#endif #ifndef QT_NO_PHONON_VIDEO QT_BEGIN_NAMESPACE @@ -116,10 +118,12 @@ void VideoWidget::setupVideoBin() GstPad *videopad = gst_element_get_pad (queue, "sink"); gst_element_add_pad (m_videoBin, gst_ghost_pad_new ("sink", videopad)); gst_object_unref (videopad); +#ifndef Q_WS_QPA QWidget *parentWidget = qobject_cast(parent()); if (parentWidget) parentWidget->winId(); // Due to some existing issues with alien in 4.4, // we must currently force the creation of a parent widget. +#endif m_isValid = true; //initialization ok, accept input } } diff --git a/src/3rdparty/phonon/gstreamer/x11renderer.h b/src/3rdparty/phonon/gstreamer/x11renderer.h index f7140da..8e2ea19 100644 --- a/src/3rdparty/phonon/gstreamer/x11renderer.h +++ b/src/3rdparty/phonon/gstreamer/x11renderer.h @@ -27,8 +27,6 @@ QT_BEGIN_NAMESPACE -#ifndef Q_WS_QWS - class QString; namespace Phonon @@ -61,8 +59,6 @@ private: } } //namespace Phonon::Gstreamer -#endif // Q_WS_QWS - QT_END_NAMESPACE #endif // Phonon_GSTREAMER_X11RENDERER_H diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp index f10c038..7b83fd3 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -61,11 +61,11 @@ extern QPointer qt_last_mouse_receiver; void QWindowSystemInterface::handleEnterEvent(QWidget *tlw) { - QWidgetData *data = qt_qwidget_data(tlw); - if (data->in_destructor) - return; - if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + QWindowSystemInterfacePrivate::EnterEvent *e = new QWindowSystemInterfacePrivate::EnterEvent(tlw); QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); } @@ -73,20 +73,22 @@ void QWindowSystemInterface::handleEnterEvent(QWidget *tlw) void QWindowSystemInterface::handleLeaveEvent(QWidget *tlw) { - QWidgetData *data = qt_qwidget_data(tlw); - if (data->in_destructor) - return; - + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + } QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(tlw); QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); } void QWindowSystemInterface::handleGeometryChange(QWidget *tlw, const QRect &newRect) { - QWidgetData *data = qt_qwidget_data(tlw); - if (data->in_destructor) - return; - + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + } QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw,newRect); QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); } @@ -114,9 +116,11 @@ void QWindowSystemInterface::handleMouseEvent(QWidget *w, const QPoint & local, void QWindowSystemInterface::handleMouseEvent(QWidget *tlw, ulong timestamp, const QPoint & local, const QPoint & global, Qt::MouseButtons b) { - QWidgetData *data = qt_qwidget_data(tlw); - if (data->in_destructor) - tlw = 0; + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + } QWindowSystemInterfacePrivate::MouseEvent * e = new QWindowSystemInterfacePrivate::MouseEvent(tlw, timestamp, local, global, b); QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); @@ -129,9 +133,11 @@ void QWindowSystemInterface::handleKeyEvent(QWidget *w, QEvent::Type t, int k, Q void QWindowSystemInterface::handleKeyEvent(QWidget *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { - QWidgetData *data = qt_qwidget_data(tlw); - if (data->in_destructor) - tlw = 0; + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + } QWindowSystemInterfacePrivate::KeyEvent * e = new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count); @@ -145,9 +151,11 @@ void QWindowSystemInterface::handleWheelEvent(QWidget *w, const QPoint & local, void QWindowSystemInterface::handleWheelEvent(QWidget *tlw, ulong timestamp, const QPoint & local, const QPoint & global, int d, Qt::Orientation o) { - QWidgetData *data = qt_qwidget_data(tlw); - if (data->in_destructor) - tlw = 0; + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + } QWindowSystemInterfacePrivate::WheelEvent *e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, d, o); diff --git a/src/plugins/phonon/gstreamer/gstreamer.pro b/src/plugins/phonon/gstreamer/gstreamer.pro index 1013205..02e0848 100644 --- a/src/plugins/phonon/gstreamer/gstreamer.pro +++ b/src/plugins/phonon/gstreamer/gstreamer.pro @@ -58,7 +58,7 @@ SOURCES += $$PHONON_GSTREAMER_DIR/abstractrenderer.cpp \ $$PHONON_GSTREAMER_DIR/volumefadereffect.cpp \ $$PHONON_GSTREAMER_DIR/widgetrenderer.cpp -!embedded { +x11 { HEADERS += $$PHONON_GSTREAMER_DIR/x11renderer.h SOURCES += $$PHONON_GSTREAMER_DIR/x11renderer.cpp } diff --git a/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp b/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp index 53f4791..b3232c8 100644 --- a/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp @@ -180,7 +180,7 @@ void QTestLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const } #else // Use MIT_SHM - if (image_info->image) { + if (image_info && image_info->image) { //qDebug() << "Here we go" << image_info->image->width << image_info->image->height; int x = 0; int y = 0; -- cgit v0.12 From 8fbcf5d1a93f50fa59f650468d203115f7a6965b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Tue, 7 Sep 2010 16:33:09 +0200 Subject: Lighthouse: fix reparenting from topLevel to child widget also fix Directfb with a hack so that moving windows works --- src/gui/kernel/qwidget_qpa.cpp | 18 ++++++++++-------- src/plugins/platforms/directfb/qdirectfbwindow.cpp | 8 ++++++++ .../platforms/directfb/qdirectfbwindowsurface.cpp | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/gui/kernel/qwidget_qpa.cpp b/src/gui/kernel/qwidget_qpa.cpp index b3599bd..ac8b37d 100644 --- a/src/gui/kernel/qwidget_qpa.cpp +++ b/src/gui/kernel/qwidget_qpa.cpp @@ -145,12 +145,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) } } if (destroyWindow) { - QTLWExtra *topData = d->maybeTopData(); - if (topData) { - delete topData->platformWindow; - topData->platformWindow = 0; - d->data.winid = 0; - } + d->deleteTLSysExtra(); } else { if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) { d->hide_sys(); @@ -403,9 +398,10 @@ void QWidgetPrivate::show_sys() window->setGeometry(geomRect); } if (q->isWindow()) { - if (QWindowSurface *surface = q->windowSurface()) + if (QWindowSurface *surface = q->windowSurface()) { if (windowRect.size() != geomRect.size()) { - surface->resize(geomRect.size()); + surface->resize(geomRect.size()); + } } if (window) @@ -781,6 +777,7 @@ void QWidgetPrivate::createSysExtra() void QWidgetPrivate::deleteSysExtra() { + } void QWidgetPrivate::createTLSysExtra() @@ -789,6 +786,11 @@ void QWidgetPrivate::createTLSysExtra() void QWidgetPrivate::deleteTLSysExtra() { + if (extra && extra->topextra) { + delete extra->topextra->platformWindow; + extra->topextra->platformWindow = 0; + extra->topextra->backingStore.destroy(); + } } void QWidgetPrivate::registerDropSite(bool on) diff --git a/src/plugins/platforms/directfb/qdirectfbwindow.cpp b/src/plugins/platforms/directfb/qdirectfbwindow.cpp index f82fbd6..21eefc4 100644 --- a/src/plugins/platforms/directfb/qdirectfbwindow.cpp +++ b/src/plugins/platforms/directfb/qdirectfbwindow.cpp @@ -44,6 +44,8 @@ #include +#include "qdirectfbwindowsurface.h" + #include QDirectFbWindow::QDirectFbWindow(QWidget *tlw, QDirectFbInput *inputhandler) @@ -95,10 +97,16 @@ QDirectFbWindow::~QDirectFbWindow() void QDirectFbWindow::setGeometry(const QRect &rect) { + bool isMoveOnly = (rect.topLeft() != geometry().topLeft()) && (rect.size() == geometry().size()); QPlatformWindow::setGeometry(rect); m_dfbWindow->SetBounds(m_dfbWindow, rect.x(),rect.y(), rect.width(), rect.height()); + //Hack. When moving since the WindowSurface of a window becomes invalid when moved + if (isMoveOnly) { //if resize then windowsurface is updated. + widget()->windowSurface()->resize(rect.size()); + widget()->update(); + } } void QDirectFbWindow::setOpacity(qreal level) diff --git a/src/plugins/platforms/directfb/qdirectfbwindowsurface.cpp b/src/plugins/platforms/directfb/qdirectfbwindowsurface.cpp index 271d061..2aef70d 100644 --- a/src/plugins/platforms/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/platforms/directfb/qdirectfbwindowsurface.cpp @@ -70,7 +70,7 @@ QDirectFbWindowSurface::QDirectFbWindowSurface(QWidget *window, WId wId) QDirectFbWindowSurface::~QDirectFbWindowSurface() { - + delete m_pixmap; } QPaintDevice *QDirectFbWindowSurface::paintDevice() -- cgit v0.12 From 184a4c66165ab49940e1eae7140a6474531c5f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Wed, 8 Sep 2010 07:40:59 +0200 Subject: Lighthouse, DFb don't show windows that Qt::WA_DontShowOnScreen --- src/plugins/platforms/directfb/qdirectfbwindow.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/directfb/qdirectfbwindow.cpp b/src/plugins/platforms/directfb/qdirectfbwindow.cpp index 21eefc4..74e7a72 100644 --- a/src/plugins/platforms/directfb/qdirectfbwindow.cpp +++ b/src/plugins/platforms/directfb/qdirectfbwindow.cpp @@ -84,6 +84,8 @@ QDirectFbWindow::QDirectFbWindow(QWidget *tlw, QDirectFbInput *inputhandler) m_dfbWindow->SetOpacity(m_dfbWindow,0xff); + setVisible(widget()->isVisible()); + DFBWindowID id; m_dfbWindow->GetID(m_dfbWindow, &id); m_inputHandler->addWindow(id,tlw); @@ -99,13 +101,15 @@ void QDirectFbWindow::setGeometry(const QRect &rect) { bool isMoveOnly = (rect.topLeft() != geometry().topLeft()) && (rect.size() == geometry().size()); QPlatformWindow::setGeometry(rect); - m_dfbWindow->SetBounds(m_dfbWindow, rect.x(),rect.y(), - rect.width(), rect.height()); - - //Hack. When moving since the WindowSurface of a window becomes invalid when moved - if (isMoveOnly) { //if resize then windowsurface is updated. - widget()->windowSurface()->resize(rect.size()); - widget()->update(); + if (widget()->isVisible() && !(widget()->testAttribute(Qt::WA_DontShowOnScreen))) { + m_dfbWindow->SetBounds(m_dfbWindow, rect.x(),rect.y(), + rect.width(), rect.height()); + + //Hack. When moving since the WindowSurface of a window becomes invalid when moved + if (isMoveOnly) { //if resize then windowsurface is updated. + widget()->windowSurface()->resize(rect.size()); + widget()->update(); + } } } -- cgit v0.12 From 34625a376b7d08856c6de1f52179d86aaaa30f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Wed, 8 Sep 2010 12:55:44 +0200 Subject: Lighthouse, compile fix eglfs --- src/plugins/platforms/eglfs/qeglfsintegration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 07605ec..a48fde8 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE QEglFSIntegration::QEglFSIntegration() - mFontDb(new QGenericUnixFontDatabase()) + : mFontDb(new QGenericUnixFontDatabase()) { m_primaryScreen = new QEglFSScreen(EGL_DEFAULT_DISPLAY); -- cgit v0.12 From bb5c934d3e2e07ddf3a1c299b2111d7119a01eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Thu, 9 Sep 2010 09:26:25 +0200 Subject: Lighthouse: Various compiler warning/error fixes compliments from Vapula --- src/gui/kernel/qapplication_qpa.cpp | 1 - src/gui/kernel/qplatformcursor_qpa.cpp | 8 ++------ src/gui/kernel/qplatformcursor_qpa.h | 2 +- src/gui/kernel/qwindowsysteminterface_qpa.cpp | 2 -- src/gui/kernel/qwindowsysteminterface_qpa_p.h | 2 -- src/plugins/platforms/fb_base/fb_base.cpp | 4 ++-- src/plugins/platforms/fb_base/fb_base.h | 2 +- src/plugins/platforms/linuxfb/qlinuxfbintegration.h | 1 + 8 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/gui/kernel/qapplication_qpa.cpp b/src/gui/kernel/qapplication_qpa.cpp index e5b5396..d432829 100644 --- a/src/gui/kernel/qapplication_qpa.cpp +++ b/src/gui/kernel/qapplication_qpa.cpp @@ -68,7 +68,6 @@ QT_BEGIN_NAMESPACE static QString appName; -static const char *appFont = 0; // application font QWidget *qt_button_down = 0; // widget got last button-down diff --git a/src/gui/kernel/qplatformcursor_qpa.cpp b/src/gui/kernel/qplatformcursor_qpa.cpp index 6665396..ac557b9 100644 --- a/src/gui/kernel/qplatformcursor_qpa.cpp +++ b/src/gui/kernel/qplatformcursor_qpa.cpp @@ -187,10 +187,6 @@ static const uchar mcur_fdiag_bits[] = { 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e, 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 }; -static const uchar cur_blank_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // 20 x 20 static const uchar forbidden_bits[] = { @@ -546,11 +542,11 @@ void QPlatformCursorImage::set(Qt::CursorShape id) \a hy the y coordinate of the cursor's hotspot */ -void QPlatformCursorImage::set(const QImage * image, int hx, int hy) +void QPlatformCursorImage::set(const QImage &image, int hx, int hy) { hot.setX(hx); hot.setY(hy); - cursorImage = *image; + cursorImage = image; } /*! diff --git a/src/gui/kernel/qplatformcursor_qpa.h b/src/gui/kernel/qplatformcursor_qpa.h index abdbfee..71d0e87 100644 --- a/src/gui/kernel/qplatformcursor_qpa.h +++ b/src/gui/kernel/qplatformcursor_qpa.h @@ -63,7 +63,7 @@ public: QImage * image() { return &cursorImage; } QPoint hotspot() { return hot; } void set(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY); - void set(const QImage * image, int hx, int hy); + void set(const QImage &image, int hx, int hy); void set(Qt::CursorShape); private: static void createSystemCursor(int id); diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp index 7b83fd3..bb29cbf 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -207,7 +207,6 @@ void QWindowSystemInterface::handleTouchEvent(QWidget *tlw, ulong timestamp, QEv Qt::TouchPointStates states; QTouchEvent::TouchPoint p; - int primaryPoint = -1; QList::const_iterator point = points.constBegin(); QList::const_iterator end = points.constEnd(); while (point != end) { @@ -217,7 +216,6 @@ void QWindowSystemInterface::handleTouchEvent(QWidget *tlw, ulong timestamp, QEv Qt::TouchPointStates state = point->state; if (point->isPrimary) { state |= Qt::TouchPointPrimary; - primaryPoint = point->id; } p.setState(state); p.setRect(point->area); diff --git a/src/gui/kernel/qwindowsysteminterface_qpa_p.h b/src/gui/kernel/qwindowsysteminterface_qpa_p.h index 5f3ac5d..78e1f33 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa_p.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa_p.h @@ -49,8 +49,6 @@ QT_BEGIN_NAMESPACE class QWindowSystemInterfacePrivate { public: - Q_ENUMS(EventType); - enum EventType { Close, GeometryChange, diff --git a/src/plugins/platforms/fb_base/fb_base.cpp b/src/plugins/platforms/fb_base/fb_base.cpp index ef7ab02..48488d4 100644 --- a/src/plugins/platforms/fb_base/fb_base.cpp +++ b/src/plugins/platforms/fb_base/fb_base.cpp @@ -67,7 +67,7 @@ void QPlatformSoftwareCursor::setCursor(Qt::CursorShape shape) graphic->set(shape); } -void QPlatformSoftwareCursor::setCursor(const QImage * image, int hotx, int hoty) +void QPlatformSoftwareCursor::setCursor(const QImage &image, int hotx, int hoty) { graphic->set(image, hotx, hoty); } @@ -85,7 +85,7 @@ void QPlatformSoftwareCursor::changeCursor(QCursor * widgetCursor, QWidget * wid if (shape == Qt::BitmapCursor) { // application supplied cursor QPoint spot = widgetCursor->hotSpot(); - setCursor(&widgetCursor->pixmap().toImage(), spot.x(), spot.y()); + setCursor(widgetCursor->pixmap().toImage(), spot.x(), spot.y()); } else { // system cursor setCursor(shape); diff --git a/src/plugins/platforms/fb_base/fb_base.h b/src/plugins/platforms/fb_base/fb_base.h index 10f292e..e52455a 100644 --- a/src/plugins/platforms/fb_base/fb_base.h +++ b/src/plugins/platforms/fb_base/fb_base.h @@ -40,7 +40,7 @@ protected: private: void setCursor(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY); void setCursor(Qt::CursorShape shape); - void setCursor(const QImage * image, int hotx, int hoty); + void setCursor(const QImage &image, int hotx, int hoty); QRect currentRect; // next place to draw the cursor QRect prevRect; // last place the cursor was drawn QRect getCurrentRect(); diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h index a5d7abd..e93495c 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h @@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE class QLinuxFbScreen : public QFbScreen { + Q_OBJECT public: QLinuxFbScreen(uchar * d, int w, int h, int lstep, QImage::Format screenFormat); void setGeometry(QRect rect); -- cgit v0.12 From ee7afe2536c7078c0a29dd409b4317869670c170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Thu, 9 Sep 2010 13:27:24 +0200 Subject: Lighthouse Compilefix --- src/gui/kernel/qapplication_qpa.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qapplication_qpa.cpp b/src/gui/kernel/qapplication_qpa.cpp index d432829..ece035c 100644 --- a/src/gui/kernel/qapplication_qpa.cpp +++ b/src/gui/kernel/qapplication_qpa.cpp @@ -68,6 +68,7 @@ QT_BEGIN_NAMESPACE static QString appName; +static QString appFont; QWidget *qt_button_down = 0; // widget got last button-down @@ -522,7 +523,7 @@ void qt_init(QApplicationPrivate *priv, int type) QByteArray arg = argv[i]; if (arg == "-fn" || arg == "-font") { if (++i < argc) - appFont = argv[i]; + appFont = QString::fromLocal8Bit(argv[i]); } else if (arg == "-platform") { if (++i < argc) platformName = QLatin1String(argv[i]); -- cgit v0.12 From 41243160f7a9fb5e2eea365ec9757f5496d0387f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 10 Sep 2010 10:22:12 +0200 Subject: Lighthouse: Fixing the openkode implementation --- .../platforms/openkode/qopenkodeintegration.cpp | 136 ++++++++------------- .../platforms/openkode/qopenkodeintegration.h | 3 +- src/plugins/platforms/openkode/qopenkodewindow.cpp | 5 +- 3 files changed, 55 insertions(+), 89 deletions(-) diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.cpp b/src/plugins/platforms/openkode/qopenkodeintegration.cpp index 8fc3862..f8b715f 100644 --- a/src/plugins/platforms/openkode/qopenkodeintegration.cpp +++ b/src/plugins/platforms/openkode/qopenkodeintegration.cpp @@ -60,33 +60,13 @@ #include "GLES2/gl2ext.h" -#include - - QT_BEGIN_NAMESPACE -QOpenKODEScreen::QOpenKODEScreen() +QOpenKODEScreen::QOpenKODEScreen(KDDisplayNV *kdDisplay, KDDesktopNV *kdDesktop) : mIsFullScreen(false) { - KDDesktopNV *kdDesktop = KD_NULL; - KDDisplayNV *kdDisplay = KD_NULL; - qDebug() << "QOpenKODEScreen::QOpenKODEIntegrationScreen()"; - // Get the default desktop and display - kdDesktop = kdGetDesktopNV(KD_DEFAULT_DESKTOP_NV, KD_NULL); - if (!kdDesktop || kdDesktop == (void*)-1) { - qErrnoWarning(kdGetError(), "Could not obtain KDDesktopNV pointer"); - return; - } - - kdDisplay = kdGetDisplayNV(KD_DEFAULT_DISPLAY_NV, KD_NULL); - if (!kdDisplay || kdDisplay == (void*)-1) { - qErrnoWarning(kdGetError(), "Could not obtain KDDisplayNV pointer"); - kdReleaseDesktopNV(kdDesktop); - return; - } - KDboolean enabled = KD_TRUE; kdSetDisplayPropertybvNV(kdDisplay, KD_DISPLAYPROPERTY_ENABLED_NV, @@ -139,64 +119,64 @@ QOpenKODEScreen::QOpenKODEScreen() } -static GLuint loadShaders(const QString &vertexShader, const QString &fragmentShader) -{ - GLuint prog = 0; - GLuint vertShader; - GLuint fragShader; - - // Create the program - prog = glCreateProgram(); - - // Create the GL shader objects - vertShader = glCreateShader(GL_VERTEX_SHADER); - fragShader = glCreateShader(GL_FRAGMENT_SHADER); - - // Load shader sources into GL and compile - QFile vertexFile(vertexShader); - vertexFile.open(QFile::ReadOnly); - QByteArray vertSource = vertexFile.readAll(); - const char *vertChar = vertSource.constData(); - int vertSize = vertSource.size(); - - QFile fragFile(fragmentShader); - fragFile.open(QFile::ReadOnly); - QByteArray fragSource = fragFile.readAll(); - const char *fragChar = fragSource.constData(); - int fragSize = fragSource.size(); - - glShaderSource(vertShader, 1, (const char**)&vertChar, &vertSize); - glCompileShader(vertShader); - - glShaderSource(fragShader, 1, (const char**)&fragChar, &fragSize); - glCompileShader(fragShader); - - // Attach the shaders to the program - glAttachShader(prog, vertShader); - glAttachShader(prog, fragShader); - - // Delete the shaders - glDeleteShader(vertShader); - glDeleteShader(fragShader); - - // Link and validate the shader program - glLinkProgram(prog); - glValidateProgram(prog); - - return prog; -} - QOpenKODEIntegration::QOpenKODEIntegration() : mEventLoopIntegration(0) { if (kdInitializeNV() == KD_ENOTINITIALIZED) { qFatal("Did not manage to initialize openkode"); } - QOpenKODEScreen *mPrimaryScreen = new QOpenKODEScreen(); - - mScreens.append(mPrimaryScreen); + KDDisplaySystemNV *kdDisplaySystem = kdCreateDisplaySystemSnapshotNV(this); + KDint32 displayCount = 0; + kdGetDisplaySystemPropertyivNV(kdDisplaySystem, KD_DISPLAYPROPERTY_COUNT_NV, 0, &displayCount); + + for (int i = 0; i < displayCount; i++) { + KDchar *displayName = 0; + KDsize displayNameLength = 0; + kdGetDisplaySystemPropertycvNV(kdDisplaySystem,KD_DISPLAYPROPERTY_NAME_NV,i,0,&displayNameLength); + if (!displayNameLength) + continue; + displayName = new KDchar[displayNameLength]; + kdGetDisplaySystemPropertycvNV(kdDisplaySystem,KD_DISPLAYPROPERTY_NAME_NV,i,displayName,&displayNameLength); + + KDDisplayNV *display = kdGetDisplayNV(displayName,this); + if (!display || display == (void*)-1) { + qErrnoWarning(kdGetError(), "Could not obtain KDDisplayNV pointer"); + return; + } + if (displayNameLength) + delete displayName; + + KDchar *desktopName = 0; + KDsize desktopNameLength = 0; + bool openkodeImpDoesNotFail = false; + if (openkodeImpDoesNotFail) { + qDebug() << "printing desktopname"; + kdGetDisplayPropertycvNV(display,KD_DISPLAYPROPERTY_DESKTOP_NAME_NV,desktopName,&desktopNameLength); + if (desktopNameLength) { + desktopName = new KDchar[desktopNameLength]; + kdGetDisplayPropertycvNV(display,KD_DISPLAYPROPERTY_DESKTOP_NAME_NV,desktopName,&desktopNameLength); + } else { + desktopName = KD_DEFAULT_DESKTOP_NV; + } + } else { + desktopName = KD_DEFAULT_DESKTOP_NV; + } + + KDDesktopNV *desktop = kdGetDesktopNV(desktopName,this); + if (!desktop || desktop == (void*)-1) { + qErrnoWarning(kdGetError(), "Could not obtain KDDesktopNV pointer"); + kdReleaseDisplayNV(display); + return; + } + if (desktopNameLength) + delete desktopName; + + QOpenKODEScreen *screen = new QOpenKODEScreen(display,desktop); + mScreens.append(screen); + } } + QOpenKODEIntegration::~QOpenKODEIntegration() { delete mEventLoopIntegration; @@ -212,7 +192,7 @@ QPlatformWindow *QOpenKODEIntegration::createPlatformWindow(QWidget *tlw, WId ) return new QOpenKODEWindow(tlw); } -QWindowSurface *QOpenKODEIntegration::createWindowSurface(QWidget *widget, WId wid) const +QWindowSurface *QOpenKODEIntegration::createWindowSurface(QWidget *widget, WId) const { QWindowSurface *returnSurface = 0; switch (widget->platformWindowFormat().windowApi()) { @@ -248,17 +228,5 @@ QPlatformEventLoopIntegration *QOpenKODEIntegration::createEventLoopIntegration( return mEventLoopIntegration; } -GLuint QOpenKODEIntegration::blitterProgram() -{ - static GLuint shaderProgram = 0; - if (!shaderProgram) { - - shaderProgram = loadShaders(":/shaders/vert.glslv",":/shaders/frag.glslf"); - if (!shaderProgram) - qFatal("QOpenKodeGraphicsSystem(): Cannot load shaders!"); - } - return shaderProgram; -} - QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.h b/src/plugins/platforms/openkode/qopenkodeintegration.h index 454aa90..939cae3 100644 --- a/src/plugins/platforms/openkode/qopenkodeintegration.h +++ b/src/plugins/platforms/openkode/qopenkodeintegration.h @@ -57,13 +57,14 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE struct KDDesktopNV; +struct KDDisplayNV; class QOpenKODECursor; class QOpenKODEScreen : public QPlatformScreen { Q_OBJECT public: - QOpenKODEScreen(); + QOpenKODEScreen(KDDisplayNV *kdDisplay, KDDesktopNV *kdDesktop); ~QOpenKODEScreen() {} QRect geometry() const { return mGeometry; } diff --git a/src/plugins/platforms/openkode/qopenkodewindow.cpp b/src/plugins/platforms/openkode/qopenkodewindow.cpp index 454a50f..fadf564 100644 --- a/src/plugins/platforms/openkode/qopenkodewindow.cpp +++ b/src/plugins/platforms/openkode/qopenkodewindow.cpp @@ -104,9 +104,8 @@ QOpenKODEWindow::QOpenKODEWindow(QWidget *tlw) format.setRedBufferSize(5); format.setGreenBufferSize(6); format.setBlueBufferSize(5); - tlw->setPlatformWindowFormat(format); - m_eglConfig = q_configFromQPlatformWindowFormat(screen->eglDisplay(),tlw->platformWindowFormat()); + m_eglConfig = q_configFromQPlatformWindowFormat(screen->eglDisplay(),format); m_kdWindow = kdCreateWindow(screen->eglDisplay(), m_eglConfig, @@ -169,7 +168,6 @@ QOpenKODEWindow::QOpenKODEWindow(QWidget *tlw) QOpenKODEWindow::~QOpenKODEWindow() { - qDebug() << "destroying window" << m_kdWindow; if (m_platformGlContext != QPlatformGLContext::defaultSharedContext()) { delete m_platformGlContext; } @@ -274,7 +272,6 @@ void QOpenKODEWindow::processMouseEvents(const KDEvent *event) default: buttons = Qt::NoButton; } - qDebug() << x << y; QPoint pos(x,y); QWindowSystemInterface::handleMouseEvent(0,event->timestamp,pos,pos,buttons); } -- cgit v0.12 From 0bf1b83cd7d972a69388cdbd759dbba8b1baffd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 10 Sep 2010 15:27:31 +0200 Subject: Lighthouse: Adding QGenericUnixFontDatabase to OpenKODE --- src/plugins/platforms/openkode/openkode.pro | 2 ++ src/plugins/platforms/openkode/qopenkodeintegration.cpp | 10 +++++++++- src/plugins/platforms/openkode/qopenkodeintegration.h | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/openkode/openkode.pro b/src/plugins/platforms/openkode/openkode.pro index 5f2c1cc..c8ae415 100644 --- a/src/plugins/platforms/openkode/openkode.pro +++ b/src/plugins/platforms/openkode/openkode.pro @@ -19,6 +19,8 @@ HEADERS = qopenkodeintegration.h \ qopenkodeeventloopintegration.h \ openkodekeytranslator.h +include (../fontdatabases/genericunix/genericunix.pri) + RESOURCES = resources.qrc target.path += $$[QT_INSTALL_PLUGINS]/platforms diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.cpp b/src/plugins/platforms/openkode/qopenkodeintegration.cpp index f8b715f..0c29a33 100644 --- a/src/plugins/platforms/openkode/qopenkodeintegration.cpp +++ b/src/plugins/platforms/openkode/qopenkodeintegration.cpp @@ -52,6 +52,8 @@ #include #include +#include "qgenericunixfontdatabase.h" + #include #include #include @@ -120,7 +122,7 @@ QOpenKODEScreen::QOpenKODEScreen(KDDisplayNV *kdDisplay, KDDesktopNV *kdDesktop } QOpenKODEIntegration::QOpenKODEIntegration() - : mEventLoopIntegration(0) + : mEventLoopIntegration(0), mFontDb(new QGenericUnixFontDatabase()) { if (kdInitializeNV() == KD_ENOTINITIALIZED) { qFatal("Did not manage to initialize openkode"); @@ -180,6 +182,7 @@ QOpenKODEIntegration::QOpenKODEIntegration() QOpenKODEIntegration::~QOpenKODEIntegration() { delete mEventLoopIntegration; + delete mFontDb; } QPixmapData *QOpenKODEIntegration::createPixmapData(QPixmapData::PixelType type) const @@ -228,5 +231,10 @@ QPlatformEventLoopIntegration *QOpenKODEIntegration::createEventLoopIntegration( return mEventLoopIntegration; } +QPlatformFontDatabase *QOpenKODEIntegration::fontDatabase() const +{ + return mFontDb; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.h b/src/plugins/platforms/openkode/qopenkodeintegration.h index 939cae3..907b7e2 100644 --- a/src/plugins/platforms/openkode/qopenkodeintegration.h +++ b/src/plugins/platforms/openkode/qopenkodeintegration.h @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -97,6 +98,8 @@ public: QPlatformEventLoopIntegration *createEventLoopIntegration() const; + QPlatformFontDatabase *fontDatabase() const; + virtual QList screens() const { return mScreens; } static GLuint blitterProgram(); @@ -104,6 +107,7 @@ public: private: QList mScreens; QOpenKODEEventLoopIntegration *mEventLoopIntegration; + QPlatformFontDatabase *mFontDb; }; QT_END_NAMESPACE -- cgit v0.12